about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-27 21:36:42 +0000
committerbors <bors@rust-lang.org>2022-03-27 21:36:42 +0000
commit62523045ec681ee8c2ecb8d395fbcaccf336284b (patch)
tree70b78bc300ece7730925ac2914c0660d69395d38
parentab0c2e18dceb7140626a158affb983ae81039bd0 (diff)
parenteca25311558ed55825189afb2af6a7ea47e3a564 (diff)
downloadrust-62523045ec681ee8c2ecb8d395fbcaccf336284b.tar.gz
rust-62523045ec681ee8c2ecb8d395fbcaccf336284b.zip
Auto merge of #95382 - Dylan-DPC:rollup-bebyfd1, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #94939 (diagnostics: suggest missing comma in bad FRU syntax)
 - #95120 (Implement `apply_switch_int_edge_effects` for backward analyses)
 - #95364 (Add long error explanation for E0667)
 - #95366 (Remove test files with duplicated checksums)
 - #95368 (Fix typo in `String::try_reserve_exact` docs)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0667.md18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs13
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs82
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs62
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs60
-rw-r--r--library/alloc/src/string.rs2
-rw-r--r--src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs9
-rw-r--r--src/test/ui/abi/auxiliary/foreign_lib.rs37
-rw-r--r--src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs9
-rw-r--r--src/test/ui/abi/cross-crate/duplicated-external-mods.rs (renamed from src/test/ui/abi/duplicated-external-mods.rs)0
-rw-r--r--src/test/ui/abi/foreign/invoke-external-foreign.rs (renamed from src/test/ui/abi/invoke-external-foreign.rs)0
-rw-r--r--src/test/ui/consts/auxiliary/cci_borrow_lib.rs3
-rw-r--r--src/test/ui/consts/auxiliary/cci_const.rs6
-rw-r--r--src/test/ui/cross-crate/const-cross-crate-const.rs (renamed from src/test/ui/consts/const-cross-crate-const.rs)0
-rw-r--r--src/test/ui/cross-crate/const-cross-crate-extern.rs (renamed from src/test/ui/consts/const-cross-crate-extern.rs)0
-rw-r--r--src/test/ui/impl-trait/impl_trait_projections.stderr3
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr1
-rw-r--r--src/test/ui/structs/struct-record-suggestion.fixed16
-rw-r--r--src/test/ui/structs/struct-record-suggestion.rs16
-rw-r--r--src/test/ui/structs/struct-record-suggestion.stderr24
23 files changed, 287 insertions, 80 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index a185902123d..61a177f291b 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -394,6 +394,7 @@ E0663: include_str!("./error_codes/E0663.md"),
 E0664: include_str!("./error_codes/E0664.md"),
 E0665: include_str!("./error_codes/E0665.md"),
 E0666: include_str!("./error_codes/E0666.md"),
+E0667: include_str!("./error_codes/E0667.md"),
 E0668: include_str!("./error_codes/E0668.md"),
 E0669: include_str!("./error_codes/E0669.md"),
 E0670: include_str!("./error_codes/E0670.md"),
@@ -633,7 +634,6 @@ E0787: include_str!("./error_codes/E0787.md"),
            // attribute
     E0640, // infer outlives requirements
 //  E0645, // trait aliases not finished
-    E0667, // `impl Trait` in projections
 //  E0694, // an unknown tool name found in scoped attributes
 //  E0702, // replaced with a generic attribute input check
 //  E0707, // multiple elided lifetimes used in arguments of `async fn`
diff --git a/compiler/rustc_error_codes/src/error_codes/E0667.md b/compiler/rustc_error_codes/src/error_codes/E0667.md
new file mode 100644
index 00000000000..0709a24c433
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0667.md
@@ -0,0 +1,18 @@
+`impl Trait` is not allowed in path parameters.
+
+Erroneous code example:
+
+```compile_fail,E0667
+fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error!
+    x.next().unwrap()
+}
+```
+
+You cannot use `impl Trait` in path parameters. If you want something
+equivalent, you can do this instead:
+
+```
+fn some_fn<T: Iterator>(mut x: T) -> T::Item { // ok!
+    x.next().unwrap()
+}
+```
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index ea71cff1616..eec6eed311b 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -45,6 +45,7 @@ use std::{iter, mem, option};
 use self::graph_cyclic_cache::GraphIsCyclicCache;
 use self::predecessors::{PredecessorCache, Predecessors};
 pub use self::query::*;
+use self::switch_sources::{SwitchSourceCache, SwitchSources};
 
 pub mod coverage;
 mod generic_graph;
@@ -58,6 +59,7 @@ mod predecessors;
 pub mod pretty;
 mod query;
 pub mod spanview;
+mod switch_sources;
 pub mod tcx;
 pub mod terminator;
 pub use terminator::*;
@@ -296,6 +298,7 @@ pub struct Body<'tcx> {
     pub is_polymorphic: bool,
 
     predecessor_cache: PredecessorCache,
+    switch_source_cache: SwitchSourceCache,
     is_cyclic: GraphIsCyclicCache,
 
     pub tainted_by_errors: Option<ErrorGuaranteed>,
@@ -344,6 +347,7 @@ impl<'tcx> Body<'tcx> {
             required_consts: Vec::new(),
             is_polymorphic: false,
             predecessor_cache: PredecessorCache::new(),
+            switch_source_cache: SwitchSourceCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
             tainted_by_errors,
         };
@@ -372,6 +376,7 @@ impl<'tcx> Body<'tcx> {
             var_debug_info: Vec::new(),
             is_polymorphic: false,
             predecessor_cache: PredecessorCache::new(),
+            switch_source_cache: SwitchSourceCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
             tainted_by_errors: None,
         };
@@ -392,6 +397,7 @@ impl<'tcx> Body<'tcx> {
         // FIXME: Use a finer-grained API for this, so only transformations that alter terminators
         // invalidate the caches.
         self.predecessor_cache.invalidate();
+        self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         &mut self.basic_blocks
     }
@@ -401,6 +407,7 @@ impl<'tcx> Body<'tcx> {
         &mut self,
     ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
         self.predecessor_cache.invalidate();
+        self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls)
     }
@@ -414,6 +421,7 @@ impl<'tcx> Body<'tcx> {
         &mut Vec<VarDebugInfo<'tcx>>,
     ) {
         self.predecessor_cache.invalidate();
+        self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
     }
@@ -542,6 +550,11 @@ impl<'tcx> Body<'tcx> {
     }
 
     #[inline]
+    pub fn switch_sources(&self) -> &SwitchSources {
+        self.switch_source_cache.compute(&self.basic_blocks)
+    }
+
+    #[inline]
     pub fn dominators(&self) -> Dominators<BasicBlock> {
         dominators(self)
     }
diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs
new file mode 100644
index 00000000000..7f62b4d0dba
--- /dev/null
+++ b/compiler/rustc_middle/src/mir/switch_sources.rs
@@ -0,0 +1,82 @@
+//! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after
+//! `Predecessors`/`PredecessorCache`.
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::OnceCell;
+use rustc_index::vec::IndexVec;
+use rustc_serialize as serialize;
+use smallvec::SmallVec;
+
+use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
+
+pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>;
+
+#[derive(Clone, Debug)]
+pub(super) struct SwitchSourceCache {
+    cache: OnceCell<SwitchSources>,
+}
+
+impl SwitchSourceCache {
+    #[inline]
+    pub(super) fn new() -> Self {
+        SwitchSourceCache { cache: OnceCell::new() }
+    }
+
+    /// Invalidates the switch source cache.
+    #[inline]
+    pub(super) fn invalidate(&mut self) {
+        self.cache = OnceCell::new();
+    }
+
+    /// Returns the switch sources for this MIR.
+    #[inline]
+    pub(super) fn compute(
+        &self,
+        basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
+    ) -> &SwitchSources {
+        self.cache.get_or_init(|| {
+            let mut switch_sources = IndexVec::from_elem(
+                IndexVec::from_elem(SmallVec::new(), basic_blocks),
+                basic_blocks,
+            );
+            for (bb, data) in basic_blocks.iter_enumerated() {
+                if let Some(Terminator {
+                    kind: TerminatorKind::SwitchInt { targets, .. }, ..
+                }) = &data.terminator
+                {
+                    for (value, target) in targets.iter() {
+                        switch_sources[target][bb].push(Some(value));
+                    }
+                    switch_sources[targets.otherwise()][bb].push(None);
+                }
+            }
+
+            switch_sources
+        })
+    }
+}
+
+impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache {
+    #[inline]
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_unit()
+    }
+}
+
+impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache {
+    #[inline]
+    fn decode(_: &mut D) -> Self {
+        Self::new()
+    }
+}
+
+impl<CTX> HashStable<CTX> for SwitchSourceCache {
+    #[inline]
+    fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
+        // do nothing
+    }
+}
+
+TrivialTypeFoldableAndLiftImpls! {
+    SwitchSourceCache,
+}
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 102e7439772..93118dfeb77 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -248,6 +248,7 @@ impl Direction for Backward {
                     );
                     propagate(pred, &tmp);
                 }
+
                 mir::TerminatorKind::InlineAsm {
                     destination: Some(dest), ref operands, ..
                 } if dest == bb => {
@@ -266,6 +267,23 @@ impl Direction for Backward {
                     propagate(pred, &tmp);
                 }
 
+                mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => {
+                    let mut applier = BackwardSwitchIntEdgeEffectsApplier {
+                        pred,
+                        exit_state,
+                        values: &body.switch_sources()[bb][pred],
+                        bb,
+                        propagate: &mut propagate,
+                        effects_applied: false,
+                    };
+
+                    analysis.apply_switch_int_edge_effects(pred, discr, &mut applier);
+
+                    if !applier.effects_applied {
+                        propagate(pred, exit_state)
+                    }
+                }
+
                 // Ignore dead unwinds.
                 mir::TerminatorKind::Call { cleanup: Some(unwind), .. }
                 | mir::TerminatorKind::Assert { cleanup: Some(unwind), .. }
@@ -286,6 +304,37 @@ impl Direction for Backward {
     }
 }
 
+struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> {
+    pred: BasicBlock,
+    exit_state: &'a mut D,
+    values: &'a [Option<u128>],
+    bb: BasicBlock,
+    propagate: &'a mut F,
+
+    effects_applied: bool,
+}
+
+impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, D, F>
+where
+    D: Clone,
+    F: FnMut(BasicBlock, &D),
+{
+    fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) {
+        assert!(!self.effects_applied);
+
+        let targets = self.values.iter().map(|&value| SwitchIntTarget { value, target: self.bb });
+
+        let mut tmp = None;
+        for target in targets {
+            let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state);
+            apply_edge_effect(tmp, target);
+            (self.propagate)(self.pred, tmp);
+        }
+
+        self.effects_applied = true;
+    }
+}
+
 /// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
 pub struct Forward;
 
@@ -528,7 +577,7 @@ impl Direction for Forward {
             }
 
             SwitchInt { ref targets, ref discr, switch_ty: _ } => {
-                let mut applier = SwitchIntEdgeEffectApplier {
+                let mut applier = ForwardSwitchIntEdgeEffectsApplier {
                     exit_state,
                     targets,
                     propagate,
@@ -537,8 +586,11 @@ impl Direction for Forward {
 
                 analysis.apply_switch_int_edge_effects(bb, discr, &mut applier);
 
-                let SwitchIntEdgeEffectApplier {
-                    exit_state, mut propagate, effects_applied, ..
+                let ForwardSwitchIntEdgeEffectsApplier {
+                    exit_state,
+                    mut propagate,
+                    effects_applied,
+                    ..
                 } = applier;
 
                 if !effects_applied {
@@ -551,7 +603,7 @@ impl Direction for Forward {
     }
 }
 
-struct SwitchIntEdgeEffectApplier<'a, D, F> {
+struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> {
     exit_state: &'a mut D,
     targets: &'a SwitchTargets,
     propagate: F,
@@ -559,7 +611,7 @@ struct SwitchIntEdgeEffectApplier<'a, D, F> {
     effects_applied: bool,
 }
 
-impl<D, F> super::SwitchIntEdgeEffects<D> for SwitchIntEdgeEffectApplier<'_, D, F>
+impl<D, F> super::SwitchIntEdgeEffects<D> for ForwardSwitchIntEdgeEffectsApplier<'_, D, F>
 where
     D: Clone,
     F: FnMut(BasicBlock, &D),
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index c51dd06de25..67c16e6c084 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -234,8 +234,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
     /// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the
     /// engine doesn't need to clone the exit state for a block unless
     /// `SwitchIntEdgeEffects::apply` is actually called.
-    ///
-    /// FIXME: This class of effects is not supported for backward dataflow analyses.
     fn apply_switch_int_edge_effects(
         &self,
         _block: BasicBlock,
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 6c2d1b85646..c221b358670 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -28,7 +28,7 @@ pub use self::drop_flag_effects::{
 pub use self::framework::{
     fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces,
     Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor,
-    ResultsRefCursor, ResultsVisitable, ResultsVisitor,
+    ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
 };
 
 use self::move_paths::MoveData;
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 0a720f15025..e5784259ce8 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -32,6 +32,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -1556,7 +1557,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if inaccessible_remaining_fields {
                 self.report_inaccessible_fields(adt_ty, span);
             } else {
-                self.report_missing_fields(adt_ty, span, remaining_fields);
+                self.report_missing_fields(
+                    adt_ty,
+                    span,
+                    remaining_fields,
+                    variant,
+                    ast_fields,
+                    substs,
+                );
             }
         }
     }
@@ -1590,6 +1598,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         adt_ty: Ty<'tcx>,
         span: Span,
         remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>,
+        variant: &'tcx ty::VariantDef,
+        ast_fields: &'tcx [hir::ExprField<'tcx>],
+        substs: SubstsRef<'tcx>,
     ) {
         let len = remaining_fields.len();
 
@@ -1615,7 +1626,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
-        struct_span_err!(
+        let mut err = struct_span_err!(
             self.tcx.sess,
             span,
             E0063,
@@ -1624,9 +1635,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             remaining_fields_names,
             truncated_fields_error,
             adt_ty
-        )
-        .span_label(span, format!("missing {}{}", remaining_fields_names, truncated_fields_error))
-        .emit();
+        );
+        err.span_label(
+            span,
+            format!("missing {}{}", remaining_fields_names, truncated_fields_error),
+        );
+
+        // If the last field is a range literal, but it isn't supposed to be, then they probably
+        // meant to use functional update syntax.
+        //
+        // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
+        if let Some((
+            last,
+            ExprKind::Struct(
+                QPath::LangItem(LangItem::Range, ..),
+                &[ref range_start, ref range_end],
+                _,
+            ),
+        )) = ast_fields.last().map(|last| (last, &last.expr.kind)) &&
+        let variant_field =
+            variant.fields.iter().find(|field| field.ident(self.tcx) == last.ident) &&
+        let range_def_id = self.tcx.lang_items().range_struct() &&
+        variant_field
+            .and_then(|field| field.ty(self.tcx, substs).ty_adt_def())
+            .map(|adt| adt.did())
+            != range_def_id
+        {
+            let instead = self
+                .tcx
+                .sess
+                .source_map()
+                .span_to_snippet(range_end.expr.span)
+                .map(|s| format!(" from `{s}`"))
+                .unwrap_or(String::new());
+            err.span_suggestion(
+                range_start.span.shrink_to_hi(),
+                &format!("to set the remaining fields{instead}, separate the last named field with a comma"),
+                ",".to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        }
+
+        err.emit();
     }
 
     /// Report an error for a struct field expression when there are invisible fields.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 71419c15196..71b6b9b41f5 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1038,7 +1038,7 @@ impl String {
     }
 
     /// Tries to reserve the minimum capacity for exactly `additional` more elements to
-    /// be inserted in the given `String`. After calling `reserve_exact`,
+    /// be inserted in the given `String`. After calling `try_reserve_exact`,
     /// capacity will be greater than or equal to `self.len() + additional`.
     /// Does nothing if the capacity is already sufficient.
     ///
diff --git a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
deleted file mode 100644
index 5cbf8093c5c..00000000000
--- a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![crate_name = "anonexternmod"]
-#![feature(rustc_private)]
-
-extern crate libc;
-
-#[link(name = "rust_test_helpers", kind = "static")]
-extern "C" {
-    pub fn rust_get_test_int() -> libc::intptr_t;
-}
diff --git a/src/test/ui/abi/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs
deleted file mode 100644
index 3c649b778bd..00000000000
--- a/src/test/ui/abi/auxiliary/foreign_lib.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![crate_name = "foreign_lib"]
-#![feature(rustc_private)]
-
-pub mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_get_test_int() -> libc::intptr_t;
-    }
-}
-
-pub mod rustrt2 {
-    extern crate libc;
-
-    extern "C" {
-        pub fn rust_get_test_int() -> libc::intptr_t;
-    }
-}
-
-pub mod rustrt3 {
-    // Different type, but same ABI (on all supported platforms).
-    // Ensures that we don't ICE or trigger LLVM asserts when
-    // importing the same symbol under different types.
-    // See https://github.com/rust-lang/rust/issues/32740.
-    extern "C" {
-        pub fn rust_get_test_int() -> *const u8;
-    }
-}
-
-pub fn local_uses() {
-    unsafe {
-        let x = rustrt::rust_get_test_int();
-        assert_eq!(x, rustrt2::rust_get_test_int());
-        assert_eq!(x as *const _, rustrt3::rust_get_test_int());
-    }
-}
diff --git a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
deleted file mode 100644
index 5cbf8093c5c..00000000000
--- a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![crate_name = "anonexternmod"]
-#![feature(rustc_private)]
-
-extern crate libc;
-
-#[link(name = "rust_test_helpers", kind = "static")]
-extern "C" {
-    pub fn rust_get_test_int() -> libc::intptr_t;
-}
diff --git a/src/test/ui/abi/duplicated-external-mods.rs b/src/test/ui/abi/cross-crate/duplicated-external-mods.rs
index 05a279a3014..05a279a3014 100644
--- a/src/test/ui/abi/duplicated-external-mods.rs
+++ b/src/test/ui/abi/cross-crate/duplicated-external-mods.rs
diff --git a/src/test/ui/abi/invoke-external-foreign.rs b/src/test/ui/abi/foreign/invoke-external-foreign.rs
index dbd2b4ad865..dbd2b4ad865 100644
--- a/src/test/ui/abi/invoke-external-foreign.rs
+++ b/src/test/ui/abi/foreign/invoke-external-foreign.rs
diff --git a/src/test/ui/consts/auxiliary/cci_borrow_lib.rs b/src/test/ui/consts/auxiliary/cci_borrow_lib.rs
deleted file mode 100644
index 7c57a1c6678..00000000000
--- a/src/test/ui/consts/auxiliary/cci_borrow_lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn foo(x: &usize) -> usize {
-    *x
-}
diff --git a/src/test/ui/consts/auxiliary/cci_const.rs b/src/test/ui/consts/auxiliary/cci_const.rs
deleted file mode 100644
index c83b3f4a5bb..00000000000
--- a/src/test/ui/consts/auxiliary/cci_const.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-pub extern "C" fn bar() {
-}
-
-pub const foopy: &'static str = "hi there";
-pub const uint_val: usize = 12;
-pub const uint_expr: usize = (1 << uint_val) - 1;
diff --git a/src/test/ui/consts/const-cross-crate-const.rs b/src/test/ui/cross-crate/const-cross-crate-const.rs
index 92020417ff5..92020417ff5 100644
--- a/src/test/ui/consts/const-cross-crate-const.rs
+++ b/src/test/ui/cross-crate/const-cross-crate-const.rs
diff --git a/src/test/ui/consts/const-cross-crate-extern.rs b/src/test/ui/cross-crate/const-cross-crate-extern.rs
index 3c61afd5bec..3c61afd5bec 100644
--- a/src/test/ui/consts/const-cross-crate-extern.rs
+++ b/src/test/ui/cross-crate/const-cross-crate-extern.rs
diff --git a/src/test/ui/impl-trait/impl_trait_projections.stderr b/src/test/ui/impl-trait/impl_trait_projections.stderr
index e85ed0eda52..82d2422c407 100644
--- a/src/test/ui/impl-trait/impl_trait_projections.stderr
+++ b/src/test/ui/impl-trait/impl_trait_projections.stderr
@@ -30,4 +30,5 @@ LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0223`.
+Some errors have detailed explanations: E0223, E0667.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
index f64545d83b8..e31393181d7 100644
--- a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
+++ b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
@@ -6,3 +6,4 @@ LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0667`.
diff --git a/src/test/ui/structs/struct-record-suggestion.fixed b/src/test/ui/structs/struct-record-suggestion.fixed
new file mode 100644
index 00000000000..48144cd1ce2
--- /dev/null
+++ b/src/test/ui/structs/struct-record-suggestion.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+#[derive(Debug, Default, Eq, PartialEq)]
+struct A {
+    b: u32,
+    c: u64,
+    d: usize,
+}
+
+fn main() {
+    let q = A { c: 5, .. Default::default() };
+    //~^ ERROR mismatched types
+    //~| ERROR missing fields
+    //~| HELP separate the last named field with a comma
+    let r = A { c: 5, .. Default::default() };
+    assert_eq!(q, r);
+}
diff --git a/src/test/ui/structs/struct-record-suggestion.rs b/src/test/ui/structs/struct-record-suggestion.rs
new file mode 100644
index 00000000000..6d169d5c6db
--- /dev/null
+++ b/src/test/ui/structs/struct-record-suggestion.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+#[derive(Debug, Default, Eq, PartialEq)]
+struct A {
+    b: u32,
+    c: u64,
+    d: usize,
+}
+
+fn main() {
+    let q = A { c: 5 .. Default::default() };
+    //~^ ERROR mismatched types
+    //~| ERROR missing fields
+    //~| HELP separate the last named field with a comma
+    let r = A { c: 5, .. Default::default() };
+    assert_eq!(q, r);
+}
diff --git a/src/test/ui/structs/struct-record-suggestion.stderr b/src/test/ui/structs/struct-record-suggestion.stderr
new file mode 100644
index 00000000000..e5bd03117b9
--- /dev/null
+++ b/src/test/ui/structs/struct-record-suggestion.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/struct-record-suggestion.rs:10:20
+   |
+LL |     let q = A { c: 5 .. Default::default() };
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::ops::Range`
+   |
+   = note: expected type `u64`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0063]: missing fields `b` and `d` in initializer of `A`
+  --> $DIR/struct-record-suggestion.rs:10:13
+   |
+LL |     let q = A { c: 5 .. Default::default() };
+   |             ^ missing `b` and `d`
+   |
+help: to set the remaining fields from `Default::default()`, separate the last named field with a comma
+   |
+LL |     let q = A { c: 5, .. Default::default() };
+   |                     +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0063, E0308.
+For more information about an error, try `rustc --explain E0063`.