about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-05-01 17:24:11 +0000
committerbors <bors@rust-lang.org>2019-05-01 17:24:11 +0000
commit9b67bd42b7cbf97f72d039afcba02f5177d0d68c (patch)
treeb2bf473a8d54ef27fbf5b390e0fd4f411e792c9f
parent6cc24f26036b28fb3366de86efe3da6c4464057a (diff)
parente5b69978c1137f05bf8b469875503d5f7fa7f747 (diff)
downloadrust-9b67bd42b7cbf97f72d039afcba02f5177d0d68c.tar.gz
rust-9b67bd42b7cbf97f72d039afcba02f5177d0d68c.zip
Auto merge of #60435 - Centril:rollup-aa5lmuw, r=Centril
Rollup of 7 pull requests

Successful merges:

 - #60287 (Use references for variances_of)
 - #60327 (Search for incompatible universes in borrow errors)
 - #60330 (Suggest using an inclusive range instead of an exclusive range when the endpoint overflows by 1)
 - #60366 (build-gcc: Create missing cc symlink)
 - #60369 (Support ZSTs in DispatchFromDyn)
 - #60404 (Implement `BorrowMut<str>` for `String`)
 - #60417 (Rename hir::ExprKind::Use to ::DropTemps and improve docs.)

Failed merges:

r? @ghost
-rwxr-xr-xsrc/ci/docker/dist-x86_64-linux/build-gcc.sh1
-rw-r--r--src/liballoc/str.rs10
-rw-r--r--src/librustc/arena.rs8
-rw-r--r--src/librustc/cfg/construct.rs2
-rw-r--r--src/librustc/hir/intravisit.rs2
-rw-r--r--src/librustc/hir/lowering.rs80
-rw-r--r--src/librustc/hir/mod.rs14
-rw-r--r--src/librustc/hir/print.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs2
-rw-r--r--src/librustc/middle/liveness.rs6
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/query/mod.rs4
-rw-r--r--src/librustc/ty/mod.rs8
-rw-r--r--src/librustc/ty/relate.rs4
-rw-r--r--src/librustc_lint/types.rs595
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs7
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_passes/rvalue_promotion.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs68
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/coherence/builtin.rs15
-rw-r--r--src/librustc_typeck/variance/mod.rs8
-rw-r--r--src/librustc_typeck/variance/solve.rs21
-rw-r--r--src/test/run-pass/dispatch_from_dyn_zst.rs49
-rw-r--r--src/test/ui/cast_char.rs4
-rw-r--r--src/test/ui/cast_char.stderr8
-rw-r--r--src/test/ui/enum/enum-discrim-too-small2.rs8
-rw-r--r--src/test/ui/enum/enum-discrim-too-small2.stderr8
-rw-r--r--src/test/ui/invalid_dispatch_from_dyn_impls.rs9
-rw-r--r--src/test/ui/invalid_dispatch_from_dyn_impls.stderr15
-rw-r--r--src/test/ui/lint/deny-overflowing-literals.rs2
-rw-r--r--src/test/ui/lint/deny-overflowing-literals.stderr2
-rw-r--r--src/test/ui/lint/lint-range-endpoint-overflow.rs17
-rw-r--r--src/test/ui/lint/lint-range-endpoint-overflow.stderr44
-rw-r--r--src/test/ui/lint/lint-type-limits2.rs2
-rw-r--r--src/test/ui/lint/lint-type-limits2.stderr2
-rw-r--r--src/test/ui/lint/lint-type-limits3.rs2
-rw-r--r--src/test/ui/lint/lint-type-limits3.stderr2
-rw-r--r--src/test/ui/lint/lint-type-overflow.rs38
-rw-r--r--src/test/ui/lint/lint-type-overflow.stderr74
-rw-r--r--src/test/ui/lint/lint-type-overflow2.stderr10
-rw-r--r--src/test/ui/lint/type-overflow.stderr2
-rw-r--r--src/test/ui/nll/local-outlives-static-via-hrtb.rs26
-rw-r--r--src/test/ui/nll/local-outlives-static-via-hrtb.stderr26
46 files changed, 759 insertions, 462 deletions
diff --git a/src/ci/docker/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/dist-x86_64-linux/build-gcc.sh
index 7f6e94d326d..ddc2066537c 100755
--- a/src/ci/docker/dist-x86_64-linux/build-gcc.sh
+++ b/src/ci/docker/dist-x86_64-linux/build-gcc.sh
@@ -32,6 +32,7 @@ hide_output ../gcc-$GCC/configure \
     --enable-languages=c,c++
 hide_output make -j10
 hide_output make install
+ln -s gcc /rustroot/bin/cc
 
 cd ..
 rm -rf gcc-build
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index e5d4e1c533c..f66ff894ae8 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -28,7 +28,7 @@
 // It's cleaner to just turn off the unused_imports warning than to fix them.
 #![allow(unused_imports)]
 
-use core::borrow::Borrow;
+use core::borrow::{Borrow, BorrowMut};
 use core::str::pattern::{Pattern, Searcher, ReverseSearcher, DoubleEndedSearcher};
 use core::mem;
 use core::ptr;
@@ -190,6 +190,14 @@ impl Borrow<str> for String {
     }
 }
 
+#[stable(feature = "string_borrow_mut", since = "1.36.0")]
+impl BorrowMut<str> for String {
+    #[inline]
+    fn borrow_mut(&mut self) -> &mut str {
+        &mut self[..]
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToOwned for str {
     type Owned = String;
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index 1cc6500d038..b48d81f2ef8 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -144,6 +144,14 @@ impl<'tcx> Arena<'tcx> {
         }
     }
 
+    #[inline]
+    pub fn alloc_slice<T: Copy>(&self, value: &[T]) -> &mut [T] {
+        if value.len() == 0 {
+            return &mut []
+        }
+        self.dropless.alloc_slice(value)
+    }
+
     pub fn alloc_from_iter<
         T: ArenaAllocatable,
         I: IntoIterator<Item = T>
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index 8a4594fe0e8..2592af7d4ad 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -369,7 +369,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             hir::ExprKind::AddrOf(_, ref e) |
             hir::ExprKind::Cast(ref e, _) |
             hir::ExprKind::Type(ref e, _) |
-            hir::ExprKind::Use(ref e) |
+            hir::ExprKind::DropTemps(ref e) |
             hir::ExprKind::Unary(_, ref e) |
             hir::ExprKind::Field(ref e, _) |
             hir::ExprKind::Yield(ref e) |
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 3d727f7cd91..0c73d97394f 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -1029,7 +1029,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_ty(typ)
         }
-        ExprKind::Use(ref subexpression) => {
+        ExprKind::DropTemps(ref subexpression) => {
             visitor.visit_expr(subexpression);
         }
         ExprKind::If(ref head_expression, ref if_block, ref optional_else) => {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index df455a725c5..f4209a39c83 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -4671,7 +4671,7 @@ impl<'a> LoweringContext<'a> {
                 // The construct was introduced in #21984.
                 // FIXME(60253): Is this still necessary?
                 // Also, add the attributes to the outer returned expr node.
-                return self.expr_use(head_sp, match_expr, e.attrs.clone())
+                return self.expr_drop_temps(head_sp, match_expr, e.attrs.clone())
             }
 
             // Desugar `ExprKind::Try`
@@ -5030,15 +5030,19 @@ impl<'a> LoweringContext<'a> {
         )
     }
 
-    /// Wrap the given `expr` in `hir::ExprKind::Use`.
+    /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`.
     ///
-    /// In terms of drop order, it has the same effect as
-    /// wrapping `expr` in `{ let _t = $expr; _t }` but
-    /// should provide better compile-time performance.
+    /// In terms of drop order, it has the same effect as wrapping `expr` in
+    /// `{ let _t = $expr; _t }` but should provide better compile-time performance.
     ///
     /// The drop order can be important in e.g. `if expr { .. }`.
-    fn expr_use(&mut self, span: Span, expr: P<hir::Expr>, attrs: ThinVec<Attribute>) -> hir::Expr {
-        self.expr(span, hir::ExprKind::Use(expr), attrs)
+    fn expr_drop_temps(
+        &mut self,
+        span: Span,
+        expr: P<hir::Expr>,
+        attrs: ThinVec<Attribute>
+    ) -> hir::Expr {
+        self.expr(span, hir::ExprKind::DropTemps(expr), attrs)
     }
 
     fn expr_match(
@@ -5400,3 +5404,65 @@ fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
     body_ids.sort_by_key(|b| bodies[b].value.span);
     body_ids
 }
+
+/// Checks if the specified expression is a built-in range literal.
+/// (See: `LoweringContext::lower_expr()`).
+pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool {
+    use hir::{Path, QPath, ExprKind, TyKind};
+
+    // Returns whether the given path represents a (desugared) range,
+    // either in std or core, i.e. has either a `::std::ops::Range` or
+    // `::core::ops::Range` prefix.
+    fn is_range_path(path: &Path) -> bool {
+        let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.as_str().to_string()).collect();
+        let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect();
+
+        // "{{root}}" is the equivalent of `::` prefix in `Path`.
+        if let ["{{root}}", std_core, "ops", range] = segs.as_slice() {
+            (*std_core == "std" || *std_core == "core") && range.starts_with("Range")
+        } else {
+            false
+        }
+    };
+
+    // Check whether a span corresponding to a range expression is a
+    // range literal, rather than an explicit struct or `new()` call.
+    fn is_lit(sess: &Session, span: &Span) -> bool {
+        let source_map = 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 `Struct`s.
+        ExprKind::Struct(ref qpath, _, _) => {
+            if let QPath::Resolved(None, ref path) = **qpath {
+                return is_range_path(&path) && is_lit(sess, &expr.span);
+            }
+        }
+
+        // `..` desugars to its struct path.
+        ExprKind::Path(QPath::Resolved(None, ref path)) => {
+            return is_range_path(&path) && is_lit(sess, &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 new_call = segment.ident.as_str() == "new";
+                    return is_range_path(&path) && is_lit(sess, &expr.span) && new_call;
+                }
+            }
+        }
+
+        _ => {}
+    }
+
+    false
+}
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 8418658ab68..5a2807ac93d 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1366,7 +1366,7 @@ impl Expr {
             ExprKind::Unary(..) => ExprPrecedence::Unary,
             ExprKind::Lit(_) => ExprPrecedence::Lit,
             ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
-            ExprKind::Use(ref expr, ..) => expr.precedence(),
+            ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
             ExprKind::If(..) => ExprPrecedence::If,
             ExprKind::While(..) => ExprPrecedence::While,
             ExprKind::Loop(..) => ExprPrecedence::Loop,
@@ -1438,7 +1438,7 @@ impl Expr {
             ExprKind::Binary(..) |
             ExprKind::Yield(..) |
             ExprKind::Cast(..) |
-            ExprKind::Use(..) |
+            ExprKind::DropTemps(..) |
             ExprKind::Err => {
                 false
             }
@@ -1488,10 +1488,12 @@ pub enum ExprKind {
     Cast(P<Expr>, P<Ty>),
     /// A type reference (e.g., `Foo`).
     Type(P<Expr>, P<Ty>),
-    /// Semantically equivalent to `{ let _t = expr; _t }`.
-    /// Maps directly to `hair::ExprKind::Use`.
-    /// Only exists to tweak the drop order in HIR.
-    Use(P<Expr>),
+    /// Wraps the expression in a terminating scope.
+    /// This makes it semantically equivalent to `{ let _t = expr; _t }`.
+    ///
+    /// This construct only exists to tweak the drop order in HIR lowering.
+    /// An example of that is the desugaring of `for` loops.
+    DropTemps(P<Expr>),
     /// An `if` block, with an optional else block.
     ///
     /// I.e., `if <expr> { <expr> } else { <expr> }`.
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 06225364f6c..54816316f0b 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1388,7 +1388,7 @@ impl<'a> State<'a> {
                 self.word_space(":")?;
                 self.print_type(&ty)?;
             }
-            hir::ExprKind::Use(ref init) => {
+            hir::ExprKind::DropTemps(ref init) => {
                 // Print `{`:
                 self.cbox(indent_unit)?;
                 self.ibox(0)?;
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 27ebcc55b1e..3b9af75bd0a 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -520,7 +520,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 self.consume_expr(&base);
             }
 
-            hir::ExprKind::Use(ref expr) => {
+            hir::ExprKind::DropTemps(ref expr) => {
                 self.consume_expr(&expr);
             }
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 966bec8381a..2ae53a5df3a 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -521,7 +521,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
       hir::ExprKind::Binary(..) |
       hir::ExprKind::AddrOf(..) |
       hir::ExprKind::Cast(..) |
-      hir::ExprKind::Use(..) |
+      hir::ExprKind::DropTemps(..) |
       hir::ExprKind::Unary(..) |
       hir::ExprKind::Break(..) |
       hir::ExprKind::Continue(_) |
@@ -1222,7 +1222,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             hir::ExprKind::AddrOf(_, ref e) |
             hir::ExprKind::Cast(ref e, _) |
             hir::ExprKind::Type(ref e, _) |
-            hir::ExprKind::Use(ref e) |
+            hir::ExprKind::DropTemps(ref e) |
             hir::ExprKind::Unary(_, ref e) |
             hir::ExprKind::Yield(ref e) |
             hir::ExprKind::Repeat(ref e, _) => {
@@ -1526,7 +1526,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
         hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) |
         hir::ExprKind::Index(..) | hir::ExprKind::Field(..) |
         hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) |
-        hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) | hir::ExprKind::Unary(..) |
+        hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) | hir::ExprKind::Unary(..) |
         hir::ExprKind::Ret(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) |
         hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
         hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index d24ee228d53..34b44234279 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -677,7 +677,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) |
             hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) |
             hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) |
-            hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) |
+            hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) |
             hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) |
             hir::ExprKind::Binary(..) | hir::ExprKind::While(..) |
             hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) |
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index f9491a1e8f4..2b88f273adc 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -908,8 +908,8 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
                 visitor.cx.var_parent = visitor.cx.parent;
             }
 
-            hir::ExprKind::Use(ref expr) => {
-                // `Use(expr)` does not denote a conditional scope.
+            hir::ExprKind::DropTemps(ref expr) => {
+                // `DropTemps(expr)` does not denote a conditional scope.
                 // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`.
                 terminating(expr.hir_id.local_id);
             }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index eaf9fd1bc76..b96ef1b7a86 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -245,13 +245,13 @@ rustc_queries! {
 
         /// Get a map with the variance of every item; use `item_variance`
         /// instead.
-        query crate_variances(_: CrateNum) -> Lrc<ty::CrateVariancesMap> {
+        query crate_variances(_: CrateNum) -> Lrc<ty::CrateVariancesMap<'tcx>> {
             desc { "computing the variances for items in this crate" }
         }
 
         /// Maps from def-id of a type or region parameter to its
         /// (inferred) variance.
-        query variances_of(_: DefId) -> Lrc<Vec<ty::Variance>> {}
+        query variances_of(_: DefId) -> &'tcx [ty::Variance] {}
     }
 
     TypeChecking {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 69532b9b2c4..6b938ea2fcc 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -332,15 +332,11 @@ pub enum Variance {
 /// `tcx.variances_of()` to get the variance for a *particular*
 /// item.
 #[derive(HashStable)]
-pub struct CrateVariancesMap {
+pub struct CrateVariancesMap<'tcx> {
     /// For each item with generics, maps to a vector of the variance
     /// of its generics. If an item has no generics, it will have no
     /// entry.
-    pub variances: FxHashMap<DefId, Lrc<Vec<ty::Variance>>>,
-
-    /// An empty vector, useful for cloning.
-    #[stable_hasher(ignore)]
-    pub empty_variance: Lrc<Vec<ty::Variance>>,
+    pub variances: FxHashMap<DefId, &'tcx [ty::Variance]>,
 }
 
 impl Variance {
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 1f5a39cbef1..2638a1c7c88 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -60,7 +60,7 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
                b_subst);
 
         let opt_variances = self.tcx().variances_of(item_def_id);
-        relate_substs(self, Some(&opt_variances), a_subst, b_subst)
+        relate_substs(self, Some(opt_variances), a_subst, b_subst)
     }
 
     /// Switch variance for the purpose of relating `a` and `b`.
@@ -122,7 +122,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
 }
 
 pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
-                                        variances: Option<&Vec<ty::Variance>>,
+                                        variances: Option<&[ty::Variance]>,
                                         a_subst: SubstsRef<'tcx>,
                                         b_subst: SubstsRef<'tcx>)
                                         -> RelateResult<'tcx, SubstsRef<'tcx>>
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index d3223c6edb8..f4ebfd79fe1 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1,6 +1,7 @@
 #![allow(non_snake_case)]
 
-use rustc::hir::Node;
+use rustc::hir::{ExprKind, Node};
+use rustc::hir::lowering::is_range_literal;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
@@ -57,6 +58,347 @@ impl TypeLimits {
     }
 }
 
+/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint.
+/// Returns `true` iff the lint was overridden.
+fn lint_overflowing_range_endpoint<'a, 'tcx>(
+    cx: &LateContext<'a, 'tcx>,
+    lit: &ast::Lit,
+    lit_val: u128,
+    max: u128,
+    expr: &'tcx hir::Expr,
+    parent_expr: &'tcx hir::Expr,
+    ty: impl std::fmt::Debug,
+) -> bool {
+    // We only want to handle exclusive (`..`) ranges,
+    // which are represented as `ExprKind::Struct`.
+    if let ExprKind::Struct(_, eps, _) = &parent_expr.node {
+        debug_assert_eq!(eps.len(), 2);
+        // We can suggest using an inclusive range
+        // (`..=`) instead only if it is the `end` that is
+        // overflowing and only by 1.
+        if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
+            let mut err = cx.struct_span_lint(
+                OVERFLOWING_LITERALS,
+                parent_expr.span,
+                &format!("range endpoint is out of range for `{:?}`", ty),
+            );
+            if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
+                use ast::{LitKind, LitIntType};
+                // We need to preserve the literal's suffix,
+                // as it may determine typing information.
+                let suffix = match lit.node {
+                    LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s),
+                    LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s),
+                    LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(),
+                    _ => bug!(),
+                };
+                let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
+                err.span_suggestion(
+                    parent_expr.span,
+                    &"use an inclusive range instead",
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
+                err.emit();
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+// For `isize` & `usize`, be conservative with the warnings, so that the
+// warnings are consistent between 32- and 64-bit platforms.
+fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
+    match int_ty {
+        ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
+        ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
+        ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
+        ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
+        ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
+        ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()),
+    }
+}
+
+fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
+    match uint_ty {
+        ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
+        ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
+        ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
+        ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
+        ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
+        ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
+    }
+}
+
+fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option<String> {
+    let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?;
+    let firstch = src.chars().next()?;
+
+    if firstch == '0' {
+        match src.chars().nth(1) {
+            Some('x') | Some('b') => return Some(src),
+            _ => return None,
+        }
+    }
+
+    None
+}
+
+fn report_bin_hex_error(
+    cx: &LateContext<'_, '_>,
+    expr: &hir::Expr,
+    ty: attr::IntType,
+    repr_str: String,
+    val: u128,
+    negative: bool,
+) {
+    let size = layout::Integer::from_attr(&cx.tcx, ty).size();
+    let (t, actually) = match ty {
+        attr::IntType::SignedInt(t) => {
+            let actually = sign_extend(val, size) as i128;
+            (format!("{:?}", t), actually.to_string())
+        }
+        attr::IntType::UnsignedInt(t) => {
+            let actually = truncate(val, size);
+            (format!("{:?}", t), actually.to_string())
+        }
+    };
+    let mut err = cx.struct_span_lint(
+        OVERFLOWING_LITERALS,
+        expr.span,
+        &format!("literal out of range for {}", t),
+    );
+    err.note(&format!(
+        "the literal `{}` (decimal `{}`) does not fit into \
+            an `{}` and will become `{}{}`",
+        repr_str, val, t, actually, t
+    ));
+    if let Some(sugg_ty) =
+        get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
+    {
+        if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
+            let (sans_suffix, _) = repr_str.split_at(pos);
+            err.span_suggestion(
+                expr.span,
+                &format!("consider using `{}` instead", sugg_ty),
+                format!("{}{}", sans_suffix, sugg_ty),
+                Applicability::MachineApplicable
+            );
+        } else {
+            err.help(&format!("consider using `{}` instead", sugg_ty));
+        }
+    }
+
+    err.emit();
+}
+
+// This function finds the next fitting type and generates a suggestion string.
+// It searches for fitting types in the following way (`X < Y`):
+//  - `iX`: if literal fits in `uX` => `uX`, else => `iY`
+//  - `-iX` => `iY`
+//  - `uX` => `uY`
+//
+// No suggestion for: `isize`, `usize`.
+fn get_type_suggestion<'a>(
+    t: Ty<'_>,
+    val: u128,
+    negative: bool,
+) -> Option<String> {
+    use syntax::ast::IntTy::*;
+    use syntax::ast::UintTy::*;
+    macro_rules! find_fit {
+        ($ty:expr, $val:expr, $negative:expr,
+         $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
+            {
+                let _neg = if negative { 1 } else { 0 };
+                match $ty {
+                    $($type => {
+                        $(if !negative && val <= uint_ty_range($utypes).1 {
+                            return Some(format!("{:?}", $utypes))
+                        })*
+                        $(if val <= int_ty_range($itypes).1 as u128 + _neg {
+                            return Some(format!("{:?}", $itypes))
+                        })*
+                        None
+                    },)*
+                    _ => None
+                }
+            }
+        }
+    }
+    match t.sty {
+        ty::Int(i) => find_fit!(i, val, negative,
+                      I8 => [U8] => [I16, I32, I64, I128],
+                      I16 => [U16] => [I32, I64, I128],
+                      I32 => [U32] => [I64, I128],
+                      I64 => [U64] => [I128],
+                      I128 => [U128] => []),
+        ty::Uint(u) => find_fit!(u, val, negative,
+                      U8 => [U8, U16, U32, U64, U128] => [],
+                      U16 => [U16, U32, U64, U128] => [],
+                      U32 => [U32, U64, U128] => [],
+                      U64 => [U64, U128] => [],
+                      U128 => [U128] => []),
+        _ => None,
+    }
+}
+
+fn lint_int_literal<'a, 'tcx>(
+    cx: &LateContext<'a, 'tcx>,
+    type_limits: &TypeLimits,
+    e: &'tcx hir::Expr,
+    lit: &ast::Lit,
+    t: ast::IntTy,
+    v: u128,
+) {
+    let int_type = if let ast::IntTy::Isize = t {
+        cx.sess().target.isize_ty
+    } else {
+        t
+    };
+
+    let (_, max) = int_ty_range(int_type);
+    let max = max as u128;
+    let negative = type_limits.negated_expr_id == e.hir_id;
+
+    // Detect literal value out of range [min, max] inclusive
+    // avoiding use of -min to prevent overflow/panic
+    if (negative && v > max + 1) || (!negative && v > max) {
+        if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
+            report_bin_hex_error(
+                cx,
+                e,
+                attr::IntType::SignedInt(t),
+                repr_str,
+                v,
+                negative,
+            );
+            return;
+        }
+
+        let par_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id);
+        if let Node::Expr(par_e) = cx.tcx.hir().get_by_hir_id(par_id) {
+            if let hir::ExprKind::Struct(..) = par_e.node {
+                if is_range_literal(cx.sess(), par_e)
+                    && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t)
+                {
+                    // The overflowing literal lint was overridden.
+                    return;
+                }
+            }
+        }
+
+        cx.span_lint(
+            OVERFLOWING_LITERALS,
+            e.span,
+            &format!("literal out of range for `{:?}`", t),
+        );
+    }
+}
+
+fn lint_uint_literal<'a, 'tcx>(
+    cx: &LateContext<'a, 'tcx>,
+    e: &'tcx hir::Expr,
+    lit: &ast::Lit,
+    t: ast::UintTy,
+) {
+    let uint_type = if let ast::UintTy::Usize = t {
+        cx.sess().target.usize_ty
+    } else {
+        t
+    };
+    let (min, max) = uint_ty_range(uint_type);
+    let lit_val: u128 = match lit.node {
+        // _v is u8, within range by definition
+        ast::LitKind::Byte(_v) => return,
+        ast::LitKind::Int(v, _) => v,
+        _ => bug!(),
+    };
+    if lit_val < min || lit_val > max {
+        let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id);
+        if let Node::Expr(par_e) = cx.tcx.hir().get_by_hir_id(parent_id) {
+            match par_e.node {
+                hir::ExprKind::Cast(..) => {
+                    if let ty::Char = cx.tables.expr_ty(par_e).sty {
+                        let mut err = cx.struct_span_lint(
+                            OVERFLOWING_LITERALS,
+                            par_e.span,
+                            "only `u8` can be cast into `char`",
+                        );
+                        err.span_suggestion(
+                            par_e.span,
+                            &"use a `char` literal instead",
+                            format!("'\\u{{{:X}}}'", lit_val),
+                            Applicability::MachineApplicable,
+                        );
+                        err.emit();
+                        return;
+                    }
+                }
+                hir::ExprKind::Struct(..)
+                    if is_range_literal(cx.sess(), par_e) => {
+                        if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
+                            // The overflowing literal lint was overridden.
+                            return;
+                        }
+                    }
+                _ => {}
+            }
+        }
+        if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
+            report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false);
+            return;
+        }
+        cx.span_lint(
+            OVERFLOWING_LITERALS,
+            e.span,
+            &format!("literal out of range for `{:?}`", t),
+        );
+    }
+}
+
+fn lint_literal<'a, 'tcx>(
+    cx: &LateContext<'a, 'tcx>,
+    type_limits: &TypeLimits,
+    e: &'tcx hir::Expr,
+    lit: &ast::Lit,
+) {
+    match cx.tables.node_type(e.hir_id).sty {
+        ty::Int(t) => {
+            match lit.node {
+                ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
+                ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
+                    lint_int_literal(cx, type_limits, e, lit, t, v)
+                }
+                _ => bug!(),
+            };
+        }
+        ty::Uint(t) => {
+            lint_uint_literal(cx, e, lit, t)
+        }
+        ty::Float(t) => {
+            let is_infinite = match lit.node {
+                ast::LitKind::Float(v, _) |
+                ast::LitKind::FloatUnsuffixed(v) => {
+                    match t {
+                        ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
+                        ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
+                    }
+                }
+                _ => bug!(),
+            };
+            if is_infinite == Ok(true) {
+                cx.span_lint(OVERFLOWING_LITERALS,
+                             e.span,
+                             &format!("literal out of range for `{:?}`", t));
+            }
+        }
+        _ => {}
+    }
+}
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
         match e.node {
@@ -73,118 +415,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                  "comparison is useless due to type limits");
                 }
             }
-            hir::ExprKind::Lit(ref lit) => {
-                match cx.tables.node_type(e.hir_id).sty {
-                    ty::Int(t) => {
-                        match lit.node {
-                            ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
-                            ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => {
-                                let int_type = if let ast::IntTy::Isize = t {
-                                    cx.sess().target.isize_ty
-                                } else {
-                                    t
-                                };
-                                let (_, max) = int_ty_range(int_type);
-                                let max = max as u128;
-                                let negative = self.negated_expr_id == e.hir_id;
-
-                                // Detect literal value out of range [min, max] inclusive
-                                // avoiding use of -min to prevent overflow/panic
-                                if (negative && v > max + 1) || (!negative && v > max) {
-                                    if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
-                                        report_bin_hex_error(
-                                            cx,
-                                            e,
-                                            attr::IntType::SignedInt(t),
-                                            repr_str,
-                                            v,
-                                            negative,
-                                        );
-                                        return;
-                                    }
-                                    cx.span_lint(
-                                        OVERFLOWING_LITERALS,
-                                        e.span,
-                                        &format!("literal out of range for {:?}", t),
-                                    );
-                                    return;
-                                }
-                            }
-                            _ => bug!(),
-                        };
-                    }
-                    ty::Uint(t) => {
-                        let uint_type = if let ast::UintTy::Usize = t {
-                            cx.sess().target.usize_ty
-                        } else {
-                            t
-                        };
-                        let (min, max) = uint_ty_range(uint_type);
-                        let lit_val: u128 = match lit.node {
-                            // _v is u8, within range by definition
-                            ast::LitKind::Byte(_v) => return,
-                            ast::LitKind::Int(v, _) => v,
-                            _ => bug!(),
-                        };
-                        if lit_val < min || lit_val > max {
-                            let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id);
-                            if let Node::Expr(parent_expr) = cx.tcx.hir().get_by_hir_id(parent_id) {
-                                if let hir::ExprKind::Cast(..) = parent_expr.node {
-                                    if let ty::Char = cx.tables.expr_ty(parent_expr).sty {
-                                        let mut err = cx.struct_span_lint(
-                                                             OVERFLOWING_LITERALS,
-                                                             parent_expr.span,
-                                                             "only u8 can be cast into char");
-                                        err.span_suggestion(
-                                            parent_expr.span,
-                                            &"use a char literal instead",
-                                            format!("'\\u{{{:X}}}'", lit_val),
-                                            Applicability::MachineApplicable
-                                        );
-                                        err.emit();
-                                        return
-                                    }
-                                }
-                            }
-                            if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
-                                report_bin_hex_error(
-                                    cx,
-                                    e,
-                                    attr::IntType::UnsignedInt(t),
-                                    repr_str,
-                                    lit_val,
-                                    false,
-                                );
-                                return;
-                            }
-                            cx.span_lint(
-                                OVERFLOWING_LITERALS,
-                                e.span,
-                                &format!("literal out of range for {:?}", t),
-                            );
-                        }
-                    }
-                    ty::Float(t) => {
-                        let is_infinite = match lit.node {
-                            ast::LitKind::Float(v, _) |
-                            ast::LitKind::FloatUnsuffixed(v) => {
-                                match t {
-                                    ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
-                                    ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
-                                }
-                            }
-                            _ => bug!(),
-                        };
-                        if is_infinite == Ok(true) {
-                            cx.span_lint(OVERFLOWING_LITERALS,
-                                         e.span,
-                                         &format!("literal out of range for {:?}", t));
-                        }
-                    }
-                    _ => (),
-                };
-            }
-            _ => (),
+            hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),
+            _ => {}
         };
 
         fn is_valid<T: cmp::PartialOrd>(binop: hir::BinOp, v: T, min: T, max: T) -> bool {
@@ -209,30 +441,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                             })
         }
 
-        // for isize & usize, be conservative with the warnings, so that the
-        // warnings are consistent between 32- and 64-bit platforms
-        fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
-            match int_ty {
-                ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
-                ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
-                ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
-                ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
-                ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
-                ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()),
-            }
-        }
-
-        fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
-            match uint_ty {
-                ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
-                ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
-                ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
-                ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
-                ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
-                ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
-            }
-        }
-
         fn check_limits(cx: &LateContext<'_, '_>,
                         binop: hir::BinOp,
                         l: &hir::Expr,
@@ -289,119 +497,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 _ => false,
             }
         }
-
-        fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option<String> {
-            let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?;
-            let firstch = src.chars().next()?;
-
-            if firstch == '0' {
-                match src.chars().nth(1) {
-                    Some('x') | Some('b') => return Some(src),
-                    _ => return None,
-                }
-            }
-
-            None
-        }
-
-        // This function finds the next fitting type and generates a suggestion string.
-        // It searches for fitting types in the following way (`X < Y`):
-        //  - `iX`: if literal fits in `uX` => `uX`, else => `iY`
-        //  - `-iX` => `iY`
-        //  - `uX` => `uY`
-        //
-        // No suggestion for: `isize`, `usize`.
-        fn get_type_suggestion<'a>(
-            t: Ty<'_>,
-            val: u128,
-            negative: bool,
-        ) -> Option<String> {
-            use syntax::ast::IntTy::*;
-            use syntax::ast::UintTy::*;
-            macro_rules! find_fit {
-                ($ty:expr, $val:expr, $negative:expr,
-                 $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
-                    {
-                        let _neg = if negative { 1 } else { 0 };
-                        match $ty {
-                            $($type => {
-                                $(if !negative && val <= uint_ty_range($utypes).1 {
-                                    return Some(format!("{:?}", $utypes))
-                                })*
-                                $(if val <= int_ty_range($itypes).1 as u128 + _neg {
-                                    return Some(format!("{:?}", $itypes))
-                                })*
-                                None
-                            },)*
-                            _ => None
-                        }
-                    }
-                }
-            }
-            match t.sty {
-                ty::Int(i) => find_fit!(i, val, negative,
-                              I8 => [U8] => [I16, I32, I64, I128],
-                              I16 => [U16] => [I32, I64, I128],
-                              I32 => [U32] => [I64, I128],
-                              I64 => [U64] => [I128],
-                              I128 => [U128] => []),
-                ty::Uint(u) => find_fit!(u, val, negative,
-                              U8 => [U8, U16, U32, U64, U128] => [],
-                              U16 => [U16, U32, U64, U128] => [],
-                              U32 => [U32, U64, U128] => [],
-                              U64 => [U64, U128] => [],
-                              U128 => [U128] => []),
-                _ => None,
-            }
-        }
-
-        fn report_bin_hex_error(
-            cx: &LateContext<'_, '_>,
-            expr: &hir::Expr,
-            ty: attr::IntType,
-            repr_str: String,
-            val: u128,
-            negative: bool,
-        ) {
-            let size = layout::Integer::from_attr(&cx.tcx, ty).size();
-            let (t, actually) = match ty {
-                attr::IntType::SignedInt(t) => {
-                    let actually = sign_extend(val, size) as i128;
-                    (format!("{:?}", t), actually.to_string())
-                }
-                attr::IntType::UnsignedInt(t) => {
-                    let actually = truncate(val, size);
-                    (format!("{:?}", t), actually.to_string())
-                }
-            };
-            let mut err = cx.struct_span_lint(
-                OVERFLOWING_LITERALS,
-                expr.span,
-                &format!("literal out of range for {}", t),
-            );
-            err.note(&format!(
-                "the literal `{}` (decimal `{}`) does not fit into \
-                 an `{}` and will become `{}{}`",
-                repr_str, val, t, actually, t
-            ));
-            if let Some(sugg_ty) =
-                get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
-            {
-                if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
-                    let (sans_suffix, _) = repr_str.split_at(pos);
-                    err.span_suggestion(
-                        expr.span,
-                        &format!("consider using `{}` instead", sugg_ty),
-                        format!("{}{}", sans_suffix, sugg_ty),
-                        Applicability::MachineApplicable
-                    );
-                } else {
-                    err.help(&format!("consider using `{}` instead", sugg_ty));
-                }
-            }
-
-            err.emit();
-        }
     }
 }
 
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 53f06baaa9d..b3439e4c970 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -106,7 +106,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
         let _ = cdata;
         tcx.calculate_dtor(def_id, &mut |_,_| Ok(()))
     }
-    variances_of => { Lrc::new(cdata.get_item_variances(def_id.index)) }
+    variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) }
     associated_item_def_ids => {
         let mut result = vec![];
         cdata.each_child_of_item(def_id.index,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index abb30d042ca..00e81ee0491 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -674,8 +674,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         borrow_region: RegionVid,
         outlived_region: RegionVid,
     ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
-        let (category, from_closure, span) =
-            self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
+        let (category, from_closure, span) = self.best_blame_constraint(
+            mir,
+            borrow_region,
+            |r| self.provides_universal_region(r, borrow_region, outlived_region)
+        );
         let outlived_fr_name =
             self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_region, &mut 1);
         (category, from_closure, span, outlived_fr_name)
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index ada8e208ec7..6e11f1dae9b 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -759,7 +759,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 }
             }
         }
-        hir::ExprKind::Use(ref source) => {
+        hir::ExprKind::DropTemps(ref source) => {
             ExprKind::Use { source: source.to_ref() }
         }
         hir::ExprKind::Box(ref value) => {
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index ce54035fe67..881f63e994d 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -437,7 +437,7 @@ fn check_expr_kind<'a, 'tcx>(
         hir::ExprKind::AddrOf(_, ref expr) |
         hir::ExprKind::Repeat(ref expr, _) |
         hir::ExprKind::Type(ref expr, _) |
-        hir::ExprKind::Use(ref expr) => {
+        hir::ExprKind::DropTemps(ref expr) => {
             v.check_expr(&expr)
         }
 
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 689996ccb25..8ae66a96c76 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -7,7 +7,7 @@ use syntax_pos::Span;
 use rustc::hir;
 use rustc::hir::def::Def;
 use rustc::hir::Node;
-use rustc::hir::print;
+use rustc::hir::{print, lowering::is_range_literal};
 use rustc::ty::{self, Ty, AssociatedItem};
 use rustc::ty::adjustment::AllowTwoPhase;
 use errors::{Applicability, DiagnosticBuilder};
@@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             hir::ExprKind::Cast(_, _) |
                             hir::ExprKind::Binary(_, _, _) => true,
                             // parenthesize borrows of range literals (Issue #54505)
-                            _ if self.is_range_literal(expr) => true,
+                            _ if is_range_literal(self.tcx.sess, expr) => true,
                             _ => false,
                         };
                         let sugg_expr = if needs_parens {
@@ -479,70 +479,6 @@ 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(ref qpath, _, _) => {
-                if let QPath::Resolved(None, ref path) = **qpath {
-                    return is_range_path(&path) && span_is_range_literal(&expr.span);
-                }
-            }
-            // `..` 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>,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 452bc74bdd0..d2d486b52b3 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4538,7 +4538,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.check_expr_eq_type(&e, ty);
                 ty
             }
-            ExprKind::Use(ref e) => {
+            ExprKind::DropTemps(ref e) => {
                 self.check_expr_with_expectation(e, expected)
             }
             ExprKind::Array(ref args) => {
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index c3b08569d2f..1be0248727d 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -223,19 +223,22 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
                     let fields = &def_a.non_enum_variant().fields;
 
                     let coerced_fields = fields.iter().filter_map(|field| {
-                        if tcx.type_of(field.did).is_phantom_data() {
-                            // ignore PhantomData fields
-                            return None
-                        }
-
                         let ty_a = field.ty(tcx, substs_a);
                         let ty_b = field.ty(tcx, substs_b);
+
+                        if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
+                            if layout.is_zst() && layout.details.align.abi.bytes() == 1 {
+                                // ignore ZST fields with alignment of 1 byte
+                                return None;
+                            }
+                        }
+
                         if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
                             if ok.obligations.is_empty() {
                                 create_err(
                                     "the trait `DispatchFromDyn` may only be implemented \
                                      for structs containing the field being coerced, \
-                                     `PhantomData` fields, and nothing else"
+                                     ZST fields with 1 byte alignment, and nothing else"
                                 ).note(
                                     &format!(
                                         "extra field `{}` of type `{}` is not allowed",
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 9b9a6bace96..88ee1d79f54 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -36,7 +36,7 @@ pub fn provide(providers: &mut Providers<'_>) {
 }
 
 fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
-                             -> Lrc<CrateVariancesMap> {
+                             -> Lrc<CrateVariancesMap<'tcx>> {
     assert_eq!(crate_num, LOCAL_CRATE);
     let mut arena = arena::TypedArena::default();
     let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena);
@@ -45,7 +45,7 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
 }
 
 fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
-                          -> Lrc<Vec<ty::Variance>> {
+                          -> &'tcx [ty::Variance] {
     let id = tcx.hir().as_local_hir_id(item_def_id).expect("expected local def-id");
     let unsupported = || {
         // Variance not relevant.
@@ -88,6 +88,6 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
 
     let crate_map = tcx.crate_variances(LOCAL_CRATE);
     crate_map.variances.get(&item_def_id)
-                       .unwrap_or(&crate_map.empty_variance)
-                       .clone()
+                       .map(|p| *p)
+                       .unwrap_or(&[])
 }
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
index 51a1d088ddc..8edf3c52ccc 100644
--- a/src/librustc_typeck/variance/solve.rs
+++ b/src/librustc_typeck/variance/solve.rs
@@ -8,7 +8,6 @@
 use rustc::hir::def_id::DefId;
 use rustc::ty;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 
 use super::constraints::*;
 use super::terms::*;
@@ -23,7 +22,9 @@ struct SolveContext<'a, 'tcx: 'a> {
     solutions: Vec<ty::Variance>,
 }
 
-pub fn solve_constraints(constraints_cx: ConstraintContext<'_, '_>) -> ty::CrateVariancesMap {
+pub fn solve_constraints<'tcx>(
+    constraints_cx: ConstraintContext<'_, 'tcx>
+) -> ty::CrateVariancesMap<'tcx> {
     let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
 
     let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
@@ -41,9 +42,8 @@ pub fn solve_constraints(constraints_cx: ConstraintContext<'_, '_>) -> ty::Crate
     };
     solutions_cx.solve();
     let variances = solutions_cx.create_map();
-    let empty_variance = Lrc::new(Vec::new());
 
-    ty::CrateVariancesMap { variances, empty_variance }
+    ty::CrateVariancesMap { variances }
 }
 
 impl<'a, 'tcx> SolveContext<'a, 'tcx> {
@@ -78,7 +78,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
         }
     }
 
-    fn enforce_const_invariance(&self, generics: &ty::Generics, variances: &mut Vec<ty::Variance>) {
+    fn enforce_const_invariance(&self, generics: &ty::Generics, variances: &mut [ty::Variance]) {
         let tcx = self.terms_cx.tcx;
 
         // Make all const parameters invariant.
@@ -94,7 +94,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
         }
     }
 
-    fn create_map(&self) -> FxHashMap<DefId, Lrc<Vec<ty::Variance>>> {
+    fn create_map(&self) -> FxHashMap<DefId, &'tcx [ty::Variance]> {
         let tcx = self.terms_cx.tcx;
 
         let solutions = &self.solutions;
@@ -103,22 +103,21 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
             let generics = tcx.generics_of(def_id);
             let count = generics.count();
 
-            let mut variances = solutions[start..(start + count)].to_vec();
-            debug!("id={} variances={:?}", id, variances);
+            let variances = tcx.arena.alloc_slice(&solutions[start..(start + count)]);
 
             // Const parameters are always invariant.
-            self.enforce_const_invariance(generics, &mut variances);
+            self.enforce_const_invariance(generics, variances);
 
             // Functions are permitted to have unused generic parameters: make those invariant.
             if let ty::FnDef(..) = tcx.type_of(def_id).sty {
-                for variance in &mut variances {
+                for variance in variances.iter_mut() {
                     if *variance == ty::Bivariant {
                         *variance = ty::Invariant;
                     }
                 }
             }
 
-            (def_id, Lrc::new(variances))
+            (def_id, &*variances)
         }).collect()
     }
 
diff --git a/src/test/run-pass/dispatch_from_dyn_zst.rs b/src/test/run-pass/dispatch_from_dyn_zst.rs
new file mode 100644
index 00000000000..a2181336e00
--- /dev/null
+++ b/src/test/run-pass/dispatch_from_dyn_zst.rs
@@ -0,0 +1,49 @@
+#![feature(unsize, dispatch_from_dyn, never_type)]
+
+#![allow(dead_code)]
+
+use std::{
+    ops::DispatchFromDyn,
+    marker::{Unsize, PhantomData},
+};
+
+struct Zst;
+struct NestedZst(PhantomData<()>, Zst);
+
+
+struct WithUnit<T: ?Sized>(Box<T>, ());
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithUnit<U>> for WithUnit<T>
+    where T: Unsize<U> {}
+
+struct WithPhantom<T: ?Sized>(Box<T>, PhantomData<()>);
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithPhantom<U>> for WithPhantom<T>
+    where T: Unsize<U> {}
+
+struct WithNever<T: ?Sized>(Box<T>, !);
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNever<U>> for WithNever<T>
+    where T: Unsize<U> {}
+
+struct WithZst<T: ?Sized>(Box<T>, Zst);
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithZst<U>> for WithZst<T>
+    where T: Unsize<U> {}
+
+struct WithNestedZst<T: ?Sized>(Box<T>, NestedZst);
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<WithNestedZst<U>> for WithNestedZst<T>
+    where T: Unsize<U> {}
+
+
+struct Generic<T: ?Sized, A>(Box<T>, A);
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, ()>> for Generic<T, ()>
+    where T: Unsize<U> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, PhantomData<()>>>
+    for Generic<T, PhantomData<()>>
+    where T: Unsize<U> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, !>> for Generic<T, !>
+    where T: Unsize<U> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, Zst>> for Generic<T, Zst>
+    where T: Unsize<U> {}
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Generic<U, NestedZst>> for Generic<T, NestedZst>
+    where T: Unsize<U> {}
+
+
+fn main() {}
diff --git a/src/test/ui/cast_char.rs b/src/test/ui/cast_char.rs
index 8c319af9c96..9634ed56f7b 100644
--- a/src/test/ui/cast_char.rs
+++ b/src/test/ui/cast_char.rs
@@ -2,9 +2,9 @@
 
 fn main() {
     const XYZ: char = 0x1F888 as char;
-    //~^ ERROR only u8 can be cast into char
+    //~^ ERROR only `u8` can be cast into `char`
     const XY: char = 129160 as char;
-    //~^ ERROR only u8 can be cast into char
+    //~^ ERROR only `u8` can be cast into `char`
     const ZYX: char = '\u{01F888}';
     println!("{}", XYZ);
 }
diff --git a/src/test/ui/cast_char.stderr b/src/test/ui/cast_char.stderr
index f0c9b898890..37ef98bcb50 100644
--- a/src/test/ui/cast_char.stderr
+++ b/src/test/ui/cast_char.stderr
@@ -1,8 +1,8 @@
-error: only u8 can be cast into char
+error: only `u8` can be cast into `char`
   --> $DIR/cast_char.rs:4:23
    |
 LL |     const XYZ: char = 0x1F888 as char;
-   |                       ^^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'`
+   |                       ^^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'`
    |
 note: lint level defined here
   --> $DIR/cast_char.rs:1:9
@@ -10,11 +10,11 @@ note: lint level defined here
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: only u8 can be cast into char
+error: only `u8` can be cast into `char`
   --> $DIR/cast_char.rs:6:22
    |
 LL |     const XY: char = 129160 as char;
-   |                      ^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'`
+   |                      ^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/enum/enum-discrim-too-small2.rs b/src/test/ui/enum/enum-discrim-too-small2.rs
index af605643025..85cd73d6f08 100644
--- a/src/test/ui/enum/enum-discrim-too-small2.rs
+++ b/src/test/ui/enum/enum-discrim-too-small2.rs
@@ -5,28 +5,28 @@
 enum Ei8 {
     Ai8 = 23,
     Bi8 = -23,
-    Ci8 = 223, //~ ERROR literal out of range for i8
+    Ci8 = 223, //~ ERROR literal out of range for `i8`
 }
 
 #[repr(i16)]
 enum Ei16 {
     Ai16 = 23,
     Bi16 = -22333,
-    Ci16 = 55555, //~ ERROR literal out of range for i16
+    Ci16 = 55555, //~ ERROR literal out of range for `i16`
 }
 
 #[repr(i32)]
 enum Ei32 {
     Ai32 = 23,
     Bi32 = -2_000_000_000,
-    Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32
+    Ci32 = 3_000_000_000, //~ ERROR literal out of range for `i32`
 }
 
 #[repr(i64)]
 enum Ei64 {
     Ai64 = 23,
     Bi64 = -9223372036854775808,
-    Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64
+    Ci64 = 9223372036854775809, //~ ERROR literal out of range for `i64`
 }
 
 // u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`.  This is a
diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr
index 6340f5a856e..f7220044ba4 100644
--- a/src/test/ui/enum/enum-discrim-too-small2.stderr
+++ b/src/test/ui/enum/enum-discrim-too-small2.stderr
@@ -1,4 +1,4 @@
-error: literal out of range for i8
+error: literal out of range for `i8`
   --> $DIR/enum-discrim-too-small2.rs:8:11
    |
 LL |     Ci8 = 223,
@@ -10,19 +10,19 @@ note: lint level defined here
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: literal out of range for i16
+error: literal out of range for `i16`
   --> $DIR/enum-discrim-too-small2.rs:15:12
    |
 LL |     Ci16 = 55555,
    |            ^^^^^
 
-error: literal out of range for i32
+error: literal out of range for `i32`
   --> $DIR/enum-discrim-too-small2.rs:22:12
    |
 LL |     Ci32 = 3_000_000_000,
    |            ^^^^^^^^^^^^^
 
-error: literal out of range for i64
+error: literal out of range for `i64`
   --> $DIR/enum-discrim-too-small2.rs:29:12
    |
 LL |     Ci64 = 9223372036854775809,
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
index c4716893fbc..b7bc766fbe0 100644
--- a/src/test/ui/invalid_dispatch_from_dyn_impls.rs
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
@@ -39,4 +39,13 @@ where
     T: Unsize<U>,
 {} //~^^^ ERROR [E0378]
 
+#[repr(align(64))]
+struct OverAlignedZst;
+struct OverAligned<T: ?Sized>(Box<T>, OverAlignedZst);
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
+    where
+        T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
 fn main() {}
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
index bd016466300..6d62d4fd071 100644
--- a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
+++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
@@ -1,4 +1,4 @@
-error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
   --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1
    |
 LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
@@ -36,6 +36,17 @@ LL | |     T: Unsize<U>,
 LL | | {}
    | |__^
 
-error: aborting due to 4 previous errors
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
+LL | |     where
+LL | |         T: Unsize<U>,
+LL | | {}
+   | |__^
+   |
+   = note: extra field `1` of type `OverAlignedZst` is not allowed
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0378`.
diff --git a/src/test/ui/lint/deny-overflowing-literals.rs b/src/test/ui/lint/deny-overflowing-literals.rs
index ebd6654d39b..b887f66e94b 100644
--- a/src/test/ui/lint/deny-overflowing-literals.rs
+++ b/src/test/ui/lint/deny-overflowing-literals.rs
@@ -1,4 +1,4 @@
 fn main() {
     let x: u8 = 256;
-    //~^ error: literal out of range for u8
+    //~^ error: literal out of range for `u8`
 }
diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr
index 7313dd0bfb5..1263a7bb7fd 100644
--- a/src/test/ui/lint/deny-overflowing-literals.stderr
+++ b/src/test/ui/lint/deny-overflowing-literals.stderr
@@ -1,4 +1,4 @@
-error: literal out of range for u8
+error: literal out of range for `u8`
   --> $DIR/deny-overflowing-literals.rs:2:17
    |
 LL |     let x: u8 = 256;
diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.rs b/src/test/ui/lint/lint-range-endpoint-overflow.rs
new file mode 100644
index 00000000000..7034d56aa5d
--- /dev/null
+++ b/src/test/ui/lint/lint-range-endpoint-overflow.rs
@@ -0,0 +1,17 @@
+#![deny(overflowing_literals)]
+
+fn main() {
+    let range_a = 0..256; //~ ERROR range endpoint is out of range for `u8`
+    let range_b = 0..=255; // ok
+    let range_c = 0..=256; //~ ERROR literal out of range for `u8`
+    let range_d = 256..5; //~ ERROR literal out of range for `u8`
+    let range_e = 0..257; //~ ERROR literal out of range for `u8`
+    let _range_f = 0..256u8;  //~ ERROR range endpoint is out of range for `u8`
+    let _range_g = 0..128i8;  //~ ERROR range endpoint is out of range for `i8`
+
+    range_a.collect::<Vec<u8>>();
+    range_b.collect::<Vec<u8>>();
+    range_c.collect::<Vec<u8>>();
+    range_d.collect::<Vec<u8>>();
+    range_e.collect::<Vec<u8>>();
+}
diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.stderr b/src/test/ui/lint/lint-range-endpoint-overflow.stderr
new file mode 100644
index 00000000000..939451d6bc0
--- /dev/null
+++ b/src/test/ui/lint/lint-range-endpoint-overflow.stderr
@@ -0,0 +1,44 @@
+error: range endpoint is out of range for `u8`
+  --> $DIR/lint-range-endpoint-overflow.rs:4:19
+   |
+LL |     let range_a = 0..256;
+   |                   ^^^^^^ help: use an inclusive range instead: `0..=255`
+   |
+note: lint level defined here
+  --> $DIR/lint-range-endpoint-overflow.rs:1:9
+   |
+LL | #![deny(overflowing_literals)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: literal out of range for `u8`
+  --> $DIR/lint-range-endpoint-overflow.rs:6:23
+   |
+LL |     let range_c = 0..=256;
+   |                       ^^^
+
+error: literal out of range for `u8`
+  --> $DIR/lint-range-endpoint-overflow.rs:7:19
+   |
+LL |     let range_d = 256..5;
+   |                   ^^^
+
+error: literal out of range for `u8`
+  --> $DIR/lint-range-endpoint-overflow.rs:8:22
+   |
+LL |     let range_e = 0..257;
+   |                      ^^^
+
+error: range endpoint is out of range for `u8`
+  --> $DIR/lint-range-endpoint-overflow.rs:9:20
+   |
+LL |     let _range_f = 0..256u8;
+   |                    ^^^^^^^^ help: use an inclusive range instead: `0..=255u8`
+
+error: range endpoint is out of range for `i8`
+  --> $DIR/lint-range-endpoint-overflow.rs:10:20
+   |
+LL |     let _range_g = 0..128i8;
+   |                    ^^^^^^^^ help: use an inclusive range instead: `0..=127i8`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/lint/lint-type-limits2.rs b/src/test/ui/lint/lint-type-limits2.rs
index c4486e06768..3f90119cd89 100644
--- a/src/test/ui/lint/lint-type-limits2.rs
+++ b/src/test/ui/lint/lint-type-limits2.rs
@@ -11,5 +11,5 @@ fn bar() -> i8 {
 
 fn baz() -> bool {
     128 > bar() //~ ERROR comparison is useless due to type limits
-                //~| WARN literal out of range for i8
+                //~| WARN literal out of range for `i8`
 }
diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr
index e7bc407422a..0b3d2928567 100644
--- a/src/test/ui/lint/lint-type-limits2.stderr
+++ b/src/test/ui/lint/lint-type-limits2.stderr
@@ -6,7 +6,7 @@ LL |     128 > bar()
    |
    = note: requested on the command line with `-D unused-comparisons`
 
-warning: literal out of range for i8
+warning: literal out of range for `i8`
   --> $DIR/lint-type-limits2.rs:13:5
    |
 LL |     128 > bar()
diff --git a/src/test/ui/lint/lint-type-limits3.rs b/src/test/ui/lint/lint-type-limits3.rs
index a715c69f784..ceecf9ab30b 100644
--- a/src/test/ui/lint/lint-type-limits3.rs
+++ b/src/test/ui/lint/lint-type-limits3.rs
@@ -7,7 +7,7 @@ fn main() { }
 fn qux() {
     let mut i = 1i8;
     while 200 != i { //~ ERROR comparison is useless due to type limits
-                     //~| WARN literal out of range for i8
+                     //~| WARN literal out of range for `i8`
         i += 1;
     }
 }
diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr
index 742b6695c24..70cd9c859ec 100644
--- a/src/test/ui/lint/lint-type-limits3.stderr
+++ b/src/test/ui/lint/lint-type-limits3.stderr
@@ -6,7 +6,7 @@ LL |     while 200 != i {
    |
    = note: requested on the command line with `-D unused-comparisons`
 
-warning: literal out of range for i8
+warning: literal out of range for `i8`
   --> $DIR/lint-type-limits3.rs:9:11
    |
 LL |     while 200 != i {
diff --git a/src/test/ui/lint/lint-type-overflow.rs b/src/test/ui/lint/lint-type-overflow.rs
index 847cdf31dc7..9672da6d358 100644
--- a/src/test/ui/lint/lint-type-overflow.rs
+++ b/src/test/ui/lint/lint-type-overflow.rs
@@ -1,5 +1,3 @@
-//
-
 #![deny(overflowing_literals)]
 
 fn test(x: i8) {
@@ -9,39 +7,39 @@ fn test(x: i8) {
 #[allow(unused_variables)]
 fn main() {
     let x1: u8 = 255; // should be OK
-    let x1: u8 = 256; //~ error: literal out of range for u8
+    let x1: u8 = 256; //~ error: literal out of range for `u8`
 
     let x1 = 255_u8; // should be OK
-    let x1 = 256_u8; //~ error: literal out of range for u8
+    let x1 = 256_u8; //~ error: literal out of range for `u8`
 
     let x2: i8 = -128; // should be OK
-    let x1: i8 = 128; //~ error: literal out of range for i8
+    let x1: i8 = 128; //~ error: literal out of range for `i8`
 
-    let x3: i8 = -129; //~ error: literal out of range for i8
-    let x3: i8 = -(129); //~ error: literal out of range for i8
-    let x3: i8 = -{129}; //~ error: literal out of range for i8
+    let x3: i8 = -129; //~ error: literal out of range for `i8`
+    let x3: i8 = -(129); //~ error: literal out of range for `i8`
+    let x3: i8 = -{129}; //~ error: literal out of range for `i8`
 
-    test(1000); //~ error: literal out of range for i8
+    test(1000); //~ error: literal out of range for `i8`
 
-    let x = 128_i8; //~ error: literal out of range for i8
+    let x = 128_i8; //~ error: literal out of range for `i8`
     let x = 127_i8;
     let x = -128_i8;
     let x = -(128_i8);
-    let x = -129_i8; //~ error: literal out of range for i8
+    let x = -129_i8; //~ error: literal out of range for `i8`
 
     let x: i32 = 2147483647; // should be OK
     let x = 2147483647_i32; // should be OK
-    let x: i32 = 2147483648; //~ error: literal out of range for i32
-    let x = 2147483648_i32; //~ error: literal out of range for i32
+    let x: i32 = 2147483648; //~ error: literal out of range for `i32`
+    let x = 2147483648_i32; //~ error: literal out of range for `i32`
     let x: i32 = -2147483648; // should be OK
     let x = -2147483648_i32; // should be OK
-    let x: i32 = -2147483649; //~ error: literal out of range for i32
-    let x = -2147483649_i32; //~ error: literal out of range for i32
-    let x = 2147483648; //~ error: literal out of range for i32
+    let x: i32 = -2147483649; //~ error: literal out of range for `i32`
+    let x = -2147483649_i32; //~ error: literal out of range for `i32`
+    let x = 2147483648; //~ error: literal out of range for `i32`
 
-    let x = 9223372036854775808_i64; //~ error: literal out of range for i64
+    let x = 9223372036854775808_i64; //~ error: literal out of range for `i64`
     let x = -9223372036854775808_i64; // should be OK
-    let x = 18446744073709551615_i64; //~ error: literal out of range for i64
-    let x: i64 = -9223372036854775809; //~ error: literal out of range for i64
-    let x = -9223372036854775809_i64; //~ error: literal out of range for i64
+    let x = 18446744073709551615_i64; //~ error: literal out of range for `i64`
+    let x: i64 = -9223372036854775809; //~ error: literal out of range for `i64`
+    let x = -9223372036854775809_i64; //~ error: literal out of range for `i64`
 }
diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr
index 9da007457aa..6fcd9b58b2d 100644
--- a/src/test/ui/lint/lint-type-overflow.stderr
+++ b/src/test/ui/lint/lint-type-overflow.stderr
@@ -1,113 +1,113 @@
-error: literal out of range for u8
-  --> $DIR/lint-type-overflow.rs:12:18
+error: literal out of range for `u8`
+  --> $DIR/lint-type-overflow.rs:10:18
    |
 LL |     let x1: u8 = 256;
    |                  ^^^
    |
 note: lint level defined here
-  --> $DIR/lint-type-overflow.rs:3:9
+  --> $DIR/lint-type-overflow.rs:1:9
    |
 LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: literal out of range for u8
-  --> $DIR/lint-type-overflow.rs:15:14
+error: literal out of range for `u8`
+  --> $DIR/lint-type-overflow.rs:13:14
    |
 LL |     let x1 = 256_u8;
    |              ^^^^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:18:18
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:16:18
    |
 LL |     let x1: i8 = 128;
    |                  ^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:20:19
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:18:19
    |
 LL |     let x3: i8 = -129;
    |                   ^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:21:19
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:19:19
    |
 LL |     let x3: i8 = -(129);
    |                   ^^^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:22:20
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:20:20
    |
 LL |     let x3: i8 = -{129};
    |                    ^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:24:10
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:22:10
    |
 LL |     test(1000);
    |          ^^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:26:13
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:24:13
    |
 LL |     let x = 128_i8;
    |             ^^^^^^
 
-error: literal out of range for i8
-  --> $DIR/lint-type-overflow.rs:30:14
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow.rs:28:14
    |
 LL |     let x = -129_i8;
    |              ^^^^^^
 
-error: literal out of range for i32
-  --> $DIR/lint-type-overflow.rs:34:18
+error: literal out of range for `i32`
+  --> $DIR/lint-type-overflow.rs:32:18
    |
 LL |     let x: i32 = 2147483648;
    |                  ^^^^^^^^^^
 
-error: literal out of range for i32
-  --> $DIR/lint-type-overflow.rs:35:13
+error: literal out of range for `i32`
+  --> $DIR/lint-type-overflow.rs:33:13
    |
 LL |     let x = 2147483648_i32;
    |             ^^^^^^^^^^^^^^
 
-error: literal out of range for i32
-  --> $DIR/lint-type-overflow.rs:38:19
+error: literal out of range for `i32`
+  --> $DIR/lint-type-overflow.rs:36:19
    |
 LL |     let x: i32 = -2147483649;
    |                   ^^^^^^^^^^
 
-error: literal out of range for i32
-  --> $DIR/lint-type-overflow.rs:39:14
+error: literal out of range for `i32`
+  --> $DIR/lint-type-overflow.rs:37:14
    |
 LL |     let x = -2147483649_i32;
    |              ^^^^^^^^^^^^^^
 
-error: literal out of range for i32
-  --> $DIR/lint-type-overflow.rs:40:13
+error: literal out of range for `i32`
+  --> $DIR/lint-type-overflow.rs:38:13
    |
 LL |     let x = 2147483648;
    |             ^^^^^^^^^^
 
-error: literal out of range for i64
-  --> $DIR/lint-type-overflow.rs:42:13
+error: literal out of range for `i64`
+  --> $DIR/lint-type-overflow.rs:40:13
    |
 LL |     let x = 9223372036854775808_i64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: literal out of range for i64
-  --> $DIR/lint-type-overflow.rs:44:13
+error: literal out of range for `i64`
+  --> $DIR/lint-type-overflow.rs:42:13
    |
 LL |     let x = 18446744073709551615_i64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: literal out of range for i64
-  --> $DIR/lint-type-overflow.rs:45:19
+error: literal out of range for `i64`
+  --> $DIR/lint-type-overflow.rs:43:19
    |
 LL |     let x: i64 = -9223372036854775809;
    |                   ^^^^^^^^^^^^^^^^^^^
 
-error: literal out of range for i64
-  --> $DIR/lint-type-overflow.rs:46:14
+error: literal out of range for `i64`
+  --> $DIR/lint-type-overflow.rs:44:14
    |
 LL |     let x = -9223372036854775809_i64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr
index 5255f6c7593..c76e9e25d5a 100644
--- a/src/test/ui/lint/lint-type-overflow2.stderr
+++ b/src/test/ui/lint/lint-type-overflow2.stderr
@@ -1,4 +1,4 @@
-warning: literal out of range for i8
+warning: literal out of range for `i8`
   --> $DIR/lint-type-overflow2.rs:9:20
    |
 LL |     let x2: i8 = --128;
@@ -10,25 +10,25 @@ note: lint level defined here
 LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for f32
+warning: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:11:14
    |
 LL |     let x = -3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for f32
+warning: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:12:14
    |
 LL |     let x =  3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for f64
+warning: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:13:14
    |
 LL |     let x = -1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for f64
+warning: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:14:14
    |
 LL |     let x =  1.7976931348623159e+308_f64;
diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr
index 5235c9851b5..dabfb876fbb 100644
--- a/src/test/ui/lint/type-overflow.stderr
+++ b/src/test/ui/lint/type-overflow.stderr
@@ -1,4 +1,4 @@
-warning: literal out of range for i8
+warning: literal out of range for `i8`
   --> $DIR/type-overflow.rs:5:17
    |
 LL |     let error = 255i8;
diff --git a/src/test/ui/nll/local-outlives-static-via-hrtb.rs b/src/test/ui/nll/local-outlives-static-via-hrtb.rs
new file mode 100644
index 00000000000..5f1f9b3a7f2
--- /dev/null
+++ b/src/test/ui/nll/local-outlives-static-via-hrtb.rs
@@ -0,0 +1,26 @@
+// Test that we handle the case when a local variable is borrowed for `'static`
+// due to an outlives constraint involving a region in an incompatible universe
+
+pub trait Outlives<'this> {}
+
+impl<'this, T> Outlives<'this> for T where T: 'this {}
+trait Reference {
+    type AssociatedType;
+}
+
+impl<'a, T: 'a> Reference for &'a T {
+    type AssociatedType = &'a ();
+}
+
+fn assert_static_via_hrtb<G>(_: G) where for<'a> G: Outlives<'a> {}
+
+fn assert_static_via_hrtb_with_assoc_type<T>(_: &'_ T)
+where
+    for<'a> &'a T: Reference<AssociatedType = &'a ()>,
+{}
+
+fn main() {
+    let local = 0;
+    assert_static_via_hrtb(&local); //~ ERROR `local` does not live long enough
+    assert_static_via_hrtb_with_assoc_type(&&local); //~ ERROR `local` does not live long enough
+}
diff --git a/src/test/ui/nll/local-outlives-static-via-hrtb.stderr b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr
new file mode 100644
index 00000000000..61009da49ff
--- /dev/null
+++ b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr
@@ -0,0 +1,26 @@
+error[E0597]: `local` does not live long enough
+  --> $DIR/local-outlives-static-via-hrtb.rs:24:28
+   |
+LL |     assert_static_via_hrtb(&local);
+   |     -----------------------^^^^^^-
+   |     |                      |
+   |     |                      borrowed value does not live long enough
+   |     argument requires that `local` is borrowed for `'static`
+LL |     assert_static_via_hrtb_with_assoc_type(&&local);
+LL | }
+   | - `local` dropped here while still borrowed
+
+error[E0597]: `local` does not live long enough
+  --> $DIR/local-outlives-static-via-hrtb.rs:25:45
+   |
+LL |     assert_static_via_hrtb_with_assoc_type(&&local);
+   |     ----------------------------------------^^^^^^-
+   |     |                                       |
+   |     |                                       borrowed value does not live long enough
+   |     argument requires that `local` is borrowed for `'static`
+LL | }
+   | - `local` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.