about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-06-10 22:01:37 +0000
committerbors <bors@rust-lang.org>2020-06-10 22:01:37 +0000
commitec42485ee95e3843a65b47533f6bcbcf06d9564e (patch)
treefea644a4f3a339e82ff54e9171bb5689aac3c500
parent449e8eaa286e407c9cd8cac655b77998fd53db6b (diff)
parent2b8f1eccaa138a2a4af61356231c33d7d93ed993 (diff)
downloadrust-ec42485ee95e3843a65b47533f6bcbcf06d9564e.tar.gz
rust-ec42485ee95e3843a65b47533f6bcbcf06d9564e.zip
Auto merge of #73206 - Dylan-DPC:rollup-rha9g8q, r=Dylan-DPC
Rollup of 9 pull requests

Successful merges:

 - #72706 (Add windows group to triagebot)
 - #72789 (resolve: Do not suggest imports from the same module in which we are resolving)
 - #72890 (improper ctypes: normalize return types and transparent structs)
 - #72897 (normalize adt fields during structural match checking)
 - #73005 (Don't create impl candidates when obligation contains errors)
 - #73023 (Remove noisy suggestion of hash_map )
 - #73070 (Add regression test for const generic ICE in #72819)
 - #73157 (Don't lose empty `where` clause when pretty-printing)
 - #73184 (Reoder order in which MinGW libs are linked to fix recent breakage)

Failed merges:

r? @ghost
-rw-r--r--src/librustc_ast/ast.rs11
-rw-r--r--src/librustc_ast/mut_visit.rs2
-rw-r--r--src/librustc_ast_pretty/pprust.rs8
-rw-r--r--src/librustc_builtin_macros/deriving/generic/ty.rs6
-rw-r--r--src/librustc_lint/types.rs100
-rw-r--r--src/librustc_middle/ty/mod.rs23
-rw-r--r--src/librustc_middle/ty/sty.rs5
-rw-r--r--src/librustc_parse/parser/generics.rs9
-rw-r--r--src/librustc_resolve/diagnostics.rs14
-rw-r--r--src/librustc_resolve/late/diagnostics.rs5
-rw-r--r--src/librustc_resolve/lib.rs3
-rw-r--r--src/librustc_target/spec/windows_gnu_base.rs2
-rw-r--r--src/librustc_trait_selection/traits/select/candidate_assembly.rs10
-rw-r--r--src/librustc_trait_selection/traits/select/mod.rs8
-rw-r--r--src/librustc_trait_selection/traits/structural_match.rs5
-rw-r--r--src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs20
-rw-r--r--src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr10
-rw-r--r--src/test/ui/derived-errors/issue-31997-1.stderr4
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.stderr4
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.rs2
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr188
-rw-r--r--src/test/ui/issues/issue-17546.stderr10
-rw-r--r--src/test/ui/issues/issue-72839-error-overflow.rs19
-rw-r--r--src/test/ui/issues/issue-72839-error-overflow.stderr9
-rw-r--r--src/test/ui/lexical-scopes.stderr5
-rw-r--r--src/test/ui/lint/lint-ctypes-66202.rs17
-rw-r--r--src/test/ui/match/issue-72896.rs23
-rw-r--r--src/test/ui/no-implicit-prelude-nested.stderr48
-rw-r--r--src/test/ui/no-implicit-prelude.stderr16
-rw-r--r--src/test/ui/proc-macro/empty-where-clause.rs18
-rw-r--r--src/test/ui/proc-macro/empty-where-clause.stderr21
-rw-r--r--src/test/ui/proc-macro/mixed-site-span.stderr4
-rw-r--r--src/test/ui/resolve/use_suggestion.stderr8
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.stderr4
-rw-r--r--triagebot.toml24
35 files changed, 350 insertions, 315 deletions
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index efcf95ec706..672ef108969 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -362,7 +362,11 @@ impl Default for Generics {
     fn default() -> Generics {
         Generics {
             params: Vec::new(),
-            where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP },
+            where_clause: WhereClause {
+                has_where_token: false,
+                predicates: Vec::new(),
+                span: DUMMY_SP,
+            },
             span: DUMMY_SP,
         }
     }
@@ -371,6 +375,11 @@ impl Default for Generics {
 /// A where-clause in a definition.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct WhereClause {
+    /// `true` if we ate a `where` token: this can happen
+    /// if we parsed no predicates (e.g. `struct Foo where {}
+    /// This allows us to accurately pretty-print
+    /// in `nt_to_tokenstream`
+    pub has_where_token: bool,
     pub predicates: Vec<WherePredicate>,
     pub span: Span,
 }
diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs
index 7ececb814a6..66b8d7f97f0 100644
--- a/src/librustc_ast/mut_visit.rs
+++ b/src/librustc_ast/mut_visit.rs
@@ -786,7 +786,7 @@ pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T)
 }
 
 pub fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
-    let WhereClause { predicates, span } = wc;
+    let WhereClause { has_where_token: _, predicates, span } = wc;
     visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
     vis.visit_span(span);
 }
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 872126646f3..8ff80df527c 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -2593,7 +2593,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
-        if where_clause.predicates.is_empty() {
+        if where_clause.predicates.is_empty() && !where_clause.has_where_token {
             return;
         }
 
@@ -2739,7 +2739,11 @@ impl<'a> State<'a> {
         }
         let generics = ast::Generics {
             params: Vec::new(),
-            where_clause: ast::WhereClause { predicates: Vec::new(), span: rustc_span::DUMMY_SP },
+            where_clause: ast::WhereClause {
+                has_where_token: false,
+                predicates: Vec::new(),
+                span: rustc_span::DUMMY_SP,
+            },
             span: rustc_span::DUMMY_SP,
         };
         let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
diff --git a/src/librustc_builtin_macros/deriving/generic/ty.rs b/src/librustc_builtin_macros/deriving/generic/ty.rs
index 62cbdb19a88..609feb6f259 100644
--- a/src/librustc_builtin_macros/deriving/generic/ty.rs
+++ b/src/librustc_builtin_macros/deriving/generic/ty.rs
@@ -216,7 +216,11 @@ fn mk_ty_param(
 }
 
 fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
-    Generics { params, where_clause: ast::WhereClause { predicates: Vec::new(), span }, span }
+    Generics {
+        params,
+        where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
+        span,
+    }
 }
 
 /// Lifetimes and bounds on type parameters
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 703c2a7a443..cdb0eda645a 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -6,7 +6,6 @@ use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, ExprKind, Node};
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{sign_extend, truncate};
@@ -511,10 +510,6 @@ enum FfiResult<'tcx> {
     FfiUnsafe { ty: Ty<'tcx>, reason: &'static str, help: Option<&'static str> },
 }
 
-fn is_zst<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, ty: Ty<'tcx>) -> bool {
-    tcx.layout_of(tcx.param_env(did).and(ty)).map(|layout| layout.is_zst()).unwrap_or(false)
-}
-
 fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.kind {
         ty::FnPtr(_) => true,
@@ -523,7 +518,7 @@ fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
             for field in field_def.all_fields() {
                 let field_ty =
                     tcx.normalize_erasing_regions(ParamEnv::reveal_all(), field.ty(tcx, substs));
-                if is_zst(tcx, field.did, field_ty) {
+                if field_ty.is_zst(tcx, field.did) {
                     continue;
                 }
 
@@ -653,32 +648,43 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
-                        // We can't completely trust repr(C) and repr(transparent) markings;
-                        // make sure the fields are actually safe.
-                        let mut all_phantom = true;
-                        for field in &def.non_enum_variant().fields {
-                            let field_ty = cx.normalize_erasing_regions(
-                                ParamEnv::reveal_all(),
-                                field.ty(cx, substs),
-                            );
-                            // repr(transparent) types are allowed to have arbitrary ZSTs, not just
-                            // PhantomData -- skip checking all ZST fields
-                            if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
-                                continue;
+                        if def.repr.transparent() {
+                            // Can assume that only one field is not a ZST, so only check
+                            // that field's type for FFI-safety.
+                            if let Some(field) =
+                                def.transparent_newtype_field(cx, self.cx.param_env)
+                            {
+                                let field_ty = cx.normalize_erasing_regions(
+                                    self.cx.param_env,
+                                    field.ty(cx, substs),
+                                );
+                                self.check_type_for_ffi(cache, field_ty)
+                            } else {
+                                FfiSafe
                             }
-                            let r = self.check_type_for_ffi(cache, field_ty);
-                            match r {
-                                FfiSafe => {
-                                    all_phantom = false;
-                                }
-                                FfiPhantom(..) => {}
-                                FfiUnsafe { .. } => {
-                                    return r;
+                        } else {
+                            // We can't completely trust repr(C) markings; make sure the fields are
+                            // actually safe.
+                            let mut all_phantom = true;
+                            for field in &def.non_enum_variant().fields {
+                                let field_ty = cx.normalize_erasing_regions(
+                                    self.cx.param_env,
+                                    field.ty(cx, substs),
+                                );
+                                let r = self.check_type_for_ffi(cache, field_ty);
+                                match r {
+                                    FfiSafe => {
+                                        all_phantom = false;
+                                    }
+                                    FfiPhantom(..) => {}
+                                    FfiUnsafe { .. } => {
+                                        return r;
+                                    }
                                 }
                             }
-                        }
 
-                        if all_phantom { FfiPhantom(ty) } else { FfiSafe }
+                            if all_phantom { FfiPhantom(ty) } else { FfiSafe }
+                        }
                     }
                     AdtKind::Union => {
                         if !def.repr.c() && !def.repr.transparent() {
@@ -708,7 +714,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             );
                             // repr(transparent) types are allowed to have arbitrary ZSTs, not just
                             // PhantomData -- skip checking all ZST fields.
-                            if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
+                            if def.repr.transparent() && field_ty.is_zst(cx, field.did) {
                                 continue;
                             }
                             let r = self.check_type_for_ffi(cache, field_ty);
@@ -774,7 +780,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                                 );
                                 // repr(transparent) types are allowed to have arbitrary ZSTs, not
                                 // just PhantomData -- skip checking all ZST fields.
-                                if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
+                                if def.repr.transparent() && field_ty.is_zst(cx, field.did) {
                                     continue;
                                 }
                                 let r = self.check_type_for_ffi(cache, field_ty);
@@ -946,7 +952,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
     }
 
-    fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>, is_static: bool) {
+    fn check_type_for_ffi_and_report_errors(
+        &mut self,
+        sp: Span,
+        ty: Ty<'tcx>,
+        is_static: bool,
+        is_return_type: bool,
+    ) {
         // We have to check for opaque types before `normalize_erasing_regions`,
         // which will replace opaque types with their underlying concrete type.
         if self.check_for_opaque_ty(sp, ty) {
@@ -957,19 +969,29 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         // it is only OK to use this function because extern fns cannot have
         // any generic types right now:
         let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
-        // C doesn't really support passing arrays by value.
-        // The only way to pass an array by value is through a struct.
-        // So we first test that the top level isn't an array,
-        // and then recursively check the types inside.
+
+        // C doesn't really support passing arrays by value - the only way to pass an array by value
+        // is through a struct. So, first test that the top level isn't an array, and then
+        // recursively check the types inside.
         if !is_static && self.check_for_array_ty(sp, ty) {
             return;
         }
 
+        // Don't report FFI errors for unit return types. This check exists here, and not in
+        // `check_foreign_fn` (where it would make more sense) so that normalization has definitely
+        // happened.
+        if is_return_type && ty.is_unit() {
+            return;
+        }
+
         match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
             FfiResult::FfiSafe => {}
             FfiResult::FfiPhantom(ty) => {
                 self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
             }
+            // If `ty` is a `repr(transparent)` newtype, and the non-zero-sized type is a generic
+            // argument, which after substitution, is `()`, then this branch can be hit.
+            FfiResult::FfiUnsafe { ty, .. } if is_return_type && ty.is_unit() => return,
             FfiResult::FfiUnsafe { ty, reason, help } => {
                 self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
             }
@@ -982,21 +1004,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(decl.inputs) {
-            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false);
+            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false, false);
         }
 
         if let hir::FnRetTy::Return(ref ret_hir) = decl.output {
             let ret_ty = sig.output();
-            if !ret_ty.is_unit() {
-                self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false);
-            }
+            self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false, true);
         }
     }
 
     fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
         let def_id = self.cx.tcx.hir().local_def_id(id);
         let ty = self.cx.tcx.type_of(def_id);
-        self.check_type_for_ffi_and_report_errors(span, ty, true);
+        self.check_type_for_ffi_and_report_errors(span, ty, true, false);
     }
 }
 
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index ffbe3a40297..caa1b4cb375 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -2390,6 +2390,29 @@ impl<'tcx> AdtDef {
     pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
         tcx.adt_sized_constraint(self.did).0
     }
+
+    /// `repr(transparent)` structs can have a single non-ZST field, this function returns that
+    /// field.
+    pub fn transparent_newtype_field(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+    ) -> Option<&FieldDef> {
+        assert!(self.is_struct() && self.repr.transparent());
+
+        for field in &self.non_enum_variant().fields {
+            let field_ty = tcx.normalize_erasing_regions(
+                param_env,
+                field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.did)),
+            );
+
+            if !field_ty.is_zst(tcx, self.did) {
+                return Some(field);
+            }
+        }
+
+        None
+    }
 }
 
 impl<'tcx> FieldDef {
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 5d4c2a54267..7550be39d4a 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -2186,6 +2186,11 @@ impl<'tcx> TyS<'tcx> {
             }
         }
     }
+
+    /// Is this a zero-sized type?
+    pub fn is_zst(&'tcx self, tcx: TyCtxt<'tcx>, did: DefId) -> bool {
+        tcx.layout_of(tcx.param_env(did).and(self)).map(|layout| layout.is_zst()).unwrap_or(false)
+    }
 }
 
 /// Typed constant value.
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index 8e8f864728c..04b64d93c70 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -157,6 +157,7 @@ impl<'a> Parser<'a> {
         Ok(ast::Generics {
             params,
             where_clause: WhereClause {
+                has_where_token: false,
                 predicates: Vec::new(),
                 span: self.prev_token.span.shrink_to_hi(),
             },
@@ -170,12 +171,16 @@ impl<'a> Parser<'a> {
     /// where T : Trait<U, V> + 'b, 'a : 'b
     /// ```
     pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
-        let mut where_clause =
-            WhereClause { predicates: Vec::new(), span: self.prev_token.span.shrink_to_hi() };
+        let mut where_clause = WhereClause {
+            has_where_token: false,
+            predicates: Vec::new(),
+            span: self.prev_token.span.shrink_to_hi(),
+        };
 
         if !self.eat_keyword(kw::Where) {
             return Ok(where_clause);
         }
+        where_clause.has_where_token = true;
         let lo = self.prev_token.span;
 
         // We are considering adding generics to the `where` keyword as an alternative higher-rank
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index cbb2878011c..bd2ce5a72e8 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -629,6 +629,7 @@ impl<'a> Resolver<'a> {
         &mut self,
         lookup_ident: Ident,
         namespace: Namespace,
+        parent_scope: &ParentScope<'a>,
         start_module: Module<'a>,
         crate_name: Ident,
         filter_fn: FilterFn,
@@ -655,7 +656,11 @@ impl<'a> Resolver<'a> {
                 }
 
                 // collect results based on the filter function
-                if ident.name == lookup_ident.name && ns == namespace {
+                // avoid suggesting anything from the same module in which we are resolving
+                if ident.name == lookup_ident.name
+                    && ns == namespace
+                    && !ptr::eq(in_module, parent_scope.module)
+                {
                     let res = name_binding.res();
                     if filter_fn(res) {
                         // create the path
@@ -680,7 +685,9 @@ impl<'a> Resolver<'a> {
                                 Res::Def(DefKind::Ctor(..), did) => this.parent(did),
                                 _ => res.opt_def_id(),
                             };
-                            candidates.push(ImportSuggestion { did, descr: res.descr(), path });
+                            if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
+                                candidates.push(ImportSuggestion { did, descr: res.descr(), path });
+                            }
                         }
                     }
                 }
@@ -722,6 +729,7 @@ impl<'a> Resolver<'a> {
         &mut self,
         lookup_ident: Ident,
         namespace: Namespace,
+        parent_scope: &ParentScope<'a>,
         filter_fn: FilterFn,
     ) -> Vec<ImportSuggestion>
     where
@@ -730,6 +738,7 @@ impl<'a> Resolver<'a> {
         let mut suggestions = self.lookup_import_candidates_from_module(
             lookup_ident,
             namespace,
+            parent_scope,
             self.graph_root,
             Ident::with_dummy_span(kw::Crate),
             &filter_fn,
@@ -754,6 +763,7 @@ impl<'a> Resolver<'a> {
                     suggestions.extend(self.lookup_import_candidates_from_module(
                         lookup_ident,
                         namespace,
+                        parent_scope,
                         crate_root,
                         ident,
                         &filter_fn,
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index b1a1f8725a1..ed7adefcb8c 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -212,7 +212,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
         let ident = path.last().unwrap().ident;
         let candidates = self
             .r
-            .lookup_import_candidates(ident, ns, is_expected)
+            .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
             .drain(..)
             .filter(|ImportSuggestion { did, .. }| {
                 match (did, res.and_then(|res| res.opt_def_id())) {
@@ -223,7 +223,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
             .collect::<Vec<_>>();
         let crate_def_id = DefId::local(CRATE_DEF_INDEX);
         if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
-            let enum_candidates = self.r.lookup_import_candidates(ident, ns, is_enum_variant);
+            let enum_candidates =
+                self.r.lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant);
             let mut enum_candidates = enum_candidates
                 .iter()
                 .map(|suggestion| import_candidate_to_enum_paths(&suggestion))
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 6bd73877fab..61792e039c7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2235,7 +2235,8 @@ impl<'a> Resolver<'a> {
                             Res::Def(DefKind::Mod, _) => true,
                             _ => false,
                         };
-                        let mut candidates = self.lookup_import_candidates(ident, TypeNS, is_mod);
+                        let mut candidates =
+                            self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
                         candidates.sort_by_cached_key(|c| {
                             (c.path.segments.len(), pprust::path_to_string(&c.path))
                         });
diff --git a/src/librustc_target/spec/windows_gnu_base.rs b/src/librustc_target/spec/windows_gnu_base.rs
index f556bf03f02..744f26239ca 100644
--- a/src/librustc_target/spec/windows_gnu_base.rs
+++ b/src/librustc_target/spec/windows_gnu_base.rs
@@ -20,9 +20,9 @@ pub fn opts() -> TargetOptions {
     late_link_args.insert(
         LinkerFlavor::Gcc,
         vec![
+            "-lmsvcrt".to_string(),
             "-lmingwex".to_string(),
             "-lmingw32".to_string(),
-            "-lmsvcrt".to_string(),
             // mingw's msvcrt is a weird hybrid import library and static library.
             // And it seems that the linker fails to use import symbols from msvcrt
             // that are required from functions in msvcrt in certain cases. For example
diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs
index d42c31a5474..9045451056b 100644
--- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs
+++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs
@@ -331,6 +331,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Result<(), SelectionError<'tcx>> {
         debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
 
+        // Essentially any user-written impl will match with an error type,
+        // so creating `ImplCandidates` isn't useful. However, we might
+        // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
+        // This helps us avoid overflow: see issue #72839
+        // Since compilation is already guaranteed to fail, this is just
+        // to try to show the 'nicest' possible errors to the user.
+        if obligation.references_error() {
+            return Ok(());
+        }
+
         self.tcx().for_each_relevant_impl(
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs
index def99a7b5b5..7ebf30f61c0 100644
--- a/src/librustc_trait_selection/traits/select/mod.rs
+++ b/src/librustc_trait_selection/traits/select/mod.rs
@@ -1104,6 +1104,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // who might care about this case, like coherence, should use
         // that function).
         if candidates.is_empty() {
+            // If there's an error type, 'downgrade' our result from
+            // `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
+            // emitting additional spurious errors, since we're guaranteed
+            // to have emitted at least one.
+            if stack.obligation.references_error() {
+                debug!("no results for error type, treating as ambiguous");
+                return Ok(None);
+            }
             return Err(Unimplemented);
         }
 
diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
index b877049fcf6..87ff667b6a0 100644
--- a/src/librustc_trait_selection/traits/structural_match.rs
+++ b/src/librustc_trait_selection/traits/structural_match.rs
@@ -251,7 +251,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
         // fields of ADT.
         let tcx = self.tcx();
         for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
-            if field_ty.visit_with(self) {
+            let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
+            debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
+
+            if ty.visit_with(self) {
                 // found an ADT without structural-match; halt visiting!
                 assert!(self.found.is_some());
                 return true;
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs
new file mode 100644
index 00000000000..225593c3178
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs
@@ -0,0 +1,20 @@
+// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type
+// bounds.
+
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+struct Arr<const N: usize>
+where Assert::<{N < usize::max_value() / 2}>: IsTrue,
+//~^ ERROR constant expression depends on a generic parameter
+{
+}
+
+enum Assert<const CHECK: bool> {}
+
+trait IsTrue {}
+
+impl IsTrue for Assert<true> {}
+
+fn main() {
+    let x: Arr<{usize::max_value()}> = Arr {};
+}
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr
new file mode 100644
index 00000000000..a9f664d0ac8
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr
@@ -0,0 +1,10 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-72819-generic-in-const-eval.rs:7:47
+   |
+LL | where Assert::<{N < usize::max_value() / 2}>: IsTrue,
+   |                                               ^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/derived-errors/issue-31997-1.stderr b/src/test/ui/derived-errors/issue-31997-1.stderr
index a4daf86cc8a..229c5c9e80f 100644
--- a/src/test/ui/derived-errors/issue-31997-1.stderr
+++ b/src/test/ui/derived-errors/issue-31997-1.stderr
@@ -4,12 +4,10 @@ error[E0433]: failed to resolve: use of undeclared type or module `HashMap`
 LL |     let mut map = HashMap::new();
    |                   ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index c0539434d02..990210ffb6b 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -16,9 +16,7 @@ LL |         Vec::new();
    |         ^^^ not found in this scope
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing one of these items
-   |
-LL |     use std::prelude::v1::Vec;
+help: consider importing this struct
    |
 LL |     use std::vec::Vec;
    |
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index a6012835f44..087f4582b21 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -11,8 +11,6 @@ fn main() {
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
-    //~| ERROR cycle detected
-    //~| ERROR cycle detected
     send(cycle2().clone());
     //~^ ERROR cannot be sent between threads safely
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 64d02f07048..679b26efe59 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires computing type of `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:22:16
+  --> $DIR/auto-trait-leak.rs:20:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,178 +84,8 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error[E0391]: cycle detected when computing type of `cycle1::{{opaque}}#0`
-  --> $DIR/auto-trait-leak.rs:12:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires computing type of `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:22:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `cycle1::{{opaque}}#0`, completing the cycle
-note: cycle used when checking item types in top-level module
-  --> $DIR/auto-trait-leak.rs:1:1
-   |
-LL | / use std::cell::Cell;
-LL | | use std::rc::Rc;
-LL | |
-LL | | fn send<T: Send>(_: T) {}
-...  |
-LL | |     Rc::new(String::from("foo"))
-LL | | }
-   | |_^
-
-error[E0391]: cycle detected when computing type of `cycle1::{{opaque}}#0`
-  --> $DIR/auto-trait-leak.rs:12:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires computing type of `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:22:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `cycle1::{{opaque}}#0`, completing the cycle
-note: cycle used when checking item types in top-level module
-  --> $DIR/auto-trait-leak.rs:1:1
-   |
-LL | / use std::cell::Cell;
-LL | | use std::rc::Rc;
-LL | |
-LL | | fn send<T: Send>(_: T) {}
-...  |
-LL | |     Rc::new(String::from("foo"))
-LL | | }
-   | |_^
-
 error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:16:5
+  --> $DIR/auto-trait-leak.rs:14:5
    |
 LL | fn send<T: Send>(_: T) {}
    |            ---- required by this bound in `send`
@@ -269,7 +99,7 @@ LL | fn cycle2() -> impl Clone {
    = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
    = note: required because it appears within the type `impl std::clone::Clone`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0391.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 8bf40790f0b..95939cf6b38 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -30,11 +30,10 @@ LL |     use std::fmt::Result;
    |
 LL |     use std::io::Result;
    |
-LL |     use std::prelude::v1::Result;
-   |
 LL |     use std::result::Result;
    |
-     and 1 other candidate
+LL |     use std::thread::Result;
+   |
 
 error[E0573]: expected type, found variant `Result`
   --> $DIR/issue-17546.rs:30:13
@@ -48,11 +47,10 @@ LL | use std::fmt::Result;
    |
 LL | use std::io::Result;
    |
-LL | use std::prelude::v1::Result;
-   |
 LL | use std::result::Result;
    |
-     and 1 other candidate
+LL | use std::thread::Result;
+   |
 
 error[E0573]: expected type, found variant `NoResult`
   --> $DIR/issue-17546.rs:35:15
diff --git a/src/test/ui/issues/issue-72839-error-overflow.rs b/src/test/ui/issues/issue-72839-error-overflow.rs
new file mode 100644
index 00000000000..6562d228409
--- /dev/null
+++ b/src/test/ui/issues/issue-72839-error-overflow.rs
@@ -0,0 +1,19 @@
+// Regression test for issue #72839
+// Tests that we do not overflow during trait selection after
+// a type error occurs
+use std::ops::Rem;
+trait Foo {}
+struct MyStruct<T>(T);
+
+impl<T, U> Rem<MyStruct<T>> for MyStruct<U> where MyStruct<U>: Rem<MyStruct<T>> {
+    type Output = u8;
+    fn rem(self, _: MyStruct<T>) -> Self::Output {
+        panic!()
+    }
+}
+
+fn main() {}
+
+fn foo() {
+    if missing_var % 8 == 0 {} //~ ERROR cannot find
+}
diff --git a/src/test/ui/issues/issue-72839-error-overflow.stderr b/src/test/ui/issues/issue-72839-error-overflow.stderr
new file mode 100644
index 00000000000..c4b6f90ca69
--- /dev/null
+++ b/src/test/ui/issues/issue-72839-error-overflow.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `missing_var` in this scope
+  --> $DIR/issue-72839-error-overflow.rs:18:8
+   |
+LL |     if missing_var % 8 == 0 {}
+   |        ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index dce70545170..1e6a35ed479 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -3,11 +3,6 @@ error[E0574]: expected struct, variant or union type, found type parameter `T`
    |
 LL |     let t = T { i: 0 };
    |             ^ not a struct, variant or union type
-   |
-help: consider importing this struct instead
-   |
-LL | use T;
-   |
 
 error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope
   --> $DIR/lexical-scopes.rs:10:10
diff --git a/src/test/ui/lint/lint-ctypes-66202.rs b/src/test/ui/lint/lint-ctypes-66202.rs
new file mode 100644
index 00000000000..ebab41d143e
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-66202.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![deny(improper_ctypes)]
+
+// This test checks that return types are normalized before being checked for FFI-safety, and that
+// transparent newtype wrappers are FFI-safe if the type being wrapped is FFI-safe.
+
+#[repr(transparent)]
+pub struct W<T>(T);
+
+extern "C" {
+    pub fn bare() -> ();
+    pub fn normalize() -> <() as ToOwned>::Owned;
+    pub fn transparent() -> W<()>;
+}
+
+fn main() {}
diff --git a/src/test/ui/match/issue-72896.rs b/src/test/ui/match/issue-72896.rs
new file mode 100644
index 00000000000..3a8b8203731
--- /dev/null
+++ b/src/test/ui/match/issue-72896.rs
@@ -0,0 +1,23 @@
+// run-pass
+trait EnumSetType {
+    type Repr;
+}
+
+enum Enum8 { }
+impl EnumSetType for Enum8 {
+    type Repr = u8;
+}
+
+#[derive(PartialEq, Eq)]
+struct EnumSet<T: EnumSetType> {
+    __enumset_underlying: T::Repr,
+}
+
+const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
+
+fn main() {
+    match CONST_SET {
+        CONST_SET => { /* ok */ }
+        _ => panic!("match fell through?"),
+    }
+}
diff --git a/src/test/ui/no-implicit-prelude-nested.stderr b/src/test/ui/no-implicit-prelude-nested.stderr
index 8a26366d751..198b630c52c 100644
--- a/src/test/ui/no-implicit-prelude-nested.stderr
+++ b/src/test/ui/no-implicit-prelude-nested.stderr
@@ -15,12 +15,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |         impl Clone for Test {}
    |              ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL |         use std::clone::Clone;
    |
-LL |         use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:13:14
@@ -28,12 +26,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |         impl Iterator for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL |         use std::iter::Iterator;
    |
-LL |         use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:14:14
@@ -41,9 +37,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |         impl ToString for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL |         use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL |         use std::string::ToString;
    |
@@ -60,12 +54,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |             drop(2)
    |             ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL |         use std::mem::drop;
    |
-LL |         use std::prelude::v1::drop;
-   |
 
 error[E0405]: cannot find trait `Add` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:23:10
@@ -84,12 +76,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |     impl Clone for Test {}
    |          ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL |     use std::clone::Clone;
    |
-LL |     use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:25:10
@@ -97,12 +87,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |     impl Iterator for Test {}
    |          ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL |     use std::iter::Iterator;
    |
-LL |     use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:26:10
@@ -110,9 +98,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |     impl ToString for Test {}
    |          ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL |     use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL |     use std::string::ToString;
    |
@@ -129,12 +115,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |         drop(2)
    |         ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL |     use std::mem::drop;
    |
-LL |     use std::prelude::v1::drop;
-   |
 
 error[E0405]: cannot find trait `Add` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:38:14
@@ -153,12 +137,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |         impl Clone for Test {}
    |              ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL |         use std::clone::Clone;
    |
-LL |         use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:40:14
@@ -166,12 +148,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |         impl Iterator for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL |         use std::iter::Iterator;
    |
-LL |         use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:41:14
@@ -179,9 +159,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |         impl ToString for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL |         use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL |         use std::string::ToString;
    |
@@ -198,12 +176,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |             drop(2)
    |             ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL |         use std::mem::drop;
    |
-LL |         use std::prelude::v1::drop;
-   |
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/no-implicit-prelude.stderr b/src/test/ui/no-implicit-prelude.stderr
index 9cda4f64c79..36a9b65b7d1 100644
--- a/src/test/ui/no-implicit-prelude.stderr
+++ b/src/test/ui/no-implicit-prelude.stderr
@@ -15,12 +15,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL | impl Clone for Test {}
    |      ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL | use std::clone::Clone;
    |
-LL | use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude.rs:12:6
@@ -28,12 +26,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL | impl Iterator for Test {}
    |      ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL | use std::iter::Iterator;
    |
-LL | use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude.rs:13:6
@@ -41,9 +37,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL | impl ToString for Test {}
    |      ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL | use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL | use std::string::ToString;
    |
@@ -60,12 +54,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |     drop(2)
    |     ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL | use std::mem::drop;
    |
-LL | use std::prelude::v1::drop;
-   |
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/proc-macro/empty-where-clause.rs b/src/test/ui/proc-macro/empty-where-clause.rs
new file mode 100644
index 00000000000..719555c092a
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-where-clause.rs
@@ -0,0 +1,18 @@
+// aux-build:test-macros.rs
+
+extern crate test_macros;
+use test_macros::recollect_attr;
+
+#[recollect_attr]
+struct FieldStruct where {
+    field: MissingType1 //~ ERROR cannot find
+}
+
+#[recollect_attr]
+struct TupleStruct(MissingType2) where; //~ ERROR cannot find
+
+enum MyEnum where {
+    Variant(MissingType3) //~ ERROR cannot find
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/empty-where-clause.stderr b/src/test/ui/proc-macro/empty-where-clause.stderr
new file mode 100644
index 00000000000..192a2b30f0d
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-where-clause.stderr
@@ -0,0 +1,21 @@
+error[E0412]: cannot find type `MissingType1` in this scope
+  --> $DIR/empty-where-clause.rs:8:12
+   |
+LL |     field: MissingType1
+   |            ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType2` in this scope
+  --> $DIR/empty-where-clause.rs:12:20
+   |
+LL | struct TupleStruct(MissingType2) where;
+   |                    ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType3` in this scope
+  --> $DIR/empty-where-clause.rs:15:13
+   |
+LL |     Variant(MissingType3)
+   |             ^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr
index 2b851a76f6a..6244ffc47a6 100644
--- a/src/test/ui/proc-macro/mixed-site-span.stderr
+++ b/src/test/ui/proc-macro/mixed-site-span.stderr
@@ -27,10 +27,6 @@ LL | pass_dollar_crate!();
    | ^^^^^^^^^^^^^^^^^^^^^ not found in `$crate`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing this struct
-   |
-LL | use ItemUse;
-   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/resolve/use_suggestion.stderr b/src/test/ui/resolve/use_suggestion.stderr
index 2fd3d5dccd2..72dda940729 100644
--- a/src/test/ui/resolve/use_suggestion.stderr
+++ b/src/test/ui/resolve/use_suggestion.stderr
@@ -10,12 +10,10 @@ error[E0433]: failed to resolve: use of undeclared type or module `HashMap`
 LL |     let x1 = HashMap::new();
    |              ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error[E0412]: cannot find type `HashMap` in this scope
   --> $DIR/use_suggestion.rs:5:13
@@ -23,12 +21,10 @@ error[E0412]: cannot find type `HashMap` in this scope
 LL |     let y1: HashMap;
    |             ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error[E0412]: cannot find type `GooMap` in this scope
   --> $DIR/use_suggestion.rs:6:13
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
index 9c337f515ad..3f91760fe21 100644
--- a/src/test/ui/resolve/use_suggestion_placement.stderr
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -26,12 +26,10 @@ error[E0412]: cannot find type `HashMap` in this scope
 LL |     type Dict<K, V> = HashMap<K, V>;
    |                       ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error: aborting due to 3 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index e43cff55386..0895bafb4d1 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -20,7 +20,7 @@ Hey LLVM ICE-breakers! This bug has been identified as a good
 [instructions] for tackling these sorts of bugs. Maybe take a look?
 Thanks! <3
 
-[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/llvm.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/llvm.html
 """
 label = "ICEBreaker-LLVM"
 
@@ -32,10 +32,30 @@ Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
 [instructions] for tackling these sorts of bugs. Maybe take a look?
 Thanks! <3
 
-[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/cleanup-crew.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/cleanup-crew.html
 """
 label = "ICEBreaker-Cleanup-Crew"
 
+[ping.windows]
+message = """\
+Hey Windows Group! This bug has been identified as a good "Windows candidate".
+In case it's useful, here are some [instructions] for tackling these sorts of
+bugs. Maybe take a look?
+Thanks! <3
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/windows.html
+"""
+label = "O-windows"
+
+[ping.arm]
+message = """\
+Hey ARM Group! This bug has been identified as a good "ARM candidate".
+In case it's useful, here are some [instructions] for tackling these sorts of
+bugs. Maybe take a look?
+Thanks! <3
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/arm.html
+"""
+label = "O-ARM"
+
 [prioritize]
 label = "I-prioritize"
 prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"]