diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2e51a786f4682..49961d02ddab7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -566,7 +566,7 @@ labels to triage issues:
   to fix the issue.
 
 * The dark blue **final-comment-period** label marks bugs that are using the
-  RFC signoff functionality of [rfcbot][rfcbot] and are currenty in the final
+  RFC signoff functionality of [rfcbot][rfcbot] and are currently in the final
   comment period.
 
 * Red, **I**-prefixed labels indicate the **importance** of the issue. The
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index e845438c0a836..2bc037e3fee12 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1822,12 +1822,12 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
             unsafe {
                 let mut ptr = self.as_mut_ptr().add(self.len());
                 let mut local_len = SetLenOnDrop::new(&mut self.len);
-                for element in iterator {
+                iterator.for_each(move |element| {
                     ptr::write(ptr, element);
                     ptr = ptr.offset(1);
                     // NB can't overflow since we would have had to alloc the address space
                     local_len.increment_len(1);
-                }
+                });
             }
         } else {
             self.extend_desugared(iterator)
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 9c4e995e24d01..388abc88cfd71 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -873,8 +873,8 @@ for ty::TyKind<'gcx>
             Tuple(inner_tys) => {
                 inner_tys.hash_stable(hcx, hasher);
             }
-            Projection(ref projection_ty) => {
-                projection_ty.hash_stable(hcx, hasher);
+            Projection(ref data) | UnnormalizedProjection(ref data) => {
+                data.hash_stable(hcx, hasher);
             }
             Opaque(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index b30ccb5976c98..6449227af4ab8 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -283,6 +283,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
             | ty::Never
             | ty::Tuple(..)
             | ty::Projection(..)
+            | ty::UnnormalizedProjection(..)
             | ty::Foreign(..)
             | ty::Param(..)
             | ty::Opaque(..) => {
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index 1cb813c39e68c..e17e777332ec6 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -193,6 +193,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
             ty::Never |
             ty::Tuple(..) |
             ty::Projection(..) |
+            ty::UnnormalizedProjection(..) |
             ty::Foreign(..) |
             ty::Param(..) |
             ty::Closure(..) |
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index d695ad88e47aa..c81d55e69b61a 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -171,7 +171,7 @@ impl<'tcx> Scalar {
     pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
         let i = i.into();
         debug_assert_eq!(truncate(i, size), i,
-                    "Unsigned value {} does not fit in {} bits", i, size.bits());
+                         "Unsigned value {} does not fit in {} bits", i, size.bits());
         Scalar::Bits { bits: i, size: size.bytes() as u8 }
     }
 
@@ -181,7 +181,7 @@ impl<'tcx> Scalar {
         // `into` performed sign extension, we have to truncate
         let truncated = truncate(i as u128, size);
         debug_assert_eq!(sign_extend(truncated, size) as i128, i,
-                    "Signed value {} does not fit in {} bits", i, size.bits());
+                         "Signed value {} does not fit in {} bits", i, size.bits());
         Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
     }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 27ef01b93cda1..30117f90dc69f 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -12,7 +12,6 @@
 //!
 //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html
 
-use graphviz::IntoCow;
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use hir::{self, HirId, InlineAsm};
@@ -327,22 +326,20 @@ impl<'tcx> Mir<'tcx> {
         if idx < stmts.len() {
             &stmts[idx].source_info
         } else {
-            assert!(idx == stmts.len());
+            assert_eq!(idx, stmts.len());
             &block.terminator().source_info
         }
     }
 
     /// Check if `sub` is a sub scope of `sup`
     pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool {
-        loop {
-            if sub == sup {
-                return true;
-            }
+        while sub != sup {
             match self.source_scopes[sub].parent_scope {
                 None => return false,
                 Some(p) => sub = p,
             }
         }
+        true
     }
 
     /// Return the return type, it always return first element from `local_decls` array
@@ -526,9 +523,7 @@ impl BorrowKind {
     pub fn allows_two_phase_borrow(&self) -> bool {
         match *self {
             BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
-            BorrowKind::Mut {
-                allow_two_phase_borrow,
-            } => allow_two_phase_borrow,
+            BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
         }
     }
 }
@@ -1574,42 +1569,42 @@ impl<'tcx> TerminatorKind<'tcx> {
                         };
                         fmt_const_val(&mut s, &c).unwrap();
                         s.into()
-                    }).chain(iter::once(String::from("otherwise").into()))
+                    }).chain(iter::once("otherwise".into()))
                     .collect()
             }
             Call {
                 destination: Some(_),
                 cleanup: Some(_),
                 ..
-            } => vec!["return".into_cow(), "unwind".into_cow()],
+            } => vec!["return".into(), "unwind".into()],
             Call {
                 destination: Some(_),
                 cleanup: None,
                 ..
-            } => vec!["return".into_cow()],
+            } => vec!["return".into()],
             Call {
                 destination: None,
                 cleanup: Some(_),
                 ..
-            } => vec!["unwind".into_cow()],
+            } => vec!["unwind".into()],
             Call {
                 destination: None,
                 cleanup: None,
                 ..
             } => vec![],
-            Yield { drop: Some(_), .. } => vec!["resume".into_cow(), "drop".into_cow()],
-            Yield { drop: None, .. } => vec!["resume".into_cow()],
+            Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
+            Yield { drop: None, .. } => vec!["resume".into()],
             DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
-                vec!["return".into_cow()]
+                vec!["return".into()]
             }
             DropAndReplace {
                 unwind: Some(_), ..
             }
             | Drop {
                 unwind: Some(_), ..
-            } => vec!["return".into_cow(), "unwind".into_cow()],
+            } => vec!["return".into(), "unwind".into()],
             Assert { cleanup: None, .. } => vec!["".into()],
-            Assert { .. } => vec!["success".into_cow(), "unwind".into_cow()],
+            Assert { .. } => vec!["success".into(), "unwind".into()],
             FalseEdges {
                 ref imaginary_targets,
                 ..
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 4d353a36db02a..7520695a7cd90 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -325,7 +325,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> {
                 String::new()
             };
 
-            let crate_disambiguator = format!("{}", tcx.crate_disambiguator(cnum));
+            let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
             // Using a shortened disambiguator of about 40 bits
             format!("{}.{}{}",
                 tcx.crate_name(cnum),
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 2a25e057a7149..fc7b4862b0ae5 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -87,8 +87,8 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
                         assert!(index < adt_def.variants.len());
                         assert_eq!(adt_def, adt_def1);
                         PlaceTy::Downcast { adt_def,
-                                             substs,
-                                             variant_index: index }
+                                            substs,
+                                            variant_index: index }
                     }
                     _ => {
                         bug!("cannot downcast non-ADT type: `{:?}`", self)
@@ -151,7 +151,7 @@ impl<'tcx> Place<'tcx> {
                     }
                 },
                 _ => None,
-            }
+            }
             _ => None,
         }
     }
@@ -255,9 +255,9 @@ impl<'tcx> Operand<'tcx> {
 
 impl<'tcx> BinOp {
       pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                    lhs_ty: Ty<'tcx>,
-                    rhs_ty: Ty<'tcx>)
-                    -> Ty<'tcx> {
+                          lhs_ty: Ty<'tcx>,
+                          rhs_ty: Ty<'tcx>)
+                          -> Ty<'tcx> {
         // FIXME: handle SIMD correctly
         match self {
             &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 7401d4099ff6d..caf549e37a907 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -475,6 +475,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
 
         ty::Error => true,
 
+        ty::UnnormalizedProjection(..) |
         ty::Closure(..) |
         ty::Generator(..) |
         ty::GeneratorWitness(..) |
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 7695f26d70115..3b3e38a8bb7ca 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -269,7 +269,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 ty::Generator(..) => Some(18),
                 ty::Foreign(..) => Some(19),
                 ty::GeneratorWitness(..) => Some(20),
-                ty::Infer(..) | ty::Error => None
+                ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             }
         }
 
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 0f330504334a6..e6bf02cd73e0d 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -292,7 +292,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
             ty::Predicate::Trait(ref data) => {
                 let trait_obligation = obligation.with(data.clone());
 
-                if data.is_global() && !data.has_late_bound_regions() {
+                if data.is_global() {
                     // no type variables present, can use evaluation for better caching.
                     // FIXME: consider caching errors too.
                     if self.selcx.infcx().predicate_must_hold(&obligation) {
@@ -362,6 +362,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
                         match binder.no_late_bound_regions() {
                             // If so, this obligation is an error (for now). Eventually we should be
                             // able to support additional cases here, like `for<'a> &'a str: 'a`.
+                            // NOTE: this is duplicate-implemented between here and fulfillment.
                             None => {
                                 ProcessResult::Error(CodeSelectionError(Unimplemented))
                             }
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index f5fb183ec1a5d..aaf03f8e7fb55 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -253,5 +253,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Generator(..) => false,
+
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
     }
 }
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 268b8e0161b6d..c9fa960a36561 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -690,10 +690,92 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 }
             }
 
-            ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
-                // we do not consider region relationships when
-                // evaluating trait matches
-                Ok(EvaluatedToOk)
+            ty::Predicate::TypeOutlives(ref binder) => {
+                assert!(!binder.has_escaping_regions());
+                // Check if the type has higher-ranked regions.
+                if binder.skip_binder().0.has_escaping_regions() {
+                    // If so, this obligation is an error (for now). Eventually we should be
+                    // able to support additional cases here, like `for<'a> &'a str: 'a`.
+
+                    // NOTE: this hack is implemented in both trait fulfillment and
+                    // evaluation. If you fix it in one place, make sure you fix it
+                    // in the other.
+
+                    // We don't want to allow this sort of reasoning in intercrate
+                    // mode, for backwards-compatibility reasons.
+                    if self.intercrate.is_some() {
+                        Ok(EvaluatedToAmbig)
+                    } else {
+                        Ok(EvaluatedToErr)
+                    }
+                } else {
+                    // If the type has no late bound regions, then if we assign all
+                    // the inference variables in it to be 'static, then the type
+                    // will be 'static itself.
+                    //
+                    // Therefore, `staticize(T): 'a` holds for any `'a`, so this
+                    // obligation is fulfilled. Because evaluation works with
+                    // staticized types (yes I know this is involved with #21974),
+                    // we are 100% OK here.
+                    Ok(EvaluatedToOk)
+                }
+            }
+
+            ty::Predicate::RegionOutlives(ref binder) => {
+                let ty::OutlivesPredicate(r_a, r_b) = binder.skip_binder();
+
+                if r_a == r_b {
+                    // for<'a> 'a: 'a. OK
+                    Ok(EvaluatedToOk)
+                } else if **r_a == ty::ReStatic {
+                    // 'static: 'x always holds.
+                    //
+                    // This special case is handled somewhat inconsistently - if we
+                    // have an inference variable that is supposed to be equal to
+                    // `'static`, then we don't allow it to be equated to an LBR,
+                    // but if we have a literal `'static`, then we *do*.
+                    //
+                    // This is actually consistent with how our region inference works.
+                    //
+                    // It would appear that this sort of inconsistency would
+                    // cause "instability" problems with evaluation caching. However,
+                    // evaluation caching is only for trait predicates, and when
+                    // trait predicates create nested obligations, they contain
+                    // inference variables for all the regions in the trait - the
+                    // only way this codepath can be reached from trait predicate
+                    // evaluation is when the user typed an explicit `where 'static: 'a`
+                    // lifetime bound (in which case we want to return EvaluatedToOk).
+                    //
+                    // If we ever want to handle inference variables that might be
+                    // equatable with ReStatic, we need to make sure we are not confused by
+                    // technically-allowed-by-RFC-447-but-probably-should-not-be
+                    // impls such as
+                    // ```Rust
+                    // impl<'a, 's, T> X<'s> for T where T: Debug + 'a, 'a: 's
+                    // ```
+                    Ok(EvaluatedToOk)
+                } else if r_a.is_late_bound() || r_b.is_late_bound() {
+                    // There is no current way to prove `for<'a> 'a: 'x`
+                    // unless `'a = 'x`, because there are no bounds involving
+                    // lifetimes.
+
+                    // It might be possible to prove `for<'a> 'x: 'a` by forcing `'x`
+                    // to be `'static`. However, this is not currently done by type
+                    // inference unless `'x` is literally ReStatic. See the comment
+                    // above.
+
+                    // We don't want to allow this sort of reasoning in intercrate
+                    // mode, for backwards-compatibility reasons.
+                    if self.intercrate.is_some() {
+                        Ok(EvaluatedToAmbig)
+                    } else {
+                        Ok(EvaluatedToErr)
+                    }
+                } else {
+                    // Relating 2 inference variable regions. These will
+                    // always hold if our query is "staticized".
+                    Ok(EvaluatedToOk)
+                }
             }
 
             ty::Predicate::ObjectSafe(trait_def_id) => {
@@ -900,6 +982,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         {
             debug!("evaluate_stack({:?}) --> recursive",
                    stack.fresh_trait_ref);
+
             let cycle = stack.iter().skip(1).take(rec_index + 1);
             let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
             if self.coinductive_match(cycle) {
@@ -2200,6 +2283,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
+            ty::UnnormalizedProjection(..) |
             ty::Infer(ty::CanonicalTy(_)) |
             ty::Infer(ty::FreshTy(_)) |
             ty::Infer(ty::FreshIntTy(_)) |
@@ -2272,6 +2356,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 Ambiguous
             }
 
+            ty::UnnormalizedProjection(..) |
             ty::Infer(ty::CanonicalTy(_)) |
             ty::Infer(ty::FreshTy(_)) |
             ty::Infer(ty::FreshIntTy(_)) |
@@ -2310,6 +2395,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 Vec::new()
             }
 
+            ty::UnnormalizedProjection(..) |
             ty::Dynamic(..) |
             ty::Param(..) |
             ty::Foreign(..) |
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 64e9d15092eb8..29b3db400b116 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2266,7 +2266,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             self,
             Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
             Generator, GeneratorWitness, Dynamic, Closure, Tuple,
-            Param, Infer, Projection, Opaque, Foreign);
+            Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("Region interner: #{}", self.interners.region.borrow().len());
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 9f9d918415e7e..b3a1b312ca1d3 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -222,6 +222,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
             ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
             ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
             ty::Projection(_) => "associated type".to_string(),
+            ty::UnnormalizedProjection(_) => "non-normalized associated type".to_string(),
             ty::Param(ref p) => {
                 if p.is_self() {
                     "Self".to_string()
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 2d055fd307dc4..0f68e7aba4def 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -103,6 +103,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::FnPtr(ref f) => {
             Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
         }
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
         ty::Projection(_) | ty::Param(_) => {
             if can_simplify_params {
                 // In normalized types, projections don't unify with
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 08d1057823873..3ccc24e73a5c9 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -150,6 +150,8 @@ impl FlagComputation {
                 self.add_projection_ty(data);
             }
 
+            &ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             &ty::Opaque(_, substs) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_substs(substs);
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index c8d104e6c321f..46d133224f819 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -463,6 +463,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         ty::Str |
         ty::FnPtr(_) |
         ty::Projection(_) |
+        ty::UnnormalizedProjection(..) |
         ty::Param(_) |
         ty::Opaque(..) |
         ty::Infer(_) |
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 8bfe46568eb19..7df8af5fa2e7d 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1123,7 +1123,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
                 tcx.layout_raw(param_env.and(normalized))?
             }
-            ty::GeneratorWitness(..) | ty::Infer(_) => {
+            ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
             }
             ty::Param(_) | ty::Error => {
@@ -1702,8 +1702,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                 }
             }
 
-            ty::Projection(_) | ty::Opaque(..) | ty::Param(_) |
-            ty::Infer(_) | ty::Error => {
+            ty::Projection(_) | ty::UnnormalizedProjection(..) |
+            ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
         })
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index b2281691bd660..77e0b9e91bce6 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2339,6 +2339,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 vec![ty]
             }
 
+            UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             Param(..) => {
                 // perf hack: if there is a `T: Sized` bound, then
                 // we know that `T` is Sized and do not need to check
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 68f6707087687..91eda66e08c6e 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -124,6 +124,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 }
             }
 
+            ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             // We assume that inference variables are fully resolved.
             // So, if we encounter an inference variable, just record
             // the unresolved variable as a component.
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index aab268c07c4fb..c3c4cbed89d88 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -876,6 +876,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
             ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
             ty::Projection(ref data) => ty::Projection(data.fold_with(folder)),
+            ty::UnnormalizedProjection(ref data) => {
+                ty::UnnormalizedProjection(data.fold_with(folder))
+            }
             ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
             ty::Bool | ty::Char | ty::Str | ty::Int(_) |
             ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
@@ -910,7 +913,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             }
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
             ty::Closure(_did, ref substs) => substs.visit_with(visitor),
-            ty::Projection(ref data) => data.visit_with(visitor),
+            ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
+                data.visit_with(visitor)
+            }
             ty::Opaque(_, ref substs) => substs.visit_with(visitor),
             ty::Bool | ty::Char | ty::Str | ty::Int(_) |
             ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 6c40dd8923916..06d559fd9dbea 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -157,6 +157,11 @@ pub enum TyKind<'tcx> {
     /// `<T as Trait<..>>::N`.
     Projection(ProjectionTy<'tcx>),
 
+    /// A placeholder type used when we do not have enough information
+    /// to normalize the projection of an associated type to an
+    /// existing concrete type. Currently only used with chalk-engine.
+    UnnormalizedProjection(ProjectionTy<'tcx>),
+
     /// Opaque (`impl Trait`) type found in a return type.
     /// The `DefId` comes either from
     /// * the `impl Trait` ast::Ty node,
@@ -1806,7 +1811,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
             Generator(_, GeneratorSubsts { ref substs }, _) => {
                 substs.regions().collect()
             }
-            Projection(ref data) => {
+            Projection(ref data) | UnnormalizedProjection(ref data) => {
                 data.substs.regions().collect()
             }
             FnDef(..) |
@@ -1886,6 +1891,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
 
             ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
 
+            ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             ty::Infer(ty::TyVar(_)) => false,
 
             ty::Infer(ty::CanonicalTy(_)) |
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 93fc77359e43a..4d7bab3cf433b 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -958,6 +958,8 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
         ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
 
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
         // Structural recursion.
         ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
 
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index cf87c2d457471..d20c4f716429b 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -97,7 +97,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::Ref(_, ty, _) => {
             stack.push(ty);
         }
-        ty::Projection(ref data) => {
+        ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
             stack.extend(data.substs.types().rev());
         }
         ty::Dynamic(ref obj, ..) => {
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 63206a660df41..397c63a149a4c 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -289,6 +289,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                     self.compute_projection(data);
                 }
 
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
                 ty::Adt(def, substs) => {
                     // WfNominalType
                     let obligations = self.nominal_obligations(def.did, substs);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 10382008e0d43..814f8880bbf2f 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -18,7 +18,7 @@ use ty::{Bool, Char, Adt};
 use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
 use ty::{Param, RawPtr, Ref, Never, Tuple};
 use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
-use ty::{Dynamic, Int, Uint, Infer};
+use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
 use util::nodemap::FxHashSet;
 
@@ -1143,6 +1143,11 @@ define_print! {
                 }
                 Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
                 Projection(ref data) => data.print(f, cx),
+                UnnormalizedProjection(ref data) => {
+                    write!(f, "Unnormalized(")?;
+                    data.print(f, cx)?;
+                    write!(f, ")")
+                }
                 Opaque(def_id, substs) => {
                     if cx.is_verbose {
                         return write!(f, "Opaque({:?}, {:?})", def_id, substs);
diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs
index f9eb80a1988af..2f110fd552a8d 100644
--- a/src/librustc_codegen_llvm/debuginfo/type_names.rs
+++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs
@@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         }
         ty::Error |
         ty::Infer(_) |
+        ty::UnnormalizedProjection(..) |
         ty::Projection(..) |
         ty::Opaque(..) |
         ty::GeneratorWitness(..) |
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 01d4d0f8cdb67..a441f7a87f763 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -722,6 +722,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             ty::Closure(..) |
             ty::Generator(..) |
             ty::GeneratorWitness(..) |
+            ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Opaque(..) |
             ty::FnDef(..) => bug!("Unexpected type in foreign function"),
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 11e27a597fbca..222d1164667d3 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -971,7 +971,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
 
 /// Undefined bytes
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    // FIXME(solson): This is a very naive, slow version.
+    // FIXME: Add a fast version for the common, nonoverlapping case
     fn copy_undef_mask(
         &mut self,
         src: Pointer,
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 3f5a05f9d0ed8..f0ea93bfffd3e 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -382,6 +382,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
             }
             ty::Error |
             ty::Infer(_) |
+            ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Param(_) |
             ty::GeneratorWitness(_) |
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index e3ec2e6b9ce02..2996fe0320042 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -272,6 +272,8 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             overflows: vec![],
         }),
 
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
         ty::Infer(..) | ty::Error => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 564ecae15dc35..285fed9544ddb 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -124,6 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
             ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)),
+            ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
             ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 71c78e7f87c07..85b6bcbd144fc 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -309,11 +309,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 };
                 if self.can_coerce(ref_ty, expected) {
                     if let Ok(src) = cm.span_to_snippet(sp) {
-                        let sugg_expr = match expr.node { // parenthesize if needed (Issue #46756)
+                        let needs_parens = match expr.node {
+                            // parenthesize if needed (Issue #46756)
                             hir::ExprKind::Cast(_, _) |
-                            hir::ExprKind::Binary(_, _, _) => format!("({})", src),
-                            _ => src,
+                            hir::ExprKind::Binary(_, _, _) => true,
+                            // parenthesize borrows of range literals (Issue #54505)
+                            _ if self.is_range_literal(expr) => true,
+                            _ => false,
                         };
+                        let sugg_expr = if needs_parens {
+                            format!("({})", src)
+                        } else {
+                            src
+                        };
+
                         if let Some(sugg) = self.can_use_as_ref(expr) {
                             return Some(sugg);
                         }
@@ -374,6 +383,66 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         None
     }
 
+    /// This function checks if the specified expression is a built-in range literal.
+    /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`).
+    fn is_range_literal(&self, expr: &hir::Expr) -> bool {
+        use hir::{Path, QPath, ExprKind, TyKind};
+
+        // We support `::std::ops::Range` and `::core::ops::Range` prefixes
+        let is_range_path = |path: &Path| {
+            let mut segs = path.segments.iter()
+                .map(|seg| seg.ident.as_str());
+
+            if let (Some(root), Some(std_core), Some(ops), Some(range), None) =
+                (segs.next(), segs.next(), segs.next(), segs.next(), segs.next())
+            {
+                // "{{root}}" is the equivalent of `::` prefix in Path
+                root == "{{root}}" && (std_core == "std" || std_core == "core")
+                    && ops == "ops" && range.starts_with("Range")
+            } else {
+                false
+            }
+        };
+
+        let span_is_range_literal = |span: &Span| {
+            // Check whether a span corresponding to a range expression
+            // is a range literal, rather than an explicit struct or `new()` call.
+            let source_map = self.tcx.sess.source_map();
+            let end_point = source_map.end_point(*span);
+
+            if let Ok(end_string) = source_map.span_to_snippet(end_point) {
+                !(end_string.ends_with("}") || end_string.ends_with(")"))
+            } else {
+                false
+            }
+        };
+
+        match expr.node {
+            // All built-in range literals but `..=` and `..` desugar to Structs
+            ExprKind::Struct(QPath::Resolved(None, ref path), _, _) |
+            // `..` desugars to its struct path
+            ExprKind::Path(QPath::Resolved(None, ref path)) => {
+                return is_range_path(&path) && span_is_range_literal(&expr.span);
+            }
+
+            // `..=` desugars into `::std::ops::RangeInclusive::new(...)`
+            ExprKind::Call(ref func, _) => {
+                if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node {
+                    if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node {
+                        let call_to_new = segment.ident.as_str() == "new";
+
+                        return is_range_path(&path) && span_is_range_literal(&expr.span)
+                            && call_to_new;
+                    }
+                }
+            }
+
+            _ => {}
+        }
+
+        false
+    }
+
     pub fn check_for_cast(&self,
                       err: &mut DiagnosticBuilder<'tcx>,
                       expr: &hir::Expr,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 17e0b0431da6e..f96c85ae7ae3f 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1637,9 +1637,39 @@ fn explicit_predicates_of<'a, 'tcx>(
     def_id: DefId,
 ) -> ty::GenericPredicates<'tcx> {
     use rustc::hir::*;
+    use rustc_data_structures::fx::FxHashSet;
 
     debug!("explicit_predicates_of(def_id={:?})", def_id);
 
+    /// A data structure with unique elements, which preserves order of insertion.
+    /// Preserving the order of insertion is important here so as not to break
+    /// compile-fail UI tests.
+    struct UniquePredicates<'tcx> {
+        predicates: Vec<(ty::Predicate<'tcx>, Span)>,
+        uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>,
+    }
+
+    impl<'tcx> UniquePredicates<'tcx> {
+        fn new() -> Self {
+            UniquePredicates {
+                predicates: vec![],
+                uniques: FxHashSet::default(),
+            }
+        }
+
+        fn push(&mut self, value: (ty::Predicate<'tcx>, Span)) {
+            if self.uniques.insert(value) {
+                self.predicates.push(value);
+            }
+        }
+
+        fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter: I) {
+            for value in iter {
+                self.push(value);
+            }
+        }
+    }
+
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let node = tcx.hir.get(node_id);
 
@@ -1649,7 +1679,7 @@ fn explicit_predicates_of<'a, 'tcx>(
     let icx = ItemCtxt::new(tcx, def_id);
     let no_generics = hir::Generics::empty();
 
-    let mut predicates = vec![];
+    let mut predicates = UniquePredicates::new();
 
     let ast_generics = match node {
         Node::TraitItem(item) => &item.generics,
@@ -1744,7 +1774,7 @@ fn explicit_predicates_of<'a, 'tcx>(
     // on a trait we need to add in the supertrait bounds and bounds found on
     // associated types.
     if let Some((_trait_ref, _)) = is_trait {
-        predicates = tcx.super_predicates_of(def_id).predicates;
+        predicates.extend(tcx.super_predicates_of(def_id).predicates);
     }
 
     // In default impls, we can assume that the self type implements
@@ -1895,6 +1925,8 @@ fn explicit_predicates_of<'a, 'tcx>(
         }))
     }
 
+    let mut predicates = predicates.predicates;
+
     // Subtle: before we store the predicates into the tcx, we
     // sort them so that predicates like `T: Foo<Item=U>` come
     // before uses of `U`.  This avoids false ambiguity errors
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 95544da0b8e0d..1125de55a0668 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -336,6 +336,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 // types, where we use Error as the Self type
             }
 
+            ty::UnnormalizedProjection(..) |
             ty::GeneratorWitness(..) |
             ty::Infer(..) => {
                 bug!("unexpected type encountered in \
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 371b631723a39..9b305ad03b056 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2737,6 +2737,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
+            ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
             ty::Infer(..) => panic!("Infer"),
             ty::Error => panic!("Error"),
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 3de4a1bd4170b..7a5353bb60ff6 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -217,6 +217,35 @@ pub trait Error: Debug + Display {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
+    /// Converts a type of [`Error`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    /// use std::mem;
+    ///
+    /// #[derive(Debug)]
+    /// struct AnError;
+    ///
+    /// impl fmt::Display for AnError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f , "An error")
+    ///     }
+    /// }
+    ///
+    /// impl Error for AnError {
+    ///     fn description(&self) -> &str {
+    ///         "Description of an error"
+    ///     }
+    /// }
+    ///
+    /// let an_error = AnError;
+    /// assert!(0 == mem::size_of_val(&an_error));
+    /// let a_boxed_error = Box::<Error>::from(an_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: E) -> Box<dyn Error + 'a> {
         Box::new(err)
     }
@@ -224,6 +253,41 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] +
+    /// [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    /// use std::mem;
+    ///
+    /// #[derive(Debug)]
+    /// struct AnError;
+    ///
+    /// impl fmt::Display for AnError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f , "An error")
+    ///     }
+    /// }
+    ///
+    /// impl Error for AnError {
+    ///     fn description(&self) -> &str {
+    ///         "Description of an error"
+    ///     }
+    /// }
+    ///
+    /// unsafe impl Send for AnError {}
+    ///
+    /// unsafe impl Sync for AnError {}
+    ///
+    /// let an_error = AnError;
+    /// assert!(0 == mem::size_of_val(&an_error));
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(an_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
         Box::new(err)
     }
@@ -231,6 +295,19 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for Box<dyn Error + Send + Sync> {
+    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_string_error = "a string error".to_string();
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_string_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: String) -> Box<dyn Error + Send + Sync> {
         #[derive(Debug)]
         struct StringError(String);
@@ -251,6 +328,18 @@ impl From<String> for Box<dyn Error + Send + Sync> {
 
 #[stable(feature = "string_box_error", since = "1.6.0")]
 impl From<String> for Box<dyn Error> {
+    /// Converts a [`String`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_string_error = "a string error".to_string();
+    /// let a_boxed_error = Box::<Error>::from(a_string_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(str_err: String) -> Box<dyn Error> {
         let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
         let err2: Box<dyn Error> = err1;
@@ -260,6 +349,19 @@ impl From<String> for Box<dyn Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_str_error = "a str error";
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_str_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
@@ -267,6 +369,18 @@ impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
 
 #[stable(feature = "string_box_error", since = "1.6.0")]
 impl<'a> From<&'a str> for Box<dyn Error> {
+    /// Converts a [`str`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_str_error = "a str error";
+    /// let a_boxed_error = Box::<Error>::from(a_str_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: &'a str) -> Box<dyn Error> {
         From::from(String::from(err))
     }
@@ -274,6 +388,20 @@ impl<'a> From<&'a str> for Box<dyn Error> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    /// use std::borrow::Cow;
+    ///
+    /// let a_cow_str_error = Cow::from("a str error");
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_cow_str_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
@@ -281,6 +409,19 @@ impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
+    /// Converts a [`Cow`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    /// use std::borrow::Cow;
+    ///
+    /// let a_cow_str_error = Cow::from("a str error");
+    /// let a_boxed_error = Box::<Error>::from(a_cow_str_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: Cow<'a, str>) -> Box<dyn Error> {
         From::from(String::from(err))
     }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f2acdb3f469d1..83a05921510b4 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2228,6 +2228,9 @@ impl<'a> State<'a> {
                 self.word_nbsp("async")?;
                 self.print_capture_clause(capture_clause)?;
                 self.s.space()?;
+                // cbox/ibox in analogy to the `ExprKind::Block` arm above
+                self.cbox(INDENT_UNIT)?;
+                self.ibox(0)?;
                 self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::Assign(ref lhs, ref rhs) => {
diff --git a/src/test/pretty/issue-54752-async-block.rs b/src/test/pretty/issue-54752-async-block.rs
new file mode 100644
index 0000000000000..6930ee1a386fe
--- /dev/null
+++ b/src/test/pretty/issue-54752-async-block.rs
@@ -0,0 +1,7 @@
+#![feature(async_await)]
+#![allow(unused_parens)]
+
+// edition:2018
+// pp-exact
+
+fn main() { let _a = (async  { }); }
diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr
index d6673f6a8a6fb..4a3e14ac03472 100644
--- a/src/test/ui/chalkify/lower_env1.stderr
+++ b/src/test/ui/chalkify/lower_env1.stderr
@@ -5,9 +5,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
-   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
+   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
 
 error: program clause dump
   --> $DIR/lower_env1.rs:19:1
@@ -16,11 +15,10 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
    = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
-   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
+   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
    = note: WellFormed(Self: Foo) :- Implemented(Self: Foo).
    = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized).
 
diff --git a/src/test/ui/issue-54302-cases.rs b/src/test/ui/issue-54302-cases.rs
new file mode 100644
index 0000000000000..6d1c61c80f06e
--- /dev/null
+++ b/src/test/ui/issue-54302-cases.rs
@@ -0,0 +1,95 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Mirror {
+    type Image;
+    fn coerce(self) -> Self::Image;
+}
+
+impl<T> Mirror for T {
+    type Image = T;
+    fn coerce(self) -> Self { self }
+}
+
+trait Foo<'x, T> {
+    fn foo(self) -> &'x T;
+}
+
+impl<'s, 'x, T: 'x> Foo<'x, T> for &'s T where &'s T: Foo2<'x, T> {
+    fn foo(self) -> &'x T { self.foo2() }
+}
+
+trait Foo2<'x, T> {
+    fn foo2(self) -> &'x T;
+}
+
+// example 1 - fails leak check
+impl<'x> Foo2<'x, u32> for &'x u32
+{
+    fn foo2(self) -> &'x u32 { self }
+}
+
+// example 2 - OK with this issue
+impl<'x, 'a: 'x> Foo2<'x, i32> for &'a i32
+{
+    fn foo2(self) -> &'x i32 { self }
+}
+
+// example 3 - fails due to issue #XYZ + Leak-check
+impl<'x, T> Foo2<'x, u64> for T
+    where T: Mirror<Image=&'x u64>
+{
+    fn foo2(self) -> &'x u64 { self.coerce() }
+}
+
+// example 4 - fails due to issue #XYZ
+impl<'x, 'a: 'x, T> Foo2<'x, i64> for T
+    where T: Mirror<Image=&'a i64>
+{
+    fn foo2(self) -> &'x i64 { self.coerce() }
+}
+
+
+trait RefFoo<T> {
+    fn ref_foo(&self) -> &'static T;
+}
+
+impl<T> RefFoo<T> for T where for<'a> &'a T: Foo<'static, T> {
+    fn ref_foo(&self) -> &'static T {
+        self.foo()
+    }
+}
+
+
+fn coerce_lifetime1(a: &u32) -> &'static u32
+{
+    <u32 as RefFoo<u32>>::ref_foo(a)
+    //~^ ERROR the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied
+}
+
+fn coerce_lifetime2(a: &i32) -> &'static i32
+{
+    <i32 as RefFoo<i32>>::ref_foo(a)
+    //~^ ERROR the requirement `for<'a> 'a : ` is not satisfied
+}
+
+fn coerce_lifetime3(a: &u64) -> &'static u64
+{
+    <u64 as RefFoo<u64>>::ref_foo(a)
+    //~^ ERROR type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64`
+}
+
+fn coerce_lifetime4(a: &i64) -> &'static i64
+{
+    <i64 as RefFoo<i64>>::ref_foo(a)
+    //~^ ERROR type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64`
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-54302-cases.stderr b/src/test/ui/issue-54302-cases.stderr
new file mode 100644
index 0000000000000..9603f7a973c13
--- /dev/null
+++ b/src/test/ui/issue-54302-cases.stderr
@@ -0,0 +1,65 @@
+error[E0277]: the trait bound `for<'a> &'a u32: Foo2<'_, u32>` is not satisfied
+  --> $DIR/issue-54302-cases.rs:73:5
+   |
+LL |     <u32 as RefFoo<u32>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Foo2<'_, u32>` is not implemented for `&'a u32`
+   |
+   = help: the following implementations were found:
+             <&'x u32 as Foo2<'x, u32>>
+   = note: required because of the requirements on the impl of `for<'a> Foo<'static, u32>` for `&'a u32`
+   = note: required because of the requirements on the impl of `RefFoo<u32>` for `u32`
+note: required by `RefFoo::ref_foo`
+  --> $DIR/issue-54302-cases.rs:61:5
+   |
+LL |     fn ref_foo(&self) -> &'static T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0279]: the requirement `for<'a> 'a : ` is not satisfied (`expected bound lifetime parameter 'a, found concrete lifetime`)
+  --> $DIR/issue-54302-cases.rs:79:5
+   |
+LL |     <i32 as RefFoo<i32>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i32>` for `&'a i32`
+   = note: required because of the requirements on the impl of `for<'a> Foo<'static, i32>` for `&'a i32`
+   = note: required because of the requirements on the impl of `RefFoo<i32>` for `i32`
+note: required by `RefFoo::ref_foo`
+  --> $DIR/issue-54302-cases.rs:61:5
+   |
+LL |     fn ref_foo(&self) -> &'static T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `for<'a> <&'a u64 as Mirror>::Image == &u64`
+  --> $DIR/issue-54302-cases.rs:85:5
+   |
+LL |     <u64 as RefFoo<u64>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime
+   |
+   = note: required because of the requirements on the impl of `for<'a> Foo2<'_, u64>` for `&'a u64`
+   = note: required because of the requirements on the impl of `for<'a> Foo<'static, u64>` for `&'a u64`
+   = note: required because of the requirements on the impl of `RefFoo<u64>` for `u64`
+note: required by `RefFoo::ref_foo`
+  --> $DIR/issue-54302-cases.rs:61:5
+   |
+LL |     fn ref_foo(&self) -> &'static T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0271]: type mismatch resolving `for<'a> <&'a i64 as Mirror>::Image == &i64`
+  --> $DIR/issue-54302-cases.rs:91:5
+   |
+LL |     <i64 as RefFoo<i64>>::ref_foo(a)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime
+   |
+   = note: required because of the requirements on the impl of `for<'a> Foo2<'_, i64>` for `&'a i64`
+   = note: required because of the requirements on the impl of `for<'a> Foo<'static, i64>` for `&'a i64`
+   = note: required because of the requirements on the impl of `RefFoo<i64>` for `i64`
+note: required by `RefFoo::ref_foo`
+  --> $DIR/issue-54302-cases.rs:61:5
+   |
+LL |     fn ref_foo(&self) -> &'static T;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0271, E0277, E0279.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issue-54302.rs b/src/test/ui/issue-54302.rs
new file mode 100644
index 0000000000000..969d19cac2d76
--- /dev/null
+++ b/src/test/ui/issue-54302.rs
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Deserialize<'de> {}
+
+trait DeserializeOwned: for<'de> Deserialize<'de> {}
+impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
+
+// Based on this impl, `&'static str` only implements Deserialize<'static>.
+// It does not implement for<'de> Deserialize<'de>.
+impl<'de: 'a, 'a> Deserialize<'de> for &'a str {}
+
+fn main() {
+    // Then why does it implement DeserializeOwned? This compiles.
+    fn assert_deserialize_owned<T: DeserializeOwned>() {}
+    assert_deserialize_owned::<&'static str>();
+    //~^ ERROR the requirement `for<'de> 'de : ` is not satisfied
+
+    // It correctly does not implement for<'de> Deserialize<'de>.
+    //fn assert_hrtb<T: for<'de> Deserialize<'de>>() {}
+    //assert_hrtb::<&'static str>();
+}
diff --git a/src/test/ui/issue-54302.stderr b/src/test/ui/issue-54302.stderr
new file mode 100644
index 0000000000000..f122daeecf63a
--- /dev/null
+++ b/src/test/ui/issue-54302.stderr
@@ -0,0 +1,17 @@
+error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
+  --> $DIR/issue-54302.rs:23:5
+   |
+LL |     assert_deserialize_owned::<&'static str>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: required because of the requirements on the impl of `for<'de> Deserialize<'de>` for `&'static str`
+   = note: required because of the requirements on the impl of `DeserializeOwned` for `&'static str`
+note: required by `main::assert_deserialize_owned`
+  --> $DIR/issue-54302.rs:22:5
+   |
+LL |     fn assert_deserialize_owned<T: DeserializeOwned>() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0279`.
diff --git a/src/test/ui/range/issue-54505-no-literals.fixed b/src/test/ui/range/issue-54505-no-literals.fixed
new file mode 100644
index 0000000000000..4d8f67182b9ac
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-literals.fixed
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(&::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(&std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(&::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(&std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(&::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(&std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(&std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(&::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(&std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(&::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.rs b/src/test/ui/range/issue-54505-no-literals.rs
new file mode 100644
index 0000000000000..dc21dcbc2db41
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-literals.rs
@@ -0,0 +1,75 @@
+// run-rustfix
+
+// Regression test for changes introduced while fixing #54505
+
+// This test uses non-literals for Ranges
+// (expecting no parens with borrow suggestion)
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::Range { start: 0, end: 1 }
+
+    take_range(::std::ops::Range { start: 0, end: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 }
+
+    take_range(std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFrom { start: 1 }
+
+    take_range(::std::ops::RangeFrom { start: 1 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFrom { start: 1 }
+
+    take_range(std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeFull {}
+
+    take_range(::std::ops::RangeFull {});
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeFull {}
+
+    take_range(std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1)
+
+    take_range(::std::ops::RangeInclusive::new(0, 1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1)
+
+    take_range(std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeTo { end: 5 }
+
+    take_range(::std::ops::RangeTo { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeTo { end: 5 }
+
+    take_range(std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 }
+
+    take_range(::std::ops::RangeToInclusive { end: 5 });
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 }
+}
diff --git a/src/test/ui/range/issue-54505-no-literals.stderr b/src/test/ui/range/issue-54505-no-literals.stderr
new file mode 100644
index 0000000000000..b8811c98d21bd
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-literals.stderr
@@ -0,0 +1,147 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:16:16
+   |
+LL |     take_range(std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:21:16
+   |
+LL |     take_range(::std::ops::Range { start: 0, end: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:26:16
+   |
+LL |     take_range(std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:31:16
+   |
+LL |     take_range(::std::ops::RangeFrom { start: 1 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:36:16
+   |
+LL |     take_range(std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:41:16
+   |
+LL |     take_range(::std::ops::RangeFull {});
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&::std::ops::RangeFull {}`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:46:16
+   |
+LL |     take_range(std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:51:16
+   |
+LL |     take_range(::std::ops::RangeInclusive::new(0, 1));
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:56:16
+   |
+LL |     take_range(std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:61:16
+   |
+LL |     take_range(::std::ops::RangeTo { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:66:16
+   |
+LL |     take_range(std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-literals.rs:71:16
+   |
+LL |     take_range(::std::ops::RangeToInclusive { end: 5 });
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs
new file mode 100644
index 0000000000000..c2b17b53ba16b
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-std.rs
@@ -0,0 +1,50 @@
+// error-pattern: `#[panic_handler]` function required, but not found
+// error-pattern: language item required, but not found: `eh_personality`
+
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+// This test doesn't use std
+// (so all Ranges resolve to core::ops::Range...)
+
+#![no_std]
+
+use core::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr
new file mode 100644
index 0000000000000..2810a3f076d4b
--- /dev/null
+++ b/src/test/ui/range/issue-54505-no-std.stderr
@@ -0,0 +1,79 @@
+error: `#[panic_handler]` function required, but not found
+
+error: language item required, but not found: `eh_personality`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:21:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `core::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:26:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:31:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:36:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:41:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505-no-std.rs:46:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `core::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `core::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/range/issue-54505.fixed b/src/test/ui/range/issue-54505.fixed
new file mode 100644
index 0000000000000..f8298c0b5ceff
--- /dev/null
+++ b/src/test/ui/range/issue-54505.fixed
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(&(0..1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(&(1..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(&(..));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(&(0..=1));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(&(..5));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(&(..=42));
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.rs b/src/test/ui/range/issue-54505.rs
new file mode 100644
index 0000000000000..03673252dd3ba
--- /dev/null
+++ b/src/test/ui/range/issue-54505.rs
@@ -0,0 +1,43 @@
+// run-rustfix
+
+// Regression test for #54505 - range borrowing suggestion had
+// incorrect syntax (missing parentheses).
+
+use std::ops::RangeBounds;
+
+
+// take a reference to any built-in range
+fn take_range(_r: &impl RangeBounds<i8>) {}
+
+
+fn main() {
+    take_range(0..1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..1)
+
+    take_range(1..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(1..)
+
+    take_range(..);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..)
+
+    take_range(0..=1);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(0..=1)
+
+    take_range(..5);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..5)
+
+    take_range(..=42);
+    //~^ ERROR mismatched types [E0308]
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &(..=42)
+}
diff --git a/src/test/ui/range/issue-54505.stderr b/src/test/ui/range/issue-54505.stderr
new file mode 100644
index 0000000000000..d6e1fb0cef238
--- /dev/null
+++ b/src/test/ui/range/issue-54505.stderr
@@ -0,0 +1,75 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:14:16
+   |
+LL |     take_range(0..1);
+   |                ^^^^
+   |                |
+   |                expected reference, found struct `std::ops::Range`
+   |                help: consider borrowing here: `&(0..1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::Range<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:19:16
+   |
+LL |     take_range(1..);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFrom`
+   |                help: consider borrowing here: `&(1..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFrom<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:24:16
+   |
+LL |     take_range(..);
+   |                ^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeFull`
+   |                help: consider borrowing here: `&(..)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeFull`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:29:16
+   |
+LL |     take_range(0..=1);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeInclusive`
+   |                help: consider borrowing here: `&(0..=1)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeInclusive<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:34:16
+   |
+LL |     take_range(..5);
+   |                ^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeTo`
+   |                help: consider borrowing here: `&(..5)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeTo<{integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-54505.rs:39:16
+   |
+LL |     take_range(..=42);
+   |                ^^^^^
+   |                |
+   |                expected reference, found struct `std::ops::RangeToInclusive`
+   |                help: consider borrowing here: `&(..=42)`
+   |
+   = note: expected type `&_`
+              found type `std::ops::RangeToInclusive<{integer}>`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs
new file mode 100644
index 0000000000000..1051bec63079e
--- /dev/null
+++ b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs
@@ -0,0 +1,33 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+
+trait Foo<'a> {
+    fn xyz(self);
+}
+impl<'a, T> Foo<'a> for T where 'static: 'a {
+    fn xyz(self) {}
+}
+
+trait Bar {
+    fn uvw(self);
+}
+impl<T> Bar for T where for<'a> T: Foo<'a> {
+    fn uvw(self) { self.xyz(); }
+}
+
+fn foo<T>(t: T) where T: Bar {
+    t.uvw();
+}
+
+fn main() {
+    foo(0);
+}