diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index cd6f27bf65f6e..7eccd5fa3b605 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -25,6 +25,7 @@ use core::mem;
 use core::ops::{self, Deref, Add, Index};
 use core::ptr;
 use core::slice;
+use core::str::Pattern;
 use unicode::str as unicode_str;
 use unicode::str::Utf16Item;
 
@@ -765,6 +766,25 @@ impl<'a> Extend<&'a str> for String {
     }
 }
 
+/// A convenience impl that delegates to the impl for `&str`
+impl<'a, 'b> Pattern<'a> for &'b String {
+    type Searcher = <&'b str as Pattern<'a>>::Searcher;
+
+    fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher {
+        self[..].into_searcher(haystack)
+    }
+
+    #[inline]
+    fn is_contained_in(self, haystack: &'a str) -> bool {
+        self[..].is_contained_in(haystack)
+    }
+
+    #[inline]
+    fn is_prefix_of(self, haystack: &'a str) -> bool {
+        self[..].is_prefix_of(haystack)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq for String {
     #[inline]
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 7bf248917a5cd..98b6533980dd9 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -474,22 +474,16 @@ impl<'a, 'b> Pattern<'a> for &'b [char] {
                       s, CharEqPattern(s));
 }
 
+/// A convenience impl that delegates to the impl for `&str`
+impl<'a, 'b> Pattern<'a> for &'b &'b str {
+    type Searcher =   <&'b str as Pattern<'a>>::Searcher;
+    associated_items!(<&'b str as Pattern<'a>>::Searcher,
+                      s, (*s));
+}
+
 /// Searches for chars that match the given predicate
 impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
     type Searcher =   <CharEqPattern<Self> as Pattern<'a>>::Searcher;
     associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
                       s, CharEqPattern(s));
 }
-
-// Deref-forward impl
-
-use ops::Deref;
-
-/// Delegates to the next deref coercion of `Self` that implements `Pattern`
-impl<'a, 'b, P: 'b + ?Sized, T: Deref<Target = P> + ?Sized> Pattern<'a> for &'b T
-    where &'b P: Pattern<'a>
-{
-    type Searcher =   <&'b P as Pattern<'a>>::Searcher;
-    associated_items!(<&'b P as Pattern<'a>>::Searcher,
-                      s, (&**s));
-}
diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs
index cac78363dd53b..38cab4f0e0942 100644
--- a/src/libcoretest/str.rs
+++ b/src/libcoretest/str.rs
@@ -13,9 +13,7 @@ fn test_pattern_deref_forward() {
     let data = "aabcdaa";
     assert!(data.contains("bcd"));
     assert!(data.contains(&"bcd"));
-    assert!(data.contains(&&"bcd"));
     assert!(data.contains(&"bcd".to_string()));
-    assert!(data.contains(&&"bcd".to_string()));
 }
 
 #[test]
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index d2b5b460d1420..d10ff060418cc 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -12,6 +12,7 @@ use super::{
     FulfillmentError,
     FulfillmentErrorCode,
     MismatchedProjectionTypes,
+    Obligation,
     ObligationCauseCode,
     OutputTypeParameterMismatch,
     PredicateObligation,
@@ -21,6 +22,7 @@ use super::{
 use fmt_macros::{Parser, Piece, Position};
 use middle::infer::InferCtxt;
 use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef};
+use middle::ty_fold::TypeFoldable;
 use std::collections::HashMap;
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::attr::{AttributeMethods, AttrMetaMethods};
@@ -137,24 +139,36 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     report
 }
 
+/// Reports that an overflow has occurred and halts compilation. We
+/// halt compilation unconditionally because it is important that
+/// overflows never be masked -- they basically represent computations
+/// whose result could not be truly determined and thus we can't say
+/// if the program type checks or not -- and they are unusual
+/// occurrences in any case.
+pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+                                          obligation: &Obligation<'tcx, T>)
+                                          -> !
+    where T: UserString<'tcx> + TypeFoldable<'tcx>
+{
+    let predicate =
+        infcx.resolve_type_vars_if_possible(&obligation.predicate);
+    span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
+              "overflow evaluating the requirement `{}`",
+              predicate.user_string(infcx.tcx));
+
+    suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
+
+    note_obligation_cause(infcx, obligation);
+
+    infcx.tcx.sess.abort_if_errors();
+    unreachable!();
+}
+
 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                         obligation: &PredicateObligation<'tcx>,
                                         error: &SelectionError<'tcx>)
 {
     match *error {
-        SelectionError::Overflow => {
-            // We could track the stack here more precisely if we wanted, I imagine.
-            let predicate =
-                infcx.resolve_type_vars_if_possible(&obligation.predicate);
-            span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
-                    "overflow evaluating the requirement `{}`",
-                    predicate.user_string(infcx.tcx));
-
-            suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
-
-            note_obligation_cause(infcx, obligation);
-        }
-
         SelectionError::Unimplemented => {
             match &obligation.cause.code {
                 &ObligationCauseCode::CompareImplMethodObligation => {
@@ -309,8 +323,9 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
-fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                   obligation: &PredicateObligation<'tcx>)
+fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+                                      obligation: &Obligation<'tcx, T>)
+    where T: UserString<'tcx>
 {
     note_obligation_cause_code(infcx,
                                &obligation.predicate,
@@ -318,10 +333,11 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                &obligation.cause.code);
 }
 
-fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        predicate: &ty::Predicate<'tcx>,
-                                        cause_span: Span,
-                                        cause_code: &ObligationCauseCode<'tcx>)
+fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+                                           predicate: &T,
+                                           cause_span: Span,
+                                           cause_code: &ObligationCauseCode<'tcx>)
+    where T: UserString<'tcx>
 {
     let tcx = infcx.tcx;
     match *cause_code {
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index f46cac308287b..24b201c960f16 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -23,9 +23,10 @@ use std::slice::Iter;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
-use util::ppaux::{Repr, UserString};
+use util::ppaux::Repr;
 
 pub use self::error_reporting::report_fulfillment_errors;
+pub use self::error_reporting::report_overflow_error;
 pub use self::error_reporting::suggest_new_overflow_limit;
 pub use self::coherence::orphan_check;
 pub use self::coherence::overlapping_impls;
@@ -151,7 +152,6 @@ pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
 #[derive(Clone,Debug)]
 pub enum SelectionError<'tcx> {
     Unimplemented,
-    Overflow,
     OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
                                 ty::PolyTraitRef<'tcx>,
                                 ty::type_err<'tcx>),
@@ -327,16 +327,9 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     let result = match fulfill_cx.select_all_or_error(infcx, typer) {
         Ok(()) => Ok(Some(())), // Success, we know it implements Copy.
         Err(errors) => {
-            // Check if overflow occurred anywhere and propagate that.
-            if errors.iter().any(
-                |err| match err.code { CodeSelectionError(Overflow) => true, _ => false })
-            {
-                return Err(Overflow);
-            }
-
-            // Otherwise, if there were any hard errors, propagate an
-            // arbitrary one of those. If no hard errors at all,
-            // report ambiguity.
+            // If there were any hard errors, propagate an arbitrary
+            // one of those. If no hard errors at all, report
+            // ambiguity.
             let sel_error =
                 errors.iter()
                       .filter_map(|err| {
@@ -384,16 +377,8 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
             // soldering on, so just treat this like not implemented
             false
         }
-        Err(Overflow) => {
-            span_err!(infcx.tcx.sess, span, E0285,
-                "overflow evaluating whether `{}` is `{}`",
-                      ty.user_string(infcx.tcx),
-                      bound.user_string(infcx.tcx));
-            suggest_new_overflow_limit(infcx.tcx, span);
-            false
-        }
         Err(_) => {
-            // other errors: not implemented.
+            // errors: not implemented.
             false
         }
     }
@@ -652,15 +637,6 @@ impl<'tcx> FulfillmentError<'tcx> {
     {
         FulfillmentError { obligation: obligation, code: code }
     }
-
-    pub fn is_overflow(&self) -> bool {
-        match self.code {
-            CodeAmbiguity => false,
-            CodeSelectionError(Overflow) => true,
-            CodeSelectionError(_) => false,
-            CodeProjectionError(_) => false,
-        }
-    }
 }
 
 impl<'tcx> TraitObligation<'tcx> {
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index 6b66d7227d300..a67410998c727 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -11,9 +11,9 @@
 //! Code for projecting associated types out of trait references.
 
 use super::elaborate_predicates;
+use super::report_overflow_error;
 use super::Obligation;
 use super::ObligationCause;
-use super::Overflow;
 use super::PredicateObligation;
 use super::SelectionContext;
 use super::SelectionError;
@@ -442,7 +442,7 @@ fn project_type<'cx,'tcx>(
     let recursion_limit = selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
-        return Err(ProjectionTyError::TraitSelectionError(Overflow));
+        report_overflow_error(selcx.infcx(), &obligation);
     }
 
     let obligation_trait_ref =
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 7dfbccea0dccd..026ef7d4d0e44 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -21,8 +21,9 @@ use super::DerivedObligationCause;
 use super::project;
 use super::project::{normalize_with_depth, Normalized};
 use super::{PredicateObligation, TraitObligation, ObligationCause};
+use super::{report_overflow_error};
 use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
-use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
+use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
 use super::{Selection};
 use super::{SelectionResult};
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
@@ -561,10 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // not update) the cache.
         let recursion_limit = self.infcx.tcx.sess.recursion_limit.get();
         if stack.obligation.recursion_depth >= recursion_limit {
-            debug!("{} --> overflow (limit={})",
-                   stack.obligation.repr(self.tcx()),
-                   recursion_limit);
-            return Err(Overflow)
+            report_overflow_error(self.infcx(), &stack.obligation);
         }
 
         // Check the cache. Note that we skolemize the trait-ref
@@ -2582,11 +2580,13 @@ impl<'o, 'tcx> Repr<'tcx> for TraitObligationStack<'o, 'tcx> {
 impl<'tcx> EvaluationResult<'tcx> {
     fn may_apply(&self) -> bool {
         match *self {
-            EvaluatedToOk
-            | EvaluatedToAmbig
-            | EvaluatedToErr(Overflow)
-            | EvaluatedToErr(OutputTypeParameterMismatch(..)) => true,
-            EvaluatedToErr(Unimplemented) => false,
+            EvaluatedToOk |
+            EvaluatedToAmbig |
+            EvaluatedToErr(OutputTypeParameterMismatch(..)) =>
+                true,
+
+            EvaluatedToErr(Unimplemented) =>
+                false,
         }
     }
 }
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 88b721ce95862..965aaf12044ec 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -514,9 +514,6 @@ impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
-            super::Overflow =>
-                format!("Overflow"),
-
             super::Unimplemented =>
                 format!("Unimplemented"),
 
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 8f5dbfe2ec000..69846d4f0e4e4 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -1025,8 +1025,9 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // shallow result we are looking for -- that is, what specific impl.
     let typer = NormalizingClosureTyper::new(tcx);
     let mut selcx = traits::SelectionContext::new(&infcx, &typer);
-    let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
-                                             trait_ref.to_poly_trait_predicate());
+    let obligation =
+        traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
+                                trait_ref.to_poly_trait_predicate());
     let selection = match selcx.select(&obligation) {
         Ok(Some(selection)) => selection,
         Ok(None) => {
@@ -1081,7 +1082,7 @@ pub fn predicates_hold<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), predicate);
         fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }
-    drain_fulfillment_cx(DUMMY_SP, &infcx, &mut fulfill_cx, &()).is_ok()
+    drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
 }
 
 pub struct NormalizingClosureTyper<'a,'tcx:'a> {
@@ -1138,7 +1139,7 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
                                                 -> T
     where T : TypeFoldable<'tcx> + Repr<'tcx>
 {
-    match drain_fulfillment_cx(span, infcx, fulfill_cx, result) {
+    match drain_fulfillment_cx(infcx, fulfill_cx, result) {
         Ok(v) => v,
         Err(errors) => {
             infcx.tcx.sess.span_bug(
@@ -1156,8 +1157,7 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
 /// inference variables that appear in `result` to be unified, and
 /// hence we need to process those obligations to get the complete
 /// picture of the type.
-pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
-                                       infcx: &infer::InferCtxt<'a,'tcx>,
+pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
                                        fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
                                        result: &T)
                                        -> StdResult<T,Vec<traits::FulfillmentError<'tcx>>>
@@ -1173,14 +1173,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
     match fulfill_cx.select_all_or_error(infcx, &typer) {
         Ok(()) => { }
         Err(errors) => {
-            // We always want to surface any overflow errors, no matter what.
-            if errors.iter().all(|e| e.is_overflow()) {
-                infcx.tcx.sess.span_fatal(
-                    span,
-                    "reached the recursion limit during monomorphization");
-            } else {
-                return Err(errors);
-            }
+            return Err(errors);
         }
     }
 
diff --git a/src/test/compile-fail/issue-18400.rs b/src/test/compile-fail/issue-18400.rs
index 015f1fa603a20..f8d85f939374d 100644
--- a/src/test/compile-fail/issue-18400.rs
+++ b/src/test/compile-fail/issue-18400.rs
@@ -33,7 +33,4 @@ fn main() {
 
     0.contains(bits);
     //~^ ERROR overflow
-    //~| ERROR overflow
-    //~| ERROR overflow
-    //~| ERROR mismatched types
 }
diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs
index e8bc11317f2aa..368269999a296 100644
--- a/src/test/compile-fail/recursion_limit.rs
+++ b/src/test/compile-fail/recursion_limit.rs
@@ -42,12 +42,5 @@ fn is_send<T:Send>() { }
 fn main() {
     is_send::<A>();
     //~^ ERROR overflow evaluating
-    //~^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
-    //~^^^ NOTE required by `is_send`
-    //~^^^^ ERROR overflow evaluating
-    //~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
-    //~^^^^^^ NOTE required by `is_send`
-    //~^^^^^^^ ERROR overflow evaluating
-    //~^^^^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
-    //~^^^^^^^^^ NOTE required by `is_send`
+    //~| NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
 }