]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #107608 - P1n3appl3:master, r=tmandry
authorMatthias Krüger <matthias.krueger@famsik.de>
Fri, 3 Feb 2023 05:30:25 +0000 (06:30 +0100)
committerGitHub <noreply@github.com>
Fri, 3 Feb 2023 05:30:25 +0000 (06:30 +0100)
Use triple rather than arch for fuchsia test-runner

This allows the user of the test-runner script to specify a full triple rather than just an architecture which helps with the transition from the two component to three component target triples for fuchsia.

87 files changed:
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_error_messages/locales/en-US/parse.ftl
compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
compiler/rustc_hir_typeck/src/mem_categorization.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/typeck_results.rs
compiler/rustc_mir_transform/src/copy_prop.rs
compiler/rustc_parse/src/errors.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/pat.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_parse_format/src/lib.rs
compiler/rustc_passes/src/hir_id_validator.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/ident.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/edition.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
config.toml.example
library/core/benches/char/methods.rs
library/core/benches/num/flt2dec/strategy/dragon.rs
library/core/benches/num/flt2dec/strategy/grisu.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/defaults/config.compiler.toml
src/bootstrap/defaults/config.library.toml
src/librustdoc/clean/mod.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/visit_ast.rs
tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff [new file with mode: 0644]
tests/mir-opt/copy-prop/issue_107511.rs [new file with mode: 0644]
tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
tests/mir-opt/issue_101973.inner.ConstProp.diff
tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
tests/mir-opt/simplify_match.main.ConstProp.diff
tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff
tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff
tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr [new file with mode: 0644]
tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr [new file with mode: 0644]
tests/rustdoc/hidden-private.rs [new file with mode: 0644]
tests/rustdoc/impl-in-const-block.rs [new file with mode: 0644]
tests/rustdoc/redirect.rs
tests/ui/async-await/future-sizes/future-as-arg.rs [new file with mode: 0644]
tests/ui/async-await/future-sizes/large-arg.rs [new file with mode: 0644]
tests/ui/async-await/future-sizes/large-arg.stdout [new file with mode: 0644]
tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed [new file with mode: 0644]
tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
tests/ui/fmt/format-string-wrong-order.rs [new file with mode: 0644]
tests/ui/fmt/format-string-wrong-order.stderr [new file with mode: 0644]
tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs
tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr
tests/ui/parser/issue-102806.stderr
tests/ui/parser/issues/issue-63135.stderr
tests/ui/parser/issues/issue-87086-colon-path-sep.rs
tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
tests/ui/parser/type-ascription-in-pattern.rs [new file with mode: 0644]
tests/ui/parser/type-ascription-in-pattern.stderr [new file with mode: 0644]
tests/ui/stats/hir-stats.rs
tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
tests/ui/uninhabited/issue-107505.rs [new file with mode: 0644]

index fa8567eac609074925d82b465c6bae7feaf21ea9..d7767efa9841bc65383b76767c821ddae74379d0 100644 (file)
@@ -131,7 +131,7 @@ pub fn print_crate<'a>(
 
         // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
         // root, so this is not needed, and actually breaks things.
-        if edition.rust_2015() {
+        if edition.is_rust_2015() {
             // `#![no_std]`
             let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
             s.print_attribute(&fake_attr);
index 87db08ef5b5108e3b6439883ce5d8bb869f90967..7901a5046abad12a466cf045b9591d4fe618f5f1 100644 (file)
@@ -583,10 +583,12 @@ fn report_fnmut_error(
         let err = FnMutError {
             span: *span,
             ty_err: match output_ty.kind() {
-                ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
                 ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => {
                     FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
                 }
+                _ if output_ty.contains_closure() => {
+                    FnMutReturnTypeErr::ReturnClosure { span: *span }
+                }
                 _ => FnMutReturnTypeErr::ReturnRef { span: *span },
             },
         };
@@ -997,7 +999,7 @@ fn suggest_adding_lifetime_params(
     fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
         let map = self.infcx.tcx.hir();
         let body_id = map.body_owned_by(self.mir_def_id());
-        let expr = &map.body(body_id).value;
+        let expr = &map.body(body_id).value.peel_blocks();
         let mut closure_span = None::<rustc_span::Span>;
         match expr.kind {
             hir::ExprKind::MethodCall(.., args, _) => {
@@ -1012,20 +1014,14 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
                     }
                 }
             }
-            hir::ExprKind::Block(blk, _) => {
-                if let Some(expr) = blk.expr {
-                    // only when the block is a closure
-                    if let hir::ExprKind::Closure(hir::Closure {
-                        capture_clause: hir::CaptureBy::Ref,
-                        body,
-                        ..
-                    }) = expr.kind
-                    {
-                        let body = map.body(*body);
-                        if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
-                            closure_span = Some(expr.span.shrink_to_lo());
-                        }
-                    }
+            hir::ExprKind::Closure(hir::Closure {
+                capture_clause: hir::CaptureBy::Ref,
+                body,
+                ..
+            }) => {
+                let body = map.body(*body);
+                if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+                    closure_span = Some(expr.span.shrink_to_lo());
                 }
             }
             _ => {}
index 2605a1491fb35427609d13dd00475820eb2fdfc1..6c67e1a00c35c38a8b119cb6c9ceec5715b3bae6 100644 (file)
@@ -1484,7 +1484,10 @@ fn check_call_dest(
                 }
             }
             None => {
-                if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) {
+                // The signature in this call can reference region variables,
+                // so erase them before calling a query.
+                let output_ty = self.tcx().erase_regions(sig.output());
+                if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) {
                     span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
                 }
             }
index 21cf4bd789c7e8ecf3bc4548b77314359a85c6a5..244eb41eb39eba2ba32b4d0556d939293df4fc51 100644 (file)
@@ -203,8 +203,9 @@ parse_inclusive_range_extra_equals = unexpected `=` after inclusive range
     .suggestion_remove_eq = use `..=` instead
     .note = inclusive ranges end with a single equals sign (`..=`)
 
-parse_inclusive_range_match_arrow = unexpected `=>` after open range
-    .suggestion_add_space = add a space between the pattern and `=>`
+parse_inclusive_range_match_arrow = unexpected `>` after inclusive range
+    .label = this is parsed as an inclusive range `..=`
+    .suggestion = add a space between the pattern and `=>`
 
 parse_inclusive_range_no_end = inclusive range with no end
     .suggestion_open_range = use `..` instead
@@ -535,8 +536,8 @@ parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` ar
 
 parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
 
-parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
-    .suggestion = to omit remaining fields, use one fewer `.`
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+    .suggestion = to omit remaining fields, use `..`
 
 parse_expected_comma_after_pattern_field = expected `,`
 
index a355a54d6959abb5570144e9c40b53f2e973ce3f..237142acca6604a8af1731bd66919209b9ee7a09 100644 (file)
@@ -454,8 +454,7 @@ pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
             None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
             None => {
                 bug!(
-                    "no type for node {}: {} in fcx {}",
-                    id,
+                    "no type for node {} in fcx {}",
                     self.tcx.hir().node_to_string(id),
                     self.tag()
                 );
index 48c75cde9a5fc544948e231ea4077a86ad698f9d..92240b66eb1d4727a4a6aaa9d6df41efa26b43ef 100644 (file)
@@ -155,8 +155,7 @@ fn resolve_type_vars_or_error(
             None if self.is_tainted_by_errors() => Err(()),
             None => {
                 bug!(
-                    "no type for node {}: {} in mem_categorization",
-                    id,
+                    "no type for node {} in mem_categorization",
                     self.tcx().hir().node_to_string(id)
                 );
             }
index 5bd6b0704426b667b4e0435cd4ac3bb30f5f66a8..7f2994fd79b98af288b56103a3482b240ebc5bc7 100644 (file)
@@ -290,7 +290,7 @@ pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
     #[track_caller]
     pub fn parent_id(self, hir_id: HirId) -> HirId {
         self.opt_parent_id(hir_id)
-            .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
+            .unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id)))
     }
 
     pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
@@ -1191,12 +1191,10 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
 }
 
 fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
-    let id_str = format!(" (hir_id={})", id);
-
     let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id());
 
     let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
-    let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str);
+    let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
 
     match map.find(id) {
         Some(Node::Item(item)) => {
@@ -1225,10 +1223,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
                 ItemKind::TraitAlias(..) => "trait alias",
                 ItemKind::Impl { .. } => "impl",
             };
-            format!("{} {}{}", item_str, path_str(item.owner_id.def_id), id_str)
+            format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
         }
         Some(Node::ForeignItem(item)) => {
-            format!("foreign item {}{}", path_str(item.owner_id.def_id), id_str)
+            format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
         }
         Some(Node::ImplItem(ii)) => {
             let kind = match ii.kind {
@@ -1236,7 +1234,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
                 ImplItemKind::Fn(..) => "method",
                 ImplItemKind::Type(_) => "assoc type",
             };
-            format!("{} {} in {}{}", kind, ii.ident, path_str(ii.owner_id.def_id), id_str)
+            format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
         }
         Some(Node::TraitItem(ti)) => {
             let kind = match ti.kind {
@@ -1245,13 +1243,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
                 TraitItemKind::Type(..) => "assoc type",
             };
 
-            format!("{} {} in {}{}", kind, ti.ident, path_str(ti.owner_id.def_id), id_str)
+            format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
         }
         Some(Node::Variant(ref variant)) => {
-            format!("variant {} in {}{}", variant.ident, path_str(variant.def_id), id_str)
+            format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
         }
         Some(Node::Field(ref field)) => {
-            format!("field {} in {}{}", field.ident, path_str(field.def_id), id_str)
+            format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
         }
         Some(Node::AnonConst(_)) => node_str("const"),
         Some(Node::Expr(_)) => node_str("expr"),
@@ -1269,16 +1267,15 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Some(Node::Infer(_)) => node_str("infer"),
         Some(Node::Local(_)) => node_str("local"),
         Some(Node::Ctor(ctor)) => format!(
-            "ctor {}{}",
+            "{id} (ctor {})",
             ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
-            id_str
         ),
         Some(Node::Lifetime(_)) => node_str("lifetime"),
         Some(Node::GenericParam(ref param)) => {
-            format!("generic_param {}{}", path_str(param.def_id), id_str)
+            format!("{id} (generic_param {})", path_str(param.def_id))
         }
-        Some(Node::Crate(..)) => String::from("root_crate"),
-        None => format!("unknown node{}", id_str),
+        Some(Node::Crate(..)) => String::from("(root_crate)"),
+        None => format!("{id} (unknown node)"),
     }
 }
 
index b63b9e754cf466a963adc68740971e5f6fa0e0ff..f98172e420162c4ae6aecc0b8fd247e3589757f2 100644 (file)
@@ -2171,7 +2171,7 @@ pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
             self.late_bound_vars_map(id.owner)
                 .and_then(|map| map.get(&id.local_id).cloned())
                 .unwrap_or_else(|| {
-                    bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
+                    bug!("No bound vars found for {}", self.hir().node_to_string(id))
                 })
                 .iter(),
         )
index 060d864389cb0f4ffa3f3c84b9f9ab5bcb353705..98d6b68356368c14e06717b05a5c4ccc72e05915 100644 (file)
@@ -2043,6 +2043,28 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         cf.is_break()
     }
 
+    /// Checks whether a type recursively contains any closure
+    ///
+    /// Example: `Option<[closure@file.rs:4:20]>` returns true
+    pub fn contains_closure(self) -> bool {
+        struct ContainsClosureVisitor;
+
+        impl<'tcx> TypeVisitor<'tcx> for ContainsClosureVisitor {
+            type BreakTy = ();
+
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                if let ty::Closure(_, _) = t.kind() {
+                    ControlFlow::Break(())
+                } else {
+                    t.super_visit_with(self)
+                }
+            }
+        }
+
+        let cf = self.visit_with(&mut ContainsClosureVisitor);
+        cf.is_break()
+    }
+
     /// Returns the type and mutability of `*ty`.
     ///
     /// The parameter `explicit` indicates if this is an *explicit* dereference.
index 79a6c730d7159a5abcbf323ae029566c709952e6..9beaac87183a7fcde3369cab7949c5eca5a299ee 100644 (file)
@@ -372,7 +372,7 @@ pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
 
     pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
         self.node_type_opt(id).unwrap_or_else(|| {
-            bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+            bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
         })
     }
 
@@ -551,9 +551,8 @@ fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
 fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
     ty::tls::with(|tcx| {
         bug!(
-            "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+            "node {} cannot be placed in TypeckResults with hir_owner {:?}",
             tcx.hir().node_to_string(hir_id),
-            hir_id.owner,
             hir_owner
         )
     });
index 182b3015dd7d784c4ad215d834d749e2915d73e6..4c7d45be0753e1944d25e60434463fb964a462b2 100644 (file)
@@ -162,17 +162,20 @@ fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
     }
 
     fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
-        if let StatementKind::StorageDead(l) = stmt.kind
-            && self.storage_to_remove.contains(l)
-        {
-            stmt.make_nop();
-        } else if let StatementKind::Assign(box (ref place, ref mut rvalue)) = stmt.kind
-            && place.as_local().is_some()
-        {
-            // Do not replace assignments.
-            self.visit_rvalue(rvalue, loc)
-        } else {
-            self.super_statement(stmt, loc);
+        match stmt.kind {
+            // When removing storage statements, we need to remove both (#107511).
+            StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
+                if self.storage_to_remove.contains(l) =>
+            {
+                stmt.make_nop()
+            }
+            StatementKind::Assign(box (ref place, ref mut rvalue))
+                if place.as_local().is_some() =>
+            {
+                // Do not replace assignments.
+                self.visit_rvalue(rvalue, loc)
+            }
+            _ => self.super_statement(stmt, loc),
         }
     }
 }
index 145611923ff16a127f4668b9ce999b542d9eda2b..fd4333dbbecc3763f3dace3162c65890403af1cc 100644 (file)
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
 use rustc_ast::token::Token;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
@@ -668,13 +670,10 @@ pub(crate) struct InclusiveRangeExtraEquals {
 #[diag(parse_inclusive_range_match_arrow)]
 pub(crate) struct InclusiveRangeMatchArrow {
     #[primary_span]
+    pub arrow: Span,
+    #[label]
     pub span: Span,
-    #[suggestion(
-        suggestion_add_space,
-        style = "verbose",
-        code = " ",
-        applicability = "machine-applicable"
-    )]
+    #[suggestion(style = "verbose", code = " ", applicability = "machine-applicable")]
     pub after_pat: Span,
 }
 
@@ -1802,8 +1801,9 @@ pub(crate) struct EnumPatternInsteadOfIdentifier {
 #[diag(parse_dot_dot_dot_for_remaining_fields)]
 pub(crate) struct DotDotDotForRemainingFields {
     #[primary_span]
-    #[suggestion(code = "..", applicability = "machine-applicable")]
+    #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")]
     pub span: Span,
+    pub token_str: Cow<'static, str>,
 }
 
 #[derive(Diagnostic)]
index 16d5edfd303a3fc0b58202e608e11499dfd46128..cd9d85b1d919c9c3f45541e83a9223857550be9c 100644 (file)
@@ -2405,26 +2405,42 @@ pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
         if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
             || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
         {
+            let mut snapshot_type = self.create_snapshot_for_diagnostic();
+            snapshot_type.bump(); // `:`
+            match snapshot_type.parse_ty() {
+                Err(inner_err) => {
+                    inner_err.cancel();
+                }
+                Ok(ty) => {
+                    let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else {
+                        return first_pat;
+                    };
+                    err.span_label(ty.span, "specifying the type of a pattern isn't supported");
+                    self.restore_snapshot(snapshot_type);
+                    let span = first_pat.span.to(ty.span);
+                    first_pat = self.mk_pat(span, PatKind::Wild);
+                    err.emit();
+                }
+            }
             return first_pat;
         }
         // The pattern looks like it might be a path with a `::` -> `:` typo:
         // `match foo { bar:baz => {} }`
-        let span = self.token.span;
+        let colon_span = self.token.span;
         // We only emit "unexpected `:`" error here if we can successfully parse the
         // whole pattern correctly in that case.
-        let snapshot = self.create_snapshot_for_diagnostic();
+        let mut snapshot_pat = self.create_snapshot_for_diagnostic();
+        let mut snapshot_type = self.create_snapshot_for_diagnostic();
 
         // Create error for "unexpected `:`".
         match self.expected_one_of_not_found(&[], &[]) {
             Err(mut err) => {
-                self.bump(); // Skip the `:`.
-                match self.parse_pat_no_top_alt(expected) {
+                // Skip the `:`.
+                snapshot_pat.bump();
+                snapshot_type.bump();
+                match snapshot_pat.parse_pat_no_top_alt(expected) {
                     Err(inner_err) => {
-                        // Carry on as if we had not done anything, callers will emit a
-                        // reasonable error.
                         inner_err.cancel();
-                        err.cancel();
-                        self.restore_snapshot(snapshot);
                     }
                     Ok(mut pat) => {
                         // We've parsed the rest of the pattern.
@@ -2488,8 +2504,8 @@ pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
                             _ => {}
                         }
                         if show_sugg {
-                            err.span_suggestion(
-                                span,
+                            err.span_suggestion_verbose(
+                                colon_span.until(self.look_ahead(1, |t| t.span)),
                                 "maybe write a path separator here",
                                 "::",
                                 Applicability::MaybeIncorrect,
@@ -2497,13 +2513,24 @@ pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
                         } else {
                             first_pat = self.mk_pat(new_span, PatKind::Wild);
                         }
-                        err.emit();
+                        self.restore_snapshot(snapshot_pat);
                     }
                 }
+                match snapshot_type.parse_ty() {
+                    Err(inner_err) => {
+                        inner_err.cancel();
+                    }
+                    Ok(ty) => {
+                        err.span_label(ty.span, "specifying the type of a pattern isn't supported");
+                        self.restore_snapshot(snapshot_type);
+                        let new_span = first_pat.span.to(ty.span);
+                        first_pat = self.mk_pat(new_span, PatKind::Wild);
+                    }
+                }
+                err.emit();
             }
             _ => {
                 // Carry on as if we had not done anything. This should be unreachable.
-                self.restore_snapshot(snapshot);
             }
         };
         first_pat
index b7a023868fced9e84107b4194816a3db53bede7f..3d42a9dcbbea1916b3c6d3e66e408d2fc1eff1e9 100644 (file)
@@ -2717,6 +2717,14 @@ fn check_let_expr(expr: &Expr) -> (bool, bool) {
                     );
                     err.emit();
                     this.bump();
+                } else if matches!(
+                    (&this.prev_token.kind, &this.token.kind),
+                    (token::DotDotEq, token::Gt)
+                ) {
+                    // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`,
+                    // so we supress the error here
+                    err.delay_as_bug();
+                    this.bump();
                 } else {
                     return Err(err);
                 }
index 81fd084ccb38e25c691e7d72a8e4598ad0b47c15..628e9d88cf1df27451b7811dc010fc9b08ed5cdd 100644 (file)
@@ -2247,7 +2247,7 @@ pub(super) fn parse_fn_front_matter(
         let ext = self.parse_extern(case);
 
         if let Async::Yes { span, .. } = asyncness {
-            if span.rust_2015() {
+            if span.is_rust_2015() {
                 self.sess.emit_err(AsyncFnIn2015 { span, help: HelpUseLatestEdition::new() });
             }
         }
index e75554ba124b39d850c24d2c4777cc374042223b..b054dc59a0c9d93b43d1b2a365a4ec12d23c22ea 100644 (file)
@@ -743,7 +743,7 @@ pub(super) fn inclusive_range_with_incorrect_end(&mut self) {
             }
             token::Gt if no_space => {
                 let after_pat = span.with_hi(span.hi() - rustc_span::BytePos(1)).shrink_to_hi();
-                self.sess.emit_err(InclusiveRangeMatchArrow { span, after_pat });
+                self.sess.emit_err(InclusiveRangeMatchArrow { span, arrow: tok.span, after_pat });
             }
             _ => {
                 self.sess.emit_err(InclusiveRangeNoEnd { span });
@@ -962,12 +962,15 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<PatField>, bool)> {
             }
             ate_comma = false;
 
-            if self.check(&token::DotDot) || self.token == token::DotDotDot {
+            if self.check(&token::DotDot)
+                || self.check_noexpect(&token::DotDotDot)
+                || self.check_keyword(kw::Underscore)
+            {
                 etc = true;
                 let mut etc_sp = self.token.span;
 
-                self.recover_one_fewer_dotdot();
-                self.bump(); // `..` || `...`
+                self.recover_bad_dot_dot();
+                self.bump(); // `..` || `...` || `_`
 
                 if self.token == token::CloseDelim(Delimiter::Brace) {
                     etc_span = Some(etc_sp);
@@ -1060,14 +1063,15 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<PatField>, bool)> {
         Ok((fields, etc))
     }
 
-    /// Recover on `...` as if it were `..` to avoid further errors.
+    /// Recover on `...` or `_` as if it were `..` to avoid further errors.
     /// See issue #46718.
-    fn recover_one_fewer_dotdot(&self) {
-        if self.token != token::DotDotDot {
+    fn recover_bad_dot_dot(&self) {
+        if self.token == token::DotDot {
             return;
         }
 
-        self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span });
+        let token_str = pprust::token_to_string(&self.token);
+        self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str });
     }
 
     fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
index 646e2f45e640cb8a6a233bf01170f5cba002afc8..a19ea04fa5e75e47128fa769952be3b6083a68c6 100644 (file)
@@ -614,7 +614,7 @@ fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
     /// Is a `dyn B0 + ... + Bn` type allowed here?
     fn is_explicit_dyn_type(&mut self) -> bool {
         self.check_keyword(kw::Dyn)
-            && (!self.token.uninterpolated_span().rust_2015()
+            && (self.token.uninterpolated_span().rust_2018()
                 || self.look_ahead(1, |t| {
                     (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
                         && !can_continue_type_after_non_fn_ident(t)
index a6dfcd29762474933a31022e2f09f409d3e35865..088a87ca5710457386e77017260650aa8cfb4daf 100644 (file)
@@ -273,7 +273,13 @@ fn next(&mut self) -> Option<Piece<'a>> {
                                 );
                             }
                         } else {
-                            self.suggest_positional_arg_instead_of_captured_arg(arg);
+                            if let Some(&(_, maybe)) = self.cur.peek() {
+                                if maybe == '?' {
+                                    self.suggest_format();
+                                } else {
+                                    self.suggest_positional_arg_instead_of_captured_arg(arg);
+                                }
+                            }
                         }
                         Some(NextArgument(Box::new(arg)))
                     }
@@ -832,6 +838,27 @@ fn integer(&mut self) -> Option<usize> {
         if found { Some(cur) } else { None }
     }
 
+    fn suggest_format(&mut self) {
+        if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) {
+            let word = self.word();
+            let _end = self.current_pos();
+            let pos = self.to_span_index(pos);
+            self.errors.insert(
+                0,
+                ParseError {
+                    description: "expected format parameter to occur after `:`".to_owned(),
+                    note: Some(
+                        format!("`?` comes after `:`, try `{}:{}` instead", word, "?").to_owned(),
+                    ),
+                    label: "expected `?` to occur after `:`".to_owned(),
+                    span: pos.to(pos),
+                    secondary_label: None,
+                    should_be_replaced_with_positional_argument: false,
+                },
+            );
+        }
+    }
+
     fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
         if let Some(end) = self.consume_pos('.') {
             let byte_pos = self.to_span_index(end);
index d143adb2eb9417c50e879e693296dedf428fba94..de0e50a65de6ebba0d48d65f729b8ab01cf63f99 100644 (file)
@@ -74,37 +74,26 @@ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: hir::OwnerI
             .expect("owning item has no entry");
 
         if max != self.hir_ids_seen.len() - 1 {
-            // Collect the missing ItemLocalIds
-            let missing: Vec<_> = (0..=max as u32)
-                .filter(|&i| !self.hir_ids_seen.contains(ItemLocalId::from_u32(i)))
-                .collect();
-
-            // Try to map those to something more useful
-            let mut missing_items = Vec::with_capacity(missing.len());
+            let hir = self.tcx.hir();
+            let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
 
-            for local_id in missing {
-                let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) };
+            let missing_items: Vec<_> = (0..=max as u32)
+                .map(|i| ItemLocalId::from_u32(i))
+                .filter(|&local_id| !self.hir_ids_seen.contains(local_id))
+                .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+                .collect();
 
-                trace!("missing hir id {:#?}", hir_id);
+            let seen_items: Vec<_> = self
+                .hir_ids_seen
+                .iter()
+                .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+                .collect();
 
-                missing_items.push(format!(
-                    "[local_id: {}, owner: {}]",
-                    local_id,
-                    self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
-                ));
-            }
             self.error(|| {
                 format!(
                     "ItemLocalIds not assigned densely in {}. \
-                Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}",
-                    self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose(),
-                    max,
-                    missing_items,
-                    self.hir_ids_seen
-                        .iter()
-                        .map(|local_id| HirId { owner, local_id })
-                        .map(|h| format!("({:?} {})", h, self.tcx.hir().node_to_string(h)))
-                        .collect::<Vec<_>>()
+                Max ItemLocalId = {}, missing IDs = {:#?}; seen IDs = {:#?}",
+                    pretty_owner, max, missing_items, seen_items
                 )
             });
         }
index 84421dc1f62253354794e3b8079c190213e7d66b..2fb62ce53ba6e357b0f4be8d04eef0fa949b949d 100644 (file)
@@ -265,7 +265,7 @@ fn try_resolve_visibility<'ast>(
                 let ident = path.segments.get(0).expect("empty path in visibility").ident;
                 let crate_root = if ident.is_path_segment_keyword() {
                     None
-                } else if ident.span.rust_2015() {
+                } else if ident.span.is_rust_2015() {
                     Some(Segment::from_ident(Ident::new(
                         kw::PathRoot,
                         path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()),
@@ -435,10 +435,10 @@ fn build_reduced_graph_for_use_tree(
         // appears, so imports in braced groups can have roots prepended independently.
         let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob);
         let crate_root = match prefix_iter.peek() {
-            Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
+            Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => {
                 Some(seg.ident.span.ctxt())
             }
-            None if is_glob && use_tree.span.rust_2015() => Some(use_tree.span.ctxt()),
+            None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()),
             _ => None,
         }
         .map(|ctxt| {
index 3bf041cebcb88a6996b704dce8f2ce409a304cd9..a08ae0f184bb2f62cb7400353a063e6e417ed998 100644 (file)
@@ -462,7 +462,9 @@ pub(crate) fn lint_if_path_starts_with_module(
 
         let first_name = match path.get(0) {
             // In the 2018 edition this lint is a hard error, so nothing to do
-            Some(seg) if seg.ident.span.rust_2015() && self.session.rust_2015() => seg.ident.name,
+            Some(seg) if seg.ident.span.is_rust_2015() && self.session.is_rust_2015() => {
+                seg.ident.name
+            }
             _ => return,
         };
 
@@ -1717,7 +1719,7 @@ pub(crate) fn report_path_resolution_error(
                         Applicability::MaybeIncorrect,
                     )),
                 )
-            } else if self.session.rust_2015() {
+            } else if self.session.is_rust_2015() {
                 (
                     format!("maybe a missing crate `{ident}`?"),
                     Some((
@@ -1996,7 +1998,7 @@ fn make_external_crate_suggestion(
         mut path: Vec<Segment>,
         parent_scope: &ParentScope<'b>,
     ) -> Option<(Vec<Segment>, Option<String>)> {
-        if path[1].ident.span.rust_2015() {
+        if path[1].ident.span.is_rust_2015() {
             return None;
         }
 
index 1c985d43658ae25f1b66acfedfc1ccde9a75cdfa..d03ccf256fad79f2ddc6a1d48e002e821a67e7fe 100644 (file)
@@ -85,7 +85,7 @@ pub(crate) fn visit_scopes<T>(
         // 4c. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude: builtin attributes (closed, controlled).
 
-        let rust_2015 = ctxt.edition().rust_2015();
+        let rust_2015 = ctxt.edition().is_rust_2015();
         let (ns, macro_kind, is_absolute_path) = match scope_set {
             ScopeSet::All(ns, _) => (ns, None, false),
             ScopeSet::AbsolutePath(ns) => (ns, None, true),
@@ -1397,7 +1397,8 @@ pub(crate) fn resolve_path_with_ribs(
                         module = Some(ModuleOrUniformRoot::ExternPrelude);
                         continue;
                     }
-                    if name == kw::PathRoot && ident.span.rust_2015() && self.session.rust_2018() {
+                    if name == kw::PathRoot && ident.span.is_rust_2015() && self.session.rust_2018()
+                    {
                         // `::a::b` from 2015 macro on 2018 global edition
                         module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
                         continue;
index 83932c089b311afba738f9e3fb9ff652befe1079..3ca10ac50baa6392ed0fcf47f46de5ad34b9871e 100644 (file)
@@ -2145,7 +2145,7 @@ fn future_proof_import(&mut self, use_tree: &UseTree) {
         let segments = &use_tree.prefix.segments;
         if !segments.is_empty() {
             let ident = segments[0].ident;
-            if ident.is_path_segment_keyword() || ident.span.rust_2015() {
+            if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
                 return;
             }
 
index 37beff37c1fb9d988c33ae968afa86fb96370603..cee0a7f3c203d8e4eeb871f99f978ccfac100839 100644 (file)
@@ -1343,7 +1343,7 @@ fn smart_resolve_context_dependent_help(
                     "!",
                     Applicability::MaybeIncorrect,
                 );
-                if path_str == "try" && span.rust_2015() {
+                if path_str == "try" && span.is_rust_2015() {
                     err.note("if you want the `try` keyword, you need Rust 2018 or later");
                 }
             }
index 746e0f169bcf30ca37971009f60aabce0cc5b481..dbd419c1406f867c09644875e70b9231e8b355fd 100644 (file)
@@ -919,8 +919,8 @@ pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -
     }
 
     /// Is this edition 2015?
-    pub fn rust_2015(&self) -> bool {
-        self.edition().rust_2015()
+    pub fn is_rust_2015(&self) -> bool {
+        self.edition().is_rust_2015()
     }
 
     /// Are we allowed to use features from the Rust 2018 edition?
index e66ec07904341b8585d529f82c2d87adc829bbc7..f16db69aae2323d6efef2998b64dc43ee307837a 100644 (file)
@@ -77,7 +77,7 @@ pub fn is_stable(self) -> bool {
     }
 
     /// Is this edition 2015?
-    pub fn rust_2015(self) -> bool {
+    pub fn is_rust_2015(self) -> bool {
         self == Edition::Edition2015
     }
 
index 006102a5f2fcfc471abf0c1523bd1d1f22c029fc..e095cf3fda20d53cef6edd184b5c29d998d74b99 100644 (file)
@@ -705,8 +705,8 @@ pub fn edition(self) -> edition::Edition {
     }
 
     #[inline]
-    pub fn rust_2015(self) -> bool {
-        self.edition().rust_2015()
+    pub fn is_rust_2015(self) -> bool {
+        self.edition().is_rust_2015()
     }
 
     #[inline]
index b35b9d62759c73267bf4d3f217616a6305b23592..87dbf7c3fd699b2649d36acb122d49de5a99676c 100644 (file)
@@ -133,7 +133,7 @@ fn get_from_await_ty<F>(
                                         .cloned()
                                         .unwrap_or_else(|| {
                                             bug!(
-                                                "node_type: no type for node `{}`",
+                                                "node_type: no type for node {}",
                                                 ty::tls::with(|tcx| tcx
                                                     .hir()
                                                     .node_to_string(await_expr.hir_id))
index 85f058f3664e3e5d388643fb86e70feeca400f83..df4478bb0cb85ac75cfb31fbc78349d30fcfa96b 100644 (file)
@@ -662,7 +662,8 @@ changelog-seen = 2
 
 # Select LTO mode that will be used for compiling rustc. By default, thin local LTO
 # (LTO within a single crate) is used (like for any Rust crate). You can also select
-# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib.
+# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib, or "off" to disable
+# LTO entirely.
 #lto = "thin-local"
 
 # =============================================================================
index 9408f83c32f7cd368f9b685bdac3a3fa471e5751..5d4df1ac8bd5883b5539539f7f11db2316d84a50 100644 (file)
@@ -1,26 +1,26 @@
-use test::Bencher;
+use test::{black_box, Bencher};
 
 const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9'];
 const RADIX: [u32; 5] = [2, 8, 10, 16, 32];
 
 #[bench]
 fn bench_to_digit_radix_2(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(2)).min())
 }
 
 #[bench]
 fn bench_to_digit_radix_10(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(10)).min())
 }
 
 #[bench]
 fn bench_to_digit_radix_16(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(16)).min())
 }
 
 #[bench]
 fn bench_to_digit_radix_36(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(36)).min())
 }
 
 #[bench]
@@ -31,47 +31,59 @@ fn bench_to_digit_radix_var(b: &mut Bencher) {
             .cycle()
             .zip(RADIX.iter().cycle())
             .take(10_000)
-            .map(|(c, radix)| c.to_digit(*radix))
+            .map(|(c, radix)| black_box(c).to_digit(*radix))
             .min()
     })
 }
 
 #[bench]
 fn bench_to_ascii_uppercase(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_uppercase()).min())
 }
 
 #[bench]
 fn bench_to_ascii_lowercase(b: &mut Bencher) {
-    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min())
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_lowercase()).min())
 }
 
 #[bench]
 fn bench_ascii_mix_to_uppercase(b: &mut Bencher) {
-    b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+    b.iter(|| {
+        (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+    })
 }
 
 #[bench]
 fn bench_ascii_mix_to_lowercase(b: &mut Bencher) {
-    b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+    b.iter(|| {
+        (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+    })
 }
 
 #[bench]
 fn bench_ascii_char_to_uppercase(b: &mut Bencher) {
-    b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+    b.iter(|| {
+        (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+    })
 }
 
 #[bench]
 fn bench_ascii_char_to_lowercase(b: &mut Bencher) {
-    b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+    b.iter(|| {
+        (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+    })
 }
 
 #[bench]
 fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) {
-    b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+    b.iter(|| {
+        (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+    })
 }
 
 #[bench]
 fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) {
-    b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+    b.iter(|| {
+        (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+    })
 }
index 319b9773e49fee6042cbcb8cd67d82ed80b268bb..377c99effd03c7b0f58435f4013aa88ce46470af 100644 (file)
@@ -1,14 +1,14 @@
 use super::super::*;
 use core::num::flt2dec::strategy::dragon::*;
 use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_small_shortest(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -17,7 +17,7 @@ fn bench_big_shortest(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -26,7 +26,7 @@ fn bench_small_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -35,7 +35,7 @@ fn bench_big_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -44,7 +44,7 @@ fn bench_small_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -53,7 +53,7 @@ fn bench_big_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -62,7 +62,7 @@ fn bench_small_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -71,6 +71,6 @@ fn bench_big_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
index 8e47a046cdea5fc330308a9f91160c4d57dd820b..6bea5e55d37bbc1bafad53c1ac0c98a4eafe5d15 100644 (file)
@@ -1,7 +1,7 @@
 use super::super::*;
 use core::num::flt2dec::strategy::grisu::*;
 use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
@@ -15,7 +15,7 @@ fn bench_small_shortest(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -24,7 +24,7 @@ fn bench_big_shortest(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
     b.iter(|| {
-        format_shortest(&decoded, &mut buf);
+        format_shortest(black_box(&decoded), &mut buf);
     });
 }
 
@@ -33,7 +33,7 @@ fn bench_small_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -42,7 +42,7 @@ fn bench_big_exact_3(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 3];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -51,7 +51,7 @@ fn bench_small_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -60,7 +60,7 @@ fn bench_big_exact_12(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 12];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -69,7 +69,7 @@ fn bench_small_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(3.141592f64);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
 
@@ -78,6 +78,6 @@ fn bench_big_exact_inf(b: &mut Bencher) {
     let decoded = decode_finite(f64::MAX);
     let mut buf = [MaybeUninit::new(0); 1024];
     b.iter(|| {
-        format_exact(&decoded, &mut buf, i16::MIN);
+        format_exact(black_box(&decoded), &mut buf, i16::MIN);
     });
 }
index 68d1db0160a2e7cd0872fd56dd6003245f9acc7d..07c0d2233caeb29f8a74d03a5963e25dafdcc8c0 100644 (file)
@@ -379,6 +379,9 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
     if stage >= 1 {
         cargo.rustflag("-Cembed-bitcode=yes");
     }
+    if builder.config.rust_lto == RustcLto::Off {
+        cargo.rustflag("-Clto=off");
+    }
 
     // By default, rustc does not include unwind tables unless they are required
     // for a particular target. They are not required by RISC-V targets, but
@@ -722,6 +725,13 @@ fn run(self, builder: &Builder<'_>) {
                     cargo.rustflag("-Cembed-bitcode=yes");
                 }
                 RustcLto::ThinLocal => { /* Do nothing, this is the default */ }
+                RustcLto::Off => {
+                    cargo.rustflag("-Clto=off");
+                }
+            }
+        } else {
+            if builder.config.rust_lto == RustcLto::Off {
+                cargo.rustflag("-Clto=off");
             }
         }
 
index 165502b0a41d8214d8389a075bdfe07ea2d7b26f..e5fad538969711ce0516fe242b9cbd5e654d3c34 100644 (file)
@@ -333,8 +333,9 @@ fn default_for_platform(target: &str) -> Self {
 }
 
 /// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone)]
+#[derive(Default, Clone, PartialEq)]
 pub enum RustcLto {
+    Off,
     #[default]
     ThinLocal,
     Thin,
@@ -349,6 +350,7 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
             "thin-local" => Ok(RustcLto::ThinLocal),
             "thin" => Ok(RustcLto::Thin),
             "fat" => Ok(RustcLto::Fat),
+            "off" => Ok(RustcLto::Off),
             _ => Err(format!("Invalid value for rustc LTO: {}", s)),
         }
     }
index 2f4ccb825c4d8738199976676b69195e5345a445..b98b13119e8ad56b8c44c73ba4c5e26020ebff20 100644 (file)
@@ -12,6 +12,8 @@ debug-logging = true
 incremental = true
 # Print backtrace on internal compiler errors during bootstrap
 backtrace-on-ice = true
+# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
+lto = "off"
 
 [llvm]
 # Will download LLVM from CI if available on your platform.
index 7bc054d3a49fc97a4be9c0fced37855268f1728a..f362c4111f107f99c8d6ee14b2dd559d4e11a6a0 100644 (file)
@@ -8,6 +8,8 @@ bench-stage = 0
 [rust]
 # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
 incremental = true
+# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
+lto = "off"
 
 [llvm]
 # Will download LLVM from CI if available on your platform.
index e2ced191a00c0e267eaf71e3d353eed379d7bd6b..80493b100bb45cecf4271e01c6be350b655d150e 100644 (file)
@@ -2213,21 +2213,17 @@ fn clean_maybe_renamed_item<'tcx>(
             get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs);
         }
 
-        if !extra_attrs.is_empty() {
+        let mut item = if !extra_attrs.is_empty() {
             extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
             let attrs = Attributes::from_ast(&extra_attrs);
             let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
 
-            vec![Item::from_def_id_and_attrs_and_parts(
-                def_id,
-                Some(name),
-                kind,
-                Box::new(attrs),
-                cfg,
-            )]
+            Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg)
         } else {
-            vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
-        }
+            Item::from_def_id_and_parts(def_id, Some(name), kind, cx)
+        };
+        item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
+        vec![item]
     })
 }
 
index 6b71ecc24bde6f8e3604729a57e0df84172ea715..54749e9a3171856b0ef735ac240fc0b21225de59 100644 (file)
@@ -138,7 +138,7 @@ fn collect(path: &Path, krate: &str) -> io::Result<(Vec<String>, Vec<String>)> {
         Ok((ret, krates))
     }
 
-    /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
+    /// Read a file and return all lines that match the <code>"{crate}":{data},\ </code> format,
     /// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
     ///
     /// This forms the payload of files that look like this:
index e07a788a72a41e53bc3ea98827579b4717067dc4..8c733ddefc0a5a1efe02dd3d95647f85533a297b 100644 (file)
@@ -1,4 +1,6 @@
 //! Strip all doc(hidden) items from the output.
+
+use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 use std::mem;
 
@@ -7,6 +9,7 @@
 use crate::core::DocContext;
 use crate::fold::{strip_item, DocFolder};
 use crate::passes::{ImplStripper, Pass};
+use crate::visit_ast::inherits_doc_hidden;
 
 pub(crate) const STRIP_HIDDEN: Pass = Pass {
     name: "strip-hidden",
@@ -21,7 +24,12 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
 
     // strip all #[doc(hidden)] items
     let krate = {
-        let mut stripper = Stripper { retained: &mut retained, update_retained: true };
+        let mut stripper = Stripper {
+            retained: &mut retained,
+            update_retained: true,
+            tcx: cx.tcx,
+            is_in_hidden_item: false,
+        };
         stripper.fold_crate(krate)
     };
 
@@ -36,40 +44,89 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
     stripper.fold_crate(krate)
 }
 
-struct Stripper<'a> {
+struct Stripper<'a, 'tcx> {
     retained: &'a mut ItemIdSet,
     update_retained: bool,
+    tcx: TyCtxt<'tcx>,
+    is_in_hidden_item: bool,
+}
+
+impl<'a, 'tcx> Stripper<'a, 'tcx> {
+    fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
+        let prev = self.is_in_hidden_item;
+        self.is_in_hidden_item |= is_in_hidden_item;
+        let ret = self.fold_item_recur(i);
+        self.is_in_hidden_item = prev;
+        ret
+    }
+
+    /// In case `i` is a non-hidden impl block, then we special-case it by changing the value
+    /// of `is_in_hidden_item` to `true` because the impl children inherit its visibility.
+    fn recurse_in_impl(&mut self, i: Item) -> Item {
+        let prev = mem::replace(&mut self.is_in_hidden_item, false);
+        let ret = self.fold_item_recur(i);
+        self.is_in_hidden_item = prev;
+        ret
+    }
 }
 
-impl<'a> DocFolder for Stripper<'a> {
+impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
-        if i.attrs.lists(sym::doc).has_word(sym::hidden) {
-            debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
-            // Use a dedicated hidden item for fields, variants, and modules.
-            // We need to keep private fields and variants, so that the docs
-            // can show a placeholder "// some variants omitted". We need to keep
-            // private modules, because they can contain impl blocks, and impl
-            // block privacy is inherited from the type and trait, not from the
-            // module it's defined in. Both of these are marked "stripped," and
-            // not included in the final docs, but since they still have an effect
-            // on the final doc, cannot be completely removed from the Clean IR.
-            match *i.kind {
-                clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
-                    // We need to recurse into stripped modules to
-                    // strip things like impl methods but when doing so
-                    // we must not add any items to the `retained` set.
-                    let old = mem::replace(&mut self.update_retained, false);
-                    let ret = strip_item(self.fold_item_recur(i));
-                    self.update_retained = old;
-                    return Some(ret);
-                }
-                _ => return None,
+        let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden);
+        let is_impl = matches!(*i.kind, clean::ImplItem(..));
+        let mut is_hidden = has_doc_hidden;
+        if !is_impl {
+            is_hidden = self.is_in_hidden_item || has_doc_hidden;
+            if !is_hidden && i.inline_stmt_id.is_none() {
+                // We don't need to check if it's coming from a reexport since the reexport itself was
+                // already checked.
+                is_hidden = i
+                    .item_id
+                    .as_def_id()
+                    .and_then(|def_id| def_id.as_local())
+                    .map(|def_id| inherits_doc_hidden(self.tcx, def_id))
+                    .unwrap_or(false);
             }
-        } else {
+        }
+        if !is_hidden {
             if self.update_retained {
                 self.retained.insert(i.item_id);
             }
+            return Some(if is_impl {
+                self.recurse_in_impl(i)
+            } else {
+                self.set_is_in_hidden_item_and_fold(false, i)
+            });
+        }
+        debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
+        // Use a dedicated hidden item for fields, variants, and modules.
+        // We need to keep private fields and variants, so that the docs
+        // can show a placeholder "// some variants omitted". We need to keep
+        // private modules, because they can contain impl blocks, and impl
+        // block privacy is inherited from the type and trait, not from the
+        // module it's defined in. Both of these are marked "stripped," and
+        // not included in the final docs, but since they still have an effect
+        // on the final doc, cannot be completely removed from the Clean IR.
+        match *i.kind {
+            clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
+                // We need to recurse into stripped modules to
+                // strip things like impl methods but when doing so
+                // we must not add any items to the `retained` set.
+                let old = mem::replace(&mut self.update_retained, false);
+                let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i));
+                self.update_retained = old;
+                Some(ret)
+            }
+            _ => {
+                let ret = self.set_is_in_hidden_item_and_fold(true, i);
+                if has_doc_hidden {
+                    // If the item itself has `#[doc(hidden)]`, then we simply remove it.
+                    None
+                } else {
+                    // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it.
+                    Some(strip_item(ret))
+                }
+            }
         }
-        Some(self.fold_item_recur(i))
     }
 }
index a89d6fa83983d685e8a6baf94d63327320beca71..088cb3f339492be74fc4e8091b5693f7e2427fdc 100644 (file)
@@ -5,7 +5,9 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
+use rustc_hir::intravisit::{walk_item, Visitor};
 use rustc_hir::{Node, CRATE_HIR_ID};
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{DefIdTree, TyCtxt};
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -53,19 +55,26 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<Symbol> {
     std::iter::once(crate_name).chain(relative).collect()
 }
 
-pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: LocalDefId) -> bool {
-    while let Some(id) = tcx.opt_local_parent(node) {
-        node = id;
-        if tcx.is_doc_hidden(node.to_def_id()) {
+pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: LocalDefId) -> bool {
+    let hir = tcx.hir();
+    while let Some(id) = tcx.opt_local_parent(def_id) {
+        def_id = id;
+        if tcx.is_doc_hidden(def_id.to_def_id()) {
             return true;
+        } else if let Some(node) = hir.find_by_def_id(def_id) &&
+            matches!(
+                node,
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),
+            )
+        {
+            // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
+            // on them, they don't inherit it from the parent context.
+            return false;
         }
     }
     false
 }
 
-// Also, is there some reason that this doesn't use the 'visit'
-// framework from syntax?.
-
 pub(crate) struct RustdocVisitor<'a, 'tcx> {
     cx: &'a mut core::DocContext<'tcx>,
     view_item_stack: LocalDefIdSet,
@@ -73,6 +82,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     /// Are the current module and all of its parents public?
     inside_public_path: bool,
     exact_paths: DefIdMap<Vec<Symbol>>,
+    modules: Vec<Module<'tcx>>,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -80,12 +90,19 @@ pub(crate) fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx
         // If the root is re-exported, terminate all recursion.
         let mut stack = LocalDefIdSet::default();
         stack.insert(CRATE_DEF_ID);
+        let om = Module::new(
+            cx.tcx.crate_name(LOCAL_CRATE),
+            CRATE_DEF_ID,
+            cx.tcx.hir().root_module().spans.inner_span,
+        );
+
         RustdocVisitor {
             cx,
             view_item_stack: stack,
             inlining: false,
             inside_public_path: true,
             exact_paths: Default::default(),
+            modules: vec![om],
         }
     }
 
@@ -95,12 +112,10 @@ fn store_path(&mut self, did: DefId) {
     }
 
     pub(crate) fn visit(mut self) -> Module<'tcx> {
-        let mut top_level_module = self.visit_mod_contents(
-            CRATE_DEF_ID,
-            self.cx.tcx.hir().root_module(),
-            self.cx.tcx.crate_name(LOCAL_CRATE),
-            None,
-        );
+        let root_module = self.cx.tcx.hir().root_module();
+        self.visit_mod_contents(CRATE_DEF_ID, root_module);
+
+        let mut top_level_module = self.modules.pop().unwrap();
 
         // `#[macro_export] macro_rules!` items are reexported at the top level of the
         // crate, regardless of where they're defined. We want to document the
@@ -115,15 +130,13 @@ pub(crate) fn visit(mut self) -> Module<'tcx> {
         // macro in the same module.
         let mut inserted = FxHashSet::default();
         for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
-            if let Res::Def(DefKind::Macro(_), def_id) = export.res {
-                if let Some(local_def_id) = def_id.as_local() {
-                    if self.cx.tcx.has_attr(def_id, sym::macro_export) {
-                        if inserted.insert(def_id) {
-                            let item = self.cx.tcx.hir().expect_item(local_def_id);
-                            top_level_module.items.push((item, None, None));
-                        }
-                    }
-                }
+            if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
+                let Some(local_def_id) = def_id.as_local() &&
+                self.cx.tcx.has_attr(def_id, sym::macro_export) &&
+                inserted.insert(def_id)
+            {
+                    let item = self.cx.tcx.hir().expect_item(local_def_id);
+                    top_level_module.items.push((item, None, None));
             }
         }
 
@@ -157,23 +170,22 @@ pub(crate) fn visit(mut self) -> Module<'tcx> {
         top_level_module
     }
 
-    fn visit_mod_contents(
-        &mut self,
-        def_id: LocalDefId,
-        m: &'tcx hir::Mod<'tcx>,
-        name: Symbol,
-        parent_id: Option<LocalDefId>,
-    ) -> Module<'tcx> {
-        let mut om = Module::new(name, def_id, m.spans.inner_span);
+    /// This method will go through the given module items in two passes:
+    /// 1. The items which are not glob imports/reexports.
+    /// 2. The glob imports/reexports.
+    fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) {
+        debug!("Going through module {:?}", m);
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
         self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public();
+
+        // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
+        // the second loop):
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
-            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                continue;
+            if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                self.visit_item(item);
             }
-            self.visit_item(item, None, &mut om, parent_id);
         }
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
@@ -181,11 +193,11 @@ fn visit_mod_contents(
             // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
             // imported items appear last, then they'll be the ones that get discarded.
             if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
-                self.visit_item(item, None, &mut om, parent_id);
+                self.visit_item(item);
             }
         }
         self.inside_public_path = orig_inside_public_path;
-        om
+        debug!("Leaving module {:?}", m);
     }
 
     /// Tries to resolve the target of a `pub use` statement and inlines the
@@ -203,7 +215,6 @@ fn maybe_inline_local(
         res: Res,
         renamed: Option<Symbol>,
         glob: bool,
-        om: &mut Module<'tcx>,
         please_inline: bool,
     ) -> bool {
         debug!("maybe_inline_local res: {:?}", res);
@@ -213,33 +224,30 @@ fn maybe_inline_local(
         }
 
         let tcx = self.cx.tcx;
-        let Some(res_did) = res.opt_def_id() else {
+        let Some(ori_res_did) = res.opt_def_id() else {
             return false;
         };
 
         let use_attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id));
         // Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
         let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
-            || tcx.is_doc_hidden(def_id.to_def_id());
+            || use_attrs.lists(sym::doc).has_word(sym::hidden);
 
         // For cross-crate impl inlining we need to know whether items are
         // reachable in documentation -- a previously unreachable item can be
         // made reachable by cross-crate inlining which we're checking here.
         // (this is done here because we need to know this upfront).
-        if !res_did.is_local() && !is_no_inline {
-            crate::visit_lib::lib_embargo_visit_item(self.cx, res_did);
+        if !ori_res_did.is_local() && !is_no_inline {
+            crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
             return false;
         }
 
-        let Some(res_did) = res_did.as_local() else {
+        let Some(res_did) = ori_res_did.as_local() else {
             return false;
         };
 
-        let is_private = !self
-            .cx
-            .cache
-            .effective_visibilities
-            .is_directly_public(self.cx.tcx, res_did.to_def_id());
+        let is_private =
+            !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did);
         let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did);
 
         // Only inline if requested or if the item would otherwise be stripped.
@@ -256,20 +264,20 @@ fn maybe_inline_local(
                 let prev = mem::replace(&mut self.inlining, true);
                 for &i in m.item_ids {
                     let i = self.cx.tcx.hir().item(i);
-                    self.visit_item(i, None, om, Some(def_id));
+                    self.visit_item_inner(i, None, Some(def_id));
                 }
                 self.inlining = prev;
                 true
             }
             Node::Item(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_item(it, renamed, om, Some(def_id));
+                self.visit_item_inner(it, renamed, Some(def_id));
                 self.inlining = prev;
                 true
             }
             Node::ForeignItem(it) if !glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                self.visit_foreign_item(it, renamed, om);
+                self.visit_foreign_item_inner(it, renamed);
                 self.inlining = prev;
                 true
             }
@@ -279,18 +287,28 @@ fn maybe_inline_local(
         ret
     }
 
-    fn visit_item(
+    #[inline]
+    fn add_to_current_mod(
         &mut self,
         item: &'tcx hir::Item<'_>,
         renamed: Option<Symbol>,
-        om: &mut Module<'tcx>,
         parent_id: Option<LocalDefId>,
     ) {
+        self.modules.last_mut().unwrap().items.push((item, renamed, parent_id))
+    }
+
+    fn visit_item_inner(
+        &mut self,
+        item: &'tcx hir::Item<'_>,
+        renamed: Option<Symbol>,
+        import_id: Option<LocalDefId>,
+    ) -> bool {
         debug!("visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident.name);
+        let tcx = self.cx.tcx;
 
         let def_id = item.owner_id.to_def_id();
-        let is_pub = self.cx.tcx.visibility(def_id).is_public();
+        let is_pub = tcx.visibility(def_id).is_public();
 
         if is_pub {
             self.store_path(item.owner_id.to_def_id());
@@ -299,8 +317,8 @@ fn visit_item(
         match item.kind {
             hir::ItemKind::ForeignMod { items, .. } => {
                 for item in items {
-                    let item = self.cx.tcx.hir().foreign_item(item.id);
-                    self.visit_foreign_item(item, None, om);
+                    let item = tcx.hir().foreign_item(item.id);
+                    self.visit_foreign_item_inner(item, None);
                 }
             }
             // If we're inlining, skip private items or item reexported as "_".
@@ -315,7 +333,8 @@ fn visit_item(
                         continue;
                     }
 
-                    let attrs = self.cx.tcx.hir().attrs(item.hir_id());
+                    let attrs =
+                        tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(item.owner_id.def_id));
 
                     // If there was a private module in the current path then don't bother inlining
                     // anything as it will probably be stripped anyway.
@@ -333,14 +352,13 @@ fn visit_item(
                             res,
                             ident,
                             is_glob,
-                            om,
                             please_inline,
                         ) {
                             continue;
                         }
                     }
 
-                    om.items.push((item, renamed, parent_id))
+                    self.add_to_current_mod(item, renamed, import_id);
                 }
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
@@ -357,14 +375,14 @@ fn visit_item(
 
                 let def_id = item.owner_id.to_def_id();
                 let is_macro_2_0 = !macro_def.macro_rules;
-                let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
+                let nonexported = !tcx.has_attr(def_id, sym::macro_export);
 
                 if is_macro_2_0 || nonexported || self.inlining {
-                    om.items.push((item, renamed, None));
+                    self.add_to_current_mod(item, renamed, None);
                 }
             }
             hir::ItemKind::Mod(ref m) => {
-                om.mods.push(self.visit_mod_contents(item.owner_id.def_id, m, name, parent_id));
+                self.enter_mod(item.owner_id.def_id, m, name);
             }
             hir::ItemKind::Fn(..)
             | hir::ItemKind::ExternCrate(..)
@@ -375,33 +393,87 @@ fn visit_item(
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Trait(..)
-            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
+            | hir::ItemKind::TraitAlias(..) => {
+                self.add_to_current_mod(item, renamed, import_id);
+            }
             hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
                 if name != kw::Underscore {
-                    om.items.push((item, renamed, parent_id));
+                    self.add_to_current_mod(item, renamed, import_id);
                 }
             }
             hir::ItemKind::Impl(impl_) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
                 if !self.inlining && impl_.of_trait.is_none() {
-                    om.items.push((item, None, None));
+                    self.add_to_current_mod(item, None, None);
                 }
             }
         }
+        true
     }
 
-    fn visit_foreign_item(
+    fn visit_foreign_item_inner(
         &mut self,
         item: &'tcx hir::ForeignItem<'_>,
         renamed: Option<Symbol>,
-        om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
         if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
-            om.foreigns.push((item, renamed));
+            self.modules.last_mut().unwrap().foreigns.push((item, renamed));
+        }
+    }
+
+    /// This method will create a new module and push it onto the "modules stack" then call
+    /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
+    /// add into the list of modules of the current module.
+    fn enter_mod(&mut self, id: LocalDefId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
+        self.modules.push(Module::new(name, id, m.spans.inner_span));
+
+        self.visit_mod_contents(id, m);
+
+        let last = self.modules.pop().unwrap();
+        self.modules.last_mut().unwrap().mods.push(last);
+    }
+}
+
+// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
+// such as impl blocks in const blocks.
+impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
+    type NestedFilter = nested_filter::All;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.cx.tcx.hir()
+    }
+
+    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
+        if self.visit_item_inner(i, None, None) {
+            walk_item(self, i);
         }
     }
+
+    fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
+        // Handled in `visit_item_inner`
+    }
+
+    fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) {
+        // Handled in `visit_item_inner`
+    }
+
+    fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) {
+        // Handled in `visit_item_inner`
+    }
+
+    fn visit_label(&mut self, _: &rustc_ast::Label) {
+        // Unneeded.
+    }
+
+    fn visit_infer(&mut self, _: &hir::InferArg) {
+        // Unneeded.
+    }
+
+    fn visit_lifetime(&mut self, _: &hir::Lifetime) {
+        // Unneeded.
+    }
 }
index 5e587be1f1653f482d6bb3a8678ce14bf847cfda..4405b55875ed92ed4f401c9ead6a1cfa5e4230c7 100644 (file)
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/const_debuginfo.rs:+1:9: +1:10
           _1 = const 1_u8;                 // scope 0 at $DIR/const_debuginfo.rs:+1:13: +1:16
-          StorageLive(_2);                 // scope 1 at $DIR/const_debuginfo.rs:+2:9: +2:10
           _2 = const 2_u8;                 // scope 1 at $DIR/const_debuginfo.rs:+2:13: +2:16
-          StorageLive(_3);                 // scope 2 at $DIR/const_debuginfo.rs:+3:9: +3:10
           _3 = const 3_u8;                 // scope 2 at $DIR/const_debuginfo.rs:+3:13: +3:16
           StorageLive(_4);                 // scope 3 at $DIR/const_debuginfo.rs:+4:9: +4:12
           StorageLive(_5);                 // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:20
index e085a88b2da8ba155f44730090f1545df43ce64b..ae9ffd519a148ec6efd25eed5dbe487e231ee483 100644 (file)
@@ -18,7 +18,6 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10
           _1 = const 0_i32;                // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14
           StorageLive(_2);                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11
 -         _4 = Eq(_1, const 0_i32);        // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
index e3f5b120a3234d8bb12f2eb2b99fe3199f04422d..22f710387db71d8321606cc4c303f361bfd09a65 100644 (file)
@@ -11,7 +11,6 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10
           _1 = const 1_u32;                // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14
           StorageLive(_2);                 // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
 -         _2 = consume(_1) -> bb1;         // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
index bc5083e1ad01a9c9e00b35bf8df741867778348c..3e61869e82f11f2085a133825c7ea62b86d52ed9 100644 (file)
@@ -29,7 +29,7 @@
       }
   
       bb1: {
-          StorageLive(_2);                 // scope 1 at $DIR/cycle.rs:+2:9: +2:10
+-         StorageLive(_2);                 // scope 1 at $DIR/cycle.rs:+2:9: +2:10
           _2 = _1;                         // scope 1 at $DIR/cycle.rs:+2:13: +2:14
 -         StorageLive(_3);                 // scope 2 at $DIR/cycle.rs:+3:9: +3:10
 -         _3 = _2;                         // scope 2 at $DIR/cycle.rs:+3:13: +3:14
index 918817da56ce48b2b2d6dfbd791b5379d2043954..d48b04e2de273887ca85aa141f8812c1a36be817 100644 (file)
@@ -11,7 +11,6 @@ fn f(_1: usize) -> usize {
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/dead_stores_79191.rs:+1:9: +1:10
         _2 = _1;                         // scope 0 at $DIR/dead_stores_79191.rs:+1:13: +1:14
         _1 = const 5_usize;              // scope 1 at $DIR/dead_stores_79191.rs:+2:5: +2:10
         _1 = _2;                         // scope 1 at $DIR/dead_stores_79191.rs:+3:5: +3:10
index cf21fadd437907823c5a5a63f251e272fa1035e7..727791f50a4ef67b0b15283df8ff7677ebbea1d5 100644 (file)
@@ -11,7 +11,6 @@ fn f(_1: usize) -> usize {
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10
         _2 = _1;                         // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14
         _1 = const 5_usize;              // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10
         _1 = _2;                         // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10
diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
new file mode 100644 (file)
index 0000000..28ba651
--- /dev/null
@@ -0,0 +1,140 @@
+- // MIR for `main` before CopyProp
++ // MIR for `main` after CopyProp
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/issue_107511.rs:+0:11: +0:11
+      let mut _1: i32;                     // in scope 0 at $DIR/issue_107511.rs:+1:9: +1:16
+      let mut _3: std::ops::Range<usize>;  // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+      let mut _4: std::ops::Range<usize>;  // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+      let mut _5: usize;                   // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+      let mut _6: &[i32];                  // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+      let mut _7: &[i32; 4];               // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+      let mut _9: ();                      // in scope 0 at $DIR/issue_107511.rs:+0:1: +9:2
+      let _10: ();                         // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+      let mut _11: std::option::Option<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+      let mut _12: &mut std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+      let mut _13: &mut std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+      let mut _14: isize;                  // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6
+      let mut _15: !;                      // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6
+      let mut _17: i32;                    // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+      let _18: usize;                      // in scope 0 at $DIR/issue_107511.rs:+7:18: +7:19
+      let mut _19: usize;                  // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+      let mut _20: bool;                   // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+      scope 1 {
+          debug sum => _1;                 // in scope 1 at $DIR/issue_107511.rs:+1:9: +1:16
+          let _2: [i32; 4];                // in scope 1 at $DIR/issue_107511.rs:+2:9: +2:10
+          scope 2 {
+              debug a => _2;               // in scope 2 at $DIR/issue_107511.rs:+2:9: +2:10
+              let mut _8: std::ops::Range<usize>; // in scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+              scope 3 {
+                  debug iter => _8;        // in scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+                  let _16: usize;          // in scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+                  scope 4 {
+                      debug i => _16;      // in scope 4 at $DIR/issue_107511.rs:+6:9: +6:10
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/issue_107511.rs:+1:9: +1:16
+          _1 = const 0_i32;                // scope 0 at $DIR/issue_107511.rs:+1:19: +1:20
+          StorageLive(_2);                 // scope 1 at $DIR/issue_107511.rs:+2:9: +2:10
+          _2 = [const 0_i32, const 10_i32, const 20_i32, const 30_i32]; // scope 1 at $DIR/issue_107511.rs:+2:13: +2:28
+          StorageLive(_3);                 // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          StorageLive(_4);                 // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          StorageLive(_5);                 // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+          StorageLive(_6);                 // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+          StorageLive(_7);                 // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+          _7 = &_2;                        // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+          _6 = move _7 as &[i32] (Pointer(Unsize)); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+          StorageDead(_7);                 // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18
+          _5 = core::slice::<impl [i32]>::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+                                           // mir::Constant
+                                           // + span: $DIR/issue_107511.rs:10:19: 10:22
+                                           // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::<impl [i32]>::len}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_6);                 // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+          Deinit(_4);                      // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          (_4.0: usize) = const 0_usize;   // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          (_4.1: usize) = move _5;         // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          StorageDead(_5);                 // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+          _3 = <std::ops::Range<usize> as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+                                           // mir::Constant
+                                           // + span: $DIR/issue_107511.rs:10:14: 10:24
+                                           // + literal: Const { ty: fn(std::ops::Range<usize>) -> <std::ops::Range<usize> as IntoIterator>::IntoIter {<std::ops::Range<usize> as IntoIterator>::into_iter}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_4);                 // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+          StorageLive(_8);                 // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          _8 = move _3;                    // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+          goto -> bb3;                     // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+      }
+  
+      bb3: {
+-         StorageLive(_10);                // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          StorageLive(_11);                // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          StorageLive(_12);                // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          StorageLive(_13);                // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          _13 = &mut _8;                   // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          _12 = &mut (*_13);               // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          _11 = <std::ops::Range<usize> as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+                                           // mir::Constant
+                                           // + span: $DIR/issue_107511.rs:10:14: 10:24
+                                           // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<usize>) -> Option<<std::ops::Range<usize> as Iterator>::Item> {<std::ops::Range<usize> as Iterator>::next}, val: Value(<ZST>) }
+      }
+  
+      bb4: {
+          StorageDead(_12);                // scope 3 at $DIR/issue_107511.rs:+6:23: +6:24
+          _14 = discriminant(_11);         // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+          switchInt(move _14) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+      }
+  
+      bb5: {
+-         StorageLive(_16);                // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+          _16 = ((_11 as Some).0: usize);  // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+          StorageLive(_17);                // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+-         StorageLive(_18);                // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19
+-         _18 = _16;                       // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19
+          _19 = Len(_2);                   // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+-         _20 = Lt(_18, _19);              // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+-         assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++         _20 = Lt(_16, _19);              // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++         assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+      }
+  
+      bb6: {
+          unreachable;                     // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+      }
+  
+      bb7: {
+          _0 = const ();                   // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+          StorageDead(_13);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+          StorageDead(_11);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+-         StorageDead(_10);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+          StorageDead(_8);                 // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6
+          StorageDead(_3);                 // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6
+          StorageDead(_2);                 // scope 1 at $DIR/issue_107511.rs:+9:1: +9:2
+          StorageDead(_1);                 // scope 0 at $DIR/issue_107511.rs:+9:1: +9:2
+          return;                          // scope 0 at $DIR/issue_107511.rs:+9:2: +9:2
+      }
+  
+      bb8: {
+-         _17 = _2[_18];                   // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++         _17 = _2[_16];                   // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+          _1 = Add(_1, move _17);          // scope 4 at $DIR/issue_107511.rs:+7:9: +7:20
+          StorageDead(_17);                // scope 4 at $DIR/issue_107511.rs:+7:19: +7:20
+-         StorageDead(_18);                // scope 4 at $DIR/issue_107511.rs:+7:20: +7:21
+-         _10 = const ();                  // scope 4 at $DIR/issue_107511.rs:+6:25: +8:6
+-         StorageDead(_16);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+          StorageDead(_13);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+          StorageDead(_11);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+-         StorageDead(_10);                // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+-         _9 = const ();                   // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+          goto -> bb3;                     // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs
new file mode 100644 (file)
index 0000000..d593f28
--- /dev/null
@@ -0,0 +1,13 @@
+// unit-test: CopyProp
+
+// EMIT_MIR issue_107511.main.CopyProp.diff
+fn main() {
+    let mut sum = 0;
+    let a = [0, 10, 20, 30];
+
+    // `i` is assigned in a loop. Only removing its `StorageDead` would mean that
+    // execution sees repeated `StorageLive`. This would be UB.
+    for i in 0..a.len() {
+        sum += a[i];
+    }
+}
index 6870d7d6c45b457b8459dce4a63f514fdb4cbdc8..9c3f87f47c12c0ebab94e7691ada61e6f4ca4e79 100644 (file)
@@ -16,9 +16,7 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
           _1 = const u8::MAX;              // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
-          StorageLive(_2);                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
           _2 = const 1_u8;                 // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
           _5 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
index df9f8dcf1a407b7496b9f719db0d88d374162b5c..7c5d28069d59d4f2bf1ec800f8fd4e1a7e179eb3 100644 (file)
@@ -79,7 +79,6 @@
       }
   
       bb6: {
-          StorageLive(_10);                // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
           _10 = ((_7 as Some).0: usize);   // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
           StorageLive(_11);                // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
           _11 = &mut (*_1);                // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
index 30bf2c0684e52525ba75d3da0232559318bd75f4..002392c5cf81a24c59eb8b600647cda96a1427a9 100644 (file)
@@ -33,7 +33,6 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
           StorageLive(_3);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58
-          StorageLive(_4);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17
           StorageLive(_12);                // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
           StorageLive(_13);                // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
           _14 = CheckedShr(_1, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
@@ -63,7 +62,6 @@
           StorageDead(_13);                // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
           _4 = BitOr(const 0_u32, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27
           StorageDead(_12);                // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
-          StorageLive(_6);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageLive(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
           StorageLive(_8);                 // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
           _10 = CheckedShr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
index c14780052fb091f257fefbd178c0c05357f2c7c7..cc4f7cc06991f6b77ce66f0cee3f33c8789ede9e 100644 (file)
@@ -29,7 +29,6 @@
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/issue_76432.rs:+1:9: +1:10
-          StorageLive(_4);                 // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
           StorageLive(_5);                 // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
           _5 = [_1, _1, _1];               // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
           _4 = &_5;                        // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
index 35ffc4963cb63b4f8d707e2d633ceca9a720548e..b700adfb105b041ff1401f8de61169c5842846cf 100644 (file)
@@ -10,7 +10,6 @@
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_match.rs:+1:17: +1:18
           _2 = const false;                // scope 0 at $DIR/simplify_match.rs:+1:21: +1:26
 -         switchInt(_2) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
 +         switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
index d1f6fd97dc7c6cf58349fe1e087562b84bb12af5..da6389676f0d47967a061b36841635925825d333 100644 (file)
       }
   
       bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+-         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+-         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+-         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
index 259cd4118960884844bdfedf7e746a4c09ee23bf..294c3272f4f1020b92e7b6da63ae7e8999660947 100644 (file)
       }
   
       bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
           _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
 -         StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
index c3b8e7d2eba256530fe2bff824cb42f06fe898fd..5e4bdbdfa2e2f9683e0b5206db7181c30c81db94 100644 (file)
       }
   
       bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+-         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
           _21 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
           _3 = ((*_21).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+-         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
           _22 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
           _4 = ((*_22).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+-         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
           _23 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
           _5 = ((*_23).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+-         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
           _24 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
           _6 = ((*_24).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
           StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
index a43e84d29c7add13d800b436f50349c55987a8ee..45af6600cd4e8ed268756a700123dbe015795fea 100644 (file)
       }
   
       bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
           _13 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
           _3 = ((*_13).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
           _14 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
           _4 = ((*_14).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
           _15 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
           _5 = ((*_15).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
           _16 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
           _6 = ((*_16).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
 -         StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
index 7c67d2abcf7c37ccf1e0997d8550779a58c4d52f..a4d2660ca6aeb54ff421adcb22bbd51462ab335b 100644 (file)
@@ -30,7 +30,6 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb1: {
-        StorageLive(_5);                 // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
         _5 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
         Deinit(_2);                      // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
         ((_2 as Break).0: E) = move _5;  // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
@@ -40,7 +39,6 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb2: {
-        StorageLive(_4);                 // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
         _4 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
         Deinit(_2);                      // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
         ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
@@ -50,7 +48,6 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb3: {
-        StorageLive(_8);                 // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
         _8 = move ((_2 as Break).0: E);  // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
         Deinit(_0);                      // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
         ((_0 as Err).0: E) = move _8;    // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
@@ -64,7 +61,6 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb5: {
-        StorageLive(_7);                 // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
         _7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
         Deinit(_0);                      // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
         ((_0 as Ok).0: T) = move _7;     // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
index 4a838e140262e76e51434fcb2f51f5bf4a743ea1..37851c66a6076006578e735fee0b181559b75db8 100644 (file)
@@ -19,7 +19,6 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb1: {
-        StorageLive(_4);                 // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
         _4 = move ((_1 as Err).0: E);    // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
         Deinit(_0);                      // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
         ((_0 as Err).0: E) = move _4;    // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
@@ -32,7 +31,6 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
     }
 
     bb3: {
-        StorageLive(_3);                 // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
         _3 = move ((_1 as Ok).0: T);     // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
         Deinit(_0);                      // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
         ((_0 as Ok).0: T) = move _3;     // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
index 4b1e04234c870594bcaaf458bb9b2fbe39507c8c..939da186fbcdb2dcac7b1f6b7f5dca4d7c280f32 100644 (file)
@@ -1,12 +1,10 @@
-// check-pass
 // normalize-stderr-test: "`.*`" -> "`DEF_ID`"
 // normalize-stdout-test: "`.*`" -> "`DEF_ID`"
 // edition:2018
 
 pub async fn f() -> impl std::fmt::Debug {
-    // rustdoc doesn't care that this is infinitely sized
     #[derive(Debug)]
-    enum E {
+    enum E { //~ ERROR
         This(E),
         Unit,
     }
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
new file mode 100644 (file)
index 0000000..aff7402
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0072]: recursive type `DEF_ID` has infinite size
+  --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
+   |
+LL |     enum E {
+   |     ^^^^^^
+LL |         This(E),
+   |              - recursive without indirection
+   |
+help: insert some indirection (e.g., a `DEF_ID`) to break the cycle
+   |
+LL |         This(Box<E>),
+   |              ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `DEF_ID`.
index ac79582fb3f0df48e75c11cc1101e0d9f99ac5bc..ac51725749867cea7f7b979839320140378480d3 100644 (file)
@@ -1,8 +1,5 @@
-// check-pass
-
 fn f() -> impl Sized {
-    // rustdoc doesn't care that this is infinitely sized
-    enum E {
+    enum E { //~ ERROR
         V(E),
     }
     unimplemented!()
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
new file mode 100644 (file)
index 0000000..a61577b
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0072]: recursive type `f::E` has infinite size
+  --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
+   |
+LL |     enum E {
+   |     ^^^^^^
+LL |         V(E),
+   |           - recursive without indirection
+   |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+   |
+LL |         V(Box<E>),
+   |           ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/rustdoc/hidden-private.rs b/tests/rustdoc/hidden-private.rs
new file mode 100644 (file)
index 0000000..834ba52
--- /dev/null
@@ -0,0 +1,50 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/106373>.
+// It ensures that the items in the `doc(hidden)` const block don't show up in the
+// generated docs.
+
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// @count - '//*[@class="item-table"]//a[@class="struct"]' 2
+// @count - '//*[@class="item-table"]//a[@class="trait"]' 1
+// @count - '//*[@class="item-table"]//a[@class="macro"]' 0
+#[doc(hidden)]
+const _: () = {
+    macro_rules! stry {
+        () => {};
+    }
+
+    struct ShouldBeHidden;
+
+    // @has 'foo/struct.Foo.html'
+    // @!has - '//*[@class="code-header"]' 'impl Bar for Foo'
+    #[doc(hidden)]
+    impl Bar for Foo {
+        fn bar(&self) {
+            struct SHouldAlsoBeHidden;
+        }
+    }
+
+    // @has 'foo/struct.Private.html'
+    // @has - '//*[@id="impl-Bar-for-Private"]/*[@class="code-header"]' 'impl Bar for Private'
+    // @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar(&self)'
+    impl Bar for Private {
+        fn bar(&self) {}
+    }
+
+    // @has - '//*[@id="impl-Private"]/*[@class="code-header"]' 'impl Private'
+    // @has - '//*[@id="method.tralala"]/*[@class="code-header"]' 'fn tralala()'
+    impl Private {
+        fn tralala() {}
+    }
+};
+
+
+struct Private;
+pub struct Foo;
+
+pub trait Bar {
+    fn bar(&self);
+}
diff --git a/tests/rustdoc/impl-in-const-block.rs b/tests/rustdoc/impl-in-const-block.rs
new file mode 100644 (file)
index 0000000..b44e713
--- /dev/null
@@ -0,0 +1,43 @@
+// Regression test for #83026.
+// The goal of this test is to ensure that impl blocks inside
+// const expressions are documented as well.
+
+#![crate_name = "foo"]
+
+// @has 'foo/struct.A.html'
+// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)'
+// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)'
+// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()'
+// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()'
+pub struct A;
+
+const _: () = {
+    impl A {
+        const FOO: () = {
+            impl A {
+                pub fn woo(&self) {}
+            }
+        };
+
+        pub fn new() -> A {
+            A
+        }
+    }
+};
+pub const X: () = {
+    impl A {
+        pub fn bar(&self) {}
+    }
+};
+
+fn foo() {
+    impl A {
+        pub fn yoo() {}
+    }
+    const _: () = {
+        impl A {
+            pub fn yuu() {}
+        }
+    };
+}
index e3a14c7a74a0024465899c1c1c85591e447efd8a..5b7a76e1a7739403e4f66a8bda012e8f9413eb6d 100644 (file)
@@ -9,9 +9,10 @@ pub trait Foo {}
 // @has redirect/index.html
 // @has - '//code' 'pub use reexp_stripped::Bar'
 // @has - '//code/a' 'Bar'
+// @has - '//a[@href="../reexp_stripped/hidden/struct.Bar.html"]' 'Bar'
 // @has reexp_stripped/hidden/struct.Bar.html
-// @has - '//p/a' '../../reexp_stripped/struct.Bar.html'
 // @has 'reexp_stripped/struct.Bar.html'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
 #[doc(no_inline)]
 pub use reexp_stripped::Bar;
 impl Foo for Bar {}
diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs
new file mode 100644 (file)
index 0000000..93c69b0
--- /dev/null
@@ -0,0 +1,16 @@
+// edition: 2021
+// run-pass
+
+async fn test(_arg: [u8; 16]) {}
+
+async fn use_future(fut: impl std::future::Future<Output = ()>) {
+    fut.await
+}
+
+fn main() {
+    let actual = std::mem::size_of_val(
+        &use_future(use_future(use_future(use_future(use_future(test([0; 16])))))));
+    // Not using an exact number in case it slightly changes over different commits
+    let expected = 550;
+    assert!(actual > expected, "expected: >{expected}, actual: {actual}");
+}
diff --git a/tests/ui/async-await/future-sizes/large-arg.rs b/tests/ui/async-await/future-sizes/large-arg.rs
new file mode 100644 (file)
index 0000000..7e7ff9d
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// edition: 2021
+// build-pass
+// ignore-pass
+
+pub async fn test() {
+    let _ = a([0u8; 1024]).await;
+}
+
+pub async fn a<T>(t: T) -> T {
+    b(t).await
+}
+async fn b<T>(t: T) -> T {
+    c(t).await
+}
+async fn c<T>(t: T) -> T {
+    t
+}
diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout
new file mode 100644 (file)
index 0000000..c206d79
--- /dev/null
@@ -0,0 +1,60 @@
+print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 3075 bytes
+print-type-size         local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 3074 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.__awaitee`: 2050 bytes
+print-type-size     variant `Unresumed`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 3075 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 3075 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 3075 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 2049 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         local `.__awaitee`: 1025 bytes
+print-type-size     variant `Unresumed`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 2050 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 2050 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 2050 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Unresumed`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 1024 bytes
+print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1025 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1025 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 1025 bytes
+print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Ready`: 1024 bytes
+print-type-size         field `.0`: 1024 bytes
+print-type-size     variant `Pending`: 0 bytes
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed
new file mode 100644 (file)
index 0000000..1a08470
--- /dev/null
@@ -0,0 +1,26 @@
+// run-rustfix
+#![allow(dead_code, path_statements)]
+fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
+    None.into_iter()
+        .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
+        //~^ ERROR captured variable cannot escape `FnMut` closure body
+        //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+fn foo2(s: &str) -> impl Sized + '_ {
+    move |()| s.chars().map(move |c| format!("{}{}", c, s))
+    //~^ ERROR lifetime may not live long enough
+    //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+pub struct X;
+pub fn foo3<'a>(
+    bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+    Some(()).iter().flat_map(move |()| {
+        Some(()).iter().map(move |()| { bar; }) //~ ERROR captured variable cannot escape
+        //~^ HELP consider adding 'move' keyword before the nested closure
+    })
+}
+
+fn main() {}
index 95847d8d301a65249988a6bf843bdd7fd194858d..b93292e3589d371a67bad831dc716efc96ff59d0 100644 (file)
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(dead_code, path_statements)]
 fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
     None.into_iter()
         .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
@@ -11,4 +13,14 @@ fn foo2(s: &str) -> impl Sized + '_ {
     //~| HELP consider adding 'move' keyword before the nested closure
 }
 
+pub struct X;
+pub fn foo3<'a>(
+    bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+    Some(()).iter().flat_map(move |()| {
+        Some(()).iter().map(|()| { bar; }) //~ ERROR captured variable cannot escape
+        //~^ HELP consider adding 'move' keyword before the nested closure
+    })
+}
+
 fn main() {}
index 2eae614a2f5987504231e3960ed06c097fab10b2..776c338deacf40f4c6d2db778e8e710f44557d40 100644 (file)
@@ -1,5 +1,5 @@
 error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29
+  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:5:29
    |
 LL | fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
    |         - variable defined here
@@ -7,7 +7,7 @@ LL |     None.into_iter()
 LL |         .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
    |                           - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                           | |
-   |                           | returns a reference to a captured variable which escapes the closure body
+   |                           | returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |                           | variable captured here
    |                           inferred to be a `FnMut` closure
    |
@@ -19,12 +19,12 @@ LL |         .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
    |                                           ++++
 
 error: lifetime may not live long enough
-  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15
+  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:11:15
    |
 LL |     move |()| s.chars().map(|c| format!("{}{}", c, s))
    |     --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
    |     |       |
-   |     |       return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2`
+   |     |       return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2`
    |     lifetime `'1` represents this closure's body
    |
    = note: closure implements `Fn`, so references to captured variables can't escape the closure
@@ -33,5 +33,26 @@ help: consider adding 'move' keyword before the nested closure
 LL |     move |()| s.chars().map(move |c| format!("{}{}", c, s))
    |                             ++++
 
-error: aborting due to 2 previous errors
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-95079-missing-move-in-nested-closure.rs:21:9
+   |
+LL |     bar: &'a X,
+   |     --- variable defined here
+LL | ) -> impl Iterator<Item = ()> + 'a {
+LL |     Some(()).iter().flat_map(move |()| {
+   |                                      - inferred to be a `FnMut` closure
+LL |         Some(()).iter().map(|()| { bar; })
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^^
+   |         |                          |
+   |         |                          variable captured here
+   |         returns a closure that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+help: consider adding 'move' keyword before the nested closure
+   |
+LL |         Some(()).iter().map(move |()| { bar; })
+   |                             ++++
+
+error: aborting due to 3 previous errors
 
index bfe1ed32859b928fb4886a9f05a17bfc8332cdb4..589b2c3784926dc5a35ef647a26f02be58708b96 100644 (file)
@@ -2,7 +2,12 @@ error: expected field pattern, found `...`
   --> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55
    |
 LL |             PersonalityInventory { expressivity: exp, ... } => exp
-   |                                                       ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+   |                                                       ^^^
+   |
+help: to omit remaining fields, use `..`
+   |
+LL |             PersonalityInventory { expressivity: exp, .. } => exp
+   |                                                       ~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs
new file mode 100644 (file)
index 0000000..0bad540
--- /dev/null
@@ -0,0 +1,15 @@
+fn main() {
+    let bar = 3;
+    format!("{?:}", bar);
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    format!("{?:bar}");
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    format!("{?:?}", bar);
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+    format!("{??}", bar);
+    //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+    format!("{?;bar}");
+    //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+    format!("{?:#?}", bar);
+    //~^ ERROR invalid format string: expected format parameter to occur after `:`
+}
diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr
new file mode 100644 (file)
index 0000000..461af35
--- /dev/null
@@ -0,0 +1,54 @@
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:3:15
+   |
+LL |     format!("{?:}", bar);
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:5:15
+   |
+LL |     format!("{?:bar}");
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `bar:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:7:15
+   |
+LL |     format!("{?:?}", bar);
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected `'}'`, found `'?'`
+  --> $DIR/format-string-wrong-order.rs:9:15
+   |
+LL |     format!("{??}", bar);
+   |              -^ expected `}` in format string
+   |              |
+   |              because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'?'`
+  --> $DIR/format-string-wrong-order.rs:11:15
+   |
+LL |     format!("{?;bar}");
+   |              -^ expected `}` in format string
+   |              |
+   |              because of this opening brace
+   |
+   = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected format parameter to occur after `:`
+  --> $DIR/format-string-wrong-order.rs:13:15
+   |
+LL |     format!("{?:#?}", bar);
+   |               ^ expected `?` to occur after `:` in format string
+   |
+   = note: `?` comes after `:`, try `:?` instead
+
+error: aborting due to 6 previous errors
+
index 7ba2b6d857cd0207ae19ee3eee3806ba65ad7f34..30173b1b4be031eb2642eab7234bb7b65e439548 100644 (file)
@@ -2,7 +2,8 @@ fn main() {
     let x = 42;
     match x {
         0..=73 => {},
-        74..=> {},   //~ ERROR unexpected `=>` after open range
-                     //~^ ERROR expected one of `=>`, `if`, or `|`, found `>`
+        74..=> {},
+        //~^ ERROR unexpected `>` after inclusive range
+        //~| NOTE this is parsed as an inclusive range `..=`
     }
 }
index 9ba6d15113cd648775785808181b66bb0782d73c..cb7f998df7a5b1471191ee7c46381b2662caf061 100644 (file)
@@ -1,19 +1,15 @@
-error: unexpected `=>` after open range
-  --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:11
+error: unexpected `>` after inclusive range
+  --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14
    |
 LL |         74..=> {},
-   |           ^^^
+   |           ---^
+   |           |
+   |           this is parsed as an inclusive range `..=`
    |
 help: add a space between the pattern and `=>`
    |
 LL |         74.. => {},
    |             +
 
-error: expected one of `=>`, `if`, or `|`, found `>`
-  --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14
-   |
-LL |         74..=> {},
-   |              ^ expected one of `=>`, `if`, or `|`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 6872b8bc0afec880c9f4e66f23ca63381d8fa5bf..ba8174a823b2a30991c0179edbc664a6c8f4e202 100644 (file)
@@ -32,7 +32,12 @@ error: expected field pattern, found `...`
   --> $DIR/issue-102806.rs:21:22
    |
 LL |     let V3 { z: val, ... } = v;
-   |                      ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+   |                      ^^^
+   |
+help: to omit remaining fields, use `..`
+   |
+LL |     let V3 { z: val, .. } = v;
+   |                      ~~
 
 error[E0063]: missing fields `x` and `y` in initializer of `V3`
   --> $DIR/issue-102806.rs:17:13
index 80e9ac5bedf13292da7a83650e3de4311a7e4953..e0dc356d5467bb996d9c9db592bf4dc0859e411d 100644 (file)
@@ -20,7 +20,12 @@ error: expected field pattern, found `...`
   --> $DIR/issue-63135.rs:3:8
    |
 LL | fn i(n{...,f #
-   |        ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+   |        ^^^
+   |
+help: to omit remaining fields, use `..`
+   |
+LL | fn i(n{..,f #
+   |        ~~
 
 error: expected `}`, found `,`
   --> $DIR/issue-63135.rs:3:11
index 0b7b67496d6f32df39107feb43e1c957a029ae21..e1ea38f2795df698983f335bbf6b77f13d29dad1 100644 (file)
@@ -68,7 +68,6 @@ fn main() {
         Foo:Bar::Baz => {}
         //~^ ERROR: expected one of
         //~| HELP: maybe write a path separator here
-        //~| ERROR: failed to resolve: `Bar` is a variant, not a module
     }
     match myfoo {
         Foo::Bar => {}
index 2050a16beb34983c63e96f847a82c1d23f3f16d5..63b072ac4cdc68c6c4f9ec8734f49945c45de38e 100644 (file)
@@ -2,89 +2,118 @@ error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:17:12
    |
 LL |         Foo:Bar => {}
-   |            ^
+   |            ^--- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         Foo::Bar => {}
+   |            ~~
 
 error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:23:17
    |
 LL |         qux::Foo:Bar => {}
-   |                 ^
+   |                 ^--- specifying the type of a pattern isn't supported
    |                 |
    |                 expected one of 8 possible tokens
-   |                 help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         qux::Foo::Bar => {}
+   |                 ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:29:12
    |
 LL |         qux:Foo::Baz => {}
-   |            ^
+   |            ^-------- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         qux::Foo::Baz => {}
+   |            ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:35:12
    |
 LL |         qux: Foo::Baz if true => {}
-   |            ^
+   |            ^ -------- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         qux::Foo::Baz if true => {}
+   |            ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:40:15
    |
 LL |     if let Foo:Bar = f() {
-   |               ^
+   |               ^--- specifying the type of a pattern isn't supported
    |               |
    |               expected one of `@` or `|`
-   |               help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |     if let Foo::Bar = f() {
+   |               ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:48:16
    |
 LL |         ref qux: Foo::Baz => {}
-   |                ^
+   |                ^ -------- specifying the type of a pattern isn't supported
    |                |
    |                expected one of `@` or `|`
-   |                help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         ref qux::Foo::Baz => {}
+   |                ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:57:16
    |
 LL |         mut qux: Foo::Baz => {}
-   |                ^
+   |                ^ -------- specifying the type of a pattern isn't supported
    |                |
    |                expected one of `@` or `|`
-   |                help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         mut qux::Foo::Baz => {}
+   |                ~~
 
 error: expected one of `@` or `|`, found `:`
   --> $DIR/issue-87086-colon-path-sep.rs:68:12
    |
 LL |         Foo:Bar::Baz => {}
-   |            ^
+   |            ^-------- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
+   |
+help: maybe write a path separator here
+   |
+LL |         Foo::Bar::Baz => {}
+   |            ~~
 
 error: expected one of `@` or `|`, found `:`
-  --> $DIR/issue-87086-colon-path-sep.rs:75:12
+  --> $DIR/issue-87086-colon-path-sep.rs:74:12
    |
 LL |         Foo:Bar => {}
-   |            ^
+   |            ^--- specifying the type of a pattern isn't supported
    |            |
    |            expected one of `@` or `|`
-   |            help: maybe write a path separator here: `::`
-
-error[E0433]: failed to resolve: `Bar` is a variant, not a module
-  --> $DIR/issue-87086-colon-path-sep.rs:68:13
    |
-LL |         Foo:Bar::Baz => {}
-   |             ^^^ `Bar` is a variant, not a module
+help: maybe write a path separator here
+   |
+LL |         Foo::Bar => {}
+   |            ~~
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
-For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs
new file mode 100644 (file)
index 0000000..fec168a
--- /dev/null
@@ -0,0 +1,16 @@
+fn foo(x: bool) -> i32 {
+    match x {
+        x: i32 => x, //~ ERROR expected
+        //~^ ERROR mismatched types
+        true => 42.,
+        false => 0.333,
+    }
+}
+
+fn main() {
+    match foo(true) {
+        42: i32 => (), //~ ERROR expected
+        _: f64 => (), //~ ERROR expected
+        x: i32 => (), //~ ERROR expected
+    }
+}
diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr
new file mode 100644 (file)
index 0000000..0919075
--- /dev/null
@@ -0,0 +1,54 @@
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:3:10
+   |
+LL |         x: i32 => x,
+   |          ^ --- specifying the type of a pattern isn't supported
+   |          |
+   |          expected one of `@` or `|`
+   |
+help: maybe write a path separator here
+   |
+LL |         x::i32 => x,
+   |          ~~
+
+error: expected one of `...`, `..=`, `..`, or `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:12:11
+   |
+LL |         42: i32 => (),
+   |           ^ --- specifying the type of a pattern isn't supported
+   |           |
+   |           expected one of `...`, `..=`, `..`, or `|`
+
+error: expected `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:13:10
+   |
+LL |         _: f64 => (),
+   |          ^ --- specifying the type of a pattern isn't supported
+   |          |
+   |          expected `|`
+
+error: expected one of `@` or `|`, found `:`
+  --> $DIR/type-ascription-in-pattern.rs:14:10
+   |
+LL |         x: i32 => (),
+   |          ^ --- specifying the type of a pattern isn't supported
+   |          |
+   |          expected one of `@` or `|`
+   |
+help: maybe write a path separator here
+   |
+LL |         x::i32 => (),
+   |          ~~
+
+error[E0308]: mismatched types
+  --> $DIR/type-ascription-in-pattern.rs:3:19
+   |
+LL | fn foo(x: bool) -> i32 {
+   |                    --- expected `i32` because of return type
+LL |     match x {
+LL |         x: i32 => x,
+   |                   ^ expected `i32`, found `bool`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 0b89d0b160b3db12e645fe0217b414c98acdb4db..9bb87026b6418b00eaf1b8d778549f5e733583eb 100644 (file)
@@ -1,7 +1,11 @@
 // check-pass
 // compile-flags: -Zhir-stats
 // only-x86_64
-// ignore-stage1  FIXME: remove after next bootstrap bump
+
+// Type layouts sometimes change. When that happens, until the next bootstrap
+// bump occurs, stage1 and stage2 will give different outputs for this test.
+// Add an `ignore-stage1` comment marker to work around that problem during
+// that time.
 
 // The aim here is to include at least one of every different type of top-level
 // AST/HIR node reported by `-Zhir-stats`.
index c30b8a1e1f1a7c3bd74f599c7f7e3feae8d87e5f..b569993c6143edeff75e58bcf35395ba12bcee61 100644 (file)
@@ -7,6 +7,5 @@ fn main() {
     let foo = Some(Foo::Other);
 
     if let Some(Foo::Bar {_}) = foo {}
-    //~^ ERROR expected identifier, found reserved identifier `_`
-    //~| ERROR pattern does not mention field `bar` [E0027]
+    //~^ ERROR expected field pattern, found `_`
 }
index 16f751444a558c6d67cd2a567e32d3747b031ddf..2f3a150e5cba92566aadd814edcbad3e2fb000a4 100644 (file)
@@ -1,24 +1,13 @@
-error: expected identifier, found reserved identifier `_`
+error: expected field pattern, found `_`
   --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27
    |
 LL |     if let Some(Foo::Bar {_}) = foo {}
-   |                           ^ expected identifier, found reserved identifier
-
-error[E0027]: pattern does not mention field `bar`
-  --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17
-   |
-LL |     if let Some(Foo::Bar {_}) = foo {}
-   |                 ^^^^^^^^^^^^ missing field `bar`
-   |
-help: include the missing field in the pattern
+   |                           ^
    |
-LL |     if let Some(Foo::Bar {_, bar }) = foo {}
-   |                            ~~~~~~~
-help: if you don't care about this missing field, you can explicitly ignore it
+help: to omit remaining fields, use `..`
    |
-LL |     if let Some(Foo::Bar {_, .. }) = foo {}
-   |                            ~~~~~~
+LL |     if let Some(Foo::Bar {..}) = foo {}
+   |                           ~~
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0027`.
diff --git a/tests/ui/uninhabited/issue-107505.rs b/tests/ui/uninhabited/issue-107505.rs
new file mode 100644 (file)
index 0000000..6159854
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+// Make sure we don't pass inference variables to uninhabitedness checks in borrowck
+
+struct Command<'s> {
+    session: &'s (),
+    imp: std::convert::Infallible,
+}
+
+fn command(_: &()) -> Command<'_> {
+    unreachable!()
+}
+
+fn with_session<'s>(a: &std::process::Command, b: &'s ()) -> Command<'s> {
+    a.get_program();
+    command(b)
+}