about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-08-25 00:47:28 +0000
committerbors <bors@rust-lang.org>2019-08-25 00:47:28 +0000
commit9267119019b48b0c3c6fb44cd3cbab64b2a1a6b5 (patch)
treebe5fa33785bd8f04fb8b37e64e0cf2e26de26e2e
parenteeba189cfb2cfc5c5898513352d4ca8f1df06e05 (diff)
parent4d3d06ae53408536443f3a20507b3e96c1ea526a (diff)
downloadrust-9267119019b48b0c3c6fb44cd3cbab64b2a1a6b5.tar.gz
rust-9267119019b48b0c3c6fb44cd3cbab64b2a1a6b5.zip
Auto merge of #63873 - Centril:rollup-jgglypd, r=Centril
Rollup of 6 pull requests

Successful merges:

 - #62744 (Refactor `TinyList::contains` and `len` to iterate instead of recurse)
 - #63813 (Do not suggest `.try_into()` on `i32::from(x)`)
 - #63833 (Suggest calling closure with resolved return type when appropriate)
 - #63839 (Ensure miri can do bit ops on pointer values)
 - #63854 (Modifies how Arg, Arm, Field, FieldPattern and Variant are visited)
 - #63859 (Don't unwrap the result of `span_to_snippet`)

Failed merges:

r? @ghost
-rw-r--r--src/librustc/hir/map/def_collector.rs7
-rw-r--r--src/librustc/lint/context.rs35
-rw-r--r--src/librustc/lint/mod.rs36
-rw-r--r--src/librustc/ty/sty.rs2
-rw-r--r--src/librustc_data_structures/tiny_list.rs56
-rw-r--r--src/librustc_data_structures/tiny_list/tests.rs35
-rw-r--r--src/librustc_lint/builtin.rs2
-rw-r--r--src/librustc_lint/nonstandard_style.rs5
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs84
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs4
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs13
-rw-r--r--src/librustc_mir/interpret/operand.rs9
-rw-r--r--src/librustc_mir/interpret/traits.rs6
-rw-r--r--src/librustc_passes/ast_validation.rs3
-rw-r--r--src/librustc_passes/hir_stats.rs7
-rw-r--r--src/librustc_typeck/check/coercion.rs13
-rw-r--r--src/librustc_typeck/check/demand.rs24
-rw-r--r--src/librustc_typeck/check/mod.rs130
-rw-r--r--src/libsyntax/ext/expand.rs10
-rw-r--r--src/libsyntax/mut_visit.rs126
-rw-r--r--src/libsyntax/util/node_count.rs7
-rw-r--r--src/libsyntax/visit.rs54
-rw-r--r--src/test/ui/borrowck/move-error-snippets-ext.rs7
-rw-r--r--src/test/ui/borrowck/move-error-snippets.rs23
-rw-r--r--src/test/ui/borrowck/move-error-snippets.stderr15
-rw-r--r--src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs2
-rw-r--r--src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr16
-rw-r--r--src/test/ui/suggestions/mismatched-types-numeric-from.rs3
-rw-r--r--src/test/ui/suggestions/mismatched-types-numeric-from.stderr9
29 files changed, 436 insertions, 307 deletions
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index d725afa4052..17bcb1d0859 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -154,7 +154,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         });
     }
 
-    fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
+    fn visit_variant(&mut self, v: &'a Variant) {
         let def = self.create_def(v.id,
                                   DefPathData::TypeNs(v.ident.as_interned_str()),
                                   v.span);
@@ -162,12 +162,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             if let Some(ctor_hir_id) = v.data.ctor_id() {
                 this.create_def(ctor_hir_id, DefPathData::Ctor, v.span);
             }
-            visit::walk_variant(this, v, g, item_id)
+            visit::walk_variant(this, v)
         });
     }
 
-    fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
-                          _: &'a Generics, _: NodeId, _: Span) {
+    fn visit_variant_data(&mut self, data: &'a VariantData) {
         for (index, field) in data.fields().iter().enumerate() {
             let name = field.ident.map(|ident| ident.name)
                 .unwrap_or_else(|| sym::integer(index));
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 6801fa8d8db..8126db14292 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1040,13 +1040,13 @@ for LateContextAndPass<'a, 'tcx, T> {
 
     fn visit_variant_data(&mut self,
                         s: &'tcx hir::VariantData,
-                        name: ast::Name,
-                        g: &'tcx hir::Generics,
-                        item_id: hir::HirId,
+                        _: ast::Name,
+                        _: &'tcx hir::Generics,
+                        _: hir::HirId,
                         _: Span) {
-        lint_callback!(self, check_struct_def, s, name, g, item_id);
+        lint_callback!(self, check_struct_def, s);
         hir_visit::walk_struct_def(self, s);
-        lint_callback!(self, check_struct_def_post, s, name, g, item_id);
+        lint_callback!(self, check_struct_def_post, s);
     }
 
     fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
@@ -1061,9 +1061,9 @@ for LateContextAndPass<'a, 'tcx, T> {
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
         self.with_lint_attrs(v.id, &v.attrs, |cx| {
-            lint_callback!(cx, check_variant, v, g);
+            lint_callback!(cx, check_variant, v);
             hir_visit::walk_variant(cx, v, g, item_id);
-            lint_callback!(cx, check_variant_post, v, g);
+            lint_callback!(cx, check_variant_post, v);
         })
     }
 
@@ -1214,18 +1214,13 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         run_early_pass!(self, check_fn_post, fk, decl, span, id);
     }
 
-    fn visit_variant_data(&mut self,
-                        s: &'a ast::VariantData,
-                        ident: ast::Ident,
-                        g: &'a ast::Generics,
-                        item_id: ast::NodeId,
-                        _: Span) {
-        run_early_pass!(self, check_struct_def, s, ident, g, item_id);
+    fn visit_variant_data(&mut self, s: &'a ast::VariantData) {
+        run_early_pass!(self, check_struct_def, s);
         if let Some(ctor_hir_id) = s.ctor_id() {
             self.check_id(ctor_hir_id);
         }
         ast_visit::walk_struct_def(self, s);
-        run_early_pass!(self, check_struct_def_post, s, ident, g, item_id);
+        run_early_pass!(self, check_struct_def_post, s);
     }
 
     fn visit_struct_field(&mut self, s: &'a ast::StructField) {
@@ -1235,11 +1230,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
         })
     }
 
-    fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) {
-        self.with_lint_attrs(item_id, &v.attrs, |cx| {
-            run_early_pass!(cx, check_variant, v, g);
-            ast_visit::walk_variant(cx, v, g, item_id);
-            run_early_pass!(cx, check_variant_post, v, g);
+    fn visit_variant(&mut self, v: &'a ast::Variant) {
+        self.with_lint_attrs(v.id, &v.attrs, |cx| {
+            run_early_pass!(cx, check_variant, v);
+            ast_visit::walk_variant(cx, v);
+            run_early_pass!(cx, check_variant_post, v);
         })
     }
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 2b58627cdea..7e2707b98d5 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -248,21 +248,11 @@ macro_rules! late_lint_methods {
             fn check_trait_item_post(a: &$hir hir::TraitItem);
             fn check_impl_item(a: &$hir hir::ImplItem);
             fn check_impl_item_post(a: &$hir hir::ImplItem);
-            fn check_struct_def(
-                a: &$hir hir::VariantData,
-                b: ast::Name,
-                c: &$hir hir::Generics,
-                d: hir::HirId
-            );
-            fn check_struct_def_post(
-                a: &$hir hir::VariantData,
-                b: ast::Name,
-                c: &$hir hir::Generics,
-                d: hir::HirId
-            );
+            fn check_struct_def(a: &$hir hir::VariantData);
+            fn check_struct_def_post(a: &$hir hir::VariantData);
             fn check_struct_field(a: &$hir hir::StructField);
-            fn check_variant(a: &$hir hir::Variant, b: &$hir hir::Generics);
-            fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics);
+            fn check_variant(a: &$hir hir::Variant);
+            fn check_variant_post(a: &$hir hir::Variant);
             fn check_lifetime(a: &$hir hir::Lifetime);
             fn check_path(a: &$hir hir::Path, b: hir::HirId);
             fn check_attribute(a: &$hir ast::Attribute);
@@ -395,21 +385,11 @@ macro_rules! early_lint_methods {
             fn check_trait_item_post(a: &ast::TraitItem);
             fn check_impl_item(a: &ast::ImplItem);
             fn check_impl_item_post(a: &ast::ImplItem);
-            fn check_struct_def(
-                a: &ast::VariantData,
-                b: ast::Ident,
-                c: &ast::Generics,
-                d: ast::NodeId
-            );
-            fn check_struct_def_post(
-                a: &ast::VariantData,
-                b: ast::Ident,
-                c: &ast::Generics,
-                d: ast::NodeId
-            );
+            fn check_struct_def(a: &ast::VariantData);
+            fn check_struct_def_post(a: &ast::VariantData);
             fn check_struct_field(a: &ast::StructField);
-            fn check_variant(a: &ast::Variant, b: &ast::Generics);
-            fn check_variant_post(a: &ast::Variant, b: &ast::Generics);
+            fn check_variant(a: &ast::Variant);
+            fn check_variant_post(a: &ast::Variant);
             fn check_lifetime(a: &ast::Lifetime);
             fn check_path(a: &ast::Path, b: ast::NodeId);
             fn check_attribute(a: &ast::Attribute);
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index da66fdf5b1b..f41fffe507d 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -385,7 +385,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
         let ty = self.closure_sig_ty(def_id, tcx);
         match ty.sty {
             ty::FnPtr(sig) => sig,
-            _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty),
+            _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty),
         }
     }
 }
diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs
index 1c0d9360f25..ea771d9f20f 100644
--- a/src/librustc_data_structures/tiny_list.rs
+++ b/src/librustc_data_structures/tiny_list.rs
@@ -20,7 +20,6 @@ pub struct TinyList<T: PartialEq> {
 }
 
 impl<T: PartialEq> TinyList<T> {
-
     #[inline]
     pub fn new() -> TinyList<T> {
         TinyList {
@@ -60,20 +59,24 @@ impl<T: PartialEq> TinyList<T> {
 
     #[inline]
     pub fn contains(&self, data: &T) -> bool {
-        if let Some(ref head) = self.head {
-            head.contains(data)
-        } else {
-            false
+        let mut elem = self.head.as_ref();
+        while let Some(ref e) = elem {
+            if &e.data == data {
+                return true;
+            }
+            elem = e.next.as_ref().map(|e| &**e);
         }
+        false
     }
 
     #[inline]
     pub fn len(&self) -> usize {
-        if let Some(ref head) = self.head {
-            head.len()
-        } else {
-            0
+        let (mut elem, mut count) = (self.head.as_ref(), 0);
+        while let Some(ref e) = elem {
+            count += 1;
+            elem = e.next.as_ref().map(|e| &**e);
         }
+        count
     }
 }
 
@@ -84,40 +87,13 @@ struct Element<T: PartialEq> {
 }
 
 impl<T: PartialEq> Element<T> {
-
     fn remove_next(&mut self, data: &T) -> bool {
-        let new_next = if let Some(ref mut next) = self.next {
-            if next.data != *data {
-                return next.remove_next(data)
-            } else {
-                next.next.take()
-            }
-        } else {
-            return false
+        let new_next = match self.next {
+            Some(ref mut next) if next.data == *data => next.next.take(),
+            Some(ref mut next) => return next.remove_next(data),
+            None => return false,
         };
-
         self.next = new_next;
-
         true
     }
-
-    fn len(&self) -> usize {
-        if let Some(ref next) = self.next {
-            1 + next.len()
-        } else {
-            1
-        }
-    }
-
-    fn contains(&self, data: &T) -> bool {
-        if self.data == *data {
-            return true
-        }
-
-        if let Some(ref next) = self.next {
-            next.contains(data)
-        } else {
-            false
-        }
-    }
 }
diff --git a/src/librustc_data_structures/tiny_list/tests.rs b/src/librustc_data_structures/tiny_list/tests.rs
index 8374659e1e6..0142631590c 100644
--- a/src/librustc_data_structures/tiny_list/tests.rs
+++ b/src/librustc_data_structures/tiny_list/tests.rs
@@ -1,7 +1,7 @@
 use super::*;
 
 extern crate test;
-use test::Bencher;
+use test::{Bencher, black_box};
 
 #[test]
 fn test_contains_and_insert() {
@@ -98,36 +98,59 @@ fn test_remove_single() {
 #[bench]
 fn bench_insert_empty(b: &mut Bencher) {
     b.iter(|| {
-        let mut list = TinyList::new();
+        let mut list = black_box(TinyList::new());
         list.insert(1);
+        list
     })
 }
 
 #[bench]
 fn bench_insert_one(b: &mut Bencher) {
     b.iter(|| {
-        let mut list = TinyList::new_single(0);
+        let mut list = black_box(TinyList::new_single(0));
         list.insert(1);
+        list
     })
 }
 
 #[bench]
+fn bench_contains_empty(b: &mut Bencher) {
+    b.iter(|| {
+        black_box(TinyList::new()).contains(&1)
+    });
+}
+
+#[bench]
+fn bench_contains_unknown(b: &mut Bencher) {
+    b.iter(|| {
+        black_box(TinyList::new_single(0)).contains(&1)
+    });
+}
+
+#[bench]
+fn bench_contains_one(b: &mut Bencher) {
+    b.iter(|| {
+        black_box(TinyList::new_single(1)).contains(&1)
+    });
+}
+
+#[bench]
 fn bench_remove_empty(b: &mut Bencher) {
     b.iter(|| {
-        TinyList::new().remove(&1)
+        black_box(TinyList::new()).remove(&1)
     });
 }
 
 #[bench]
 fn bench_remove_unknown(b: &mut Bencher) {
     b.iter(|| {
-        TinyList::new_single(0).remove(&1)
+        black_box(TinyList::new_single(0)).remove(&1)
     });
 }
 
 #[bench]
 fn bench_remove_one(b: &mut Bencher) {
     b.iter(|| {
-        TinyList::new_single(1).remove(&1)
+        black_box(TinyList::new_single(1)).remove(&1)
     });
 }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ce7681c974a..d3c94060e27 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -482,7 +482,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
         }
     }
 
-    fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) {
+    fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant) {
         self.check_missing_docs_attrs(cx,
                                       Some(v.id),
                                       &v.attrs,
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index acd17f76632..bb6119d0ff2 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -146,7 +146,7 @@ impl EarlyLintPass for NonCamelCaseTypes {
         }
     }
 
-    fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant, _: &ast::Generics) {
+    fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant) {
         self.check_case(cx, "variant", &v.ident);
     }
 
@@ -350,9 +350,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
         &mut self,
         cx: &LateContext<'_, '_>,
         s: &hir::VariantData,
-        _: ast::Name,
-        _: &hir::Generics,
-        _: hir::HirId,
     ) {
         for sf in s.fields() {
             self.check_snake_case(cx, "structure field", &sf.ident);
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 738a091b0dd..f10ff71b15e 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -415,20 +415,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             "{:?}",
             move_place.ty(self.body, self.infcx.tcx).ty,
         );
-        let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap();
-        let is_option = move_ty.starts_with("std::option::Option");
-        let is_result = move_ty.starts_with("std::result::Result");
-        if  is_option || is_result {
-            err.span_suggestion(
-                span,
-                &format!("consider borrowing the `{}`'s content", if is_option {
-                    "Option"
-                } else {
-                    "Result"
-                }),
-                format!("{}.as_ref()", snippet),
-                Applicability::MaybeIncorrect,
-            );
+        if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+            let is_option = move_ty.starts_with("std::option::Option");
+            let is_result = move_ty.starts_with("std::result::Result");
+            if is_option || is_result {
+                err.span_suggestion(
+                    span,
+                    &format!("consider borrowing the `{}`'s content", if is_option {
+                        "Option"
+                    } else {
+                        "Result"
+                    }),
+                    format!("{}.as_ref()", snippet),
+                    Applicability::MaybeIncorrect,
+                );
+            }
         }
         err
     }
@@ -439,19 +440,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         err: &mut DiagnosticBuilder<'a>,
         span: Span,
     ) {
-        let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap();
         match error {
             GroupedMoveError::MovesFromPlace {
                 mut binds_to,
                 move_from,
                 ..
             } => {
-                err.span_suggestion(
-                    span,
-                    "consider borrowing here",
-                    format!("&{}", snippet),
-                    Applicability::Unspecified,
-                );
+                if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                        Applicability::Unspecified,
+                    );
+                }
 
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
@@ -517,27 +519,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ..
                 }))
             ) = bind_to.is_user_variable {
-                let pat_snippet = self.infcx.tcx.sess.source_map()
-                    .span_to_snippet(pat_span)
-                    .unwrap();
-                if pat_snippet.starts_with('&') {
-                    let pat_snippet = pat_snippet[1..].trim_start();
-                    let suggestion;
-                    let to_remove;
-                    if pat_snippet.starts_with("mut")
-                        && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
-                    {
-                        suggestion = pat_snippet["mut".len()..].trim_start();
-                        to_remove = "&mut";
-                    } else {
-                        suggestion = pat_snippet;
-                        to_remove = "&";
+                if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
+                {
+                    if pat_snippet.starts_with('&') {
+                        let pat_snippet = pat_snippet[1..].trim_start();
+                        let suggestion;
+                        let to_remove;
+                        if pat_snippet.starts_with("mut")
+                            && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
+                        {
+                            suggestion = pat_snippet["mut".len()..].trim_start();
+                            to_remove = "&mut";
+                        } else {
+                            suggestion = pat_snippet;
+                            to_remove = "&";
+                        }
+                        suggestions.push((
+                            pat_span,
+                            to_remove,
+                            suggestion.to_owned(),
+                        ));
                     }
-                    suggestions.push((
-                        pat_span,
-                        to_remove,
-                        suggestion.to_owned(),
-                    ));
                 }
             }
         }
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 937c6383be3..e7f37431e50 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -711,8 +711,8 @@ fn annotate_struct_field(
 }
 
 /// If possible, suggest replacing `ref` with `ref mut`.
-fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<(String)> {
-    let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap();
+fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<String> {
+    let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?;
     if hi_src.starts_with("ref")
         && hi_src["ref".len()..].starts_with(Pattern_White_Space)
     {
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 4c86c53256e..334f1ea1a69 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -95,7 +95,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | "bitreverse" => {
                 let ty = substs.type_at(0);
                 let layout_of = self.layout_of(ty)?;
-                let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
+                let val = self.read_scalar(args[0])?.not_undef()?;
+                let bits = self.force_bits(val, layout_of.size)?;
                 let kind = match layout_of.abi {
                     ty::layout::Abi::Scalar(ref scalar) => scalar.value,
                     _ => throw_unsup!(TypeNotPrimitive(ty)),
@@ -149,7 +150,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // term since the sign of the second term can be inferred from this and
                         // the fact that the operation has overflowed (if either is 0 no
                         // overflow can occur)
-                        let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
+                        let first_term: u128 = self.force_bits(l.to_scalar()?, l.layout.size)?;
                         let first_term_positive = first_term & (1 << (num_bits-1)) == 0;
                         if first_term_positive {
                             // Negative overflow not possible since the positive first term
@@ -187,7 +188,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?;
                 if overflowed {
                     let layout = self.layout_of(substs.type_at(0))?;
-                    let r_val = r.to_scalar()?.to_bits(layout.size)?;
+                    let r_val = self.force_bits(r.to_scalar()?, layout.size)?;
                     throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name);
                 }
                 self.write_scalar(val, dest)?;
@@ -196,8 +197,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
                 let layout = self.layout_of(substs.type_at(0))?;
-                let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?;
-                let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?;
+                let val = self.read_scalar(args[0])?.not_undef()?;
+                let val_bits = self.force_bits(val, layout.size)?;
+                let raw_shift = self.read_scalar(args[1])?.not_undef()?;
+                let raw_shift_bits = self.force_bits(raw_shift, layout.size)?;
                 let width_bits = layout.size.bits() as u128;
                 let shift_bits = raw_shift_bits % width_bits;
                 let inv_shift_bits = (width_bits - shift_bits) % width_bits;
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 7a545e8ad6f..b5aab992e3a 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -629,11 +629,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // post-process
         Ok(match *discr_kind {
             layout::DiscriminantKind::Tag => {
-                let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
-                    Ok(raw_discr) => raw_discr,
-                    Err(_) =>
-                        throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag())),
-                };
+                let bits_discr = raw_discr
+                    .not_undef()
+                    .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size))
+                    .map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?;
                 let real_discr = if discr_val.layout.ty.is_signed() {
                     // going from layout tag type to typeck discriminant type
                     // requires first sign extending with the layout discriminant
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index a2fc75739ff..34a10de7de7 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -144,11 +144,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let size = alloc.read_ptr_sized(
             self,
             vtable.offset(pointer_size, self)?
-        )?.to_bits(pointer_size)? as u64;
+        )?.not_undef()?;
+        let size = self.force_bits(size, pointer_size)? as u64;
         let align = alloc.read_ptr_sized(
             self,
             vtable.offset(pointer_size * 2, self)?,
-        )?.to_bits(pointer_size)? as u64;
+        )?.not_undef()?;
+        let align = self.force_bits(align, pointer_size)? as u64;
         Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
     }
 }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index bd46ca4779a..5b78727fdd5 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -813,8 +813,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_poly_trait_ref(self, t, m);
     }
 
-    fn visit_variant_data(&mut self, s: &'a VariantData, _: Ident,
-                          _: &'a Generics, _: NodeId, _: Span) {
+    fn visit_variant_data(&mut self, s: &'a VariantData) {
         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
     }
 
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 8fba3256ec4..7e03df5b75b 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -334,12 +334,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
         ast_visit::walk_struct_field(self, s)
     }
 
-    fn visit_variant(&mut self,
-                     v: &'v ast::Variant,
-                     g: &'v ast::Generics,
-                     item_id: NodeId) {
+    fn visit_variant(&mut self, v: &'v ast::Variant) {
         self.record("Variant", Id::None, v);
-        ast_visit::walk_variant(self, v, g, item_id)
+        ast_visit::walk_variant(self, v)
     }
 
     fn visit_lifetime(&mut self, lifetime: &'v ast::Lifetime) {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 4edb6ad8931..61b9c2a15ba 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -799,12 +799,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// adjusted type of the expression, if successful.
     /// Adjustments are only recorded if the coercion succeeded.
     /// The expressions *must not* have any pre-existing adjustments.
-    pub fn try_coerce(&self,
-                      expr: &hir::Expr,
-                      expr_ty: Ty<'tcx>,
-                      target: Ty<'tcx>,
-                      allow_two_phase: AllowTwoPhase)
-                      -> RelateResult<'tcx, Ty<'tcx>> {
+    pub fn try_coerce(
+        &self,
+        expr: &hir::Expr,
+        expr_ty: Ty<'tcx>,
+        target: Ty<'tcx>,
+        allow_two_phase: AllowTwoPhase,
+    ) -> RelateResult<'tcx, Ty<'tcx>> {
         let source = self.resolve_type_vars_with_obligations(expr_ty);
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index de5ba8bc8eb..0efc433341c 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -587,6 +587,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return false;
             }
         }
+        if let hir::ExprKind::Call(path, args) = &expr.node {
+            if let (
+                hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)),
+                1,
+            ) = (&path.node, args.len()) {
+                // `expr` is a conversion like `u32::from(val)`, do not suggest anything (#63697).
+                if let (
+                    hir::TyKind::Path(hir::QPath::Resolved(None, base_ty_path)),
+                    sym::from,
+                ) = (&base_ty.node, path_segment.ident.name) {
+                    if let Some(ident) = &base_ty_path.segments.iter().map(|s| s.ident).next() {
+                        match ident.name {
+                            sym::i128 | sym::i64 | sym::i32 | sym::i16 | sym::i8 |
+                            sym::u128 | sym::u64 | sym::u32 | sym::u16 | sym::u8 |
+                            sym::isize | sym::usize
+                            if base_ty_path.segments.len() == 1 => {
+                                return false;
+                            }
+                            _ => {}
+                        }
+                    }
+                }
+            }
+        }
 
         let msg = format!("you can convert an `{}` to `{}`", checked_ty, expected_ty);
         let cast_msg = format!("you can cast an `{} to `{}`", checked_ty, expected_ty);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 9c7ac83e82e..d92ce29f284 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3917,75 +3917,99 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
     ) -> bool {
-        match found.sty {
-            ty::FnDef(..) | ty::FnPtr(_) => {}
-            _ => return false,
-        }
         let hir = self.tcx.hir();
+        let (def_id, sig) = match found.sty {
+            ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)),
+            ty::Closure(def_id, substs) => {
+                // We don't use `closure_sig` to account for malformed closures like
+                // `|_: [_; continue]| {}` and instead we don't suggest anything.
+                let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
+                (def_id, match closure_sig_ty.sty {
+                    ty::FnPtr(sig) => sig,
+                    _ => return false,
+                })
+            }
+            _ => return false,
+        };
 
-        let sig = found.fn_sig(self.tcx);
         let sig = self
             .replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, &sig)
             .0;
         let sig = self.normalize_associated_types_in(expr.span, &sig);
-        if let Ok(_) = self.try_coerce(expr, sig.output(), expected, AllowTwoPhase::No) {
+        if self.can_coerce(sig.output(), expected) {
             let (mut sugg_call, applicability) = if sig.inputs().is_empty() {
                 (String::new(), Applicability::MachineApplicable)
             } else {
                 ("...".to_string(), Applicability::HasPlaceholders)
             };
             let mut msg = "call this function";
-            if let ty::FnDef(def_id, ..) = found.sty {
-                match hir.get_if_local(def_id) {
-                    Some(Node::Item(hir::Item {
-                        node: ItemKind::Fn(.., body_id),
-                        ..
-                    })) |
-                    Some(Node::ImplItem(hir::ImplItem {
-                        node: hir::ImplItemKind::Method(_, body_id),
-                        ..
-                    })) |
-                    Some(Node::TraitItem(hir::TraitItem {
-                        node: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)),
-                        ..
-                    })) => {
-                        let body = hir.body(*body_id);
-                        sugg_call = body.arguments.iter()
-                            .map(|arg| match &arg.pat.node {
-                                hir::PatKind::Binding(_, _, ident, None)
-                                if ident.name != kw::SelfLower => ident.to_string(),
-                                _ => "_".to_string(),
-                            }).collect::<Vec<_>>().join(", ");
+            match hir.get_if_local(def_id) {
+                Some(Node::Item(hir::Item {
+                    node: ItemKind::Fn(.., body_id),
+                    ..
+                })) |
+                Some(Node::ImplItem(hir::ImplItem {
+                    node: hir::ImplItemKind::Method(_, body_id),
+                    ..
+                })) |
+                Some(Node::TraitItem(hir::TraitItem {
+                    node: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)),
+                    ..
+                })) => {
+                    let body = hir.body(*body_id);
+                    sugg_call = body.arguments.iter()
+                        .map(|arg| match &arg.pat.node {
+                            hir::PatKind::Binding(_, _, ident, None)
+                            if ident.name != kw::SelfLower => ident.to_string(),
+                            _ => "_".to_string(),
+                        }).collect::<Vec<_>>().join(", ");
+                }
+                Some(Node::Expr(hir::Expr {
+                    node: ExprKind::Closure(_, _, body_id, closure_span, _),
+                    span: full_closure_span,
+                    ..
+                })) => {
+                    if *full_closure_span == expr.span {
+                        return false;
                     }
-                    Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
-                        sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                        match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) {
-                            Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
-                                msg = "instantiate this tuple variant";
-                            }
-                            Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => {
-                                msg = "instantiate this tuple struct";
-                            }
-                            _ => {}
+                    err.span_label(*closure_span, "closure defined here");
+                    msg = "call this closure";
+                    let body = hir.body(*body_id);
+                    sugg_call = body.arguments.iter()
+                        .map(|arg| match &arg.pat.node {
+                            hir::PatKind::Binding(_, _, ident, None)
+                            if ident.name != kw::SelfLower => ident.to_string(),
+                            _ => "_".to_string(),
+                        }).collect::<Vec<_>>().join(", ");
+                }
+                Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
+                    sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                    match hir.as_local_hir_id(def_id).and_then(|hir_id| hir.def_kind(hir_id)) {
+                        Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
+                            msg = "instantiate this tuple variant";
                         }
+                        Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => {
+                            msg = "instantiate this tuple struct";
+                        }
+                        _ => {}
                     }
-                    Some(Node::ForeignItem(hir::ForeignItem {
-                        node: hir::ForeignItemKind::Fn(_, idents, _),
-                        ..
-                    })) |
-                    Some(Node::TraitItem(hir::TraitItem {
-                        node: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)),
-                        ..
-                    })) => sugg_call = idents.iter()
-                            .map(|ident| if ident.name != kw::SelfLower {
-                                ident.to_string()
-                            } else {
-                                "_".to_string()
-                            }).collect::<Vec<_>>()
-                            .join(", "),
-                    _ => {}
                 }
-            };
+                Some(Node::ForeignItem(hir::ForeignItem {
+                    node: hir::ForeignItemKind::Fn(_, idents, _),
+                    ..
+                })) |
+                Some(Node::TraitItem(hir::TraitItem {
+                    node: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)),
+                    ..
+                })) => sugg_call = idents.iter()
+                        .map(|ident| if ident.name != kw::SelfLower {
+                            ident.to_string()
+                        } else {
+                            "_".to_string()
+                        }).collect::<Vec<_>>()
+                        .join(", "),
+                _ => {}
+            }
             if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) {
                 err.span_suggestion(
                     expr.span,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index c8c0f4ce36e..a6b56e4d597 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1209,9 +1209,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         }
     }
 
-    fn visit_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
-        self.cfg.configure_generic_params(params);
-        noop_visit_generic_params(params, self);
+   fn flat_map_generic_param(
+       &mut self,
+       param: ast::GenericParam
+    ) -> SmallVec<[ast::GenericParam; 1]>
+    {
+        let param = configure!(self, param);
+        noop_flat_map_generic_param(param, self)
     }
 
     fn visit_attribute(&mut self, at: &mut ast::Attribute) {
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 9785f8e2de0..414d234e434 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -98,8 +98,8 @@ pub trait MutVisitor: Sized {
         noop_visit_fn_header(header, self);
     }
 
-    fn visit_struct_field(&mut self, sf: &mut StructField) {
-        noop_visit_struct_field(sf, self);
+    fn flat_map_struct_field(&mut self, sf: StructField) -> SmallVec<[StructField; 1]> {
+        noop_flat_map_struct_field(sf, self)
     }
 
     fn visit_item_kind(&mut self, i: &mut ItemKind) {
@@ -130,8 +130,8 @@ pub trait MutVisitor: Sized {
         noop_flat_map_stmt(s, self)
     }
 
-    fn visit_arm(&mut self, a: &mut Arm) {
-        noop_visit_arm(a, self);
+    fn flat_map_arm(&mut self, arm: Arm) -> SmallVec<[Arm; 1]> {
+        noop_flat_map_arm(arm, self)
     }
 
     fn visit_pat(&mut self, p: &mut P<Pat>) {
@@ -174,8 +174,8 @@ pub trait MutVisitor: Sized {
         noop_visit_foreign_mod(nm, self);
     }
 
-    fn visit_variant(&mut self, v: &mut Variant) {
-        noop_visit_variant(v, self);
+    fn flat_map_variant(&mut self, v: Variant) -> SmallVec<[Variant; 1]>  {
+        noop_flat_map_variant(v, self)
     }
 
     fn visit_ident(&mut self, i: &mut Ident) {
@@ -225,8 +225,8 @@ pub trait MutVisitor: Sized {
         noop_visit_attribute(at, self);
     }
 
-    fn visit_arg(&mut self, a: &mut Arg) {
-        noop_visit_arg(a, self);
+    fn flat_map_arg(&mut self, arg: Arg) -> SmallVec<[Arg; 1]> {
+        noop_flat_map_arg(arg, self)
     }
 
     fn visit_generics(&mut self, generics: &mut Generics) {
@@ -245,12 +245,8 @@ pub trait MutVisitor: Sized {
         noop_visit_variant_data(vdata, self);
     }
 
-    fn visit_generic_param(&mut self, param: &mut GenericParam) {
-        noop_visit_generic_param(param, self);
-    }
-
-    fn visit_generic_params(&mut self, params: &mut Vec<GenericParam>) {
-        noop_visit_generic_params(params, self);
+    fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
+        noop_flat_map_generic_param(param, self)
     }
 
     fn visit_tt(&mut self, tt: &mut TokenTree) {
@@ -277,8 +273,8 @@ pub trait MutVisitor: Sized {
         noop_visit_mt(mt, self);
     }
 
-    fn visit_field(&mut self, field: &mut Field) {
-        noop_visit_field(field, self);
+    fn flat_map_field(&mut self, f: Field) -> SmallVec<[Field; 1]> {
+        noop_flat_map_field(f, self)
     }
 
     fn visit_where_clause(&mut self, where_clause: &mut WhereClause) {
@@ -300,6 +296,10 @@ pub trait MutVisitor: Sized {
     fn visit_span(&mut self, _sp: &mut Span) {
         // Do nothing.
     }
+
+    fn flat_map_field_pattern(&mut self, fp: FieldPat) -> SmallVec<[FieldPat; 1]> {
+        noop_flat_map_field_pattern(fp, self)
+    }
 }
 
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
@@ -362,6 +362,26 @@ pub fn visit_method_sig<T: MutVisitor>(MethodSig { header, decl }: &mut MethodSi
     vis.visit_fn_decl(decl);
 }
 
+pub fn noop_flat_map_field_pattern<T: MutVisitor>(
+    mut fp: FieldPat,
+    vis: &mut T,
+) -> SmallVec<[FieldPat; 1]> {
+    let FieldPat {
+        attrs,
+        id,
+        ident,
+        is_shorthand: _,
+        pat,
+        span,
+    } = &mut fp;
+    vis.visit_id(id);
+    vis.visit_ident(ident);
+    vis.visit_pat(pat);
+    vis.visit_span(span);
+    visit_thin_attrs(attrs, vis);
+    smallvec![fp]
+}
+
 pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
     let UseTree { prefix, kind, span } = use_tree;
     vis.visit_path(prefix);
@@ -382,16 +402,18 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_arm<T: MutVisitor>(
-    Arm { attrs, pats, guard, body, span, id }: &mut Arm,
+pub fn noop_flat_map_arm<T: MutVisitor>(
+    mut arm: Arm,
     vis: &mut T,
-) {
+) -> SmallVec<[Arm; 1]> {
+    let Arm { attrs, pats, guard, body, span, id } = &mut arm;
     visit_attrs(attrs, vis);
     vis.visit_id(id);
     visit_vec(pats, |pat| vis.visit_pat(pat));
     visit_opt(guard, |guard| vis.visit_expr(guard));
     vis.visit_expr(body);
     vis.visit_span(span);
+    smallvec![arm]
 }
 
 pub fn noop_visit_ty_constraint<T: MutVisitor>(
@@ -425,7 +447,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
         }
         TyKind::BareFn(bft) => {
             let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut();
-            vis.visit_generic_params(generic_params);
+            generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_fn_decl(decl);
         }
         TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)),
@@ -455,14 +477,17 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis:
     items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
 }
 
-pub fn noop_visit_variant<T: MutVisitor>(variant: &mut Variant, vis: &mut T) {
-    let Variant { ident, attrs, id, data, disr_expr, span } = variant;
+pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, vis: &mut T)
+    -> SmallVec<[Variant; 1]>
+{
+    let Variant { ident, attrs, id, data, disr_expr, span } = &mut variant;
     vis.visit_ident(ident);
     visit_attrs(attrs, vis);
     vis.visit_id(id);
     vis.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr));
     vis.visit_span(span);
+    smallvec![variant]
 }
 
 pub fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis: &mut T) {
@@ -562,12 +587,14 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) {
+pub fn noop_flat_map_arg<T: MutVisitor>(mut arg: Arg, vis: &mut T) -> SmallVec<[Arg; 1]> {
+    let Arg { attrs, id, pat, span, ty } = &mut arg;
     vis.visit_id(id);
     visit_thin_attrs(attrs, vis);
     vis.visit_pat(pat);
     vis.visit_span(span);
     vis.visit_ty(ty);
+    smallvec![arg]
 }
 
 pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
@@ -693,7 +720,7 @@ pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T)
 
 pub fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) {
     let FnDecl { inputs, output, c_variadic: _ } = decl.deref_mut();
-    visit_vec(inputs, |input| vis.visit_arg(input));
+    inputs.flat_map_in_place(|arg| vis.flat_map_arg(arg));
     match output {
         FunctionRetTy::Default(span) => vis.visit_span(span),
         FunctionRetTy::Ty(ty) => vis.visit_ty(ty),
@@ -707,8 +734,12 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
     }
 }
 
-pub fn noop_visit_generic_param<T: MutVisitor>(param: &mut GenericParam, vis: &mut T) {
-    let GenericParam { id, ident, attrs, bounds, kind } = param;
+pub fn noop_flat_map_generic_param<T: MutVisitor>(
+    mut param: GenericParam,
+    vis: &mut T
+) -> SmallVec<[GenericParam; 1]>
+{
+    let GenericParam { id, ident, attrs, bounds, kind } = &mut param;
     vis.visit_id(id);
     vis.visit_ident(ident);
     visit_thin_attrs(attrs, vis);
@@ -722,10 +753,7 @@ pub fn noop_visit_generic_param<T: MutVisitor>(param: &mut GenericParam, vis: &m
             vis.visit_ty(ty);
         }
     }
-}
-
-pub fn noop_visit_generic_params<T: MutVisitor>(params: &mut Vec<GenericParam>, vis: &mut T){
-    visit_vec(params, |param| vis.visit_generic_param(param));
+    smallvec![param]
 }
 
 pub fn noop_visit_label<T: MutVisitor>(Label { ident }: &mut Label, vis: &mut T) {
@@ -739,7 +767,7 @@ fn noop_visit_lifetime<T: MutVisitor>(Lifetime { id, ident }: &mut Lifetime, vis
 
 pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T) {
     let Generics { params, where_clause, span } = generics;
-    vis.visit_generic_params(params);
+    params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
     vis.visit_where_clause(where_clause);
     vis.visit_span(span);
 }
@@ -755,7 +783,7 @@ pub fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis:
         WherePredicate::BoundPredicate(bp) => {
             let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp;
             vis.visit_span(span);
-            vis.visit_generic_params(bound_generic_params);
+            bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_ty(bounded_ty);
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
         }
@@ -777,9 +805,11 @@ pub fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis:
 
 pub fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T) {
     match vdata {
-        VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)),
+        VariantData::Struct(fields, ..) => {
+            fields.flat_map_in_place(|field| vis.flat_map_struct_field(field));
+        },
         VariantData::Tuple(fields, id) => {
-            visit_vec(fields, |field| vis.visit_struct_field(field));
+            fields.flat_map_in_place(|field| vis.flat_map_struct_field(field));
             vis.visit_id(id);
         },
         VariantData::Unit(id) => vis.visit_id(id),
@@ -793,28 +823,32 @@ pub fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut Trait
 
 pub fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
     let PolyTraitRef { bound_generic_params, trait_ref, span } = p;
-    vis.visit_generic_params(bound_generic_params);
+    bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
     vis.visit_trait_ref(trait_ref);
     vis.visit_span(span);
 }
 
-pub fn noop_visit_struct_field<T: MutVisitor>(f: &mut StructField, visitor: &mut T) {
-    let StructField { span, ident, vis, id, ty, attrs } = f;
+pub fn noop_flat_map_struct_field<T: MutVisitor>(mut sf: StructField, visitor: &mut T)
+    -> SmallVec<[StructField; 1]>
+{
+    let StructField { span, ident, vis, id, ty, attrs } = &mut sf;
     visitor.visit_span(span);
     visit_opt(ident, |ident| visitor.visit_ident(ident));
     visitor.visit_vis(vis);
     visitor.visit_id(id);
     visitor.visit_ty(ty);
     visit_attrs(attrs, visitor);
+    smallvec![sf]
 }
 
-pub fn noop_visit_field<T: MutVisitor>(f: &mut Field, vis: &mut T) {
-    let Field { ident, expr, span, is_shorthand: _, attrs, id } = f;
+pub fn noop_flat_map_field<T: MutVisitor>(mut f: Field, vis: &mut T) -> SmallVec<[Field; 1]> {
+    let Field { ident, expr, span, is_shorthand: _, attrs, id } = &mut f;
     vis.visit_ident(ident);
     vis.visit_expr(expr);
     vis.visit_id(id);
     vis.visit_span(span);
     visit_thin_attrs(attrs, vis);
+    smallvec![f]
 }
 
 pub fn noop_visit_mt<T: MutVisitor>(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mut T) {
@@ -858,7 +892,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             vis.visit_generics(generics);
         }
         ItemKind::Enum(EnumDef { variants }, generics) => {
-            visit_vec(variants, |variant| vis.visit_variant(variant));
+            variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
             vis.visit_generics(generics);
         }
         ItemKind::Struct(variant_data, generics) |
@@ -1042,13 +1076,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
         }
         PatKind::Struct(path, fields, _etc) => {
             vis.visit_path(path);
-            for FieldPat { ident, pat, is_shorthand: _, attrs, id, span } in fields {
-                vis.visit_ident(ident);
-                vis.visit_id(id);
-                vis.visit_pat(pat);
-                visit_thin_attrs(attrs, vis);
-                vis.visit_span(span);
-            };
+            fields.flat_map_in_place(|field| vis.flat_map_field_pattern(field));
         }
         PatKind::Box(inner) => vis.visit_pat(inner),
         PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
@@ -1130,7 +1158,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
         }
         ExprKind::Match(expr, arms) => {
             vis.visit_expr(expr);
-            visit_vec(arms, |arm| vis.visit_arm(arm));
+            arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
         }
         ExprKind::Closure(_capture_by, asyncness, _movability, decl, body, span) => {
             vis.visit_asyncness(asyncness);
@@ -1193,7 +1221,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
         ExprKind::Mac(mac) => vis.visit_mac(mac),
         ExprKind::Struct(path, fields, expr) => {
             vis.visit_path(path);
-            visit_vec(fields, |field| vis.visit_field(field));
+            fields.flat_map_in_place(|field| vis.flat_map_field(field));
             visit_opt(expr, |expr| vis.visit_expr(expr));
         },
         ExprKind::Paren(expr) => {
diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs
index f17eb3b3943..a64fec70961 100644
--- a/src/libsyntax/util/node_count.rs
+++ b/src/libsyntax/util/node_count.rs
@@ -93,8 +93,7 @@ impl<'ast> Visitor<'ast> for NodeCounter {
         self.count += 1;
         walk_poly_trait_ref(self, t, m)
     }
-    fn visit_variant_data(&mut self, s: &VariantData, _: Ident,
-                          _: &Generics, _: NodeId, _: Span) {
+    fn visit_variant_data(&mut self, s: &VariantData) {
         self.count += 1;
         walk_struct_def(self, s)
     }
@@ -107,9 +106,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
         self.count += 1;
         walk_enum_def(self, enum_definition, generics, item_id)
     }
-    fn visit_variant(&mut self, v: &Variant, g: &Generics, item_id: NodeId) {
+    fn visit_variant(&mut self, v: &Variant) {
         self.count += 1;
-        walk_variant(self, v, g, item_id)
+        walk_variant(self, v)
     }
     fn visit_lifetime(&mut self, lifetime: &Lifetime) {
         self.count += 1;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 91b92d84a81..86f6d36c3c6 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -92,8 +92,7 @@ pub trait Visitor<'ast>: Sized {
     fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
         walk_poly_trait_ref(self, t, m)
     }
-    fn visit_variant_data(&mut self, s: &'ast VariantData, _: Ident,
-                          _: &'ast Generics, _: NodeId, _: Span) {
+    fn visit_variant_data(&mut self, s: &'ast VariantData) {
         walk_struct_def(self, s)
     }
     fn visit_struct_field(&mut self, s: &'ast StructField) { walk_struct_field(self, s) }
@@ -101,8 +100,8 @@ pub trait Visitor<'ast>: Sized {
                       generics: &'ast Generics, item_id: NodeId, _: Span) {
         walk_enum_def(self, enum_definition, generics, item_id)
     }
-    fn visit_variant(&mut self, v: &'ast Variant, g: &'ast Generics, item_id: NodeId) {
-        walk_variant(self, v, g, item_id)
+    fn visit_variant(&mut self, v: &'ast Variant) {
+        walk_variant(self, v)
     }
     fn visit_label(&mut self, label: &'ast Label) {
         walk_label(self, label)
@@ -163,6 +162,12 @@ pub trait Visitor<'ast>: Sized {
     fn visit_fn_header(&mut self, _header: &'ast FnHeader) {
         // Nothing to do
     }
+    fn visit_field(&mut self, f: &'ast Field) {
+        walk_field(self, f)
+    }
+    fn visit_field_pattern(&mut self, fp: &'ast FieldPat) {
+        walk_field_pattern(self, fp)
+    }
 }
 
 #[macro_export]
@@ -280,8 +285,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
         ItemKind::Struct(ref struct_definition, ref generics) |
         ItemKind::Union(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
-            visitor.visit_variant_data(struct_definition, item.ident,
-                                     generics, item.id, item.span);
+            visitor.visit_variant_data(struct_definition);
         }
         ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
@@ -300,24 +304,32 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
 
 pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V,
                                  enum_definition: &'a EnumDef,
-                                 generics: &'a Generics,
-                                 item_id: NodeId) {
-    walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id);
+                                 _: &'a Generics,
+                                 _: NodeId) {
+    walk_list!(visitor, visit_variant, &enum_definition.variants);
 }
 
-pub fn walk_variant<'a, V>(visitor: &mut V,
-                           variant: &'a Variant,
-                           generics: &'a Generics,
-                           item_id: NodeId)
+pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
     where V: Visitor<'a>,
 {
     visitor.visit_ident(variant.ident);
-    visitor.visit_variant_data(&variant.data, variant.ident,
-                             generics, item_id, variant.span);
+    visitor.visit_variant_data(&variant.data);
     walk_list!(visitor, visit_anon_const, &variant.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.attrs);
 }
 
+pub fn walk_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a Field) {
+    visitor.visit_expr(&f.expr);
+    visitor.visit_ident(f.ident);
+    walk_list!(visitor, visit_attribute, f.attrs.iter());
+}
+
+pub fn walk_field_pattern<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a FieldPat) {
+    visitor.visit_ident(fp.ident);
+    visitor.visit_pat(&fp.pat);
+    walk_list!(visitor, visit_attribute, fp.attrs.iter());
+}
+
 pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
     match typ.node {
         TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => {
@@ -441,11 +453,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
         }
         PatKind::Struct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id);
-            for field in fields {
-                walk_list!(visitor, visit_attribute, field.attrs.iter());
-                visitor.visit_ident(field.ident);
-                visitor.visit_pat(&field.pat)
-            }
+            walk_list!(visitor, visit_field_pattern, fields);
         }
         PatKind::Box(ref subpattern) |
         PatKind::Ref(ref subpattern, _) |
@@ -686,11 +694,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         }
         ExprKind::Struct(ref path, ref fields, ref optional_base) => {
             visitor.visit_path(path, expression.id);
-            for field in fields {
-                walk_list!(visitor, visit_attribute, field.attrs.iter());
-                visitor.visit_ident(field.ident);
-                visitor.visit_expr(&field.expr)
-            }
+            walk_list!(visitor, visit_field, fields);
             walk_list!(visitor, visit_expr, optional_base);
         }
         ExprKind::Tup(ref subexpressions) => {
diff --git a/src/test/ui/borrowck/move-error-snippets-ext.rs b/src/test/ui/borrowck/move-error-snippets-ext.rs
new file mode 100644
index 00000000000..c77f6c8276e
--- /dev/null
+++ b/src/test/ui/borrowck/move-error-snippets-ext.rs
@@ -0,0 +1,7 @@
+// ignore-test
+
+macro_rules! aaa {
+    ($c:ident) => {{
+        let a = $c;
+    }}
+}
diff --git a/src/test/ui/borrowck/move-error-snippets.rs b/src/test/ui/borrowck/move-error-snippets.rs
new file mode 100644
index 00000000000..64f95653828
--- /dev/null
+++ b/src/test/ui/borrowck/move-error-snippets.rs
@@ -0,0 +1,23 @@
+// Test that we don't ICE after trying to construct a cross-file snippet #63800.
+
+// compile-flags: --test
+
+#[macro_use]
+#[path = "move-error-snippets-ext.rs"]
+mod move_error_snippets_ext;
+
+struct A;
+
+macro_rules! sss {
+    () => {
+        #[test]
+        fn fff() {
+            static D: A = A;
+            aaa!(D);         //~ ERROR cannot move
+        }
+    };
+}
+
+sss!();
+
+fn main() {}
diff --git a/src/test/ui/borrowck/move-error-snippets.stderr b/src/test/ui/borrowck/move-error-snippets.stderr
new file mode 100644
index 00000000000..77463c48591
--- /dev/null
+++ b/src/test/ui/borrowck/move-error-snippets.stderr
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of static item `D`
+  --> $DIR/move-error-snippets.rs:16:18
+   |
+LL | | #[macro_use]
+   | |__________________^ move occurs because `D` has type `A`, which does not implement the `Copy` trait
+...
+LL |               aaa!(D);
+   |  __________________^
+...
+LL |   sss!();
+   |   ------- in this macro invocation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs
index 9b6b1074817..dd5af3e344c 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.rs
@@ -42,4 +42,6 @@ fn main() {
     let _: usize = X::bal; //~ ERROR mismatched types
     let _: usize = X.ban; //~ ERROR attempted to take value of method
     let _: usize = X.bal; //~ ERROR attempted to take value of method
+    let closure = || 42;
+    let _: usize = closure; //~ ERROR mismatched types
 }
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 0686b56f97d..28b331bdbdc 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -214,7 +214,21 @@ error[E0615]: attempted to take value of method `bal` on type `X`
 LL |     let _: usize = X.bal;
    |                      ^^^ help: use parentheses to call the method: `bal()`
 
-error: aborting due to 16 previous errors
+error[E0308]: mismatched types
+  --> $DIR/fn-or-tuple-struct-without-args.rs:46:20
+   |
+LL |     let closure = || 42;
+   |                   -- closure defined here
+LL |     let _: usize = closure;
+   |                    ^^^^^^^
+   |                    |
+   |                    expected usize, found closure
+   |                    help: use parentheses to call this closure: `closure()`
+   |
+   = note: expected type `usize`
+              found type `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:24]`
+
+error: aborting due to 17 previous errors
 
 Some errors have detailed explanations: E0308, E0423, E0615.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.rs b/src/test/ui/suggestions/mismatched-types-numeric-from.rs
new file mode 100644
index 00000000000..56549da9c73
--- /dev/null
+++ b/src/test/ui/suggestions/mismatched-types-numeric-from.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let _: u32 = i32::from(0_u8); //~ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/mismatched-types-numeric-from.stderr b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr
new file mode 100644
index 00000000000..223b6747322
--- /dev/null
+++ b/src/test/ui/suggestions/mismatched-types-numeric-from.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-numeric-from.rs:2:18
+   |
+LL |     let _: u32 = i32::from(0_u8);
+   |                  ^^^^^^^^^^^^^^^ expected u32, found i32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.