diff options
399 files changed, 4635 insertions, 3945 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6693182e0c5..771cef6e4d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -297,7 +297,7 @@ jobs: os: ubuntu-20.04-xl - name: dist-x86_64-apple env: - SCRIPT: "./x.py dist --host=x86_64-apple-darwin --target=x86_64-apple-darwin" + SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -308,7 +308,7 @@ jobs: os: macos-latest - name: dist-apple-various env: - SCRIPT: "./x.py dist --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" + SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -318,7 +318,7 @@ jobs: os: macos-latest - name: dist-x86_64-apple-alt env: - SCRIPT: "./x.py dist" + SCRIPT: "./x.py dist bootstrap --include-default-paths" RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -350,7 +350,7 @@ jobs: os: macos-latest - name: dist-aarch64-apple env: - SCRIPT: "./x.py dist --stage 2" + SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --host=aarch64-apple-darwin --target=aarch64-apple-darwin --enable-full-tools --enable-sanitizers --enable-profiler --disable-docs --set rust.jemalloc --set llvm.ninja=false" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 USE_XCODE_CLANG: 1 @@ -424,19 +424,19 @@ jobs: - name: dist-x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist + SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 os: windows-latest-xl - name: dist-i686-msvc env: RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 os: windows-latest-xl - name: dist-aarch64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 WINDOWS_SDK_20348_HACK: 1 os: windows-latest-xl @@ -444,13 +444,13 @@ jobs: env: RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain" NO_DOWNLOAD_CI_LLVM: 1 - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 os: windows-latest-xl - name: dist-x86_64-mingw env: - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain" NO_DOWNLOAD_CI_LLVM: 1 CUSTOM_MINGW: 1 @@ -459,7 +459,7 @@ jobs: - name: dist-x86_64-msvc-alt env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-extended --enable-profiler" - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths os: windows-latest-xl timeout-minutes: 600 runs-on: "${{ matrix.os }}" diff --git a/Cargo.lock b/Cargo.lock index cec227d2ed6..16c0b644e4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3263,7 +3263,6 @@ dependencies = [ "bitflags", "cstr", "libc", - "libloading", "measureme", "object 0.29.0", "rustc-demangle", diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 24672efc63c..85306d7184d 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -237,7 +237,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Wrap the expression in an AnonConst. let parent_def_id = self.current_hir_id_owner; let node_id = self.next_node_id(); - self.create_def(parent_def_id, node_id, DefPathData::AnonConst); + self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst); let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { anon_const: self.lower_anon_const(&anon_const), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6c09269352c..94137391568 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -359,7 +359,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, DefPathData::AnonConst); + self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst); let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 85846b56762..6d716796343 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -24,7 +24,7 @@ pub(super) struct NodeCollector<'a, 'hir> { /// The parent of this node parent_node: hir::ItemLocalId, - owner: LocalDefId, + owner: OwnerId, definitions: &'a definitions::Definitions, } @@ -81,9 +81,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", self.source_map.span_to_diagnostic_string(span), node, - self.definitions.def_path(self.owner).to_string_no_crate_verbose(), + self.definitions.def_path(self.owner.def_id).to_string_no_crate_verbose(), self.owner, - self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(), + self.definitions.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(), hir_id.owner, ) } @@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - self.insert_nested(item.def_id); + self.insert_nested(item.def_id.def_id); } fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - self.insert_nested(item_id.def_id); + self.insert_nested(item_id.def_id.def_id); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.insert_nested(item_id.def_id); + self.insert_nested(item_id.def_id.def_id); } fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { - self.insert_nested(foreign_id.def_id); + self.insert_nested(foreign_id.def_id.def_id); } fn visit_nested_body(&mut self, id: BodyId) { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dfd04fe2974..d9b18d68e53 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -68,7 +68,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { bodies: Vec::new(), attrs: SortedMap::default(), children: FxHashMap::default(), - current_hir_id_owner: CRATE_DEF_ID, + current_hir_id_owner: hir::CRATE_OWNER_ID, item_local_id_counter: hir::ItemLocalId::new(0), node_id_to_local_id: Default::default(), local_id_to_def_id: SortedMap::new(), @@ -177,7 +177,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { - let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }]; + let mut node_ids = + smallvec![hir::ItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; if let ItemKind::Use(ref use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); } @@ -193,7 +194,9 @@ impl<'hir> LoweringContext<'_, 'hir> { match tree.kind { UseTreeKind::Nested(ref nested_vec) => { for &(ref nested, id) in nested_vec { - vec.push(hir::ItemId { def_id: self.local_def_id(id) }); + vec.push(hir::ItemId { + def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + }); self.lower_item_id_use_tree(nested, id, vec); } } @@ -202,7 +205,9 @@ impl<'hir> LoweringContext<'_, 'hir> { for (_, &id) in iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) { - vec.push(hir::ItemId { def_id: self.local_def_id(id) }); + vec.push(hir::ItemId { + def_id: hir::OwnerId { def_id: self.local_def_id(id) }, + }); } } } @@ -553,7 +558,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: new_id, + def_id: hir::OwnerId { def_id: new_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -627,7 +632,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let item = hir::Item { - def_id: new_hir_id, + def_id: hir::OwnerId { def_id: new_hir_id }, ident: this.lower_ident(ident), kind, vis_span, @@ -689,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { hir::ForeignItemRef { - id: hir::ForeignItemId { def_id: self.local_def_id(i.id) }, + id: hir::ForeignItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), } @@ -851,7 +856,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::MacCall(..) => unimplemented!(), }; - let id = hir::TraitItemId { def_id: self.local_def_id(i.id) }; + let id = hir::TraitItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; hir::TraitItemRef { id, ident: self.lower_ident(i.ident), @@ -931,7 +936,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { hir::ImplItemRef { - id: hir::ImplItemId { def_id: self.local_def_id(i.id) }, + id: hir::ImplItemId { def_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }, ident: self.lower_ident(i.ident), span: self.lower_span(i.span), kind: match &i.kind { @@ -1050,9 +1055,9 @@ impl<'hir> LoweringContext<'_, 'hir> { asyncness: Async, body: Option<&Block>, ) -> hir::BodyId { - let closure_id = match asyncness { - Async::Yes { closure_id, .. } => closure_id, - Async::No => return self.lower_fn_body_block(span, decl, body), + let (closure_id, body) = match (asyncness, body) { + (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body), + _ => return self.lower_fn_body_block(span, decl, body), }; self.lower_body(|this| { @@ -1194,16 +1199,15 @@ impl<'hir> LoweringContext<'_, 'hir> { parameters.push(new_parameter); } - let body_span = body.map_or(span, |b| b.span); let async_expr = this.make_async_expr( CaptureBy::Value, closure_id, None, - body_span, + body.span, hir::AsyncGeneratorKind::Fn, |this| { // Create a block from the user's function body: - let user_body = this.lower_block_expr_opt(body_span, body); + let user_body = this.lower_block_expr(body); // Transform into `drop-temps { <user-body> }`, an expression: let desugared_span = @@ -1235,7 +1239,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( this.arena.alloc_from_iter(parameters), - this.expr(body_span, async_expr, AttrVec::new()), + this.expr(body.span, async_expr, AttrVec::new()), ) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a11721ba021..186c10065f3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -126,7 +126,7 @@ struct LoweringContext<'a, 'hir> { is_in_trait_impl: bool, is_in_dyn_type: bool, - current_hir_id_owner: LocalDefId, + current_hir_id_owner: hir::OwnerId, item_local_id_counter: hir::ItemLocalId, local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>, trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>, @@ -572,7 +572,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let current_node_ids = std::mem::take(&mut self.node_id_to_local_id); let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); let current_trait_map = std::mem::take(&mut self.trait_map); - let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id); + let current_owner = + std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id }); let current_local_counter = std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); @@ -587,7 +588,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert_eq!(_old, None); let item = f(self); - debug_assert_eq!(def_id, item.def_id()); + debug_assert_eq!(def_id, item.def_id().def_id); // `f` should have consumed all the elements in these vectors when constructing `item`. debug_assert!(self.impl_trait_defs.is_empty()); debug_assert!(self.impl_trait_bounds.is_empty()); @@ -786,7 +787,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { if self.tcx.sess.opts.unstable_opts.incremental_relative_spans { - span.with_parent(Some(self.current_hir_id_owner)) + span.with_parent(Some(self.current_hir_id_owner.def_id)) } else { // Do not make spans relative when not using incremental compilation. span @@ -812,7 +813,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( - self.current_hir_id_owner, + self.current_hir_id_owner.def_id, param, DefPathData::LifetimeNs(kw::UnderscoreLifetime), ); @@ -1062,7 +1063,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_hir_id_owner; let impl_trait_node_id = self.next_node_id(); - self.create_def(parent_def_id, impl_trait_node_id, DefPathData::ImplTrait); + self.create_def( + parent_def_id.def_id, + impl_trait_node_id, + DefPathData::ImplTrait, + ); self.with_dyn_type_scope(false, |this| { let node_id = this.next_node_id(); @@ -1154,7 +1159,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, DefPathData::AnonConst); + self.create_def( + parent_def_id.def_id, + node_id, + DefPathData::AnonConst, + ); let span = self.lower_span(ty.span); let path_expr = Expr { @@ -1551,7 +1560,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?lifetimes); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. - hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) + hir::TyKind::OpaqueDef( + hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, + lifetimes, + in_trait, + ) } /// Registers a new opaque type with the proper `NodeId`s and @@ -1567,7 +1580,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Generate an `type Foo = impl Trait;` declaration. trace!("registering opaque type with id {:#?}", opaque_ty_id); let opaque_ty_item = hir::Item { - def_id: opaque_ty_id, + def_id: hir::OwnerId { def_id: opaque_ty_id }, ident: Ident::empty(), kind: opaque_ty_item_kind, vis_span: self.lower_span(span.shrink_to_lo()), @@ -2018,7 +2031,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::OpaqueDef( - hir::ItemId { def_id: opaque_ty_def_id }, + hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } }, generic_args, in_trait, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7fff5988785..799b3f7f575 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span, move_spans, *moved_place, - Some(used_place), partially_str, loop_message, move_msg, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index baabeea5823..7ccb679d88b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -972,7 +972,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, move_spans: UseSpans<'tcx>, moved_place: Place<'tcx>, - used_place: Option<PlaceRef<'tcx>>, partially_str: &str, loop_message: &str, move_msg: &str, @@ -1060,9 +1059,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place_name, partially_str, loop_message ), ); - // If we have a `&mut` ref, we need to reborrow. - if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place - .map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind()) + // If the moved place was a `&mut` ref, then we can + // suggest to reborrow it where it was moved, so it + // will still be valid by the time we get to the usage. + if let ty::Ref(_, _, hir::Mutability::Mut) = + moved_place.ty(self.body, self.infcx.tcx).ty.kind() { // If we are in a loop this will be suggested later. if !is_loop_move { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 8d4c38d3a8e..5a47f45677e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(use_spans) = use_spans { self.explain_captures( - &mut err, span, span, use_spans, move_place, None, "", "", "", false, true, + &mut err, span, span, use_spans, move_place, "", "", "", false, true, ); } err diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 202729b4744..8ad40c0aa0a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -932,7 +932,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let opt_suggestions = self .infcx .tcx - .typeck(path_segment.hir_id.owner) + .typeck(path_segment.hir_id.owner.def_id) .type_dependent_def_id(*hir_id) .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id)) .map(|def_id| self.infcx.tcx.associated_items(def_id)) @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if look_at_return && hir.get_return_block(closure_id).is_some() { // ...otherwise we are probably in the tail expression of the function, point at the // return type. - match hir.get_by_def_id(hir.get_parent_item(fn_call_id)) { + match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) { hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. }) | hir::Node::TraitItem(hir::TraitItem { ident, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 34be2874fcb..43d67bfa729 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -281,7 +281,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; match tcx.hir().get_if_local(def_id) { Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { + match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) + { Some(Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. @@ -291,7 +292,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } Some(Node::TraitItem(trait_item)) => { let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did) { + match tcx.hir().find_by_def_id(trait_did.def_id) { Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { // The method being called is defined in the `trait`, but the `'static` // obligation comes from the `impl`. Find that `impl` so that we can point diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 6c1eaa809c9..419e6c81791 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -707,7 +707,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::AsyncGeneratorKind::Block => " of async block", hir::AsyncGeneratorKind::Closure => " of async closure", hir::AsyncGeneratorKind::Fn => { - let parent_item = hir.get_by_def_id(hir.get_parent_item(mir_hir_id)); + let parent_item = + hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id); let output = &parent_item .fn_decl() .expect("generator lowered from async fn should be in fn") diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index cb16bec57ee..6b90f2daeea 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -134,7 +134,7 @@ fn mir_borrowck<'tcx>( let opt_closure_req = tcx .infer_ctxt() - .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner)) + .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)) .enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow(); diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index f1b1c33a105..e0140e281ee 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -362,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); } + + OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => { + self.region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a)); + } } } } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 74115353aaf..a068aa2ec62 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,6 @@ doctest = false bitflags = "1.0" cstr = "0.2" libc = "0.2" -libloading = "0.7.1" measureme = "10.0.0" object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] } tracing = "0.1" diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index a89df00e248..2049422b79a 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,8 +1,6 @@ -use crate::back::write::{ - self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers, -}; -use crate::llvm::{self, build_string, False, True}; -use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm}; +use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers}; +use crate::llvm::{self, build_string}; +use crate::{LlvmCodegenBackend, ModuleLlvm}; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; @@ -597,61 +595,9 @@ pub(crate) fn run_pass_manager( 1, ); } - if llvm_util::should_use_new_llvm_pass_manager( - &config.new_llvm_pass_manager, - &cgcx.target_arch, - ) { - let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; - let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); - write::optimize_with_new_llvm_pass_manager( - cgcx, - diag_handler, - module, - config, - opt_level, - opt_stage, - )?; - debug!("lto done"); - return Ok(()); - } - - let pm = llvm::LLVMCreatePassManager(); - llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm); - - if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); - llvm::LLVMRustAddPass(pm, pass.unwrap()); - } - - let opt_level = config - .opt_level - .map(|x| to_llvm_opt_settings(x).0) - .unwrap_or(llvm::CodeGenOptLevel::None); - with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| { - if thin { - llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm); - } else { - llvm::LLVMRustPassManagerBuilderPopulateLTOPassManager( - b, pm, /* Internalize = */ False, /* RunInliner = */ True, - ); - } - }); - - // We always generate bitcode through ThinLTOBuffers, - // which do not support anonymous globals - if config.bitcode_needed() { - let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast()); - llvm::LLVMRustAddPass(pm, pass.unwrap()); - } - - if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); - llvm::LLVMRustAddPass(pm, pass.unwrap()); - } - - llvm::LLVMRunPassManager(pm, module.module_llvm.llmod()); - - llvm::LLVMDisposePassManager(pm); + let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; + let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); + write::llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?; } debug!("lto done"); Ok(()) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a695df8409b..db526746fa7 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -21,7 +21,6 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; -use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; use rustc_session::Session; @@ -417,7 +416,7 @@ fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> { } } -pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( +pub(crate) unsafe fn llvm_optimize( cgcx: &CodegenContext<LlvmCodegenBackend>, diag_handler: &Handler, module: &ModuleCodegen<ModuleLlvm>, @@ -465,7 +464,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. // We would have to add upstream support for this first, before we can support // config.inline_threshold and our more aggressive default thresholds. - let result = llvm::LLVMRustOptimizeWithNewPassManager( + let result = llvm::LLVMRustOptimize( module.module_llvm.llmod(), &*module.module_llvm.tm, to_pass_builder_opt_level(opt_level), @@ -509,18 +508,11 @@ pub(crate) unsafe fn optimize( let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; - let tm = &*module.module_llvm.tm; let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); let module_name = module.name.clone(); let module_name = Some(&module_name[..]); - if let Some(false) = config.new_llvm_pass_manager && llvm_util::get_version() >= (15, 0, 0) { - diag_handler.warn( - "ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported with LLVM 15", - ); - } - if config.emit_no_opt_bc { let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); let out = path_to_c_string(&out); @@ -528,184 +520,17 @@ pub(crate) unsafe fn optimize( } if let Some(opt_level) = config.opt_level { - if llvm_util::should_use_new_llvm_pass_manager( - &config.new_llvm_pass_manager, - &cgcx.target_arch, - ) { - let opt_stage = match cgcx.lto { - Lto::Fat => llvm::OptStage::PreLinkFatLTO, - Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, - _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, - _ => llvm::OptStage::PreLinkNoLTO, - }; - return optimize_with_new_llvm_pass_manager( - cgcx, - diag_handler, - module, - config, - opt_level, - opt_stage, - ); - } - - if cgcx.prof.llvm_recording_enabled() { - diag_handler - .warn("`-Z self-profile-events = llvm` requires `-Z new-llvm-pass-manager`"); - } - - // Create the two optimizing pass managers. These mirror what clang - // does, and are by populated by LLVM's default PassManagerBuilder. - // Each manager has a different set of passes, but they also share - // some common passes. - let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); - let mpm = llvm::LLVMCreatePassManager(); - - { - let find_pass = |pass_name: &str| { - let pass_name = SmallCStr::new(pass_name); - llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) - }; - - if config.verify_llvm_ir { - // Verification should run as the very first pass. - llvm::LLVMRustAddPass(fpm, find_pass("verify").unwrap()); - } - - let mut extra_passes = Vec::new(); - let mut have_name_anon_globals_pass = false; - - for pass_name in &config.passes { - if pass_name == "lint" { - // Linting should also be performed early, directly on the generated IR. - llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap()); - continue; - } - - if let Some(pass) = find_pass(pass_name) { - extra_passes.push(pass); - } else { - diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass_name)); - } - - if pass_name == "name-anon-globals" { - have_name_anon_globals_pass = true; - } - } - - // Instrumentation must be inserted before optimization, - // otherwise LLVM may optimize some functions away which - // breaks llvm-cov. - // - // This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp. - if config.instrument_gcov { - llvm::LLVMRustAddPass(mpm, find_pass("insert-gcov-profiling").unwrap()); - } - if config.instrument_coverage { - llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap()); - } - if config.debug_info_for_profiling { - llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap()); - } - - add_sanitizer_passes(config, &mut extra_passes); - - // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need - // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise - // we'll get errors in LLVM. - let using_thin_buffers = config.bitcode_needed(); - if !config.no_prepopulate_passes { - llvm::LLVMAddAnalysisPasses(tm, fpm); - llvm::LLVMAddAnalysisPasses(tm, mpm); - let opt_level = to_llvm_opt_settings(opt_level).0; - let prepare_for_thin_lto = cgcx.lto == Lto::Thin - || cgcx.lto == Lto::ThinLocal - || (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled()); - with_llvm_pmb(llmod, config, opt_level, prepare_for_thin_lto, &mut |b| { - llvm::LLVMRustAddLastExtensionPasses( - b, - extra_passes.as_ptr(), - extra_passes.len() as size_t, - ); - llvm::LLVMRustPassManagerBuilderPopulateFunctionPassManager(b, fpm); - llvm::LLVMRustPassManagerBuilderPopulateModulePassManager(b, mpm); - }); - - have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto; - if using_thin_buffers && !prepare_for_thin_lto { - llvm::LLVMRustAddPass(mpm, find_pass("name-anon-globals").unwrap()); - have_name_anon_globals_pass = true; - } - } else { - // If we don't use the standard pipeline, directly populate the MPM - // with the extra passes. - for pass in extra_passes { - llvm::LLVMRustAddPass(mpm, pass); - } - } - - if using_thin_buffers && !have_name_anon_globals_pass { - // As described above, this will probably cause an error in LLVM - if config.no_prepopulate_passes { - diag_handler.err( - "The current compilation is going to use thin LTO buffers \ - without running LLVM's NameAnonGlobals pass. \ - This will likely cause errors in LLVM. Consider adding \ - -C passes=name-anon-globals to the compiler command line.", - ); - } else { - bug!( - "We are using thin LTO buffers without running the NameAnonGlobals pass. \ - This will likely cause errors in LLVM and should never happen." - ); - } - } - } - - diag_handler.abort_if_errors(); - - // Finally, run the actual optimization passes - { - let _timer = cgcx.prof.extra_verbose_generic_activity( - "LLVM_module_optimize_function_passes", - &*module.name, - ); - llvm::LLVMRustRunFunctionPassManager(fpm, llmod); - } - { - let _timer = cgcx.prof.extra_verbose_generic_activity( - "LLVM_module_optimize_module_passes", - &*module.name, - ); - llvm::LLVMRunPassManager(mpm, llmod); - } - - // Deallocate managers that we're now done with - llvm::LLVMDisposePassManager(fpm); - llvm::LLVMDisposePassManager(mpm); + let opt_stage = match cgcx.lto { + Lto::Fat => llvm::OptStage::PreLinkFatLTO, + Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, + _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, + _ => llvm::OptStage::PreLinkNoLTO, + }; + return llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage); } Ok(()) } -unsafe fn add_sanitizer_passes(config: &ModuleConfig, passes: &mut Vec<&'static mut llvm::Pass>) { - if config.sanitizer.contains(SanitizerSet::ADDRESS) { - let recover = config.sanitizer_recover.contains(SanitizerSet::ADDRESS); - passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover)); - passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover)); - } - if config.sanitizer.contains(SanitizerSet::MEMORY) { - let track_origins = config.sanitizer_memory_track_origins as c_int; - let recover = config.sanitizer_recover.contains(SanitizerSet::MEMORY); - passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover)); - } - if config.sanitizer.contains(SanitizerSet::THREAD) { - passes.push(llvm::LLVMRustCreateThreadSanitizerPass()); - } - if config.sanitizer.contains(SanitizerSet::HWADDRESS) { - let recover = config.sanitizer_recover.contains(SanitizerSet::HWADDRESS); - passes.push(llvm::LLVMRustCreateHWAddressSanitizerPass(recover)); - } -} - pub(crate) fn link( cgcx: &CodegenContext<LlvmCodegenBackend>, diag_handler: &Handler, @@ -1072,72 +897,6 @@ unsafe fn embed_bitcode( } } -pub unsafe fn with_llvm_pmb( - llmod: &llvm::Module, - config: &ModuleConfig, - opt_level: llvm::CodeGenOptLevel, - prepare_for_thin_lto: bool, - f: &mut dyn FnMut(&llvm::PassManagerBuilder), -) { - use std::ptr; - - // Create the PassManagerBuilder for LLVM. We configure it with - // reasonable defaults and prepare it to actually populate the pass - // manager. - let builder = llvm::LLVMRustPassManagerBuilderCreate(); - let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1); - let inline_threshold = config.inline_threshold; - let pgo_gen_path = get_pgo_gen_path(config); - let pgo_use_path = get_pgo_use_path(config); - let pgo_sample_use_path = get_pgo_sample_use_path(config); - - llvm::LLVMRustConfigurePassManagerBuilder( - builder, - opt_level, - config.merge_functions, - config.vectorize_slp, - config.vectorize_loop, - prepare_for_thin_lto, - pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), - opt_size as c_int, - ); - - llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins); - - // Here we match what clang does (kinda). For O0 we only inline - // always-inline functions (but don't add lifetime intrinsics), at O1 we - // inline with lifetime intrinsics, and O2+ we add an inliner with a - // thresholds copied from clang. - match (opt_level, opt_size, inline_threshold) { - (.., Some(t)) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, t); - } - (llvm::CodeGenOptLevel::Aggressive, ..) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 275); - } - (_, llvm::CodeGenOptSizeDefault, _) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 75); - } - (_, llvm::CodeGenOptSizeAggressive, _) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 25); - } - (llvm::CodeGenOptLevel::None, ..) => { - llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); - } - (llvm::CodeGenOptLevel::Less, ..) => { - llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); - } - (llvm::CodeGenOptLevel::Default, ..) => { - llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 225); - } - } - - f(builder); - llvm::LLVMRustPassManagerBuilderDispose(builder); -} - // Create a `__imp_<symbol> = &symbol` global for every public static `symbol`. // This is required to satisfy `dllimport` references to static data in .rlibs // when using MSVC linker. We do this only for data, as linker can fix up diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 09f2c356897..42cb694c0e7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1792,18 +1792,9 @@ extern "C" { /// Writes a module to the specified path. Returns 0 on success. pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; - /// Creates a pass manager. + /// Creates a legacy pass manager -- only used for final codegen. pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; - /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> &mut PassManager<'_>; - - /// Disposes a pass manager. - pub fn LLVMDisposePassManager<'a>(PM: &'a mut PassManager<'a>); - - /// Runs a pass manager on a module. - pub fn LLVMRunPassManager<'a>(PM: &PassManager<'a>, M: &'a Module) -> Bool; - pub fn LLVMInitializePasses(); pub fn LLVMTimeTraceProfilerInitialize(); @@ -1814,32 +1805,6 @@ extern "C" { pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); - pub fn LLVMRustPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; - pub fn LLVMRustPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); - pub fn LLVMRustPassManagerBuilderUseInlinerWithThreshold( - PMB: &PassManagerBuilder, - threshold: c_uint, - ); - pub fn LLVMRustPassManagerBuilderPopulateModulePassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - ); - - pub fn LLVMRustPassManagerBuilderPopulateFunctionPassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - ); - pub fn LLVMRustPassManagerBuilderPopulateLTOPassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - Internalize: Bool, - RunInliner: Bool, - ); - pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - PMB: &PassManagerBuilder, - PM: &PassManager<'_>, - ); - pub fn LLVMGetHostCPUFeatures() -> *mut c_char; pub fn LLVMDisposeMessage(message: *mut c_char); @@ -2244,22 +2209,6 @@ extern "C" { pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; - pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; - pub fn LLVMRustCreateAddressSanitizerFunctionPass(Recover: bool) -> &'static mut Pass; - pub fn LLVMRustCreateModuleAddressSanitizerPass(Recover: bool) -> &'static mut Pass; - pub fn LLVMRustCreateMemorySanitizerPass( - TrackOrigins: c_int, - Recover: bool, - ) -> &'static mut Pass; - pub fn LLVMRustCreateThreadSanitizerPass() -> &'static mut Pass; - pub fn LLVMRustCreateHWAddressSanitizerPass(Recover: bool) -> &'static mut Pass; - pub fn LLVMRustAddPass(PM: &PassManager<'_>, Pass: &'static mut Pass); - pub fn LLVMRustAddLastExtensionPasses( - PMB: &PassManagerBuilder, - Passes: *const &'static mut Pass, - NumPasses: size_t, - ); - pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); @@ -2293,29 +2242,11 @@ extern "C" { SplitDwarfFile: *const c_char, ) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); - pub fn LLVMRustAddBuilderLibraryInfo<'a>( - PMB: &'a PassManagerBuilder, - M: &'a Module, - DisableSimplifyLibCalls: bool, - ); - pub fn LLVMRustConfigurePassManagerBuilder( - PMB: &PassManagerBuilder, - OptLevel: CodeGenOptLevel, - MergeFunctions: bool, - SLPVectorize: bool, - LoopVectorize: bool, - PrepareForThinLTO: bool, - PGOGenPath: *const c_char, - PGOUsePath: *const c_char, - PGOSampleUsePath: *const c_char, - SizeLevel: c_int, - ); pub fn LLVMRustAddLibraryInfo<'a>( PM: &PassManager<'a>, M: &'a Module, DisableSimplifyLibCalls: bool, ); - pub fn LLVMRustRunFunctionPassManager<'a>(PM: &PassManager<'a>, M: &'a Module); pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, PM: &PassManager<'a>, @@ -2324,7 +2255,7 @@ extern "C" { DwoOutput: *const c_char, FileType: FileType, ) -> LLVMRustResult; - pub fn LLVMRustOptimizeWithNewPassManager<'a>( + pub fn LLVMRustOptimize<'a>( M: &'a Module, TM: &'a TargetMachine, OptLevel: PassBuilderOptLevel, @@ -2362,7 +2293,6 @@ extern "C" { pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); - pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool); pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 60707a1c34e..2fd58567c48 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,6 @@ use crate::back::write::create_informational_target_machine; -use crate::{llvm, llvm_util}; +use crate::llvm; use libc::c_int; -use libloading::Library; use rustc_codegen_ssa::target_features::{ supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES, }; @@ -16,7 +15,6 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy}; use smallvec::{smallvec, SmallVec}; use std::ffi::{CStr, CString}; -use std::mem; use std::path::Path; use std::ptr; use std::slice; @@ -120,22 +118,6 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - // Use the legacy plugin registration if we don't use the new pass manager - if !should_use_new_llvm_pass_manager( - &sess.opts.unstable_opts.new_llvm_pass_manager, - &sess.target.arch, - ) { - // Register LLVM plugins by loading them into the compiler process. - for plugin in &sess.opts.unstable_opts.llvm_plugins { - let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e)); - debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin); - - // Intentionally leak the dynamic library. We can't ever unload it - // since the library can make things that will live arbitrarily long. - mem::forget(lib); - } - } - rustc_llvm::initialize_available_targets(); llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); @@ -539,19 +521,3 @@ pub fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.unstable_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } - -pub(crate) fn should_use_new_llvm_pass_manager(user_opt: &Option<bool>, target_arch: &str) -> bool { - // The new pass manager is enabled by default for LLVM >= 13. - // This matches Clang, which also enables it since Clang 13. - - // Since LLVM 15, the legacy pass manager is no longer supported. - if llvm_util::get_version() >= (15, 0, 0) { - return true; - } - - // There are some perf issues with the new pass manager when targeting - // s390x with LLVM 13, so enable the new pass manager only with LLVM 14. - // See https://github.com/rust-lang/rust/issues/89609. - let min_version = if target_arch == "s390x" { 14 } else { 13 }; - user_opt.unwrap_or_else(|| llvm_util::get_version() >= (min_version, 0, 0)) -} diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 68f3b19b715..680b9b642d9 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -113,7 +113,6 @@ pub struct ModuleConfig { pub vectorize_slp: bool, pub merge_functions: bool, pub inline_threshold: Option<u32>, - pub new_llvm_pass_manager: Option<bool>, pub emit_lifetime_markers: bool, pub llvm_plugins: Vec<String>, } @@ -265,7 +264,6 @@ impl ModuleConfig { }, inline_threshold: sess.opts.cg.inline_threshold, - new_llvm_pass_manager: sess.opts.unstable_opts.new_llvm_pass_manager, emit_lifetime_markers: sess.emit_lifetime_markers(), llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]), } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index fb35399fa3a..b0dcbf76b01 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1009,7 +1009,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if needs_non_const_drop { self.check_op_spanned( - ops::LiveDrop { dropped_at: Some(terminator.source_info.span) }, + ops::LiveDrop { + dropped_at: Some(terminator.source_info.span), + dropped_ty: ty_of_dropped_place, + }, err_span, ); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 5fb4bf638b3..b56b230201e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -422,10 +422,11 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm { } #[derive(Debug)] -pub struct LiveDrop { +pub struct LiveDrop<'tcx> { pub dropped_at: Option<Span>, + pub dropped_ty: Ty<'tcx>, } -impl<'tcx> NonConstOp<'tcx> for LiveDrop { +impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { fn build_error( &self, ccx: &ConstCx<'_, 'tcx>, @@ -435,9 +436,13 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop { ccx.tcx.sess, span, E0493, - "destructors cannot be evaluated at compile-time" + "destructor of `{}` cannot be evaluated at compile-time", + self.dropped_ty, + ); + err.span_label( + span, + format!("the destructor for this type cannot be evaluated in {}s", ccx.const_kind()), ); - err.span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind())); if let Some(span) = self.dropped_at { err.span_label(span, "value is dropped here"); } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index 4e210f66353..d4570c59889 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Location}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::{symbol::sym, Span}; use super::check::Qualifs; @@ -58,9 +58,9 @@ impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { } } -impl CheckLiveDrops<'_, '_> { - fn check_live_drop(&self, span: Span) { - ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit(); +impl<'tcx> CheckLiveDrops<'_, 'tcx> { + fn check_live_drop(&self, span: Span, dropped_ty: Ty<'tcx>) { + ops::LiveDrop { dropped_at: None, dropped_ty }.build_error(self.ccx, span).emit(); } } @@ -90,7 +90,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { } if dropped_place.is_indirect() { - self.check_live_drop(terminator.source_info.span); + self.check_live_drop(terminator.source_info.span, dropped_ty); return; } @@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { if self.qualifs.needs_non_const_drop(self.ccx, dropped_place.local, location) { // Use the span where the dropped local was declared for the error. let span = self.body.local_decls[dropped_place.local].source_info.span; - self.check_live_drop(span); + self.check_live_drop(span, dropped_ty); } } diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 2874fa0caff..e97da4322fa 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -329,7 +329,7 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { let typeck_results = self.maybe_typeck_results.get().or_else(|| { self.tcx .hir() - .maybe_body_owned_by(expr.hir_id.owner) + .maybe_body_owned_by(expr.hir_id.owner.def_id) .map(|body_id| self.tcx.typeck_body(body_id)) }); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a52e95e92d5..1c440a0a07e 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -339,10 +339,9 @@ impl Diagnostic { // The lint index inside the attribute is manually transferred here. let lint_index = expectation_id.get_lint_index(); expectation_id.set_lint_index(None); - let mut stable_id = unstable_to_stable + let mut stable_id = *unstable_to_stable .get(&expectation_id) - .expect("each unstable `LintExpectationId` must have a matching stable id") - .normalize(); + .expect("each unstable `LintExpectationId` must have a matching stable id"); stable_id.set_lint_index(lint_index); *expectation_id = stable_id; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68971cebc35..b44cf352233 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1205,7 +1205,7 @@ impl HandlerInner { if let Some(expectation_id) = diagnostic.level.get_expectation_id() { self.suppressed_expected_diag = true; - self.fulfilled_expectations.insert(expectation_id.normalize()); + self.fulfilled_expectations.insert(expectation_id); } if matches!(diagnostic.level, Warning(_)) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a8436ea64f8..018b7cc5d9d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,6 @@ use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::DefId; -pub(crate) use crate::hir_id::{HirId, ItemLocalId}; +pub(crate) use crate::hir_id::{HirId, ItemLocalId, OwnerId}; use crate::intravisit::FnKind; use crate::LangItem; @@ -2206,14 +2206,14 @@ pub struct FnSig<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct TraitItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl TraitItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -2224,7 +2224,7 @@ impl TraitItemId { #[derive(Debug, HashStable_Generic)] pub struct TraitItem<'hir> { pub ident: Ident, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: TraitItemKind<'hir>, pub span: Span, @@ -2235,7 +2235,7 @@ impl TraitItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn trait_item_id(&self) -> TraitItemId { @@ -2270,14 +2270,14 @@ pub enum TraitItemKind<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ImplItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl ImplItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -2285,7 +2285,7 @@ impl ImplItemId { #[derive(Debug, HashStable_Generic)] pub struct ImplItem<'hir> { pub ident: Ident, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub generics: &'hir Generics<'hir>, pub kind: ImplItemKind<'hir>, pub defaultness: Defaultness, @@ -2297,7 +2297,7 @@ impl ImplItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn impl_item_id(&self) -> ImplItemId { @@ -2888,14 +2888,14 @@ impl<'hir> VariantData<'hir> { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)] pub struct ItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl ItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -2905,7 +2905,7 @@ impl ItemId { #[derive(Debug, HashStable_Generic)] pub struct Item<'hir> { pub ident: Ident, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub kind: ItemKind<'hir>, pub span: Span, pub vis_span: Span, @@ -2915,7 +2915,7 @@ impl Item<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn item_id(&self) -> ItemId { @@ -3132,14 +3132,14 @@ pub enum AssocItemKind { // so it can fetched later. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct ForeignItemId { - pub def_id: LocalDefId, + pub def_id: OwnerId, } impl ForeignItemId { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } } @@ -3160,7 +3160,7 @@ pub struct ForeignItemRef { pub struct ForeignItem<'hir> { pub ident: Ident, pub kind: ForeignItemKind<'hir>, - pub def_id: LocalDefId, + pub def_id: OwnerId, pub span: Span, pub vis_span: Span, } @@ -3169,7 +3169,7 @@ impl ForeignItem<'_> { #[inline] pub fn hir_id(&self) -> HirId { // Items are always HIR owners. - HirId::make_owner(self.def_id) + HirId::make_owner(self.def_id.def_id) } pub fn foreign_item_id(&self) -> ForeignItemId { @@ -3263,7 +3263,7 @@ impl<'hir> OwnerNode<'hir> { Node::generics(self.into()) } - pub fn def_id(self) -> LocalDefId { + pub fn def_id(self) -> OwnerId { match self { OwnerNode::Item(Item { def_id, .. }) | OwnerNode::TraitItem(TraitItem { def_id, .. }) diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 84b0740c7b3..752f760ea97 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,6 +1,43 @@ -use crate::def_id::{LocalDefId, CRATE_DEF_ID}; +use crate::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_span::{def_id::DefPathHash, HashStableContext}; use std::fmt; +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Encodable, Decodable)] +pub struct OwnerId { + pub def_id: LocalDefId, +} + +impl From<OwnerId> for HirId { + fn from(owner: OwnerId) -> HirId { + HirId { owner, local_id: ItemLocalId::from_u32(0) } + } +} + +impl OwnerId { + #[inline] + pub fn to_def_id(self) -> DefId { + self.def_id.to_def_id() + } +} + +impl<CTX: HashStableContext> HashStable<CTX> for OwnerId { + #[inline] + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + self.to_stable_hash_key(hcx).hash_stable(hcx, hasher); + } +} + +impl<CTX: HashStableContext> ToStableHashKey<CTX> for OwnerId { + type KeyType = DefPathHash; + + #[inline] + fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash { + hcx.def_path_hash(self.to_def_id()) + } +} + /// Uniquely identifies a node in the HIR of the current crate. It is /// composed of the `owner`, which is the `LocalDefId` of the directly enclosing /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"), @@ -15,22 +52,23 @@ use std::fmt; #[derive(Encodable, Decodable, HashStable_Generic)] #[rustc_pass_by_value] pub struct HirId { - pub owner: LocalDefId, + pub owner: OwnerId, pub local_id: ItemLocalId, } impl HirId { /// Signal local id which should never be used. - pub const INVALID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::INVALID }; + pub const INVALID: HirId = + HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::INVALID }; #[inline] - pub fn expect_owner(self) -> LocalDefId { + pub fn expect_owner(self) -> OwnerId { assert_eq!(self.local_id.index(), 0); self.owner } #[inline] - pub fn as_owner(self) -> Option<LocalDefId> { + pub fn as_owner(self) -> Option<OwnerId> { if self.local_id.index() == 0 { Some(self.owner) } else { None } } @@ -41,11 +79,14 @@ impl HirId { #[inline] pub fn make_owner(owner: LocalDefId) -> Self { - Self { owner, local_id: ItemLocalId::from_u32(0) } + Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::from_u32(0) } } pub fn index(self) -> (usize, usize) { - (rustc_index::vec::Idx::index(self.owner), rustc_index::vec::Idx::index(self.local_id)) + ( + rustc_index::vec::Idx::index(self.owner.def_id), + rustc_index::vec::Idx::index(self.local_id), + ) } } @@ -94,4 +135,7 @@ impl ItemLocalId { } /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. -pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::from_u32(0) }; +pub const CRATE_HIR_ID: HirId = + HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) }; + +pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID }; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 946da9265ba..556ff1cc48e 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,7 @@ #![feature(associated_type_defaults)] #![feature(closure_track_caller)] -#![feature(const_btree_new)] +#![feature(const_btree_len)] #![cfg_attr(bootstrap, feature(let_else))] #![feature(once_cell)] #![feature(min_specialization)] diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 5b9c42686c3..06b7a65662e 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -20,7 +20,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { - let def_path_hash = self.owner.to_stable_hash_key(hcx); + let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx); (def_path_hash, self.local_id) } } @@ -49,7 +49,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } @@ -58,7 +58,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } @@ -67,7 +67,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } @@ -76,7 +76,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { - self.def_id.to_stable_hash_key(hcx) + self.def_id.def_id.to_stable_hash_key(hcx) } } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 710c4a01b24..09163e4f25f 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -149,19 +149,19 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } for id in crate_items.trait_items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } for id in crate_items.impl_items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } for id in crate_items.foreign_items() { - dirty_clean_visitor.check_item(id.def_id); + dirty_clean_visitor.check_item(id.def_id.def_id); } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 82099d9e3f3..99469d1e1e7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2440,7 +2440,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let ast_generics = self.tcx.hir().get_generics(hir_id.owner); + let ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id); let bounds = ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id)); // `sp` only covers `T`, change it so that it covers @@ -2481,6 +2481,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{}`", p), GenericKind::Projection(ref p) => format!("the associated type `{}`", p), + GenericKind::Opaque(def_id, substs) => { + format!("the opaque type `{}`", self.tcx.def_path_str_with_substs(def_id, substs)) + } }; if let Some(SubregionOrigin::CompareImplItemObligation { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index ae56bea6f86..2ccfcd51b11 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -185,8 +185,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() { let parent_id = tcx.hir().get_parent_item(*hir_id); - let parent_id = tcx.hir().local_def_id_to_hir_id(parent_id); - if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) { + if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { let mut span: MultiSpan = fn_decl.output.span().into(); let mut add_label = true; if let hir::FnRetTy::Return(ty) = fn_decl.output { @@ -415,7 +414,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let tcx = self.tcx(); match tcx.hir().get_if_local(def_id) { Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { + match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) + { Some(Node::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. @@ -425,7 +425,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } Some(Node::TraitItem(trait_item)) => { let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did) { + match tcx.hir().find_by_def_id(trait_did.def_id) { Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { // The method being called is defined in the `trait`, but the `'static` // obligation comes from the `impl`. Find that `impl` so that we can point diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 55cf9b7a2ea..efc9c1ca46f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -16,6 +16,7 @@ use rustc_data_structures::undo_log::Rollback; use rustc_data_structures::unify as ut; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::hir_id::OwnerId; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; @@ -583,9 +584,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_typeck_results` with fresh `TypeckResults`. /// Will also change the scope for opaque type defining use checks to the given owner. - pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self { + pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: OwnerId) -> Self { self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner))); - self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner)) + self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner.def_id)) } /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 76c340a5efa..9bf92f08aa5 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -616,7 +616,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi let scope = tcx.hir().get_defining_scope(opaque_hir_id); // We walk up the node tree until we hit the root or the scope of the opaque type. while hir_id != scope && hir_id != hir::CRATE_HIR_ID { - hir_id = tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(hir_id)); + hir_id = tcx.hir().get_parent_item(hir_id).into(); } // Syntactically, we are allowed to define the concrete type if: let res = hir_id == scope; diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index b2d7f4a663a..14ee9f05190 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -3,8 +3,9 @@ // RFC for reference. use rustc_data_structures::sso::SsoHashSet; +use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitable}; use smallvec::{smallvec, SmallVec}; #[derive(Debug)] @@ -45,6 +46,8 @@ pub enum Component<'tcx> { // them. This gives us room to improve the regionck reasoning in // the future without breaking backwards compat. EscapingProjection(Vec<Component<'tcx>>), + + Opaque(DefId, SubstsRef<'tcx>), } /// Push onto `out` all the things that must outlive `'a` for the condition @@ -120,6 +123,17 @@ fn compute_components<'tcx>( out.push(Component::Param(p)); } + // Ignore lifetimes found in opaque types. Opaque types can + // have lifetimes in their substs which their hidden type doesn't + // actually use. If we inferred that an opaque type is outlived by + // its parameter lifetimes, then we could prove that any lifetime + // outlives any other lifetime, which is unsound. + // See https://github.com/rust-lang/rust/issues/84305 for + // more details. + ty::Opaque(def_id, substs) => { + out.push(Component::Opaque(def_id, substs)); + }, + // For projections, we prefer to generate an obligation like // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the // regionck more ways to prove that it holds. However, @@ -168,7 +182,6 @@ fn compute_components<'tcx>( ty::Float(..) | // OutlivesScalar ty::Never | // ... ty::Adt(..) | // OutlivesNominalType - ty::Opaque(..) | // OutlivesNominalType (ish) ty::Foreign(..) | // OutlivesNominalType ty::Str | // OutlivesScalar (ish) ty::Slice(..) | // ... diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index 872886da362..113d4f09066 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -53,6 +53,7 @@ pub struct OutlivesEnvironment<'tcx> { } /// Builder of OutlivesEnvironment. +#[derive(Debug)] struct OutlivesEnvironmentBuilder<'tcx> { param_env: ty::ParamEnv<'tcx>, region_relation: TransitiveRelationBuilder<Region<'tcx>>, @@ -109,6 +110,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> { impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> { #[inline] + #[instrument(level = "debug")] fn build(self) -> OutlivesEnvironment<'tcx> { OutlivesEnvironment { param_env: self.param_env, @@ -140,6 +142,10 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> { self.region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); } + OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => { + self.region_bound_pairs + .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a)); + } OutlivesBound::RegionSubRegion(r_a, r_b) => { if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) { infcx diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 5bd1774f6b1..229b69b92e6 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,10 +68,11 @@ use crate::infer::{ }; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; +use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable}; use smallvec::smallvec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -283,6 +284,9 @@ where Component::Param(param_ty) => { self.param_ty_must_outlive(origin, region, *param_ty); } + Component::Opaque(def_id, substs) => { + self.opaque_must_outlive(*def_id, substs, origin, region) + } Component::Projection(projection_ty) => { self.projection_must_outlive(origin, region, *projection_ty); } @@ -314,17 +318,69 @@ where ); let generic = GenericKind::Param(param_ty); - let verify_bound = self.verify_bound.generic_bound(generic); + let verify_bound = self.verify_bound.param_bound(param_ty); self.delegate.push_verify(origin, generic, region, verify_bound); } #[instrument(level = "debug", skip(self))] + fn opaque_must_outlive( + &mut self, + def_id: DefId, + substs: SubstsRef<'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + ) { + self.generic_must_outlive( + origin, + region, + GenericKind::Opaque(def_id, substs), + def_id, + substs, + true, + |ty| match *ty.kind() { + ty::Opaque(def_id, substs) => (def_id, substs), + _ => bug!("expected only projection types from env, not {:?}", ty), + }, + ); + } + + #[instrument(level = "debug", skip(self))] fn projection_must_outlive( &mut self, origin: infer::SubregionOrigin<'tcx>, region: ty::Region<'tcx>, projection_ty: ty::ProjectionTy<'tcx>, ) { + self.generic_must_outlive( + origin, + region, + GenericKind::Projection(projection_ty), + projection_ty.item_def_id, + projection_ty.substs, + false, + |ty| match ty.kind() { + ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs), + _ => bug!("expected only projection types from env, not {:?}", ty), + }, + ); + } + + #[instrument(level = "debug", skip(self, filter))] + fn generic_must_outlive( + &mut self, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + generic: GenericKind<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + is_opaque: bool, + filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>), + ) { + // An optimization for a common case with opaque types. + if substs.is_empty() { + return; + } + // This case is thorny for inference. The fundamental problem is // that there are many cases where we have choice, and inference // doesn't like choice (the current region inference in @@ -343,16 +399,15 @@ where // These are guaranteed to apply, no matter the inference // results. let trait_bounds: Vec<_> = - self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect(); + self.verify_bound.declared_region_bounds(def_id, substs).collect(); debug!(?trait_bounds); // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. - let mut approx_env_bounds = - self.verify_bound.projection_approx_declared_bounds_from_env(projection_ty); - debug!("projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds); + let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic); + debug!(?approx_env_bounds); // Remove outlives bounds that we get from the environment but // which are also deducible from the trait. This arises (cc @@ -366,14 +421,8 @@ where // If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait` // will be invoked with `['b => ^1]` and so we will get `^1` returned. let bound = bound_outlives.skip_binder(); - match *bound.0.kind() { - ty::Projection(projection_ty) => self - .verify_bound - .projection_declared_bounds_from_trait(projection_ty) - .all(|r| r != bound.1), - - _ => panic!("expected only projection types from env, not {:?}", bound.0), - } + let (def_id, substs) = filter(bound.0); + self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1) }); // If declared bounds list is empty, the only applicable rule is @@ -390,29 +439,11 @@ where // the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. - let needs_infer = projection_ty.needs_infer(); - if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { - debug!("projection_must_outlive: no declared bounds"); - - let constraint = origin.to_constraint_category(); - for k in projection_ty.substs { - match k.unpack() { - GenericArgKind::Lifetime(lt) => { - self.delegate.push_sub_region_constraint( - origin.clone(), - region, - lt, - constraint, - ); - } - GenericArgKind::Type(ty) => { - self.type_must_outlive(origin.clone(), ty, region, constraint); - } - GenericArgKind::Const(_) => { - // Const parameters don't impose constraints. - } - } - } + let needs_infer = substs.needs_infer(); + if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) { + debug!("no declared bounds"); + + self.substs_must_outlive(substs, origin, region); return; } @@ -442,8 +473,8 @@ where .all(|b| b == Some(trait_bounds[0])) { let unique_bound = trait_bounds[0]; - debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound); - debug!("projection_must_outlive: unique declared bound appears in trait ref"); + debug!(?unique_bound); + debug!("unique declared bound appears in trait ref"); let category = origin.to_constraint_category(); self.delegate.push_sub_region_constraint(origin, region, unique_bound, category); return; @@ -454,11 +485,42 @@ where // projection outlive; in some cases, this may add insufficient // edges into the inference graph, leading to inference failures // even though a satisfactory solution exists. - let generic = GenericKind::Projection(projection_ty); - let verify_bound = self.verify_bound.generic_bound(generic); + let verify_bound = self.verify_bound.projection_opaque_bounds( + generic, + def_id, + substs, + &mut Default::default(), + ); debug!("projection_must_outlive: pushing {:?}", verify_bound); self.delegate.push_verify(origin, generic, region, verify_bound); } + + fn substs_must_outlive( + &mut self, + substs: SubstsRef<'tcx>, + origin: infer::SubregionOrigin<'tcx>, + region: ty::Region<'tcx>, + ) { + let constraint = origin.to_constraint_category(); + for k in substs { + match k.unpack() { + GenericArgKind::Lifetime(lt) => { + self.delegate.push_sub_region_constraint( + origin.clone(), + region, + lt, + constraint, + ); + } + GenericArgKind::Type(ty) => { + self.type_must_outlive(origin.clone(), ty, region, constraint); + } + GenericArgKind::Const(_) => { + // Const parameters don't impose constraints. + } + } + } + } } impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> { diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index e344e192a76..f470b2eb8c1 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -2,11 +2,10 @@ use crate::infer::outlives::components::{compute_components_recursive, Component use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::region_constraints::VerifyIfEq; use crate::infer::{GenericKind, VerifyBound}; -use rustc_data_structures::captures::Captures; use rustc_data_structures::sso::SsoHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::GenericArg; -use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, SubstsRef, Ty, TyCtxt}; use smallvec::smallvec; @@ -38,20 +37,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { Self { tcx, region_bound_pairs, implicit_region_bound, param_env } } - /// Returns a "verify bound" that encodes what we know about - /// `generic` and the regions it outlives. - pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> { - let mut visited = SsoHashSet::new(); - match generic { - GenericKind::Param(param_ty) => self.param_bound(param_ty), - GenericKind::Projection(projection_ty) => { - self.projection_bound(projection_ty, &mut visited) - } - } - } - #[instrument(level = "debug", skip(self))] - fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { + pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> { // Start with anything like `T: 'a` we can scrape from the // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. @@ -105,41 +92,31 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// the clause from the environment only applies if `'0 = 'a`, /// which we don't know yet. But we would still include `'b` in /// this list. - pub fn projection_approx_declared_bounds_from_env( + pub fn approx_declared_bounds_from_env( &self, - projection_ty: ty::ProjectionTy<'tcx>, + generic: GenericKind<'tcx>, ) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> { - let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx); + let projection_ty = generic.to_ty(self.tcx); let erased_projection_ty = self.tcx.erase_regions(projection_ty); self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty) } - /// Searches the where-clauses in scope for regions that - /// `projection_ty` is known to outlive. Currently requires an - /// exact match. - pub fn projection_declared_bounds_from_trait( + #[instrument(level = "debug", skip(self, visited))] + pub fn projection_opaque_bounds( &self, - projection_ty: ty::ProjectionTy<'tcx>, - ) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> { - self.declared_projection_bounds_from_trait(projection_ty) - } - - pub fn projection_bound( - &self, - projection_ty: ty::ProjectionTy<'tcx>, + generic: GenericKind<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, visited: &mut SsoHashSet<GenericArg<'tcx>>, ) -> VerifyBound<'tcx> { - debug!("projection_bound(projection_ty={:?})", projection_ty); - - let projection_ty_as_ty = - self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); + let generic_ty = generic.to_ty(self.tcx); // Search the env for where clauses like `P: 'a`. - let env_bounds = self - .projection_approx_declared_bounds_from_env(projection_ty) + let projection_opaque_bounds = self + .approx_declared_bounds_from_env(generic) .into_iter() .map(|binder| { - if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == projection_ty_as_ty { + if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty { // Micro-optimize if this is an exact match (this // occurs often when there are no region variables // involved). @@ -149,21 +126,19 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { VerifyBound::IfEq(verify_if_eq_b) } }); - // Extend with bounds that we can find from the trait. - let trait_bounds = self - .projection_declared_bounds_from_trait(projection_ty) - .map(|r| VerifyBound::OutlivedBy(r)); + let trait_bounds = + self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)); // see the extensive comment in projection_must_outlive let recursive_bound = { let mut components = smallvec![]; - let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); - compute_components_recursive(self.tcx, ty.into(), &mut components, visited); + compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited); self.bound_from_components(&components, visited) }; - VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound) + VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect()) + .or(recursive_bound) } fn bound_from_components( @@ -195,7 +170,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { match *component { Component::Region(lt) => VerifyBound::OutlivedBy(lt), Component::Param(param_ty) => self.param_bound(param_ty), - Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited), + Component::Opaque(did, substs) => self.projection_opaque_bounds( + GenericKind::Opaque(did, substs), + did, + substs, + visited, + ), + Component::Projection(projection_ty) => self.projection_opaque_bounds( + GenericKind::Projection(projection_ty), + projection_ty.item_def_id, + projection_ty.substs, + visited, + ), Component::EscapingProjection(ref components) => { self.bound_from_components(components, visited) } @@ -293,30 +279,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// } /// ``` /// - /// then this function would return `'x`. This is subject to the - /// limitations around higher-ranked bounds described in - /// `region_bounds_declared_on_associated_item`. - fn declared_projection_bounds_from_trait( - &self, - projection_ty: ty::ProjectionTy<'tcx>, - ) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> { - debug!("projection_bounds(projection_ty={:?})", projection_ty); - let tcx = self.tcx; - self.region_bounds_declared_on_associated_item(projection_ty.item_def_id) - .map(move |r| EarlyBinder(r).subst(tcx, projection_ty.substs)) - } - - /// Given the `DefId` of an associated item, returns any region - /// bounds attached to that associated item from the trait definition. - /// - /// For example: - /// - /// ```rust - /// trait Foo<'a> { - /// type Bar: 'a; - /// } - /// ``` - /// /// If we were given the `DefId` of `Foo::Bar`, we would return /// `'a`. You could then apply the substitutions from the /// projection to convert this into your namespace. This also @@ -336,17 +298,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// /// This is for simplicity, and because we are not really smart /// enough to cope with such bounds anywhere. - fn region_bounds_declared_on_associated_item( + pub fn declared_region_bounds( &self, - assoc_item_def_id: DefId, + def_id: DefId, + substs: SubstsRef<'tcx>, ) -> impl Iterator<Item = ty::Region<'tcx>> { let tcx = self.tcx; - let bounds = tcx.item_bounds(assoc_item_def_id); + let bounds = tcx.item_bounds(def_id); + trace!("{:#?}", bounds); bounds .into_iter() .filter_map(|p| p.to_opt_type_outlives()) .filter_map(|p| p.no_bound_vars()) .map(|b| b.1) + .map(move |r| EarlyBinder(r).subst(tcx, substs)) } /// Searches through a predicate list for a predicate `T: 'a`. diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index e43d28ee56e..67b3da68720 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -12,8 +12,10 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; +use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; +use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReLateBound, ReVar}; @@ -168,6 +170,7 @@ pub struct Verify<'tcx> { pub enum GenericKind<'tcx> { Param(ty::ParamTy), Projection(ty::ProjectionTy<'tcx>), + Opaque(DefId, SubstsRef<'tcx>), } /// Describes the things that some `GenericKind` value `G` is known to @@ -747,6 +750,9 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => write!(f, "{:?}", p), GenericKind::Projection(ref p) => write!(f, "{:?}", p), + GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| { + write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap())) + }), } } } @@ -756,6 +762,9 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => write!(f, "{}", p), GenericKind::Projection(ref p) => write!(f, "{}", p), + GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| { + write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap())) + }), } } } @@ -765,6 +774,7 @@ impl<'tcx> GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs), + GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs), } } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index f5a1edf6d81..e12c069dcc1 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -246,6 +246,13 @@ impl<'tcx> Elaborator<'tcx> { Component::UnresolvedInferenceVariable(_) => None, + Component::Opaque(def_id, substs) => { + let ty = tcx.mk_opaque(def_id, substs); + Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate( + ty, r_min, + ))) + } + Component::Projection(projection) => { // We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`. // With this, we can deduce that `<Bar as Baz>::Assoc: 'a`. @@ -262,8 +269,9 @@ impl<'tcx> Elaborator<'tcx> { None } }) - .map(ty::Binder::dummy) - .map(|predicate_kind| predicate_kind.to_predicate(tcx)) + .map(|predicate_kind| { + bound_predicate.rebind(predicate_kind).to_predicate(tcx) + }) .filter(|&predicate| visited.insert(predicate)) .map(|predicate| { predicate_obligation( diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 5371c513d29..2b1b931b732 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -1,4 +1,3 @@ -use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -10,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { for id in tcx.hir().items() { let attrs = finder.tcx.hir().attrs(id.hir_id()); if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) { - finder.decls = Some(id.def_id); + finder.decls = Some(id.def_id.def_id); } } @@ -19,7 +18,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { struct Finder<'tcx> { tcx: TyCtxt<'tcx>, - decls: Option<hir::def_id::LocalDefId>, + decls: Option<LocalDefId>, } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c7615a5775e..2cd959689e6 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -758,7 +758,6 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, Some(true)); - tracked!(new_llvm_pass_manager, Some(true)); tracked!(no_generate_arange_section, true); tracked!(no_link, true); tracked!(no_unique_section_names, true); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 0ff2ef5cda3..5fba1d3d3c7 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -606,7 +606,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { // Issue #11592: traits are always considered exported, even when private. if cx.tcx.visibility(it.def_id) == ty::Visibility::Restricted( - cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(), + cx.tcx.parent_module_from_def_id(it.def_id.def_id).to_def_id(), ) { return; @@ -627,13 +627,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, it.def_id, article, desc); + self.check_missing_docs_attrs(cx, it.def_id.def_id, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, trait_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, trait_item.def_id.def_id, article, desc); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { @@ -661,12 +661,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, impl_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, impl_item.def_id.def_id, article, desc); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); - self.check_missing_docs_attrs(cx, foreign_item.def_id, article, desc); + self.check_missing_docs_attrs(cx, foreign_item.def_id.def_id, article, desc); } fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) { @@ -719,7 +719,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]) impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id) { + if !cx.access_levels.is_reachable(item.def_id.def_id) { return; } let (def, ty) = match item.kind { @@ -809,7 +809,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.access_levels.is_reachable(item.def_id) { + if !cx.access_levels.is_reachable(item.def_id.def_id) { return; } @@ -836,7 +836,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { debug!("{:?}", self.impling_types); } - if !self.impling_types.as_ref().unwrap().contains(&item.def_id) { + if !self.impling_types.as_ref().unwrap().contains(&item.def_id.def_id) { cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| { lint.build(fluent::lint::builtin_missing_debug_impl) .set_arg("debug", cx.tcx.def_path_str(debug)) @@ -1206,7 +1206,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { check_no_mangle_on_generic_fn( no_mangle_attr, Some(generics), - cx.tcx.hir().get_generics(it.id.def_id).unwrap(), + cx.tcx.hir().get_generics(it.id.def_id.def_id).unwrap(), it.span, ); } @@ -1389,11 +1389,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { return; } - self.perform_lint(cx, "item", item.def_id, item.vis_span, true); + self.perform_lint(cx, "item", item.def_id.def_id, item.vis_span, true); } fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) { - self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true); + self.perform_lint(cx, "item", foreign_item.def_id.def_id, foreign_item.vis_span, true); } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { @@ -1404,7 +1404,7 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // Only lint inherent impl items. if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() { - self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false); + self.perform_lint(cx, "item", impl_item.def_id.def_id, impl_item.vis_span, false); } } } @@ -1841,7 +1841,7 @@ declare_lint! { } pub struct UnnameableTestItems { - boundary: Option<LocalDefId>, // Id of the item under which things are not nameable + boundary: Option<hir::OwnerId>, // Id of the item under which things are not nameable items_nameable: bool, } @@ -2138,7 +2138,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { use rustc_middle::middle::resolve_lifetime::Region; - let def_id = item.def_id; + let def_id = item.def_id.def_id; if let hir::ItemKind::Struct(_, ref hir_generics) | hir::ItemKind::Enum(_, ref hir_generics) | hir::ItemKind::Union(_, ref hir_generics) = item.kind diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 34506c84cb8..cbab56f2066 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -560,7 +560,7 @@ pub struct LateContext<'tcx> { /// Context for lint checking of the AST, after expansion, before lowering to HIR. pub struct EarlyContext<'a> { - pub builder: LintLevelsBuilder<'a, crate::levels::TopDown>, + pub builder: LintLevelsBuilder<'a>, pub buffered: LintBuffer, } @@ -1048,7 +1048,7 @@ impl<'tcx> LateContext<'tcx> { .filter(|typeck_results| typeck_results.hir_owner == id.owner) .or_else(|| { if self.tcx.has_typeck_results(id.owner.to_def_id()) { - Some(self.tcx.typeck(id.owner)) + Some(self.tcx.typeck(id.owner.def_id)) } else { None } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 45f54cfed2d..96ecd79a69c 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -59,7 +59,6 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { F: FnOnce(&mut Self), { let is_crate_node = id == ast::CRATE_NODE_ID; - debug!(?id); let push = self.context.builder.push(attrs, is_crate_node, None); self.check_id(id); diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index b9a3d52ca9b..699e8154318 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -16,10 +16,8 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) { return; } - let lint_expectations = tcx.lint_expectations(()); let fulfilled_expectations = tcx.sess.diagnostic().steal_fulfilled_expectation_ids(); - - tracing::debug!(?lint_expectations, ?fulfilled_expectations); + let lint_expectations = &tcx.lint_levels(()).lint_expectations; for (id, expectation) in lint_expectations { // This check will always be true, since `lint_expectations` only diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index a9ba2ad1d10..1e16ac51e9e 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -6,11 +6,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::{intravisit, HirId}; -use rustc_index::vec::IndexVec; use rustc_middle::hir::nested_filter; use rustc_middle::lint::{ - reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource, - ShallowLintLevelMap, + struct_lint_level, LevelAndSource, LintExpectation, LintLevelMap, LintLevelSets, + LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; @@ -28,292 +27,47 @@ use crate::errors::{ UnknownToolInScopedLint, }; -/// Collection of lint levels for the whole crate. -/// This is used by AST-based lints, which do not -/// wait until we have built HIR to be emitted. -#[derive(Debug)] -struct LintLevelSets { - /// Linked list of specifications. - list: IndexVec<LintStackIndex, LintSet>, -} - -rustc_index::newtype_index! { - struct LintStackIndex { - ENCODABLE = custom, // we don't need encoding - const COMMAND_LINE = 0, - } -} - -/// Specifications found at this position in the stack. This map only represents the lints -/// found for one set of attributes (like `shallow_lint_levels_on` does). -/// -/// We store the level specifications as a linked list. -/// Each `LintSet` represents a set of attributes on the same AST node. -/// The `parent` forms a linked list that matches the AST tree. -/// This way, walking the linked list is equivalent to walking the AST bottom-up -/// to find the specifications for a given lint. -#[derive(Debug)] -struct LintSet { - // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which - // flag. - specs: FxHashMap<LintId, LevelAndSource>, - parent: LintStackIndex, -} - -impl LintLevelSets { - fn new() -> Self { - LintLevelSets { list: IndexVec::new() } - } - - fn get_lint_level( - &self, - lint: &'static Lint, - idx: LintStackIndex, - aux: Option<&FxHashMap<LintId, LevelAndSource>>, - sess: &Session, - ) -> LevelAndSource { - let lint = LintId::of(lint); - let (level, mut src) = self.raw_lint_id_level(lint, idx, aux); - let level = reveal_actual_level(level, &mut src, sess, lint, |id| { - self.raw_lint_id_level(id, idx, aux) - }); - (level, src) - } - - fn raw_lint_id_level( - &self, - id: LintId, - mut idx: LintStackIndex, - aux: Option<&FxHashMap<LintId, LevelAndSource>>, - ) -> (Option<Level>, LintLevelSource) { - if let Some(specs) = aux { - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - } - loop { - let LintSet { ref specs, parent } = self.list[idx]; - if let Some(&(level, src)) = specs.get(&id) { - return (Some(level), src); - } - if idx == COMMAND_LINE { - return (None, LintLevelSource::Default); - } - idx = parent; - } - } -} - -fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { +fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let store = unerased_lint_store(tcx); + let levels = + LintLevelsBuilder::new(tcx.sess, false, &store, &tcx.resolutions(()).registered_tools); + let mut builder = LintLevelMapBuilder { levels, tcx }; + let krate = tcx.hir().krate(); - let mut builder = LintLevelsBuilder { - sess: tcx.sess, - provider: QueryMapExpectationsWrapper { - tcx, - cur: hir::CRATE_HIR_ID, - specs: ShallowLintLevelMap::default(), - expectations: Vec::new(), - unstable_to_stable_ids: FxHashMap::default(), - }, - warn_about_weird_lints: false, - store, - registered_tools: &tcx.resolutions(()).registered_tools, - }; - - builder.add_command_line(); - builder.add_id(hir::CRATE_HIR_ID); - tcx.hir().walk_toplevel_module(&mut builder); - - tcx.sess.diagnostic().update_unstable_expectation_id(&builder.provider.unstable_to_stable_ids); + builder.levels.id_to_set.reserve(krate.owners.len() + 1); - builder.provider.expectations -} + let push = + builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true, Some(hir::CRATE_HIR_ID)); -fn shallow_lint_levels_on(tcx: TyCtxt<'_>, hir_id: HirId) -> ShallowLintLevelMap { - let store = unerased_lint_store(tcx); - - let mut levels = LintLevelsBuilder { - sess: tcx.sess, - provider: LintLevelQueryMap { tcx, cur: hir_id, specs: ShallowLintLevelMap::default() }, - warn_about_weird_lints: false, - store, - registered_tools: &tcx.resolutions(()).registered_tools, - }; - - let is_crate = hir::CRATE_HIR_ID == hir_id; - if is_crate { - levels.add_command_line(); - } - debug!(?hir_id); - levels.add(tcx.hir().attrs(hir_id), is_crate, Some(hir_id)); + builder.levels.register_id(hir::CRATE_HIR_ID); + tcx.hir().walk_toplevel_module(&mut builder); + builder.levels.pop(push); - levels.provider.specs + builder.levels.update_unstable_expectation_ids(); + builder.levels.build_map() } -pub struct TopDown { +pub struct LintLevelsBuilder<'s> { + sess: &'s Session, + lint_expectations: Vec<(LintExpectationId, LintExpectation)>, + /// Each expectation has a stable and an unstable identifier. This map + /// is used to map from unstable to stable [`LintExpectationId`]s. + expectation_id_map: FxHashMap<LintExpectationId, LintExpectationId>, sets: LintLevelSets, + id_to_set: FxHashMap<HirId, LintStackIndex>, cur: LintStackIndex, -} - -pub trait LintLevelsProvider { - fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource>; - fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource>; - fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource; - fn push_expectation(&mut self, _id: LintExpectationId, _expectation: LintExpectation) {} -} - -impl LintLevelsProvider for TopDown { - fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> { - &self.sets.list[self.cur].specs - } - - fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> { - &mut self.sets.list[self.cur].specs - } - - fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource { - self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), sess) - } -} - -struct LintLevelQueryMap<'tcx> { - tcx: TyCtxt<'tcx>, - cur: HirId, - specs: ShallowLintLevelMap, -} - -impl LintLevelsProvider for LintLevelQueryMap<'_> { - fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> { - &self.specs.specs - } - fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> { - &mut self.specs.specs - } - fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { - self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) - } -} - -struct QueryMapExpectationsWrapper<'tcx> { - tcx: TyCtxt<'tcx>, - cur: HirId, - specs: ShallowLintLevelMap, - expectations: Vec<(LintExpectationId, LintExpectation)>, - unstable_to_stable_ids: FxHashMap<LintExpectationId, LintExpectationId>, -} - -impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { - fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> { - &self.specs.specs - } - fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> { - self.specs.specs.clear(); - &mut self.specs.specs - } - fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { - self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) - } - fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) { - let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") }; - let key = LintExpectationId::Unstable { attr_id, lint_index: None }; - - if !self.unstable_to_stable_ids.contains_key(&key) { - self.unstable_to_stable_ids.insert( - key, - LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None }, - ); - } - - self.expectations.push((id.normalize(), expectation)); - } -} - -impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - fn add_id(&mut self, hir_id: HirId) { - self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id)); - } -} - -impl<'tcx> intravisit::Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.provider.tcx.hir() - } - - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - self.add_id(param.hir_id); - intravisit::walk_param(self, param); - } - - fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_item(self, it); - } - - fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_foreign_item(self, it); - } - - fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { - // We will call `add_id` when we walk - // the `StmtKind`. The outer statement itself doesn't - // define the lint levels. - intravisit::walk_stmt(self, e); - } - - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - self.add_id(e.hir_id); - intravisit::walk_expr(self, e); - } - - fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { - self.add_id(s.hir_id); - intravisit::walk_field_def(self, s); - } - - fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { - self.add_id(v.id); - intravisit::walk_variant(self, v); - } - - fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { - self.add_id(l.hir_id); - intravisit::walk_local(self, l); - } - - fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { - self.add_id(a.hir_id); - intravisit::walk_arm(self, a); - } - - fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - self.add_id(trait_item.hir_id()); - intravisit::walk_trait_item(self, trait_item); - } - - fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - self.add_id(impl_item.hir_id()); - intravisit::walk_impl_item(self, impl_item); - } -} - -pub struct LintLevelsBuilder<'s, P> { - sess: &'s Session, - provider: P, warn_about_weird_lints: bool, store: &'s LintStore, registered_tools: &'s RegisteredTools, } -pub(crate) struct BuilderPush { +pub struct BuilderPush { prev: LintStackIndex, + pub changed: bool, } -impl<'s> LintLevelsBuilder<'s, TopDown> { - pub(crate) fn new( +impl<'s> LintLevelsBuilder<'s> { + pub fn new( sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore, @@ -321,66 +75,20 @@ impl<'s> LintLevelsBuilder<'s, TopDown> { ) -> Self { let mut builder = LintLevelsBuilder { sess, - provider: TopDown { sets: LintLevelSets::new(), cur: COMMAND_LINE }, + lint_expectations: Default::default(), + expectation_id_map: Default::default(), + sets: LintLevelSets::new(), + cur: COMMAND_LINE, + id_to_set: Default::default(), warn_about_weird_lints, store, registered_tools, }; - builder.process_command_line(); - assert_eq!(builder.provider.sets.list.len(), 1); + builder.process_command_line(sess, store); + assert_eq!(builder.sets.list.len(), 1); builder } - fn process_command_line(&mut self) { - self.provider.cur = self - .provider - .sets - .list - .push(LintSet { specs: FxHashMap::default(), parent: COMMAND_LINE }); - self.add_command_line(); - } - - /// Pushes a list of AST lint attributes onto this context. - /// - /// This function will return a `BuilderPush` object which should be passed - /// to `pop` when this scope for the attributes provided is exited. - /// - /// This function will perform a number of tasks: - /// - /// * It'll validate all lint-related attributes in `attrs` - /// * It'll mark all lint-related attributes as used - /// * Lint levels will be updated based on the attributes provided - /// * Lint attributes are validated, e.g., a `#[forbid]` can't be switched to - /// `#[allow]` - /// - /// Don't forget to call `pop`! - pub(crate) fn push( - &mut self, - attrs: &[ast::Attribute], - is_crate_node: bool, - source_hir_id: Option<HirId>, - ) -> BuilderPush { - let prev = self.provider.cur; - self.provider.cur = - self.provider.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev }); - - self.add(attrs, is_crate_node, source_hir_id); - - if self.provider.current_specs().is_empty() { - self.provider.sets.list.pop(); - self.provider.cur = prev; - } - - BuilderPush { prev } - } - - /// Called after `push` when the scope of a set of attributes are exited. - pub(crate) fn pop(&mut self, push: BuilderPush) { - self.provider.cur = push.prev; - } -} - -impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { pub(crate) fn sess(&self) -> &Session { self.sess } @@ -390,20 +98,24 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> { - self.provider.current_specs() + &self.sets.list[self.cur].specs } fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> { - self.provider.current_specs_mut() + &mut self.sets.list[self.cur].specs } - fn add_command_line(&mut self) { - for &(ref lint_name, level) in &self.sess.opts.lint_opts { - self.store.check_lint_name_cmdline(self.sess, &lint_name, level, self.registered_tools); + fn process_command_line(&mut self, sess: &Session, store: &LintStore) { + self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); + + self.cur = + self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: COMMAND_LINE }); + for &(ref lint_name, level) in &sess.opts.lint_opts { + store.check_lint_name_cmdline(sess, &lint_name, level, self.registered_tools); let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); - let Ok(ids) = self.store.find_lints(&lint_name) else { + let Ok(ids) = store.find_lints(&lint_name) else { // errors handled in check_lint_name_cmdline above continue }; @@ -426,11 +138,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) { - let (old_level, old_src) = self.provider.get_lint_level(id.lint, &self.sess); - if let Level::Expect(id) = &mut level && let LintExpectationId::Stable { .. } = id { - *id = id.normalize(); - } + fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { + let (old_level, old_src) = + self.sets.get_lint_level(id.lint, self.cur, Some(self.current_specs()), &self.sess); // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a // `#[forbid(..)]` attribute present, as that is overridden by `--cap-lints`. @@ -448,7 +158,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let id_name = id.lint.name_lower(); let fcw_warning = match old_src { LintLevelSource::Default => false, - LintLevelSource::Node { name, .. } => self.store.is_lint_group(name), + LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol), LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol), }; debug!( @@ -468,8 +178,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { id.to_string() )); } - LintLevelSource::Node { span, reason, .. } => { - diag.span_label(span, "`forbid` level set here"); + LintLevelSource::Node(_, forbid_source_span, reason) => { + diag.span_label(forbid_source_span, "`forbid` level set here"); if let Some(rationale) = reason { diag.note(rationale.as_str()); } @@ -489,8 +199,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { LintLevelSource::Default => { OverruledAttributeSub::DefaultSource { id: id.to_string() } } - LintLevelSource::Node { span, reason, .. } => { - OverruledAttributeSub::NodeSource { span, reason } + LintLevelSource::Node(_, forbid_source_span, reason) => { + OverruledAttributeSub::NodeSource { + span: forbid_source_span, + reason, + } } LintLevelSource::CommandLine(_, _) => { OverruledAttributeSub::CommandLineSource @@ -543,7 +256,29 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; } - fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option<HirId>) { + /// Pushes a list of AST lint attributes onto this context. + /// + /// This function will return a `BuilderPush` object which should be passed + /// to `pop` when this scope for the attributes provided is exited. + /// + /// This function will perform a number of tasks: + /// + /// * It'll validate all lint-related attributes in `attrs` + /// * It'll mark all lint-related attributes as used + /// * Lint levels will be updated based on the attributes provided + /// * Lint attributes are validated, e.g., a `#[forbid]` can't be switched to + /// `#[allow]` + /// + /// Don't forget to call `pop`! + pub(crate) fn push( + &mut self, + attrs: &[ast::Attribute], + is_crate_node: bool, + source_hir_id: Option<HirId>, + ) -> BuilderPush { + let prev = self.cur; + self.cur = self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev }); + let sess = self.sess; for (attr_index, attr) in attrs.iter().enumerate() { if attr.has_name(sym::automatically_derived) { @@ -558,17 +293,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { None => continue, // This is the only lint level with a `LintExpectationId` that can be created from an attribute Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { - let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id - else { bug!("stable id Level::from_attr") }; - - let stable_id = LintExpectationId::Stable { - hir_id, - attr_index: attr_index.try_into().unwrap(), - lint_index, - // we pass the previous unstable attr_id such that we can trace the ast id when building a map - // to go from unstable to stable id. - attr_id: Some(attr_id), - }; + let stable_id = self.create_stable_id(unstable_id, hir_id, attr_index); Level::Expect(stable_id) } @@ -683,7 +408,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), _ => false, }; - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new( reason, @@ -691,19 +416,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { is_unfulfilled_lint_expectations, tool_name, ), - ); + )); } - let src = LintLevelSource::Node { - name: meta_item - .path - .segments - .last() - .expect("empty lint name") - .ident - .name, - span: sp, + let src = LintLevelSource::Node( + meta_item.path.segments.last().expect("empty lint name").ident.name, + sp, reason, - }; + ); for &id in *ids { if self.check_gated_lint(id, attr.span) { self.insert_spec(id, (level, src)); @@ -716,26 +435,31 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { Ok(ids) => { let complete_name = &format!("{}::{}", tool_ident.unwrap().name, name); - let src = LintLevelSource::Node { - name: Symbol::intern(complete_name), - span: sp, + let src = LintLevelSource::Node( + Symbol::intern(complete_name), + sp, reason, - }; + ); for &id in ids { if self.check_gated_lint(id, attr.span) { self.insert_spec(id, (level, src)); } } if let Level::Expect(expect_id) = level { - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new(reason, sp, false, tool_name), - ); + )); } } Err((Some(ids), ref new_lint_name)) => { let lint = builtin::RENAMED_AND_REMOVED_LINTS; - let (lvl, src) = self.provider.get_lint_level(lint, &sess); + let (lvl, src) = self.sets.get_lint_level( + lint, + self.cur, + Some(self.current_specs()), + &sess, + ); struct_lint_level( self.sess, lint, @@ -759,19 +483,19 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }, ); - let src = LintLevelSource::Node { - name: Symbol::intern(&new_lint_name), - span: sp, + let src = LintLevelSource::Node( + Symbol::intern(&new_lint_name), + sp, reason, - }; + ); for id in ids { self.insert_spec(*id, (level, src)); } if let Level::Expect(expect_id) = level { - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new(reason, sp, false, tool_name), - ); + )); } } Err((None, _)) => { @@ -797,7 +521,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { CheckLintNameResult::Warning(msg, renamed) => { let lint = builtin::RENAMED_AND_REMOVED_LINTS; - let (renamed_lint_level, src) = self.provider.get_lint_level(lint, &sess); + let (renamed_lint_level, src) = self.sets.get_lint_level( + lint, + self.cur, + Some(self.current_specs()), + &sess, + ); struct_lint_level( self.sess, lint, @@ -820,7 +549,12 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } CheckLintNameResult::NoLint(suggestion) => { let lint = builtin::UNKNOWN_LINTS; - let (level, src) = self.provider.get_lint_level(lint, self.sess); + let (level, src) = self.sets.get_lint_level( + lint, + self.cur, + Some(self.current_specs()), + self.sess, + ); struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| { let name = if let Some(tool_ident) = tool_ident { format!("{}::{}", tool_ident.name, name) @@ -849,21 +583,17 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { if let CheckLintNameResult::Ok(ids) = self.store.check_lint_name(&new_name, None, self.registered_tools) { - let src = LintLevelSource::Node { - name: Symbol::intern(&new_name), - span: sp, - reason, - }; + let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason); for &id in ids { if self.check_gated_lint(id, attr.span) { self.insert_spec(id, (level, src)); } } if let Level::Expect(expect_id) = level { - self.provider.push_expectation( + self.lint_expectations.push(( expect_id, LintExpectation::new(reason, sp, false, tool_name), - ); + )); } } else { panic!("renamed lint does not exist: {}", new_name); @@ -878,12 +608,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue; } - let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src else { + let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else { continue }; let lint = builtin::UNUSED_ATTRIBUTES; - let (lint_level, lint_src) = self.provider.get_lint_level(lint, &self.sess); + let (lint_level, lint_src) = + self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess); struct_lint_level( self.sess, lint, @@ -903,13 +634,32 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { break; } } + + if self.current_specs().is_empty() { + self.sets.list.pop(); + self.cur = prev; + } + + BuilderPush { prev, changed: prev != self.cur } + } + + fn create_stable_id( + &mut self, + unstable_id: LintExpectationId, + hir_id: HirId, + attr_index: usize, + ) -> LintExpectationId { + let stable_id = + LintExpectationId::Stable { hir_id, attr_index: attr_index as u16, lint_index: None }; + + self.expectation_id_map.insert(unstable_id, stable_id); + + stable_id } /// Checks if the lint is gated on a feature that is not enabled. /// /// Returns `true` if the lint's feature is enabled. - // FIXME only emit this once for each attribute, instead of repeating it 4 times for - // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`. fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool { if let Some(feature) = lint_id.lint.feature_gate { if !self.sess.features_untracked().enabled(feature) { @@ -928,14 +678,19 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { true } + /// Called after `push` when the scope of a set of attributes are exited. + pub fn pop(&mut self, push: BuilderPush) { + self.cur = push.prev; + } + /// Find the lint level for a lint. - pub fn lint_level(&self, lint: &'static Lint) -> LevelAndSource { - self.provider.get_lint_level(lint, self.sess) + pub fn lint_level(&self, lint: &'static Lint) -> (Level, LintLevelSource) { + self.sets.get_lint_level(lint, self.cur, None, self.sess) } /// Used to emit a lint-related diagnostic based on the current state of /// this lint context. - pub(crate) fn struct_lint( + pub fn struct_lint( &self, lint: &'static Lint, span: Option<MultiSpan>, @@ -944,8 +699,141 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let (level, src) = self.lint_level(lint); struct_lint_level(self.sess, lint, level, src, span, decorate) } + + /// Registers the ID provided with the current set of lints stored in + /// this context. + pub fn register_id(&mut self, id: HirId) { + self.id_to_set.insert(id, self.cur); + } + + fn update_unstable_expectation_ids(&self) { + self.sess.diagnostic().update_unstable_expectation_id(&self.expectation_id_map); + } + + pub fn build_map(self) -> LintLevelMap { + LintLevelMap { + sets: self.sets, + id_to_set: self.id_to_set, + lint_expectations: self.lint_expectations, + } + } +} + +struct LintLevelMapBuilder<'tcx> { + levels: LintLevelsBuilder<'tcx>, + tcx: TyCtxt<'tcx>, +} + +impl LintLevelMapBuilder<'_> { + fn with_lint_attrs<F>(&mut self, id: hir::HirId, f: F) + where + F: FnOnce(&mut Self), + { + let is_crate_hir = id == hir::CRATE_HIR_ID; + let attrs = self.tcx.hir().attrs(id); + let push = self.levels.push(attrs, is_crate_hir, Some(id)); + + if push.changed { + self.levels.register_id(id); + } + f(self); + self.levels.pop(push); + } +} + +impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { + type NestedFilter = nested_filter::All; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { + self.with_lint_attrs(param.hir_id, |builder| { + intravisit::walk_param(builder, param); + }); + } + + fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { + self.with_lint_attrs(it.hir_id(), |builder| { + intravisit::walk_item(builder, it); + }); + } + + fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { + self.with_lint_attrs(it.hir_id(), |builder| { + intravisit::walk_foreign_item(builder, it); + }) + } + + fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { + // We will call `with_lint_attrs` when we walk + // the `StmtKind`. The outer statement itself doesn't + // define the lint levels. + intravisit::walk_stmt(self, e); + } + + fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { + self.with_lint_attrs(e.hir_id, |builder| { + intravisit::walk_expr(builder, e); + }) + } + + fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) { + self.with_lint_attrs(field.hir_id, |builder| { + intravisit::walk_expr_field(builder, field); + }) + } + + fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { + self.with_lint_attrs(s.hir_id, |builder| { + intravisit::walk_field_def(builder, s); + }) + } + + fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { + self.with_lint_attrs(v.id, |builder| { + intravisit::walk_variant(builder, v); + }) + } + + fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { + self.with_lint_attrs(l.hir_id, |builder| { + intravisit::walk_local(builder, l); + }) + } + + fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { + self.with_lint_attrs(a.hir_id, |builder| { + intravisit::walk_arm(builder, a); + }) + } + + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { + self.with_lint_attrs(trait_item.hir_id(), |builder| { + intravisit::walk_trait_item(builder, trait_item); + }); + } + + fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { + self.with_lint_attrs(impl_item.hir_id(), |builder| { + intravisit::walk_impl_item(builder, impl_item); + }); + } + + fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) { + self.with_lint_attrs(field.hir_id, |builder| { + intravisit::walk_pat_field(builder, field); + }) + } + + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { + self.with_lint_attrs(p.hir_id, |builder| { + intravisit::walk_generic_param(builder, p); + }); + } } -pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers }; +pub fn provide(providers: &mut Providers) { + providers.lint_levels = lint_levels; } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c760e435699..752a751f6bc 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -35,7 +35,6 @@ #![feature(iter_order_by)] #![feature(let_chains)] #![cfg_attr(bootstrap, feature(let_else))] -#![feature(min_specialization)] #![feature(never_type)] #![recursion_limit = "256"] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index cbe7afc8e55..11b2d057a07 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -92,7 +92,7 @@ pub enum LintExpectationId { /// stable and can be cached. The additional index ensures that nodes with /// several expectations can correctly match diagnostics to the individual /// expectation. - Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16>, attr_id: Option<AttrId> }, + Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16> }, } impl LintExpectationId { @@ -116,31 +116,13 @@ impl LintExpectationId { *lint_index = new_lint_index } - - /// Prepares the id for hashing. Removes references to the ast. - /// Should only be called when the id is stable. - pub fn normalize(self) -> Self { - match self { - Self::Stable { hir_id, attr_index, lint_index, .. } => { - Self::Stable { hir_id, attr_index, lint_index, attr_id: None } - } - Self::Unstable { .. } => { - unreachable!("`normalize` called when `ExpectationId` is unstable") - } - } - } } impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => { + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { hir_id.hash_stable(hcx, hasher); attr_index.hash_stable(hcx, hasher); lint_index.hash_stable(hcx, hasher); @@ -160,12 +142,9 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation #[inline] fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => (*hir_id, *attr_index, *lint_index), + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { + (*hir_id, *attr_index, *lint_index) + } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 24e18826048..09f377d349f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -31,13 +31,12 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" -#if LLVM_VERSION_GE(15, 0) +#include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" -#endif #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/Transforms/Instrumentation.h" @@ -93,172 +92,6 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { timeTraceProfilerCleanup(); } -extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) { -#if LLVM_VERSION_LT(15, 0) - StringRef SR(PassName); - PassRegistry *PR = PassRegistry::getPassRegistry(); - - const PassInfo *PI = PR->getPassInfo(SR); - if (PI) { - return wrap(PI->createPass()); - } - return nullptr; -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - const bool UseAfterScope = true; - - return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - - return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - - return wrap(createMemorySanitizerLegacyPassPass( -#if LLVM_VERSION_GE(14, 0) - MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel, /*EagerChecks=*/true} -#else - MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel} -#endif - )); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() { -#if LLVM_VERSION_LT(15, 0) - return wrap(createThreadSanitizerLegacyPassPass()); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) { -#if LLVM_VERSION_LT(15, 0) - const bool CompileKernel = false; - - return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { -#if LLVM_VERSION_LT(15, 0) - assert(RustPass); - Pass *Pass = unwrap(RustPass); - PassManagerBase *PMB = unwrap(PMR); - PMB->add(Pass); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" LLVMPassManagerBuilderRef LLVMRustPassManagerBuilderCreate() { -#if LLVM_VERSION_LT(15, 0) - return LLVMPassManagerBuilderCreate(); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderDispose(PMB); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderPopulateFunctionPassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderPopulateModulePassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderPopulateLTOPassManager( - LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, bool Internalize, bool RunInliner) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderPopulateLTOPassManager(PMB, PM, Internalize, RunInliner); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" -void LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - LLVMPassManagerBuilderRef PMBR, - LLVMPassManagerRef PMR -) { -#if LLVM_VERSION_LT(15, 0) - unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR)); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" void LLVMRustPassManagerBuilderUseInlinerWithThreshold( - LLVMPassManagerBuilderRef PMB, unsigned Threshold) { -#if LLVM_VERSION_LT(15, 0) - LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -extern "C" -void LLVMRustAddLastExtensionPasses( - LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) { -#if LLVM_VERSION_LT(15, 0) - auto AddExtensionPasses = [Passes, NumPasses]( - const PassManagerBuilder &Builder, PassManagerBase &PM) { - for (size_t I = 0; I < NumPasses; I++) { - PM.add(unwrap(Passes[I])); - } - }; - // Add the passes to both of the pre-finalization extension points, - // so they are run for optimized and non-optimized builds. - unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast, - AddExtensionPasses); - unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - AddExtensionPasses); -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - #ifdef LLVM_COMPONENT_X86 #define SUBTARGET_X86 SUBTARGET(X86) #else @@ -604,47 +437,6 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) { delete unwrap(TM); } -extern "C" void LLVMRustConfigurePassManagerBuilder( - LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel, - bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO, - const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath, - int SizeLevel) { -#if LLVM_VERSION_LT(15, 0) - unwrap(PMBR)->MergeFunctions = MergeFunctions; - unwrap(PMBR)->SLPVectorize = SLPVectorize; - unwrap(PMBR)->OptLevel = fromRust(OptLevel); - unwrap(PMBR)->LoopVectorize = LoopVectorize; - unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO; - unwrap(PMBR)->SizeLevel = SizeLevel; - unwrap(PMBR)->DisableUnrollLoops = SizeLevel != 0; - - if (PGOGenPath) { - assert(!PGOUsePath && !PGOSampleUsePath); - unwrap(PMBR)->EnablePGOInstrGen = true; - unwrap(PMBR)->PGOInstrGen = PGOGenPath; - } else if (PGOUsePath) { - assert(!PGOSampleUsePath); - unwrap(PMBR)->PGOInstrUse = PGOUsePath; - } else if (PGOSampleUsePath) { - unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath; - } -#else - report_fatal_error("Legacy PM not supported with LLVM 15"); -#endif -} - -// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo` -// field of a PassManagerBuilder, we expose our own method of doing so. -extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR, - LLVMModuleRef M, - bool DisableSimplifyLibCalls) { - Triple TargetTriple(unwrap(M)->getTargetTriple()); - TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple); - if (DisableSimplifyLibCalls) - TLI->disableAllFunctions(); - unwrap(PMBR)->LibraryInfo = TLI; -} - // Unfortunately, the LLVM C API doesn't provide a way to create the // TargetLibraryInfo pass, so we use this method to do so. extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, @@ -656,27 +448,6 @@ extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M, unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); } -// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over -// all the functions in a module, so we do that manually here. You'll find -// similar code in clang's BackendUtil.cpp file. -extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR, - LLVMModuleRef M) { - llvm::legacy::FunctionPassManager *P = - unwrap<llvm::legacy::FunctionPassManager>(PMR); - P->doInitialization(); - - // Upgrade all calls to old intrinsics first. - for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;) - UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove - - for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E; - ++I) - if (!I->isDeclaration()) - P->run(*I); - - P->doFinalization(); -} - extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) { // Initializing the command-line options more than once is not allowed. So, // check if they've already been initialized. (This could happen if we're @@ -820,7 +591,7 @@ struct LLVMRustSanitizerOptions { }; extern "C" LLVMRustResult -LLVMRustOptimizeWithNewPassManager( +LLVMRustOptimize( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, LLVMRustPassBuilderOptLevel OptLevelRust, @@ -1241,15 +1012,8 @@ extern "C" void LLVMRustPrintPasses() { PR->enumerateWith(&Listener); } -extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR, - bool AddLifetimes) { - unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes); -} - extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, size_t Len) { - llvm::legacy::PassManager passes; - auto PreserveFunctions = [=](const GlobalValue &GV) { for (size_t I = 0; I < Len; I++) { if (GV.getName() == Symbols[I]) { @@ -1259,9 +1023,7 @@ extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, return false; }; - passes.add(llvm::createInternalizePass(PreserveFunctions)); - - passes.run(*unwrap(M)); + internalizeModule(*unwrap(M), PreserveFunctions); } extern "C" void @@ -1610,11 +1372,6 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { raw_string_ostream OS(Ret->data); { if (is_thin) { -#if LLVM_VERSION_LT(15, 0) - legacy::PassManager PM; - PM.add(createWriteThinLTOBitcodePass(OS)); - PM.run(*unwrap(M)); -#else PassBuilder PB; LoopAnalysisManager LAM; FunctionAnalysisManager FAM; @@ -1628,11 +1385,8 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { ModulePassManager MPM; MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); MPM.run(*unwrap(M), MAM); -#endif } else { - legacy::PassManager PM; - PM.add(createBitcodeWriterPass(OS)); - PM.run(*unwrap(M)); + WriteBitcodeToFile(*unwrap(M), OS); } } } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index b2cfcf53c59..6f36281af23 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -12,7 +12,7 @@ #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Pass.h" -#include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Support/Signals.h" #include "llvm/ADT/Optional.h" @@ -1670,11 +1670,7 @@ LLVMRustModuleBufferCreate(LLVMModuleRef M) { auto Ret = std::make_unique<LLVMRustModuleBuffer>(); { raw_string_ostream OS(Ret->data); - { - legacy::PassManager PM; - PM.add(createBitcodeWriterPass(OS)); - PM.run(*unwrap(M)); - } + WriteBitcodeToFile(*unwrap(M), OS); } return Ret.release(); } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 32d6ba62a0d..2aa292bbce2 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -1,17 +1,17 @@ #![deny(unused_must_use)] +use super::error::throw_invalid_nested_attr; +use super::utils::{SpannedOption, SubdiagnosticKind}; use crate::diagnostics::error::{ - invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - DiagnosticDeriveError, + invalid_nested_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path, - Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, + FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; use std::collections::HashMap; -use std::str::FromStr; use syn::{ parse_quote, spanned::Spanned, Attribute, Field, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, @@ -40,10 +40,10 @@ pub(crate) struct DiagnosticDeriveBuilder { pub kind: DiagnosticDeriveKind, /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. - pub slug: Option<(Path, proc_macro::Span)>, + pub slug: SpannedOption<Path>, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. - pub code: Option<(String, proc_macro::Span)>, + pub code: SpannedOption<()>, } impl HasFieldMap for DiagnosticDeriveBuilder { @@ -127,6 +127,30 @@ impl DiagnosticDeriveBuilder { || is_subdiagnostic } + fn parse_subdiag_attribute( + &self, + attr: &Attribute, + ) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> { + let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?; + + if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag { + let meta = attr.parse_meta()?; + throw_invalid_attr!(attr, &meta, |diag| diag + .help("consider creating a `Subdiagnostic` instead")); + } + + let slug = slug.unwrap_or_else(|| match subdiag { + SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, + SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, + SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, + SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, + SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), + }); + + Ok((subdiag, slug)) + } + /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct /// attributes like `#[diag(..)]`, such as the slug and error code. Generates /// diagnostic builder calls for setting error code and creating note/help messages. @@ -135,98 +159,64 @@ impl DiagnosticDeriveBuilder { attr: &Attribute, ) -> Result<TokenStream, DiagnosticDeriveError> { let diag = &self.diag; - let span = attr.span().unwrap(); let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); let meta = attr.parse_meta()?; - let is_diag = name == "diag"; - - let nested = match meta { - // Most attributes are lists, like `#[diag(..)]` for most cases or - // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. - Meta::List(MetaList { ref nested, .. }) => nested, - // Subdiagnostics without spans can be applied to the type too, and these are just - // paths: `#[help]`, `#[note]` and `#[warning]` - Meta::Path(_) if !is_diag => { - let fn_name = if name == "warning" { - Ident::new("warn", attr.span()) - } else { - Ident::new(name, attr.span()) - }; - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); - } - _ => throw_invalid_attr!(attr, &meta), - }; - - // Check the kind before doing any further processing so that there aren't misleading - // "no kind specified" errors if there are failures later. - match name { - "error" | "lint" => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("`error` and `lint` have been replaced by `diag`") - }), - "warn_" => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("`warn_` have been replaced by `warning`") - }), - "diag" | "help" | "note" | "warning" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `diag`, `help`, `note` and `warning` are valid attributes") - }), - } + if name == "diag" { + let Meta::List(MetaList { ref nested, .. }) = meta else { + throw_invalid_attr!( + attr, + &meta + ); + }; - // First nested element should always be the path, e.g. `#[diag(typeck::invalid)]` or - // `#[help(typeck::another_help)]`. - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - // Report an error if there are any other list items after the path. - if !is_diag && nested_iter.next().is_some() { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "`help`, `note` and `warning` struct attributes can only have one argument", - ) - }); - } + let mut nested_iter = nested.into_iter().peekable(); - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) => { - if is_diag { - self.slug.set_once((path.clone(), span)); - } else { - let fn_name = proc_macro2::Ident::new(name, attr.span()); - return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); - } - } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if is_diag && meta.path().segments.last().unwrap().ident == "code" => - { - // don't error for valid follow-up attributes + match nested_iter.peek() { + Some(NestedMeta::Meta(Meta::Path(slug))) => { + self.slug.set_once(slug.clone(), slug.span().unwrap()); + nested_iter.next(); } - nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("first argument of the attribute should be the diagnostic slug") - }), + Some(NestedMeta::Meta(Meta::NameValue { .. })) => {} + Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| diag + .help("a diagnostic slug is required as the first argument")), + None => throw_invalid_attr!(attr, &meta, |diag| diag + .help("a diagnostic slug is required as the first argument")), }; - } - // Remaining attributes are optional, only `code = ".."` at the moment. - let mut tokens = Vec::new(); - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(meta) => meta, - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; + // Remaining attributes are optional, only `code = ".."` at the moment. + let mut tokens = TokenStream::new(); + for nested_attr in nested_iter { + let (value, path) = match nested_attr { + NestedMeta::Meta(Meta::NameValue(MetaNameValue { + lit: syn::Lit::Str(value), + path, + .. + })) => (value, path), + NestedMeta::Meta(Meta::Path(_)) => { + invalid_nested_attr(attr, &nested_attr) + .help("diagnostic slug must be the first argument") + .emit(); + continue; + } + _ => { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + } + }; - let path = meta.path(); - let nested_name = path.segments.last().unwrap().ident.to_string(); - // Struct attributes are only allowed to be applied once, and the diagnostic - // changes will be set in the initialisation code. - if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { - let span = s.span().unwrap(); + let nested_name = path.segments.last().unwrap().ident.to_string(); + // Struct attributes are only allowed to be applied once, and the diagnostic + // changes will be set in the initialisation code. + let span = value.span().unwrap(); match nested_name.as_str() { "code" => { - self.code.set_once((s.value(), span)); - let code = &self.code.as_ref().map(|(v, _)| v); - tokens.push(quote! { + self.code.set_once((), span); + + let code = value.value(); + tokens.extend(quote! { #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); } @@ -234,12 +224,22 @@ impl DiagnosticDeriveBuilder { .help("only `code` is a valid nested attributes following the slug") .emit(), } - } else { - invalid_nested_attr(attr, &nested_attr).emit() } + return Ok(tokens); } - Ok(tokens.into_iter().collect()) + let (subdiag, slug) = self.parse_subdiag_attribute(attr)?; + let fn_ident = format_ident!("{}", subdiag); + match subdiag { + SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { + Ok(self.add_subdiagnostic(&fn_ident, slug)) + } + SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { + throw_invalid_attr!(attr, &meta, |diag| diag + .help("`#[label]` and `#[suggestion]` can only be applied to fields")); + } + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), + } } fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { @@ -303,232 +303,83 @@ impl DiagnosticDeriveBuilder { info: FieldInfo<'_>, binding: TokenStream, ) -> Result<TokenStream, DiagnosticDeriveError> { - let meta = attr.parse_meta()?; - match meta { - Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), - Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), - _ => throw_invalid_attr!(attr, &meta), - } - } - - fn generate_inner_field_code_path( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, DiagnosticDeriveError> { - assert!(matches!(attr.parse_meta()?, Meta::Path(_))); let diag = &self.diag; - let meta = attr.parse_meta()?; - let ident = &attr.path.segments.last().unwrap().ident; - let name = ident.to_string(); - let name = name.as_str(); - match name { - "skip_arg" => { - // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. - Ok(quote! {}) - } - "primary_span" => { - match self.kind { + if let Meta::Path(_) = meta { + let ident = &attr.path.segments.last().unwrap().ident; + let name = ident.to_string(); + let name = name.as_str(); + match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + return Ok(quote! {}); + } + "primary_span" => match self.kind { DiagnosticDeriveKind::Diagnostic => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(quote! { + return Ok(quote! { #diag.set_span(#binding); - }) + }); } DiagnosticDeriveKind::LintDiagnostic => { throw_invalid_attr!(attr, &meta, |diag| { diag.help("the `primary_span` field attribute is not valid for lint diagnostics") }) } - } + }, + "subdiagnostic" => return Ok(quote! { #diag.subdiagnostic(#binding); }), + _ => {} } - "label" => { + } + + let (subdiag, slug) = self.parse_subdiag_attribute(attr)?; + + let fn_ident = format_ident!("{}", subdiag); + match subdiag { + SubdiagnosticKind::Label => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) } - "note" | "help" | "warning" => { - let warn_ident = Ident::new("warn", Span::call_site()); - let (ident, path) = match name { - "note" => (ident, parse_quote! { _subdiag::note }), - "help" => (ident, parse_quote! { _subdiag::help }), - "warning" => (&warn_ident, parse_quote! { _subdiag::warn }), - _ => unreachable!(), - }; + SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - Ok(self.add_spanned_subdiagnostic(binding, ident, path)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) } else if type_is_unit(&info.ty) { - Ok(self.add_subdiagnostic(ident, path)) + Ok(self.add_subdiagnostic(&fn_ident, slug)) } else { report_type_error(attr, "`Span` or `()`")? } } - "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ - are valid field attributes", - ) - }), - } - } - - fn generate_inner_field_code_list( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - binding: TokenStream, - ) -> Result<TokenStream, DiagnosticDeriveError> { - let meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; - - let ident = &attr.path.segments.last().unwrap().ident; - let name = path.segments.last().unwrap().ident.to_string(); - let name = name.as_ref(); - match name { - "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { - return self.generate_inner_field_code_suggestion(attr, info); - } - "label" | "help" | "note" | "warning" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "only `label`, `help`, `note`, `warn` or `suggestion{,_short,_hidden,_verbose}` are \ - valid field attributes", - ) - }), - } - - // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a - // path, e.g. `#[label(typeck::label)]`. - let mut nested_iter = nested.into_iter(); - let msg = match nested_iter.next() { - Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), - Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), - None => throw_invalid_attr!(attr, &meta), - }; - - // None of these attributes should have anything following the slug. - if nested_iter.next().is_some() { - throw_invalid_attr!(attr, &meta); - } - - match name { - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { - Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) - } - "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), - // `warning` must be special-cased because the attribute `warn` already has meaning and - // so isn't used, despite the diagnostic API being named `warn`. - "warning" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => Ok(self - .add_spanned_subdiagnostic(binding, &Ident::new("warn", Span::call_site()), msg)), - "warning" if type_is_unit(&info.ty) => { - Ok(self.add_subdiagnostic(&Ident::new("warn", Span::call_site()), msg)) - } - "note" | "help" | "warning" => report_type_error(attr, "`Span` or `()`")?, - _ => unreachable!(), - } - } - - fn generate_inner_field_code_suggestion( - &mut self, - attr: &Attribute, - info: FieldInfo<'_>, - ) -> Result<TokenStream, DiagnosticDeriveError> { - let diag = &self.diag; - - let mut meta = attr.parse_meta()?; - let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; - - let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; - - let mut msg = None; - let mut code = None; - - let mut nested_iter = nested.into_iter().peekable(); - if let Some(nested_attr) = nested_iter.peek() { - if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { - msg = Some(path.clone()); - } - }; - // Move the iterator forward if a path was found (don't otherwise so that - // code/applicability can be found or an error emitted). - if msg.is_some() { - let _ = nested_iter.next(); - } - - for nested_attr in nested_iter { - let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, - syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let span = meta.span().unwrap(); - match nested_name { - "code" => { - let formatted_str = self.build_format(&s.value(), s.span()); - code = Some(formatted_str); - } - "applicability" => { - applicability = match applicability { - Some(v) => { - span_err( - span, - "applicability cannot be set in both the field and \ - attribute", - ) - .emit(); - Some(v) - } - None => match Applicability::from_str(&s.value()) { - Ok(v) => Some(quote! { #v }), - Err(()) => { - span_err(span, "invalid applicability").emit(); - None - } - }, - } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "only `message`, `code` and `applicability` are valid field \ - attributes", - ) - }), - } + SubdiagnosticKind::Suggestion { + suggestion_kind, + applicability: static_applicability, + code, + } => { + let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; + + if let Some((static_applicability, span)) = static_applicability { + applicability.set_once(quote! { #static_applicability }, span); } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - if matches!(meta, Meta::Path(_)) { - diag.help("a diagnostic slug must be the first argument to the attribute") - } else { - diag - } - }), + + let applicability = applicability + .value() + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); + let style = suggestion_kind.to_suggestion_style(); + + Ok(quote! { + #diag.span_suggestion_with_style( + #span_field, + rustc_errors::fluent::#slug, + #code, + #applicability, + #style + ); + }) } + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), } - - let applicability = - applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - - let name = path.segments.last().unwrap().ident.to_string(); - let method = format_ident!("span_{}", name); - - let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); - let msg = quote! { rustc_errors::fluent::#msg }; - let code = code.unwrap_or_else(|| quote! { String::new() }); - - Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) } /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug @@ -561,7 +412,7 @@ impl DiagnosticDeriveBuilder { fn span_and_applicability_of_ty( &self, info: FieldInfo<'_>, - ) -> Result<(TokenStream, Option<TokenStream>), DiagnosticDeriveError> { + ) -> Result<(TokenStream, SpannedOption<TokenStream>), DiagnosticDeriveError> { match &info.ty { // If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`. ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => { @@ -573,46 +424,37 @@ impl DiagnosticDeriveBuilder { let mut span_idx = None; let mut applicability_idx = None; + fn type_err(span: &Span) -> Result<!, DiagnosticDeriveError> { + span_err(span.unwrap(), "wrong types for suggestion") + .help( + "`#[suggestion(...)]` on a tuple field must be applied to fields \ + of type `(Span, Applicability)`", + ) + .emit(); + Err(DiagnosticDeriveError::ErrorHandled) + } + for (idx, elem) in tup.elems.iter().enumerate() { if type_matches_path(elem, &["rustc_span", "Span"]) { - if span_idx.is_none() { - span_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one `Span`" - ); - } + span_idx.set_once(syn::Index::from(idx), elem.span().unwrap()); } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { - if applicability_idx.is_none() { - applicability_idx = Some(syn::Index::from(idx)); - } else { - throw_span_err!( - info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more \ - than one Applicability" - ); - } + applicability_idx.set_once(syn::Index::from(idx), elem.span().unwrap()); + } else { + type_err(&elem.span())?; } } - if let Some(span_idx) = span_idx { - let binding = &info.binding.binding; - let span = quote!(#binding.#span_idx); - let applicability = applicability_idx - .map(|applicability_idx| quote!(#binding.#applicability_idx)) - .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - - return Ok((span, Some(applicability))); - } + let Some((span_idx, _)) = span_idx else { + type_err(&tup.span())?; + }; + let Some((applicability_idx, applicability_span)) = applicability_idx else { + type_err(&tup.span())?; + }; + let binding = &info.binding.binding; + let span = quote!(#binding.#span_idx); + let applicability = quote!(#binding.#applicability_idx); - throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { - diag.help( - "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ - `(Span, Applicability)`", - ) - }); + Ok((span, Some((applicability, applicability_span)))) } // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index bdeca3420bc..6545ae086b1 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -4,98 +4,17 @@ use crate::diagnostics::error::{ span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ - report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, - Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce, + report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo, + FieldInnerTy, HasFieldMap, SetOnce, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; use std::collections::HashMap; -use std::fmt; -use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; -/// Which kind of suggestion is being created? -#[derive(Clone, Copy)] -enum SubdiagnosticSuggestionKind { - /// `#[suggestion]` - Normal, - /// `#[suggestion_short]` - Short, - /// `#[suggestion_hidden]` - Hidden, - /// `#[suggestion_verbose]` - Verbose, -} - -impl FromStr for SubdiagnosticSuggestionKind { - type Err = (); - - fn from_str(s: &str) -> Result<Self, Self::Err> { - match s { - "" => Ok(SubdiagnosticSuggestionKind::Normal), - "_short" => Ok(SubdiagnosticSuggestionKind::Short), - "_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden), - "_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose), - _ => Err(()), - } - } -} - -impl SubdiagnosticSuggestionKind { - pub fn to_suggestion_style(&self) -> TokenStream { - match self { - SubdiagnosticSuggestionKind::Normal => { - quote! { rustc_errors::SuggestionStyle::ShowCode } - } - SubdiagnosticSuggestionKind::Short => { - quote! { rustc_errors::SuggestionStyle::HideCodeInline } - } - SubdiagnosticSuggestionKind::Hidden => { - quote! { rustc_errors::SuggestionStyle::HideCodeAlways } - } - SubdiagnosticSuggestionKind::Verbose => { - quote! { rustc_errors::SuggestionStyle::ShowAlways } - } - } - } -} - -/// Which kind of subdiagnostic is being created from a variant? -#[derive(Clone)] -enum SubdiagnosticKind { - /// `#[label(...)]` - Label, - /// `#[note(...)]` - Note, - /// `#[help(...)]` - Help, - /// `#[warning(...)]` - Warn, - /// `#[suggestion{,_short,_hidden,_verbose}]` - Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream }, - /// `#[multipart_suggestion{,_short,_hidden,_verbose}]` - MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind }, -} - -impl quote::IdentFragment for SubdiagnosticKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SubdiagnosticKind::Label => write!(f, "label"), - SubdiagnosticKind::Note => write!(f, "note"), - SubdiagnosticKind::Help => write!(f, "help"), - SubdiagnosticKind::Warn => write!(f, "warn"), - SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), - SubdiagnosticKind::MultipartSuggestion { .. } => { - write!(f, "multipart_suggestion_with_style") - } - } - } - - fn span(&self) -> Option<proc_macro2::Span> { - None - } -} +use super::error::invalid_attr; +use super::utils::{SpannedOption, SubdiagnosticKind}; /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct. pub(crate) struct SubdiagnosticDerive<'a> { @@ -195,10 +114,10 @@ struct SubdiagnosticDeriveBuilder<'a> { fields: HashMap<String, TokenStream>, /// Identifier for the binding to the `#[primary_span]` field. - span_field: Option<(proc_macro2::Ident, proc_macro::Span)>, - /// If a suggestion, the identifier for the binding to the `#[applicability]` field or a - /// `rustc_errors::Applicability::*` variant directly. - applicability: Option<(TokenStream, proc_macro::Span)>, + span_field: SpannedOption<proc_macro2::Ident>, + + /// The binding to the `#[applicability]` field, if present. + applicability: SpannedOption<TokenStream>, /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error /// during finalization if still `false`. @@ -217,6 +136,7 @@ struct KindsStatistics { has_multipart_suggestion: bool, all_multipart_suggestions: bool, has_normal_suggestion: bool, + all_applicabilities_static: bool, } impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { @@ -225,8 +145,15 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { has_multipart_suggestion: false, all_multipart_suggestions: true, has_normal_suggestion: false, + all_applicabilities_static: true, }; + for kind in kinds { + if let SubdiagnosticKind::MultipartSuggestion { applicability: None, .. } + | SubdiagnosticKind::Suggestion { applicability: None, .. } = kind + { + ret.all_applicabilities_static = false; + } if let SubdiagnosticKind::MultipartSuggestion { .. } = kind { ret.has_multipart_suggestion = true; } else { @@ -246,129 +173,14 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { let mut kind_slugs = vec![]; for attr in self.variant.ast().attrs { - let span = attr.span().unwrap(); - - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - - let meta = attr.parse_meta()?; - let Meta::List(MetaList { ref nested, .. }) = meta else { - throw_invalid_attr!(attr, &meta); - }; - - let mut kind = match name { - "label" => SubdiagnosticKind::Label, - "note" => SubdiagnosticKind::Note, - "help" => SubdiagnosticKind::Help, - "warning" => SubdiagnosticKind::Warn, - _ => { - if let Some(suggestion_kind) = - name.strip_prefix("suggestion").and_then(|s| s.parse().ok()) - { - SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() } - } else if let Some(suggestion_kind) = - name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok()) - { - SubdiagnosticKind::MultipartSuggestion { suggestion_kind } - } else { - throw_invalid_attr!(attr, &meta); - } - } - }; + let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?; - let mut slug = None; - let mut code = None; + let Some(slug) = slug else { + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); - let mut nested_iter = nested.into_iter(); - if let Some(nested_attr) = nested_iter.next() { - match nested_attr { - NestedMeta::Meta(Meta::Path(path)) => { - slug.set_once((path.clone(), span)); - } - NestedMeta::Meta(meta @ Meta::NameValue(_)) - if matches!( - meta.path().segments.last().unwrap().ident.to_string().as_str(), - "code" | "applicability" - ) => - { - // Don't error for valid follow-up attributes. - } - nested_attr => { - throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "first argument of the attribute should be the diagnostic \ - slug", - ) - }) - } - }; - } - - for nested_attr in nested_iter { - let meta = match nested_attr { - NestedMeta::Meta(ref meta) => meta, - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - - let value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, - Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("a diagnostic slug must be the first argument to the attribute") - }), - _ => throw_invalid_nested_attr!(attr, &nested_attr), - }; - - match nested_name { - "code" => { - if matches!(kind, SubdiagnosticKind::Suggestion { .. }) { - let formatted_str = self.build_format(&value.value(), value.span()); - code.set_once((formatted_str, span)); - } else { - span_err( - span, - &format!( - "`code` is not a valid nested attribute of a `{}` attribute", - name - ), - ) - .emit(); - } - } - "applicability" => { - if matches!( - kind, - SubdiagnosticKind::Suggestion { .. } - | SubdiagnosticKind::MultipartSuggestion { .. } - ) { - let value = - Applicability::from_str(&value.value()).unwrap_or_else(|()| { - span_err(span, "invalid applicability").emit(); - Applicability::Unspecified - }); - self.applicability.set_once((quote! { #value }, span)); - } else { - span_err( - span, - &format!( - "`applicability` is not a valid nested attribute of a `{}` attribute", - name - ) - ).emit(); - } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("only `code` and `applicability` are valid nested attributes") - }), - } - } - - let Some((slug, _)) = slug else { throw_span_err!( - span, + attr.span().unwrap(), &format!( "diagnostic slug must be first argument of a `#[{}(...)]` attribute", name @@ -376,21 +188,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { ); }; - match kind { - SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => { - let Some((code, _)) = code else { - throw_span_err!(span, "suggestion without `code = \"...\"`"); - }; - *code_field = code; - } - SubdiagnosticKind::Label - | SubdiagnosticKind::Note - | SubdiagnosticKind::Help - | SubdiagnosticKind::Warn - | SubdiagnosticKind::MultipartSuggestion { .. } => {} - } - - kind_slugs.push((kind, slug)) + kind_slugs.push((kind, slug)); } Ok(kind_slugs) @@ -474,18 +272,18 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { "skip_arg" => Ok(quote! {}), "primary_span" => { if kind_stats.has_multipart_suggestion { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { - diag.help( + invalid_attr(attr, &Meta::Path(path)) + .help( "multipart suggestions use one or more `#[suggestion_part]`s rather \ than one `#[primary_span]`", ) - }) - } - - report_error_if_not_applied_to_span(attr, &info)?; + .emit(); + } else { + report_error_if_not_applied_to_span(attr, &info)?; - let binding = info.binding.binding.clone(); - self.span_field.set_once((binding, span)); + let binding = info.binding.binding.clone(); + self.span_field.set_once(binding, span); + } Ok(quote! {}) } @@ -495,28 +293,39 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { if kind_stats.has_multipart_suggestion { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); - Ok(quote! {}) } else { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { - diag.help( - "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead", - ) - }); + invalid_attr(attr, &Meta::Path(path)) + .help( + "`#[suggestion_part(...)]` is only valid in multipart suggestions, \ + use `#[primary_span]` instead", + ) + .emit(); } + + Ok(quote! {}) } "applicability" => { if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion { report_error_if_not_applied_to_applicability(attr, &info)?; + if kind_stats.all_applicabilities_static { + span_err( + span, + "`#[applicability]` has no effect if all `#[suggestion]`/\ + `#[multipart_suggestion]` attributes have a static \ + `applicability = \"...\"`", + ) + .emit(); + } let binding = info.binding.binding.clone(); - self.applicability.set_once((quote! { #binding }, span)); + self.applicability.set_once(quote! { #binding }, span); } else { span_err(span, "`#[applicability]` is only valid on suggestions").emit(); } Ok(quote! {}) } - _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + _ => { let mut span_attrs = vec![]; if kind_stats.has_multipart_suggestion { span_attrs.push("suggestion_part"); @@ -524,11 +333,16 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { if !kind_stats.all_multipart_suggestions { span_attrs.push("primary_span") } - diag.help(format!( - "only `{}`, `applicability` and `skip_arg` are valid field attributes", - span_attrs.join(", ") - )) - }), + + invalid_attr(attr, &Meta::Path(path)) + .help(format!( + "only `{}`, `applicability` and `skip_arg` are valid field attributes", + span_attrs.join(", ") + )) + .emit(); + + Ok(quote! {}) + } } } @@ -577,7 +391,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { match nested_name { "code" => { let formatted_str = self.build_format(&value.value(), value.span()); - code.set_once((formatted_str, span)); + code.set_once(formatted_str, span); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help("`code` is the only valid nested attribute") @@ -635,11 +449,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); - let span_field = self.span_field.as_ref().map(|(span, _)| span); - let applicability = self.applicability.take().map_or_else( - || quote! { rustc_errors::Applicability::Unspecified }, - |(applicability, _)| applicability, - ); + let span_field = self.span_field.value_ref(); let diag = &self.diag; let mut calls = TokenStream::new(); @@ -647,7 +457,13 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); let message = quote! { rustc_errors::fluent::#slug }; let call = match kind { - SubdiagnosticKind::Suggestion { suggestion_kind, code } => { + SubdiagnosticKind::Suggestion { suggestion_kind, applicability, code } => { + let applicability = applicability + .value() + .map(|a| quote! { #a }) + .or_else(|| self.applicability.take().value()) + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); + if let Some(span) = span_field { let style = suggestion_kind.to_suggestion_style(); @@ -657,7 +473,13 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> { quote! { unreachable!(); } } } - SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => { + SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability } => { + let applicability = applicability + .value() + .map(|a| quote! { #a }) + .or_else(|| self.applicability.take().value()) + .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); + if !self.has_suggestion_parts { span_err( self.span, diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index ad9ecd39b9e..a31bda9ca0d 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,12 +1,18 @@ -use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError}; +use crate::diagnostics::error::{ + span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, +}; use proc_macro::Span; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; use std::collections::{BTreeSet, HashMap}; +use std::fmt; use std::str::FromStr; use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple}; +use syn::{MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure}; +use super::error::invalid_nested_attr; + /// Checks whether the type name of `ty` matches `name`. /// /// Given some struct at `a::b::c::Foo`, this will return true for `c::Foo`, `b::c::Foo`, or @@ -172,13 +178,17 @@ pub(crate) struct FieldInfo<'a> { /// Small helper trait for abstracting over `Option` fields that contain a value and a `Span` /// for error reporting if they are set more than once. pub(crate) trait SetOnce<T> { - fn set_once(&mut self, _: (T, Span)); + fn set_once(&mut self, value: T, span: Span); fn value(self) -> Option<T>; + fn value_ref(&self) -> Option<&T>; } -impl<T> SetOnce<T> for Option<(T, Span)> { - fn set_once(&mut self, (value, span): (T, Span)) { +/// An [`Option<T>`] that keeps track of the span that caused it to be set; used with [`SetOnce`]. +pub(super) type SpannedOption<T> = Option<(T, Span)>; + +impl<T> SetOnce<T> for SpannedOption<T> { + fn set_once(&mut self, value: T, span: Span) { match self { None => { *self = Some((value, span)); @@ -194,6 +204,10 @@ impl<T> SetOnce<T> for Option<(T, Span)> { fn value(self) -> Option<T> { self.map(|(v, _)| v) } + + fn value_ref(&self) -> Option<&T> { + self.as_ref().map(|(v, _)| v) + } } pub(crate) trait HasFieldMap { @@ -303,6 +317,7 @@ pub(crate) trait HasFieldMap { /// `Applicability` of a suggestion - mirrors `rustc_errors::Applicability` - and used to represent /// the user's selection of applicability if specified in an attribute. +#[derive(Clone, Copy)] pub(crate) enum Applicability { MachineApplicable, MaybeIncorrect, @@ -359,3 +374,250 @@ pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap<Stri fields_map } + +/// Possible styles for suggestion subdiagnostics. +#[derive(Clone, Copy)] +pub(super) enum SuggestionKind { + /// `#[suggestion]` + Normal, + /// `#[suggestion_short]` + Short, + /// `#[suggestion_hidden]` + Hidden, + /// `#[suggestion_verbose]` + Verbose, +} + +impl FromStr for SuggestionKind { + type Err = (); + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "" => Ok(SuggestionKind::Normal), + "_short" => Ok(SuggestionKind::Short), + "_hidden" => Ok(SuggestionKind::Hidden), + "_verbose" => Ok(SuggestionKind::Verbose), + _ => Err(()), + } + } +} + +impl SuggestionKind { + pub fn to_suggestion_style(&self) -> TokenStream { + match self { + SuggestionKind::Normal => { + quote! { rustc_errors::SuggestionStyle::ShowCode } + } + SuggestionKind::Short => { + quote! { rustc_errors::SuggestionStyle::HideCodeInline } + } + SuggestionKind::Hidden => { + quote! { rustc_errors::SuggestionStyle::HideCodeAlways } + } + SuggestionKind::Verbose => { + quote! { rustc_errors::SuggestionStyle::ShowAlways } + } + } + } +} + +/// Types of subdiagnostics that can be created using attributes +#[derive(Clone)] +pub(super) enum SubdiagnosticKind { + /// `#[label(...)]` + Label, + /// `#[note(...)]` + Note, + /// `#[help(...)]` + Help, + /// `#[warning(...)]` + Warn, + /// `#[suggestion{,_short,_hidden,_verbose}]` + Suggestion { + suggestion_kind: SuggestionKind, + applicability: SpannedOption<Applicability>, + code: TokenStream, + }, + /// `#[multipart_suggestion{,_short,_hidden,_verbose}]` + MultipartSuggestion { + suggestion_kind: SuggestionKind, + applicability: SpannedOption<Applicability>, + }, +} + +impl SubdiagnosticKind { + /// Constructs a `SubdiagnosticKind` from a field or type attribute such as `#[note]`, + /// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the + /// `SubdiagnosticKind` and the diagnostic slug, if specified. + pub(super) fn from_attr( + attr: &Attribute, + fields: &impl HasFieldMap, + ) -> Result<(SubdiagnosticKind, Option<Path>), DiagnosticDeriveError> { + let span = attr.span().unwrap(); + + let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = name.as_str(); + + let meta = attr.parse_meta()?; + let mut kind = match name { + "label" => SubdiagnosticKind::Label, + "note" => SubdiagnosticKind::Note, + "help" => SubdiagnosticKind::Help, + "warning" => SubdiagnosticKind::Warn, + _ => { + if let Some(suggestion_kind) = + name.strip_prefix("suggestion").and_then(|s| s.parse().ok()) + { + SubdiagnosticKind::Suggestion { + suggestion_kind, + applicability: None, + code: TokenStream::new(), + } + } else if let Some(suggestion_kind) = + name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok()) + { + SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability: None } + } else { + throw_invalid_attr!(attr, &meta); + } + } + }; + + let nested = match meta { + Meta::List(MetaList { ref nested, .. }) => { + // An attribute with properties, such as `#[suggestion(code = "...")]` or + // `#[error(some::slug)]` + nested + } + Meta::Path(_) => { + // An attribute without a slug or other properties, such as `#[note]` - return + // without further processing. + // + // Only allow this if there are no mandatory properties, such as `code = "..."` in + // `#[suggestion(...)]` + match kind { + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)), + SubdiagnosticKind::Suggestion { .. } => { + throw_span_err!(span, "suggestion without `code = \"...\"`") + } + } + } + _ => { + throw_invalid_attr!(attr, &meta) + } + }; + + let mut code = None; + + let mut nested_iter = nested.into_iter().peekable(); + + // Peek at the first nested attribute: if it's a slug path, consume it. + let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() { + let path = path.clone(); + // Advance the iterator. + nested_iter.next(); + Some(path) + } else { + None + }; + + for nested_attr in nested_iter { + let meta = match nested_attr { + NestedMeta::Meta(ref meta) => meta, + NestedMeta::Lit(_) => { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + } + }; + + let span = meta.span().unwrap(); + let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + let nested_name = nested_name.as_str(); + + let value = match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value, + Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("a diagnostic slug must be the first argument to the attribute") + }), + _ => { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + } + }; + + match (nested_name, &mut kind) { + ("code", SubdiagnosticKind::Suggestion { .. }) => { + let formatted_str = fields.build_format(&value.value(), value.span()); + code.set_once(formatted_str, span); + } + ( + "applicability", + SubdiagnosticKind::Suggestion { ref mut applicability, .. } + | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, + ) => { + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { + span_err(span, "invalid applicability").emit(); + Applicability::Unspecified + }); + applicability.set_once(value, span); + } + + // Invalid nested attribute + (_, SubdiagnosticKind::Suggestion { .. }) => { + invalid_nested_attr(attr, &nested_attr) + .help("only `code` and `applicability` are valid nested attributes") + .emit(); + } + (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { + invalid_nested_attr(attr, &nested_attr) + .help("only `applicability` is a valid nested attributes") + .emit() + } + _ => { + invalid_nested_attr(attr, &nested_attr).emit(); + } + } + } + + match kind { + SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => { + *code_field = if let Some((code, _)) = code { + code + } else { + span_err(span, "suggestion without `code = \"...\"`").emit(); + quote! { "" } + } + } + SubdiagnosticKind::Label + | SubdiagnosticKind::Note + | SubdiagnosticKind::Help + | SubdiagnosticKind::Warn + | SubdiagnosticKind::MultipartSuggestion { .. } => {} + } + + Ok((kind, slug)) + } +} + +impl quote::IdentFragment for SubdiagnosticKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SubdiagnosticKind::Label => write!(f, "label"), + SubdiagnosticKind::Note => write!(f, "note"), + SubdiagnosticKind::Help => write!(f, "help"), + SubdiagnosticKind::Warn => write!(f, "warn"), + SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"), + SubdiagnosticKind::MultipartSuggestion { .. } => { + write!(f, "multipart_suggestion_with_style") + } + } + } + + fn span(&self) -> Option<proc_macro2::Span> { + None + } +} diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 2a986c41d72..9abb5c74895 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -382,7 +382,7 @@ impl<'tcx> Collector<'tcx> { let link_ordinal_attr = self .tcx .hir() - .attrs(self.tcx.hir().local_def_id_to_hir_id(child_item.id.def_id)) + .attrs(child_item.id.def_id.into()) .iter() .find(|a| a.has_name(sym::link_ordinal)) .unwrap(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 67c28461ce5..7cf00ca41fe 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1217,14 +1217,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // from name resolution point of view. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - yield foreign_item.id.def_id.local_def_index; + yield foreign_item.id.def_id.def_id.local_def_index; } } // Only encode named non-reexport children, reexports are encoded // separately and unnamed items are not used by name resolution. hir::ItemKind::ExternCrate(..) => continue, _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { - yield item_id.def_id.local_def_index; + yield item_id.def_id.def_id.local_def_index; } _ => continue, } @@ -1446,7 +1446,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.macro_definition[def_id] <- &*macro_def.body); } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.def_id, m); + return self.encode_info_for_mod(item.def_id.def_id, m); } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); @@ -1840,7 +1840,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) { + if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), @@ -1850,7 +1850,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fx_hash_map .entry(trait_ref.def_id) .or_default() - .push((id.def_id.local_def_index, simplified_self_ty)); + .push((id.def_id.def_id.local_def_index, simplified_self_ty)); } } } diff --git a/compiler/rustc_middle/benches/lib.rs b/compiler/rustc_middle/benches/lib.rs deleted file mode 100644 index 237751bcbd7..00000000000 --- a/compiler/rustc_middle/benches/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![feature(test)] - -extern crate test; - -use test::Bencher; - -// Static/dynamic method dispatch - -struct Struct { - field: isize, -} - -trait Trait { - fn method(&self) -> isize; -} - -impl Trait for Struct { - fn method(&self) -> isize { - self.field - } -} - -#[bench] -fn trait_vtable_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - let t = &s as &dyn Trait; - b.iter(|| t.method()); -} - -#[bench] -fn trait_static_method_call(b: &mut Bencher) { - let s = Struct { field: 10 }; - b.iter(|| s.method()); -} - -// Overhead of various match forms - -#[bench] -fn option_some(b: &mut Bencher) { - let x = Some(10); - b.iter(|| match x { - Some(y) => y, - None => 11, - }); -} - -#[bench] -fn vec_pattern(b: &mut Bencher) { - let x = [1, 2, 3, 4, 5, 6]; - b.iter(|| match x { - [1, 2, 3, ..] => 10, - _ => 11, - }); -} diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index eded3b3eedc..40b9d73db94 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -62,86 +62,13 @@ use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{HirId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; use rustc_span::symbol::Symbol; use std::hash::Hash; pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; -/// This struct stores metadata about each DepKind. -/// -/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value -/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual -/// jump table instead of large matches. -pub struct DepKindStruct<'tcx> { - /// Anonymous queries cannot be replayed from one compiler invocation to the next. - /// When their result is needed, it is recomputed. They are useful for fine-grained - /// dependency tracking, and caching within one compiler invocation. - pub is_anon: bool, - - /// Eval-always queries do not track their dependencies, and are always recomputed, even if - /// their inputs have not changed since the last compiler invocation. The result is still - /// cached within one compiler invocation. - pub is_eval_always: bool, - - /// Whether the query key can be recovered from the hashed fingerprint. - /// See [DepNodeParams] trait for the behaviour of each key type. - pub fingerprint_style: FingerprintStyle, - - /// The red/green evaluation system will try to mark a specific DepNode in the - /// dependency graph as green by recursively trying to mark the dependencies of - /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` - /// where we don't know if it is red or green and we therefore actually have - /// to recompute its value in order to find out. Since the only piece of - /// information that we have at that point is the `DepNode` we are trying to - /// re-evaluate, we need some way to re-run a query from just that. This is what - /// `force_from_dep_node()` implements. - /// - /// In the general case, a `DepNode` consists of a `DepKind` and an opaque - /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint - /// is usually constructed by computing a stable hash of the query-key that the - /// `DepNode` corresponds to. Consequently, it is not in general possible to go - /// back from hash to query-key (since hash functions are not reversible). For - /// this reason `force_from_dep_node()` is expected to fail from time to time - /// because we just cannot find out, from the `DepNode` alone, what the - /// corresponding query-key is and therefore cannot re-run the query. - /// - /// The system deals with this case letting `try_mark_green` fail which forces - /// the root query to be re-evaluated. - /// - /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. - /// Fortunately, we can use some contextual information that will allow us to - /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we - /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a - /// valid `DefPathHash`. Since we also always build a huge table that maps every - /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have - /// everything we need to re-run the query. - /// - /// Take the `mir_promoted` query as an example. Like many other queries, it - /// just has a single parameter: the `DefId` of the item it will compute the - /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` - /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` - /// is actually a `DefPathHash`, and can therefore just look up the corresponding - /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option<fn(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool>, - - /// Invoke a query to put the on-disk cached value in memory. - pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'tcx>, DepNode)>, -} - -impl DepKind { - #[inline(always)] - pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle { - // Only fetch the DepKindStruct once. - let data = tcx.query_kind(self); - if data.is_anon { - return FingerprintStyle::Opaque; - } - data.fingerprint_style - } -} - macro_rules! define_dep_nodes { ( $($(#[$attr:meta])* @@ -159,7 +86,7 @@ macro_rules! define_dep_nodes { $( $( #[$attr] )* $variant),* } - fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> { + pub(super) fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> { match label { $(stringify!($variant) => Ok(DepKind::$variant),)* _ => Err(()), @@ -214,11 +141,6 @@ static_assert_size!(DepNode, 18); static_assert_size!(DepNode, 24); pub trait DepNodeExt: Sized { - /// Construct a DepNode from the given DepKind and DefPathHash. This - /// method will assert that the given DepKind actually requires a - /// single DefId/DefPathHash parameter. - fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self; - /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: /// @@ -243,14 +165,6 @@ pub trait DepNodeExt: Sized { } impl DepNodeExt for DepNode { - /// Construct a DepNode from the given DepKind and DefPathHash. This - /// method will assert that the given DepKind actually requires a - /// single DefId/DefPathHash parameter. - fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode { - debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash); - DepNode { kind, hash: def_path_hash.0.into() } - } - /// Extracts the DefId corresponding to this DepNode. This will work /// if two conditions are met: /// @@ -262,7 +176,7 @@ impl DepNodeExt for DepNode { /// refers to something from the previous compilation session that /// has been removed. fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> { - if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { + if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash { Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || { panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash) })) @@ -279,8 +193,8 @@ impl DepNodeExt for DepNode { ) -> Result<DepNode, ()> { let kind = dep_kind_from_label_string(label)?; - match kind.fingerprint_style(tcx) { - FingerprintStyle::Opaque | FingerprintStyle::HirId => Err(()), + match tcx.fingerprint_style(kind) { + FingerprintStyle::Opaque => Err(()), FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)), FingerprintStyle::DefPathHash => { Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind)) @@ -355,6 +269,28 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId { } } +impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for OwnerId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { + dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() }) + } +} + impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { @@ -408,7 +344,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) { impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::HirId + FingerprintStyle::Opaque } // We actually would not need to specialize the implementation of this @@ -417,36 +353,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId { #[inline(always)] fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { let HirId { owner, local_id } = *self; - let def_path_hash = tcx.def_path_hash(owner.to_def_id()); - Fingerprint::new( - // `owner` is local, so is completely defined by the local hash - def_path_hash.local_hash(), - local_id.as_u32().into(), - ) - } - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - let HirId { owner, local_id } = *self; - format!("{}.{}", tcx.def_path_str(owner.to_def_id()), local_id.as_u32()) - } + let def_path_hash = tcx.def_path_hash(owner.to_def_id()); + let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { - if dep_node.kind.fingerprint_style(tcx) == FingerprintStyle::HirId { - let (local_hash, local_id) = Fingerprint::from(dep_node.hash).as_value(); - let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash); - let owner = tcx - .def_path_hash_to_def_id(def_path_hash, &mut || { - panic!("Failed to extract HirId: {:?} {}", dep_node.kind, dep_node.hash) - }) - .expect_local(); - let local_id = local_id - .try_into() - .unwrap_or_else(|_| panic!("local id should be u32, found {:?}", local_id)); - Some(HirId { owner, local_id: ItemLocalId::from_u32(local_id) }) - } else { - None - } + def_path_hash.0.combine(local_id) } } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index c8b3b52b0fb..2e62bebc852 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -11,15 +11,17 @@ pub use rustc_query_system::dep_graph::{ SerializedDepNodeIndex, WorkProduct, WorkProductId, }; -pub use dep_node::{label_strs, DepKind, DepKindStruct, DepNode, DepNodeExt}; +pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>; + pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>; pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>; pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>; pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>; pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>; +pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct<TyCtxt<'tcx>>; impl rustc_query_system::dep_graph::DepKind for DepKind { const NULL: Self = DepKind::Null; @@ -91,50 +93,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { self.sess } - #[inline(always)] - fn fingerprint_style(&self, kind: DepKind) -> rustc_query_system::dep_graph::FingerprintStyle { - kind.fingerprint_style(*self) - } - - #[inline(always)] - fn is_eval_always(&self, kind: DepKind) -> bool { - self.query_kind(kind).is_eval_always - } - - fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool { - debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - - // We must avoid ever having to call `force_from_dep_node()` for a - // `DepNode::codegen_unit`: - // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we - // would always end up having to evaluate the first caller of the - // `codegen_unit` query that *is* reconstructible. This might very well be - // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just - // to re-trigger calling the `codegen_unit` query with the right key. At - // that point we would already have re-done all the work we are trying to - // avoid doing in the first place. - // The solution is simple: Just explicitly call the `codegen_unit` query for - // each CGU, right after partitioning. This way `try_mark_green` will always - // hit the cache instead of having to go through `force_from_dep_node`. - // This assertion makes sure, we actually keep applying the solution above. - debug_assert!( - dep_node.kind != DepKind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" - ); - - let cb = self.query_kind(dep_node.kind); - if let Some(f) = cb.force_from_dep_node { - f(*self, dep_node); - true - } else { - false - } - } - - fn try_load_from_on_disk_cache(&self, dep_node: DepNode) { - let cb = self.query_kind(dep_node.kind); - if let Some(f) = cb.try_load_from_on_disk_cache { - f(*self, dep_node) - } + #[inline] + fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> { + &self.query_kinds[dep_kind as usize] } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ca5598f5ff1..b5f7b26ea7a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -61,7 +61,7 @@ pub struct ParentHirIterator<'hir> { } impl<'hir> Iterator for ParentHirIterator<'hir> { - type Item = HirId; + type Item = (HirId, Node<'hir>); fn next(&mut self) -> Option<Self::Item> { if self.current_id == CRATE_HIR_ID { @@ -77,7 +77,10 @@ impl<'hir> Iterator for ParentHirIterator<'hir> { } self.current_id = parent_id; - return Some(parent_id); + if let Some(node) = self.map.find(parent_id) { + return Some((parent_id, node)); + } + // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. } } } @@ -90,7 +93,7 @@ pub struct ParentOwnerIterator<'hir> { } impl<'hir> Iterator for ParentOwnerIterator<'hir> { - type Item = (LocalDefId, OwnerNode<'hir>); + type Item = (OwnerId, OwnerNode<'hir>); fn next(&mut self) -> Option<Self::Item> { if self.current_id.local_id.index() != 0 { @@ -104,13 +107,13 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { } loop { // There are nodes that do not have entries, so we need to skip them. - let parent_id = self.map.def_key(self.current_id.owner).parent; + let parent_id = self.map.def_key(self.current_id.owner.def_id).parent; - let parent_id = parent_id.map_or(CRATE_HIR_ID.owner, |local_def_index| { + let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| { let def_id = LocalDefId { local_def_index }; self.map.local_def_id_to_hir_id(def_id).owner }); - self.current_id = HirId::make_owner(parent_id); + self.current_id = HirId::make_owner(parent_id.def_id); // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { @@ -128,7 +131,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { - match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) { + match self.tcx.hir_owner(CRATE_OWNER_ID).map(|o| o.node) { Some(OwnerNode::Crate(item)) => item, _ => bug!(), } @@ -183,7 +186,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn opt_local_def_id(self, hir_id: HirId) -> Option<LocalDefId> { if hir_id.local_id == ItemLocalId::new(0) { - Some(hir_id.owner) + Some(hir_id.owner.def_id) } else { self.tcx .hir_owner_nodes(hir_id.owner) @@ -349,7 +352,7 @@ impl<'hir> Map<'hir> { } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { - let node = self.tcx.hir_owner(id)?; + let node = self.tcx.hir_owner(OwnerId { def_id: id })?; node.node.generics() } @@ -390,8 +393,8 @@ impl<'hir> Map<'hir> { } pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId { - for (_, node) in self.parent_iter(hir_id) { - if let Some(body) = associated_body(node) { + for (parent, _) in self.parent_iter(hir_id) { + if let Some(body) = self.find(parent).map(associated_body).flatten() { return self.body_owner_def_id(body); } } @@ -529,7 +532,7 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module); - match self.tcx.hir_owner(module).map(|o| o.node) { + match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { (m, span, hir_id) } @@ -619,33 +622,26 @@ impl<'hir> Map<'hir> { pub fn for_each_module(self, mut f: impl FnMut(LocalDefId)) { let crate_items = self.tcx.hir_crate_items(()); for module in crate_items.submodules.iter() { - f(*module) + f(module.def_id) } } #[inline] pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) { let crate_items = self.tcx.hir_crate_items(()); - par_for_each_in(&crate_items.submodules[..], |module| f(*module)) + par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id)) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. #[inline] - pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> + 'hir { + pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> { ParentHirIterator { current_id, map: self } } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. #[inline] - pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> { - self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?))) - } - - /// Returns an iterator for the nodes in the ancestor tree of the `current_id` - /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. - #[inline] pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> { ParentOwnerIterator { current_id, map: self } } @@ -725,27 +721,27 @@ impl<'hir> Map<'hir> { None } - /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no + /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the HIR which is recorded by the map and is an item, either an item /// in a module, trait, or impl. - pub fn get_parent_item(self, hir_id: HirId) -> LocalDefId { + pub fn get_parent_item(self, hir_id: HirId) -> OwnerId { if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() { def_id } else { - CRATE_DEF_ID + CRATE_OWNER_ID } } - /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no + /// Returns the `OwnerId` of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. - pub(super) fn get_module_parent_node(self, hir_id: HirId) -> LocalDefId { + pub(super) fn get_module_parent_node(self, hir_id: HirId) -> OwnerId { for (def_id, node) in self.parent_owner_iter(hir_id) { if let OwnerNode::Item(&Item { kind: ItemKind::Mod(_), .. }) = node { return def_id; } } - CRATE_DEF_ID + CRATE_OWNER_ID } /// When on an if expression, a match arm tail expression or a match arm, give back @@ -818,30 +814,30 @@ impl<'hir> Map<'hir> { } bug!( "expected foreign mod or inlined parent, found {}", - self.node_to_string(HirId::make_owner(parent)) + self.node_to_string(HirId::make_owner(parent.def_id)) ) } - pub fn expect_owner(self, id: LocalDefId) -> OwnerNode<'hir> { + pub fn expect_owner(self, id: OwnerId) -> OwnerNode<'hir> { self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node } pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { - match self.tcx.hir_owner(id) { + match self.tcx.hir_owner(OwnerId { def_id: id }) { Some(Owner { node: OwnerNode::Item(item), .. }) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { - match self.tcx.hir_owner(id) { + match self.tcx.hir_owner(OwnerId { def_id: id }) { Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { - match self.tcx.hir_owner(id) { + match self.tcx.hir_owner(OwnerId { def_id: id }) { Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } @@ -854,11 +850,14 @@ impl<'hir> Map<'hir> { } } - pub fn expect_foreign_item(self, id: LocalDefId) -> &'hir ForeignItem<'hir> { + pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, _ => { - bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id))) + bug!( + "expected foreign item, found {}", + self.node_to_string(HirId::make_owner(id.def_id)) + ) } } } @@ -1294,7 +1293,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { // A "crate collector" and "module collector" start at a // module item (the former starts at the crate root) but only // the former needs to collect it. ItemCollector does not do this for us. - collector.submodules.push(CRATE_DEF_ID); + collector.submodules.push(CRATE_OWNER_ID); tcx.hir().walk_toplevel_module(&mut collector); let ItemCollector { @@ -1322,7 +1321,7 @@ struct ItemCollector<'tcx> { // otherwise it collects items in some module. crate_collector: bool, tcx: TyCtxt<'tcx>, - submodules: Vec<LocalDefId>, + submodules: Vec<OwnerId>, items: Vec<ItemId>, trait_items: Vec<TraitItemId>, impl_items: Vec<ImplItemId>, @@ -1354,7 +1353,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_item(&mut self, item: &'hir Item<'hir>) { if associated_body(Node::Item(item)).is_some() { - self.body_owners.push(item.def_id); + self.body_owners.push(item.def_id.def_id); } self.items.push(item.item_id()); @@ -1390,7 +1389,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { if associated_body(Node::TraitItem(item)).is_some() { - self.body_owners.push(item.def_id); + self.body_owners.push(item.def_id.def_id); } self.trait_items.push(item.trait_item_id()); @@ -1399,7 +1398,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { if associated_body(Node::ImplItem(item)).is_some() { - self.body_owners.push(item.def_id); + self.body_owners.push(item.def_id.def_id); } self.impl_items.push(item.impl_item_id()); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 211a614717f..1ce98a03c8a 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> { /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable, Encodable, Decodable)] pub struct ModuleItems { - submodules: Box<[LocalDefId]>, + submodules: Box<[OwnerId]>, items: Box<[ItemId]>, trait_items: Box<[TraitItemId]>, impl_items: Box<[ImplItemId]>, @@ -67,10 +67,10 @@ impl ModuleItems { pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ { self.items .iter() - .map(|id| id.def_id) - .chain(self.trait_items.iter().map(|id| id.def_id)) - .chain(self.impl_items.iter().map(|id| id.def_id)) - .chain(self.foreign_items.iter().map(|id| id.def_id)) + .map(|id| id.def_id.def_id) + .chain(self.trait_items.iter().map(|id| id.def_id.def_id)) + .chain(self.impl_items.iter().map(|id| id.def_id.def_id)) + .chain(self.foreign_items.iter().map(|id| id.def_id.def_id)) } pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) { @@ -97,7 +97,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn parent_module(self, id: HirId) -> LocalDefId { - self.parent_module_from_def_id(id.owner) + self.parent_module_from_def_id(id.owner.def_id) } pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> { @@ -110,13 +110,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn provide(providers: &mut Providers) { providers.parent_module_from_def_id = |tcx, id| { let hir = tcx.hir(); - hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) + hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)).def_id }; providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners.get(id)?.as_owner()?; + let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?; let node = owner.node(); Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies }) }; @@ -128,21 +128,24 @@ pub fn provide(providers: &mut Providers) { MaybeOwner::NonOwner(hir_id) => hir_id, } }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].map(|i| &i.nodes); + providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. - tcx.opt_local_parent(id).map_or(CRATE_HIR_ID, |parent| { + tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent); - if let Some(local_id) = - tcx.hir_crate(()).owners[parent_hir_id.owner].unwrap().parenting.get(&id) + if let Some(local_id) = tcx.hir_crate(()).owners[parent_hir_id.owner.def_id] + .unwrap() + .parenting + .get(&id.def_id) { parent_hir_id.local_id = *local_id; } parent_hir_id }) }; - providers.hir_attrs = - |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); + providers.hir_attrs = |tcx, id| { + tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) + }; providers.source_span = |tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP); providers.def_span = |tcx, def_id| { @@ -177,6 +180,7 @@ pub fn provide(providers: &mut Providers) { let id = id.expect_local(); tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root()) }; - providers.in_scope_traits_map = - |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map(|owner_info| &owner_info.trait_map); + providers.in_scope_traits_map = |tcx, id| { + tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map) + }; } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index bb9e1edf86c..2f45222de47 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -1,19 +1,20 @@ use std::cmp; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan}; use rustc_hir::HirId; +use rustc_index::vec::IndexVec; +use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::{ builtin::{self, FORBIDDEN_LINT_GROUPS}, - FutureIncompatibilityReason, Level, Lint, LintId, + FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, }; use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind}; use rustc_span::{symbol, Span, Symbol, DUMMY_SP}; -use crate::ty::TyCtxt; - /// How a lint level was set. #[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)] pub enum LintLevelSource { @@ -22,12 +23,7 @@ pub enum LintLevelSource { Default, /// Lint level was set by an attribute. - Node { - name: Symbol, - span: Span, - /// RFC 2383 reason - reason: Option<Symbol>, - }, + Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */), /// Lint level was set by a command-line flag. /// The provided `Level` is the level specified on the command line. @@ -39,7 +35,7 @@ impl LintLevelSource { pub fn name(&self) -> Symbol { match *self { LintLevelSource::Default => symbol::kw::Default, - LintLevelSource::Node { name, .. } => name, + LintLevelSource::Node(name, _, _) => name, LintLevelSource::CommandLine(name, _) => name, } } @@ -47,7 +43,7 @@ impl LintLevelSource { pub fn span(&self) -> Span { match *self { LintLevelSource::Default => DUMMY_SP, - LintLevelSource::Node { span, .. } => span, + LintLevelSource::Node(_, span, _) => span, LintLevelSource::CommandLine(_, _) => DUMMY_SP, } } @@ -56,115 +52,145 @@ impl LintLevelSource { /// A tuple of a lint level and its source. pub type LevelAndSource = (Level, LintLevelSource); -/// Return type for the `shallow_lint_levels_on` query. -/// -/// This map represents the set of allowed lints and allowance levels given -/// by the attributes for *a single HirId*. -#[derive(Default, Debug, HashStable)] -pub struct ShallowLintLevelMap { +#[derive(Debug, HashStable)] +pub struct LintLevelSets { + pub list: IndexVec<LintStackIndex, LintSet>, + pub lint_cap: Level, +} + +rustc_index::newtype_index! { + #[derive(HashStable)] + pub struct LintStackIndex { + const COMMAND_LINE = 0, + } +} + +#[derive(Debug, HashStable)] +pub struct LintSet { + // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which + // flag. pub specs: FxHashMap<LintId, LevelAndSource>, + + pub parent: LintStackIndex, } -/// From an initial level and source, verify the effect of special annotations: -/// `warnings` lint level and lint caps. -/// -/// The return of this function is suitable for diagnostics. -pub fn reveal_actual_level( - level: Option<Level>, - src: &mut LintLevelSource, - sess: &Session, - lint: LintId, - probe_for_lint_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource), -) -> Level { - // If `level` is none then we actually assume the default level for this lint. - let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition())); - - // If we're about to issue a warning, check at the last minute for any - // directives against the warnings "lint". If, for example, there's an - // `allow(warnings)` in scope then we want to respect that instead. - // - // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically - // triggers in cases (like #80988) where you have `forbid(warnings)`, - // and so if we turned that into an error, it'd defeat the purpose of the - // future compatibility warning. - if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) { - let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS)); - if let Some(configured_warning_level) = warnings_level { - if configured_warning_level != Level::Warn { - level = configured_warning_level; - *src = warnings_src; +impl LintLevelSets { + pub fn new() -> Self { + LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid } + } + + pub fn get_lint_level( + &self, + lint: &'static Lint, + idx: LintStackIndex, + aux: Option<&FxHashMap<LintId, LevelAndSource>>, + sess: &Session, + ) -> LevelAndSource { + let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); + + // If `level` is none then we actually assume the default level for this + // lint. + let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition())); + + // If we're about to issue a warning, check at the last minute for any + // directives against the warnings "lint". If, for example, there's an + // `allow(warnings)` in scope then we want to respect that instead. + // + // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically + // triggers in cases (like #80988) where you have `forbid(warnings)`, + // and so if we turned that into an error, it'd defeat the purpose of the + // future compatibility warning. + if level == Level::Warn && LintId::of(lint) != LintId::of(FORBIDDEN_LINT_GROUPS) { + let (warnings_level, warnings_src) = + self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux); + if let Some(configured_warning_level) = warnings_level { + if configured_warning_level != Level::Warn { + level = configured_warning_level; + src = warnings_src; + } } } - } - // Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn - level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { - level - } else { - cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid)) - }; + // Ensure that we never exceed the `--cap-lints` argument + // unless the source is a --force-warn + level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src { + level + } else { + cmp::min(level, self.lint_cap) + }; + + if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) { + // Ensure that we never exceed driver level. + level = cmp::min(*driver_level, level); + } - if let Some(driver_level) = sess.driver_lint_caps.get(&lint) { - // Ensure that we never exceed driver level. - level = cmp::min(*driver_level, level); + (level, src) } - level -} - -impl ShallowLintLevelMap { - /// Perform a deep probe in the HIR tree looking for the actual level for the lint. - /// This lint level is not usable for diagnostics, it needs to be corrected by - /// `reveal_actual_level` beforehand. - fn probe_for_lint_level( + pub fn get_lint_id_level( &self, - tcx: TyCtxt<'_>, id: LintId, - start: HirId, + mut idx: LintStackIndex, + aux: Option<&FxHashMap<LintId, LevelAndSource>>, ) -> (Option<Level>, LintLevelSource) { - if let Some(&(level, src)) = self.specs.get(&id) { - return (Some(level), src); + if let Some(specs) = aux { + if let Some(&(level, src)) = specs.get(&id) { + return (Some(level), src); + } } - - for parent in tcx.hir().parent_id_iter(start) { - let specs = tcx.shallow_lint_levels_on(parent); - if let Some(&(level, src)) = specs.specs.get(&id) { + loop { + let LintSet { ref specs, parent } = self.list[idx]; + if let Some(&(level, src)) = specs.get(&id) { return (Some(level), src); } + if idx == COMMAND_LINE { + return (None, LintLevelSource::Default); + } + idx = parent; } - (None, LintLevelSource::Default) } +} + +#[derive(Debug)] +pub struct LintLevelMap { + /// This is a collection of lint expectations as described in RFC 2383, that + /// can be fulfilled during this compilation session. This means that at least + /// one expected lint is currently registered in the lint store. + /// + /// The [`LintExpectationId`] is stored as a part of the [`Expect`](Level::Expect) + /// lint level. + pub lint_expectations: Vec<(LintExpectationId, LintExpectation)>, + pub sets: LintLevelSets, + pub id_to_set: FxHashMap<HirId, LintStackIndex>, +} - /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_id_at_node( +impl LintLevelMap { + /// If the `id` was previously registered with `register_id` when building + /// this `LintLevelMap` this returns the corresponding lint level and source + /// of the lint level for the lint provided. + /// + /// If the `id` was not previously registered, returns `None`. If `None` is + /// returned then the parent of `id` should be acquired and this function + /// should be called again. + pub fn level_and_source( &self, - tcx: TyCtxt<'_>, - lint: LintId, + lint: &'static Lint, id: HirId, - ) -> (Level, LintLevelSource) { - let (level, mut src) = self.probe_for_lint_level(tcx, lint, id); - let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| { - self.probe_for_lint_level(tcx, lint, id) - }); - debug!(?id, ?level, ?src); - (level, src) + session: &Session, + ) -> Option<LevelAndSource> { + self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session)) } } -impl TyCtxt<'_> { - /// Fetch and return the user-visible lint level for the given lint at the given HirId. - pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) { - self.shallow_lint_levels_on(id).lint_level_id_at_node(self, LintId::of(lint), id) - } +impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap { + #[inline] + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let LintLevelMap { ref sets, ref id_to_set, ref lint_expectations } = *self; - /// Walks upwards from `id` to find a node which might change lint levels with attributes. - /// It stops at `bound` and just returns it if reached. - pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { - let hir = self.hir(); - while id != bound && self.shallow_lint_levels_on(id).specs.is_empty() { - id = hir.get_parent_node(id) - } - id + id_to_set.hash_stable(hcx, hasher); + lint_expectations.hash_stable(hcx, hasher); + + hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher)) } } @@ -235,11 +261,11 @@ pub fn explain_lint_level_source( )); } } - LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => { + LintLevelSource::Node(lint_attr_name, src, reason) => { if let Some(rationale) = reason { err.note(rationale.as_str()); } - err.span_note_once(span, "the lint level is defined here"); + err.span_note_once(src, "the lint level is defined here"); if lint_attr_name.as_str() != name { let level_str = level.as_str(); err.note_once(&format!( diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 2a1a0bbe2ae..c3bf1c717d9 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -3,8 +3,8 @@ use crate::ty; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::ItemLocalId; +use rustc_hir::def_id::DefId; +use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] @@ -49,7 +49,7 @@ pub enum ObjectLifetimeDefault { pub struct ResolveLifetimes { /// Maps from every use of a named (not anonymous) lifetime to a /// `Region` describing how that region is bound - pub defs: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Region>>, + pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>, - pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>, + pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>, } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 21ae121e1ce..fdda62719ee 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -182,7 +182,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(), MonoItem::Static(def_id) => def_id.as_local(), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id), + MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id), } .map(|def_id| tcx.def_span(def_id)) } @@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> { } } MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.index()), + MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.def_id.index()), }, item.symbol_name(tcx), ) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b4ae13edf08..eed44240f83 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -73,7 +73,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner(key: LocalDefId) -> Option<crate::hir::Owner<'tcx>> { + query hir_owner(key: hir::OwnerId) -> Option<crate::hir::Owner<'tcx>> { desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -89,7 +89,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_parent(key: LocalDefId) -> hir::HirId { + query hir_owner_parent(key: hir::OwnerId) -> hir::HirId { desc { |tcx| "HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -97,7 +97,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: LocalDefId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { + query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -105,7 +105,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> { + query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -274,14 +274,10 @@ rustc_queries! { separate_provide_extern } - query shallow_lint_levels_on(key: HirId) -> rustc_middle::lint::ShallowLintLevelMap { + query lint_levels(_: ()) -> LintLevelMap { arena_cache - desc { |tcx| "looking up lint levels for `{}`", key } - } - - query lint_expectations(_: ()) -> Vec<(LintExpectationId, LintExpectation)> { - arena_cache - desc { "computing `#[expect]`ed lints in this crate" } + eval_always + desc { "computing the lint levels for items in this crate" } } query parent_module_from_def_id(key: LocalDefId) -> LocalDefId { @@ -1408,7 +1404,7 @@ rustc_queries! { query specializes(_: (DefId, DefId)) -> bool { desc { "computing whether impls specialize one another" } } - query in_scope_traits_map(_: LocalDefId) + query in_scope_traits_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap<ItemLocalId, Box<[TraitCandidate]>>> { desc { "traits in scope at a block" } } @@ -1423,7 +1419,7 @@ rustc_queries! { separate_provide_extern } - query check_well_formed(key: LocalDefId) -> () { + query check_well_formed(key: hir::OwnerId) -> () { desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) } } @@ -1590,7 +1586,7 @@ rustc_queries! { arena_cache desc { "resolving lifetimes" } } - query named_region_map(_: LocalDefId) -> + query named_region_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap<ItemLocalId, Region>> { desc { "looking up a named region" } } @@ -1606,7 +1602,7 @@ rustc_queries! { desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) } separate_provide_extern } - query late_bound_vars_map(_: LocalDefId) + query late_bound_vars_map(_: hir::OwnerId) -> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> { desc { "looking up late bound vars" } } diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 0e6cacb9fd0..fb152b63f63 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -8,8 +8,9 @@ use crate::error::DropCheckOverflow; use crate::infer::canonical::{Canonical, QueryResponse}; use crate::ty::error::TypeError; -use crate::ty::subst::GenericArg; +use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; +use rustc_hir::def_id::DefId; use rustc_span::source_map::Span; use std::iter::FromIterator; @@ -219,4 +220,5 @@ pub enum OutlivesBound<'tcx> { RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), RegionSubParam(ty::Region<'tcx>, ty::ParamTy), RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>), + RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>), } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2b5b4017a5a..e430c327efe 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,10 +1,10 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; +use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; -use crate::lint::struct_lint_level; +use crate::lint::{struct_lint_level, LintLevelSource}; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::resolve_lifetime; use crate::middle::stability; @@ -40,6 +40,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; +use rustc_hir::hir_id::OwnerId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -54,7 +55,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{CrateType, OutputFilenames}; use rustc_session::cstore::CrateStoreDyn; use rustc_session::errors::TargetDataLayoutErrorsWrapper; -use rustc_session::lint::Lint; +use rustc_session::lint::{Level, Lint}; use rustc_session::Limit; use rustc_session::Session; use rustc_span::def_id::{DefPathHash, StableCrateId}; @@ -289,7 +290,7 @@ pub struct CommonConsts<'tcx> { } pub struct LocalTableInContext<'a, V> { - hir_owner: LocalDefId, + hir_owner: OwnerId, data: &'a ItemLocalMap<V>, } @@ -301,7 +302,7 @@ pub struct LocalTableInContext<'a, V> { /// would result in lookup errors, or worse, in silently wrong data being /// stored/returned. #[inline] -fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) { +fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) { if hir_id.owner != hir_owner { invalid_hir_id_for_typeck_results(hir_owner, hir_id); } @@ -309,7 +310,7 @@ fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) #[cold] #[inline(never)] -fn invalid_hir_id_for_typeck_results(hir_owner: LocalDefId, 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 {:?}", @@ -345,7 +346,7 @@ impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> { } pub struct LocalTableInContextMut<'a, V> { - hir_owner: LocalDefId, + hir_owner: OwnerId, data: &'a mut ItemLocalMap<V>, } @@ -417,7 +418,7 @@ pub struct GeneratorDiagnosticData<'tcx> { #[derive(TyEncodable, TyDecodable, Debug, HashStable)] pub struct TypeckResults<'tcx> { /// The `HirId::owner` all `ItemLocalId`s in this table are relative to. - pub hir_owner: LocalDefId, + pub hir_owner: OwnerId, /// Resolved definitions for `<T>::X` associated paths and /// method calls, including those of overloaded operators. @@ -592,7 +593,7 @@ pub struct TypeckResults<'tcx> { } impl<'tcx> TypeckResults<'tcx> { - pub fn new(hir_owner: LocalDefId) -> TypeckResults<'tcx> { + pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> { TypeckResults { hir_owner, type_dependent_defs: Default::default(), @@ -1084,7 +1085,7 @@ pub struct GlobalCtxt<'tcx> { pub queries: &'tcx dyn query::QueryEngine<'tcx>, pub query_caches: query::QueryCaches<'tcx>, - query_kinds: &'tcx [DepKindStruct<'tcx>], + pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>], // Internal caches for metadata decoding. No need to track deps on this. pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>, @@ -1291,10 +1292,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct<'tcx> { - &self.query_kinds[k as usize] - } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { @@ -1726,7 +1723,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn local_visibility(self, def_id: LocalDefId) -> Visibility { - self.visibility(def_id.to_def_id()).expect_local() + self.visibility(def_id).expect_local() } } @@ -2813,6 +2810,44 @@ impl<'tcx> TyCtxt<'tcx> { iter.intern_with(|xs| self.intern_bound_variable_kinds(xs)) } + /// Walks upwards from `id` to find a node which might change lint levels with attributes. + /// It stops at `bound` and just returns it if reached. + pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { + let hir = self.hir(); + loop { + if id == bound { + return bound; + } + + if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) { + return id; + } + let next = hir.get_parent_node(id); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + } + } + + pub fn lint_level_at_node( + self, + lint: &'static Lint, + mut id: hir::HirId, + ) -> (Level, LintLevelSource) { + let sets = self.lint_levels(()); + loop { + if let Some(pair) = sets.level_and_source(lint, id, self.sess) { + return pair; + } + let next = self.hir().get_parent_node(id); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + } + } + /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`, /// typically generated by `#[derive(LintDiagnostic)]`). pub fn emit_spanned_lint( @@ -2869,7 +2904,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner).map_or(false, |set| { + self.is_late_bound_map(id.owner.def_id).map_or(false, |set| { let def_id = self.hir().local_def_id(id); set.contains(&def_id) }) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 01e1e97b21a..52f16ad88f6 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -861,7 +861,7 @@ fn foo(&self) -> Self::T { String::new() } // When `body_owner` is an `impl` or `trait` item, look in its associated types for // `expected` and point at it. let parent_id = self.hir().get_parent_item(hir_id); - let item = self.hir().find_by_def_id(parent_id); + let item = self.hir().find_by_def_id(parent_id.def_id); debug!("expected_projection parent item {:?}", item); match item { Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => { diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index be208a9fc70..169da348a29 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -1,6 +1,6 @@ use crate::dep_graph; use crate::infer::canonical::{self, Canonical}; -use crate::lint::LintExpectation; +use crate::lint::LintLevelMap; use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; @@ -44,14 +44,13 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; -use rustc_hir::hir_id::HirId; +use rustc_hir::hir_id::OwnerId; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{CrateDepKind, CrateSource}; use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib}; -use rustc_session::lint::LintExpectationId; use rustc_session::utils::NativeLibKind; use rustc_session::Limits; use rustc_span::symbol::Symbol; @@ -338,7 +337,7 @@ macro_rules! define_callbacks { rustc_query_append! { define_callbacks! } mod sealed { - use super::{DefId, LocalDefId}; + use super::{DefId, LocalDefId, OwnerId}; /// An analogue of the `Into` trait that's intended only for query parameters. /// @@ -368,6 +367,13 @@ mod sealed { self.to_def_id() } } + + impl IntoQueryParam<DefId> for OwnerId { + #[inline(always)] + fn into_query_param(self) -> DefId { + self.to_def_id() + } + } } use sealed::IntoQueryParam; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 3b42f4b51fc..1164cf3e01a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -272,7 +272,10 @@ impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C) impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> { type Lifted = Option<T::Lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - tcx.lift(self?).map(Some) + Some(match self { + Some(x) => Some(tcx.lift(x)?), + None => None, + }) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e773b3032aa..258fb2e2f9f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1133,9 +1133,13 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - let parent = tcx.parent(self.item_def_id); - assert_eq!(tcx.def_kind(parent), DefKind::Trait); - parent + match tcx.def_kind(self.item_def_id) { + DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id), + DefKind::ImplTraitPlaceholder => { + tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id)) + } + kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"), + } } /// Extracts the underlying trait reference and own substs from this projection. diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index f1a25a60d52..5cd7a7f760f 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1246,7 +1246,7 @@ impl<'v> RootCollector<'_, 'v> { } } DefKind::Fn => { - self.push_if_root(id.def_id); + self.push_if_root(id.def_id.def_id); } _ => {} } @@ -1254,7 +1254,7 @@ impl<'v> RootCollector<'_, 'v> { fn process_impl_item(&mut self, id: hir::ImplItemId) { if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) { - self.push_if_root(id.def_id); + self.push_if_root(id.def_id.def_id); } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index dcea11eadcb..0a81cde93be 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -289,7 +289,7 @@ pub enum BadTypePlusSub { #[diag(parser::maybe_recover_from_bad_qpath_stage_2)] struct BadQPathStage2 { #[primary_span] - #[suggestion(applicability = "maybe-incorrect")] + #[suggestion(code = "", applicability = "maybe-incorrect")] span: Span, ty: String, } @@ -298,7 +298,7 @@ struct BadQPathStage2 { #[diag(parser::incorrect_semicolon)] struct IncorrectSemicolon<'a> { #[primary_span] - #[suggestion_short(applicability = "machine-applicable")] + #[suggestion_short(code = "", applicability = "machine-applicable")] span: Span, #[help] opt_help: Option<()>, @@ -309,7 +309,7 @@ struct IncorrectSemicolon<'a> { #[diag(parser::incorrect_use_of_await)] struct IncorrectUseOfAwait { #[primary_span] - #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")] + #[suggestion(parser::parentheses_suggestion, code = "", applicability = "machine-applicable")] span: Span, } @@ -329,7 +329,7 @@ struct IncorrectAwait { struct InInTypo { #[primary_span] span: Span, - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] sugg_span: Span, } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e55b5ce71cd..e385ac44113 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1715,6 +1715,7 @@ impl<'a> Parser<'a> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { + let snapshot = self.create_snapshot_for_diagnostic(); let err = if self.check_fn_front_matter(false) { let inherited_vis = Visibility { span: rustc_span::DUMMY_SP, @@ -1735,6 +1736,22 @@ impl<'a> Parser<'a> { err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks"); err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); err + } else if self.eat_keyword(kw::Struct) { + match self.parse_item_struct() { + Ok((ident, _)) => { + let mut err = self.struct_span_err( + lo.with_hi(ident.span.hi()), + &format!("structs are not allowed in {adt_ty} definitions"), + ); + err.help("consider creating a new `struct` definition instead of nesting"); + err + } + Err(err) => { + err.cancel(); + self.restore_snapshot(snapshot); + self.expected_ident_found() + } + } } else { self.expected_ident_found() }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f112f1274b8..a21521ff68b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -11,9 +11,11 @@ use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan}; use rustc_expand::base::resolve_path; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID}; +use rustc_hir::{ + self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID, +}; use rustc_hir::{MethodKind, Target}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; @@ -35,7 +37,7 @@ pub(crate) fn target_from_impl_item<'tcx>( match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, hir::ImplItemKind::Fn(..) => { - let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id()); + let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let containing_item = tcx.hir().expect_item(parent_def_id); let containing_impl_is_for_trait = match &containing_item.kind { hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(), @@ -640,7 +642,7 @@ impl CheckAttrVisitor<'_> { let span = meta.span(); if let Some(location) = match target { Target::AssocTy => { - let parent_def_id = self.tcx.hir().get_parent_item(hir_id); + let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id; let containing_item = self.tcx.hir().expect_item(parent_def_id); if Target::from_item(containing_item) == Target::Impl { Some("type alias in implementation block") @@ -649,7 +651,7 @@ impl CheckAttrVisitor<'_> { } } Target::AssocConst => { - let parent_def_id = self.tcx.hir().get_parent_item(hir_id); + let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id; let containing_item = self.tcx.hir().expect_item(parent_def_id); // We can't link to trait impl's consts. let err = "associated constant in trait implementation block"; @@ -878,7 +880,7 @@ impl CheckAttrVisitor<'_> { self.tcx.struct_span_lint_hir(INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| { let mut err = lint.build(fluent::passes::attr_crate_level); if attr.style == AttrStyle::Outer - && self.tcx.hir().get_parent_item(hir_id) == CRATE_DEF_ID + && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID { if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) { src.insert(1, '!'); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 57f7c379d04..e9d71bc93ac 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -317,7 +317,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { - let item = self.tcx.local_parent(impl_item.def_id); + let item = self.tcx.local_parent(impl_item.def_id.def_id); if self.tcx.impl_trait_ref(item).is_none() { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static @@ -374,7 +374,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { if has_repr_c || (f.is_positional() && has_repr_simd) { return Some(def_id); } - if !tcx.visibility(f.hir_id.owner).is_public() { + if !tcx.visibility(f.hir_id.owner.def_id).is_public() { return None; } if tcx.visibility(def_id).is_public() { Some(def_id) } else { None } @@ -528,7 +528,7 @@ fn check_item<'tcx>( ) { let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id()); if allow_dead_code { - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } match tcx.def_kind(id.def_id) { @@ -554,7 +554,7 @@ fn check_item<'tcx>( let of_trait = tcx.impl_trait_ref(id.def_id); if of_trait.is_some() { - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } // get DefIds from another query @@ -577,12 +577,12 @@ fn check_item<'tcx>( if let hir::ItemKind::Struct(ref variant_data, _) = item.kind && let Some(ctor_hir_id) = variant_data.ctor_hir_id() { - struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id); + struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id.def_id); } } DefKind::GlobalAsm => { // global_asm! is always live. - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } _ => {} } @@ -595,7 +595,7 @@ fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec<LocalDefId>, id: if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id()) { - worklist.push(trait_item.def_id); + worklist.push(trait_item.def_id.def_id); } } } @@ -608,7 +608,7 @@ fn check_foreign_item<'tcx>( if matches!(tcx.def_kind(id.def_id), DefKind::Static(_) | DefKind::Fn) && has_allow_dead_code_or_lang_attr(tcx, id.hir_id()) { - worklist.push(id.def_id); + worklist.push(id.def_id.def_id); } } @@ -871,13 +871,13 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if !live_symbols.contains(&item.def_id) { - let parent = tcx.local_parent(item.def_id); + if !live_symbols.contains(&item.def_id.def_id) { + let parent = tcx.local_parent(item.def_id.def_id); if parent != module && !live_symbols.contains(&parent) { // We already have diagnosed something. continue; } - visitor.check_definition(item.def_id); + visitor.check_definition(item.def_id.def_id); continue; } @@ -926,16 +926,21 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional) } - visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants, false); + visitor.warn_dead_fields_and_variants( + item.def_id.def_id, + "constructed", + dead_variants, + false, + ); } } for impl_item in module_items.impl_items() { - visitor.check_definition(impl_item.def_id); + visitor.check_definition(impl_item.def_id.def_id); } for foreign_item in module_items.foreign_items() { - visitor.check_definition(foreign_item.def_id); + visitor.check_definition(foreign_item.def_id.def_id); } // We do not warn trait items. diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index e6b69d8986c..e428d9293db 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -74,19 +74,19 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } for id in crate_items.trait_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } for id in crate_items.impl_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } for id in crate_items.foreign_items() { - observe_item(tcx, &mut diagnostic_items, id.def_id); + observe_item(tcx, &mut diagnostic_items, id.def_id.def_id); } diagnostic_items diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index cd10170d3ba..eec37d19a88 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -82,7 +82,7 @@ fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: } fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { - let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID); + let at_root = ctxt.tcx.opt_local_parent(id.def_id.def_id) == Some(CRATE_DEF_ID); match entry_point_type(ctxt, id, at_root) { EntryPointType::None => { @@ -99,7 +99,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } EntryPointType::RustcMainAttr => { if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id()))); + ctxt.attr_main_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); } else { struct_span_err!( ctxt.tcx.sess, @@ -118,11 +118,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { EntryPointType::Start => { err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`"); if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id()))); + ctxt.start_fn = Some((id.def_id.def_id, ctxt.tcx.def_span(id.def_id))); } else { struct_span_err!( ctxt.tcx.sess, - ctxt.tcx.def_span(id.def_id.to_def_id()), + ctxt.tcx.def_span(id.def_id), E0138, "multiple `start` functions" ) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index cdfa7cf7f93..cc231af71a2 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -462,7 +462,7 @@ pub struct LinkSection { pub struct NoMangleForeign { #[label] pub span: Span, - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] pub attr_span: Span, pub foreign_item_kind: &'static str, } @@ -596,7 +596,7 @@ pub enum UnusedNote { #[derive(LintDiagnostic)] #[diag(passes::unused)] pub struct Unused { - #[suggestion(applicability = "machine-applicable")] + #[suggestion(code = "", applicability = "machine-applicable")] pub attr_span: Span, #[subdiagnostic] pub note: UnusedNote, diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 3bb8c0bb48c..3ee8c8bcb1d 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,6 +1,5 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit; use rustc_hir::{HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; @@ -42,7 +41,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { struct HirIdValidator<'a, 'hir> { hir_map: Map<'hir>, - owner: Option<LocalDefId>, + owner: Option<hir::OwnerId>, hir_ids_seen: GrowableBitSet<ItemLocalId>, errors: &'a Lock<Vec<String>>, } @@ -63,12 +62,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.errors.lock().push(f()); } - fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: LocalDefId, walk: F) { + fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: hir::OwnerId, walk: F) { assert!(self.owner.is_none()); self.owner = Some(owner); walk(self); - if owner == CRATE_DEF_ID { + if owner == hir::CRATE_OWNER_ID { return; } @@ -97,14 +96,14 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { missing_items.push(format!( "[local_id: {}, owner: {}]", local_id, - self.hir_map.def_path(owner).to_string_no_crate_verbose() + self.hir_map.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.hir_map.def_path(owner).to_string_no_crate_verbose(), + self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose(), max, missing_items, self.hir_ids_seen @@ -138,8 +137,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { format!( "HirIdValidator: The recorded owner of {} is {} instead of {}", self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(hir_id.owner).to_string_no_crate_verbose(), - self.hir_map.def_path(owner).to_string_no_crate_verbose() + self.hir_map.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(), + self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose() ) }); } diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index fd03f657111..46c4a702fde 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -16,7 +16,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) { DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union ) { for attr in tcx.get_attrs(id.def_id.to_def_id(), sym::rustc_layout) { - dump_layout_of(tcx, id.def_id, attr); + dump_layout_of(tcx, id.def_id.def_id, attr); } } } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 75244124e20..16055641aca 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -153,7 +153,7 @@ impl<'tcx> ReachableContext<'tcx> { hir::ImplItemKind::Fn(..) => { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let impl_did = self.tcx.hir().get_parent_item(hir_id); - method_might_be_inlined(self.tcx, impl_item, impl_did) + method_might_be_inlined(self.tcx, impl_item, impl_did.def_id) } hir::ImplItemKind::TyAlias(_) => false, }, @@ -305,8 +305,8 @@ fn check_item<'tcx>( worklist: &mut Vec<LocalDefId>, access_levels: &privacy::AccessLevels, ) { - if has_custom_linkage(tcx, id.def_id) { - worklist.push(id.def_id); + if has_custom_linkage(tcx, id.def_id.def_id) { + worklist.push(id.def_id.def_id); } if !matches!(tcx.def_kind(id.def_id), DefKind::Impl) { @@ -318,8 +318,8 @@ fn check_item<'tcx>( if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) = item.kind { - if !access_levels.is_reachable(item.def_id) { - worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id)); + if !access_levels.is_reachable(item.def_id.def_id) { + worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id.def_id)); let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else { unreachable!(); @@ -403,8 +403,8 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> { } for id in crate_items.impl_items() { - if has_custom_linkage(tcx, id.def_id) { - reachable_context.worklist.push(id.def_id); + if has_custom_linkage(tcx, id.def_id.def_id) { + reachable_context.worklist.push(id.def_id.def_id); } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3f23b027aef..e50beb27d2a 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } self.annotate( - i.def_id, + i.def_id.def_id, i.span, fn_sig, kind, @@ -404,7 +404,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ti.def_id, + ti.def_id.def_id, ti.span, fn_sig, AnnotationKind::Required, @@ -427,7 +427,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { }; self.annotate( - ii.def_id, + ii.def_id.def_id, ii.span, fn_sig, kind, @@ -485,7 +485,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { self.annotate( - i.def_id, + i.def_id.def_id, i.span, None, AnnotationKind::Required, @@ -573,25 +573,25 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { hir::ItemKind::Impl(hir::Impl { of_trait: None, .. }) | hir::ItemKind::ForeignMod { .. } ) { - self.check_missing_stability(i.def_id, i.span); + self.check_missing_stability(i.def_id.def_id, i.span); } // Ensure stable `const fn` have a const stability attribute. - self.check_missing_const_stability(i.def_id, i.span); + self.check_missing_const_stability(i.def_id.def_id, i.span); intravisit::walk_item(self, i) } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { - self.check_missing_stability(ti.def_id, ti.span); + self.check_missing_stability(ti.def_id.def_id, ti.span); intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); if self.tcx.impl_trait_ref(impl_def_id).is_none() { - self.check_missing_stability(ii.def_id, ii.span); - self.check_missing_const_stability(ii.def_id, ii.span); + self.check_missing_stability(ii.def_id.def_id, ii.span); + self.check_missing_const_stability(ii.def_id.def_id, ii.span); } intravisit::walk_impl_item(self, ii); } @@ -610,7 +610,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { - self.check_missing_stability(i.def_id, i.span); + self.check_missing_stability(i.def_id.def_id, i.span); intravisit::walk_foreign_item(self, i); } // Note that we don't need to `check_missing_stability` for default generic parameters, @@ -716,7 +716,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { return; } - let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else { + let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id.def_id) else { return; }; let def_id = cnum.as_def_id(); @@ -869,7 +869,7 @@ fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool { } // If this is a path that isn't a use, we don't need to do anything special - if !matches!(tcx.hir().item(hir::ItemId { def_id }).kind, ItemKind::Use(..)) { + if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) { return false; } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8f5ee51e6cf..72867447250 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -506,8 +506,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { let module = self.tcx.hir().get_module(module_def_id).0; for item_id in module.item_ids { let def_kind = self.tcx.def_kind(item_id.def_id); - let vis = self.tcx.local_visibility(item_id.def_id); - self.update_macro_reachable_def(item_id.def_id, def_kind, vis, defining_mod); + let vis = self.tcx.local_visibility(item_id.def_id.def_id); + self.update_macro_reachable_def(item_id.def_id.def_id, def_kind, vis, defining_mod); } if let Some(exports) = self.tcx.module_reexports(module_def_id) { for export in exports { @@ -627,11 +627,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let item_level = match item.kind { hir::ItemKind::Impl { .. } => { - let impl_level = - Option::<AccessLevel>::of_impl(item.def_id, self.tcx, &self.access_levels); - self.update(item.def_id, impl_level) + let impl_level = Option::<AccessLevel>::of_impl( + item.def_id.def_id, + self.tcx, + &self.access_levels, + ); + self.update(item.def_id.def_id, impl_level) } - _ => self.get(item.def_id), + _ => self.get(item.def_id.def_id), }; // Update levels of nested things. @@ -652,13 +655,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { if impl_.of_trait.is_some() || self.tcx.visibility(impl_item_ref.id.def_id).is_public() { - self.update(impl_item_ref.id.def_id, item_level); + self.update(impl_item_ref.id.def_id.def_id, item_level); } } } hir::ItemKind::Trait(.., trait_item_refs) => { for trait_item_ref in trait_item_refs { - self.update(trait_item_ref.id.def_id, item_level); + self.update(trait_item_ref.id.def_id.def_id, item_level); } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { @@ -674,12 +677,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } hir::ItemKind::Macro(ref macro_def, _) => { - self.update_reachability_from_macro(item.def_id, macro_def); + self.update_reachability_from_macro(item.def_id.def_id, macro_def); } hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { if self.tcx.visibility(foreign_item.id.def_id).is_public() { - self.update(foreign_item.id.def_id, item_level); + self.update(foreign_item.id.def_id.def_id, item_level); } } } @@ -717,7 +720,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // reachable if they are returned via `impl Trait`, even from private functions. let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait)); - self.reach(item.def_id, exist_level).generics().predicates().ty(); + self.reach(item.def_id.def_id, exist_level).generics().predicates().ty(); } } // Visit everything. @@ -726,16 +729,16 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::Fn(..) | hir::ItemKind::TyAlias(..) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates().ty(); + self.reach(item.def_id.def_id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., trait_item_refs) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { let tcx = self.tcx; - let mut reach = self.reach(trait_item_ref.id.def_id, item_level); + let mut reach = self.reach(trait_item_ref.id.def_id.def_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == AssocItemKind::Type @@ -750,18 +753,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); } } // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref(); + self.reach(item.def_id.def_id, item_level) + .generics() + .predicates() + .ty() + .trait_ref(); for impl_item_ref in impl_.items { - let impl_item_level = self.get(impl_item_ref.id.def_id); + let impl_item_level = self.get(impl_item_ref.id.def_id.def_id); if impl_item_level.is_some() { - self.reach(impl_item_ref.id.def_id, impl_item_level) + self.reach(impl_item_ref.id.def_id.def_id, impl_item_level) .generics() .predicates() .ty(); @@ -773,7 +780,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); } for variant in def.variants { let variant_level = self.get(self.tcx.hir().local_def_id(variant.id)); @@ -784,13 +791,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.reach(item.def_id, variant_level).ty(); + self.reach(item.def_id.def_id, variant_level).ty(); } if let Some(hir_id) = variant.data.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id, ctor_level).ty(); + self.reach(item.def_id.def_id, ctor_level).ty(); } } } @@ -798,9 +805,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { - let foreign_item_level = self.get(foreign_item.id.def_id); + let foreign_item_level = self.get(foreign_item.id.def_id.def_id); if foreign_item_level.is_some() { - self.reach(foreign_item.id.def_id, foreign_item_level) + self.reach(foreign_item.id.def_id.def_id, foreign_item_level) .generics() .predicates() .ty(); @@ -810,7 +817,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // Visit everything except for private fields. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.def_id, item_level).generics().predicates(); + self.reach(item.def_id.def_id, item_level).generics().predicates(); for field in struct_def.fields() { let def_id = self.tcx.hir().local_def_id(field.hir_id); let field_level = self.get(def_id); @@ -823,7 +830,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { let ctor_def_id = self.tcx.hir().local_def_id(hir_id); let ctor_level = self.get(ctor_def_id); if ctor_level.is_some() { - self.reach(item.def_id, ctor_level).ty(); + self.reach(item.def_id.def_id, ctor_level).ty(); } } } @@ -945,7 +952,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); match item.kind { hir::ItemKind::Enum(ref def, _) => { @@ -969,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - self.access_level_diagnostic(item.def_id); + self.access_level_diagnostic(item.def_id.def_id); } } @@ -1058,7 +1065,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); intravisit::walk_item(self, item); self.current_item = orig_current_item; } @@ -1361,7 +1368,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.def_id); + let orig_current_item = mem::replace(&mut self.current_item, item.def_id.def_id); let old_maybe_typeck_results = self.maybe_typeck_results.take(); intravisit::walk_item(self, item); self.maybe_typeck_results = old_maybe_typeck_results; @@ -1503,7 +1510,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::Trait(.., bounds, _) => { - if !self.trait_is_public(item.def_id) { + if !self.trait_is_public(item.def_id.def_id) { return; } @@ -1564,7 +1571,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => { - self.access_levels.is_reachable(impl_item_ref.id.def_id) + self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) } hir::ImplItemKind::TyAlias(_) => false, } @@ -1584,7 +1591,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) - if self.item_is_public(impl_item.def_id) => + if self.item_is_public(impl_item.def_id.def_id) => { intravisit::walk_impl_item(self, impl_item) } @@ -1625,7 +1632,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // methods will be visible as `Public::foo`. let mut found_pub_static = false; for impl_item_ref in impl_.items { - if self.access_levels.is_reachable(impl_item_ref.id.def_id) + if self.access_levels.is_reachable(impl_item_ref.id.def_id.def_id) || self.tcx.visibility(impl_item_ref.id.def_id).is_public() { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); @@ -1654,7 +1661,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { hir::ItemKind::TyAlias(..) => return, // Not at all public, so we don't care. - _ if !self.item_is_public(item.def_id) => { + _ if !self.item_is_public(item.def_id.def_id) => { return; } @@ -1685,7 +1692,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - if self.access_levels.is_reachable(item.def_id) { + if self.access_levels.is_reachable(item.def_id.def_id) { intravisit::walk_foreign_item(self, item) } } @@ -1922,43 +1929,44 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { pub fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; - let item_visibility = tcx.local_visibility(id.def_id); - let def_kind = tcx.def_kind(id.def_id); + let def_id = id.def_id.def_id; + let item_visibility = tcx.local_visibility(def_id); + let def_kind = tcx.def_kind(def_id); match def_kind { DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { - self.check(id.def_id, item_visibility).generics().predicates().ty(); + self.check(def_id, item_visibility).generics().predicates().ty(); } DefKind::OpaqueTy => { // `ty()` for opaque types is the underlying type, // it's not a part of interface, so we skip it. - self.check(id.def_id, item_visibility).generics().bounds(); + self.check(def_id, item_visibility).generics().bounds(); } DefKind::Trait => { let item = tcx.hir().item(id); if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind { - self.check(item.def_id, item_visibility).generics().predicates(); + self.check(item.def_id.def_id, item_visibility).generics().predicates(); for trait_item_ref in trait_item_refs { self.check_assoc_item( - trait_item_ref.id.def_id, + trait_item_ref.id.def_id.def_id, trait_item_ref.kind, item_visibility, ); if let AssocItemKind::Type = trait_item_ref.kind { - self.check(trait_item_ref.id.def_id, item_visibility).bounds(); + self.check(trait_item_ref.id.def_id.def_id, item_visibility).bounds(); } } } } DefKind::TraitAlias => { - self.check(id.def_id, item_visibility).generics().predicates(); + self.check(def_id, item_visibility).generics().predicates(); } DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref def, _) = item.kind { - self.check(item.def_id, item_visibility).generics().predicates(); + self.check(item.def_id.def_id, item_visibility).generics().predicates(); for variant in def.variants { for field in variant.data.fields() { @@ -1973,8 +1981,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { for foreign_item in items { - let vis = tcx.local_visibility(foreign_item.id.def_id); - self.check(foreign_item.id.def_id, vis).generics().predicates().ty(); + let vis = tcx.local_visibility(foreign_item.id.def_id.def_id); + self.check(foreign_item.id.def_id.def_id, vis).generics().predicates().ty(); } } } @@ -1984,7 +1992,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { - self.check(item.def_id, item_visibility).generics().predicates(); + self.check(item.def_id.def_id, item_visibility).generics().predicates(); for field in struct_def.fields() { let def_id = tcx.hir().local_def_id(field.hir_id); @@ -2000,20 +2008,21 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { DefKind::Impl => { let item = tcx.hir().item(id); if let hir::ItemKind::Impl(ref impl_) = item.kind { - let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default()); + let impl_vis = + ty::Visibility::of_impl(item.def_id.def_id, tcx, &Default::default()); // check that private components do not appear in the generics or predicates of inherent impls // this check is intentionally NOT performed for impls of traits, per #90586 if impl_.of_trait.is_none() { - self.check(item.def_id, impl_vis).generics().predicates(); + self.check(item.def_id.def_id, impl_vis).generics().predicates(); } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { - min(tcx.local_visibility(impl_item_ref.id.def_id), impl_vis, tcx) + min(tcx.local_visibility(impl_item_ref.id.def_id.def_id), impl_vis, tcx) } else { impl_vis }; self.check_assoc_item( - impl_item_ref.id.def_id, + impl_item_ref.id.def_id.def_id, impl_item_ref.kind, impl_item_vis, ); @@ -2061,7 +2070,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { // Visibilities of trait impl items are inherited from their traits // and are not filled in resolve. Node::ImplItem(impl_item) => { - match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id)) { + match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id).def_id) { Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(tr), .. }), .. diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index f1c2d03b9be..47762440e29 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -1,7 +1,7 @@ //! Defines the set of legal keys that can be used in queries. use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; -use rustc_hir::hir_id::HirId; +use rustc_hir::hir_id::OwnerId; use rustc_middle::infer::canonical::Canonical; use rustc_middle::mir; use rustc_middle::traits; @@ -105,6 +105,19 @@ impl Key for CrateNum { } } +impl Key for OwnerId { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.to_def_id().default_span(tcx) + } + fn key_as_def_id(&self) -> Option<DefId> { + Some(self.to_def_id()) + } +} + impl Key for LocalDefId { #[inline(always)] fn query_crate_is_local(&self) -> bool { @@ -544,19 +557,3 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) { DUMMY_SP } } - -impl Key for HirId { - #[inline(always)] - fn query_crate_is_local(&self) -> bool { - true - } - - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - tcx.hir().span(*self) - } - - #[inline(always)] - fn key_as_def_id(&self) -> Option<DefId> { - None - } -} diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index c87d26b3950..8e018d3e4a4 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -1,6 +1,8 @@ //! Support for serializing the dep-graph and reloading it. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref +#![feature(const_mut_refs)] #![feature(min_specialization)] #![feature(never_type)] #![feature(once_cell)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d819f4774d5..2b3850bc0df 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -3,7 +3,8 @@ //! manage the caches, and so forth. use crate::keys::Key; -use crate::on_disk_cache::CacheDecoder; +use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}; +use crate::profiling_support::QueryKeyStringCache; use crate::{on_disk_cache, Queries}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU64, Lock}; @@ -173,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> { pub(super) fn encode_query_results( self, - encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>, - query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, + encoder: &mut CacheEncoder<'_, 'tcx>, + query_result_index: &mut EncodedDepNodeIndex, ) { - macro_rules! expand_if_cached { - ([] $encode:expr) => {}; - ([(cache) $($rest:tt)*] $encode:expr) => { - $encode - }; - ([$other:tt $($modifiers:tt)*] $encode:expr) => { - expand_if_cached!([$($modifiers)*] $encode) - }; - } - - macro_rules! encode_queries { - ( - $($(#[$attr:meta])* - [$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => { - $( - expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>( - self, - encoder, - query_result_index - )); - )* + for query in &self.queries.query_structs { + if let Some(encode) = query.encode_query_results { + encode(self, encoder, query_result_index); } } - - rustc_query_append!(encode_queries!); } pub fn try_print_query_stack( @@ -213,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> { } } +#[derive(Clone, Copy)] +pub(crate) struct QueryStruct<'tcx> { + pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>, + pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache), + pub encode_query_results: + Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>, +} + macro_rules! handle_cycle_error { ([]) => {{ rustc_query_system::HandleCycleError::Error @@ -380,6 +369,24 @@ where Q::Key: DepNodeParams<TyCtxt<'tcx>>, Q::Value: Value<TyCtxt<'tcx>>, { + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we + // would always end up having to evaluate the first caller of the + // `codegen_unit` query that *is* reconstructible. This might very well be + // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just + // to re-trigger calling the `codegen_unit` query with the right key. At + // that point we would already have re-done all the work we are trying to + // avoid doing in the first place. + // The solution is simple: Just explicitly call the `codegen_unit` query for + // each CGU, right after partitioning. This way `try_mark_green` will always + // hit the cache instead of having to go through `force_from_dep_node`. + // This assertion makes sure, we actually keep applying the solution above. + debug_assert!( + dep_node.kind != DepKind::codegen_unit, + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + if let Some(key) = Q::Key::recover(tcx, &dep_node) { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); @@ -420,6 +427,18 @@ where } } +macro_rules! expand_if_cached { + ([], $tokens:expr) => {{ + None + }}; + ([(cache) $($rest:tt)*], $tokens:expr) => {{ + Some($tokens) + }}; + ([$other:tt $($modifiers:tt)*], $tokens:expr) => { + expand_if_cached!([$($modifiers)*], $tokens) + }; +} + // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_query_append`. macro_rules! define_queries { @@ -553,6 +572,59 @@ macro_rules! define_queries { })* } + mod query_structs { + use rustc_middle::ty::TyCtxt; + use $crate::plumbing::{QueryStruct, QueryCtxt}; + use $crate::profiling_support::QueryKeyStringCache; + use rustc_query_system::query::{QueryDescription, QueryMap}; + + pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> { + fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> { + None + } + fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {} + + QueryStruct { + try_collect_active_jobs: noop_try_collect_active_jobs, + alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings, + encode_query_results: None, + } + } + + pub(super) use dummy_query_struct as Null; + pub(super) use dummy_query_struct as Red; + pub(super) use dummy_query_struct as TraitSelect; + pub(super) use dummy_query_struct as CompileCodegenUnit; + pub(super) use dummy_query_struct as CompileMonoItem; + + $( + pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct { + try_collect_active_jobs: |tcx, qmap| { + let make_query = |tcx, key| { + let kind = rustc_middle::dep_graph::DepKind::$name; + let name = stringify!($name); + $crate::plumbing::create_query_frame(tcx, super::queries::$name::describe, key, kind, name) + }; + tcx.queries.$name.try_collect_active_jobs( + tcx, + make_query, + qmap, + ) + }, + alloc_self_profile_query_strings: |tcx, string_cache| { + $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( + tcx, + stringify!($name), + &tcx.query_caches.$name, + string_cache, + ) + }, + encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index| + $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index) + ), + }})* + } + pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] { arena.alloc_from_iter(make_dep_kind_array!(query_callbacks)) } @@ -567,9 +639,11 @@ impl<'tcx> Queries<'tcx> { extern_providers: ExternProviders, on_disk_cache: Option<OnDiskCache<'tcx>>, ) -> Self { + use crate::query_structs; Queries { local_providers: Box::new(local_providers), extern_providers: Box::new(extern_providers), + query_structs: make_dep_kind_array!(query_structs).to_vec(), on_disk_cache, jobs: AtomicU64::new(1), ..Queries::default() @@ -584,6 +658,7 @@ macro_rules! define_queries_struct { pub struct Queries<'tcx> { local_providers: Box<Providers>, extern_providers: Box<ExternProviders>, + query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>, pub on_disk_cache: Option<OnDiskCache<'tcx>>, @@ -600,18 +675,9 @@ macro_rules! define_queries_struct { let tcx = QueryCtxt { tcx, queries: self }; let mut jobs = QueryMap::default(); - $( - let make_query = |tcx, key| { - let kind = dep_graph::DepKind::$name; - let name = stringify!($name); - $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name) - }; - self.$name.try_collect_active_jobs( - tcx, - make_query, - &mut jobs, - )?; - )* + for query in &self.query_structs { + (query.try_collect_active_jobs)(tcx, &mut jobs); + } Some(jobs) } diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 98ec3bc0977..2cc311d48c8 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -1,3 +1,4 @@ +use crate::QueryCtxt; use measureme::{StringComponent, StringId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfiler; @@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache; use std::fmt::Debug; use std::io::Write; -struct QueryKeyStringCache { +pub(crate) struct QueryKeyStringCache { def_id_cache: FxHashMap<DefId, StringId>, } @@ -226,7 +227,7 @@ where /// Allocate the self-profiling query strings for a single query cache. This /// method is called from `alloc_self_profile_query_strings` which knows all /// the queries via macro magic. -fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( +pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( tcx: TyCtxt<'tcx>, query_name: &'static str, query_cache: &C, @@ -298,27 +299,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( /// If we are recording only summary data, the ids will point to /// just the query names. If we are recording query keys too, we /// allocate the corresponding strings here. -pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { +pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) { if !tcx.prof.enabled() { return; } let mut string_cache = QueryKeyStringCache::new(); + let queries = QueryCtxt::from_tcx(tcx); - macro_rules! alloc_once { - ( - $($(#[$attr:meta])* - [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - $( - alloc_self_profile_query_strings_for_query_cache( - tcx, - stringify!($name), - &tcx.query_caches.$name, - &mut string_cache, - ); - )+ - } + for query in &queries.queries.query_structs { + (query.alloc_self_profile_query_strings)(tcx, &mut string_cache); } - - rustc_query_append! { alloc_once! } } diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 162c274d8a2..5c6ce0556eb 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -47,6 +47,7 @@ use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir::definitions::DefPathHash; use std::fmt; use std::hash::Hash; @@ -88,6 +89,17 @@ impl<K: DepKind> DepNode<K> { dep_node } + + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + pub fn from_def_path_hash<Ctxt>(tcx: Ctxt, def_path_hash: DefPathHash, kind: K) -> Self + where + Ctxt: super::DepContext<DepKind = K>, + { + debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash); + DepNode { kind, hash: def_path_hash.0.into() } + } } impl<K: DepKind> fmt::Debug for DepNode<K> { @@ -149,6 +161,67 @@ where } } +/// This struct stores metadata about each DepKind. +/// +/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value +/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual +/// jump table instead of large matches. +pub struct DepKindStruct<CTX: DepContext> { + /// Anonymous queries cannot be replayed from one compiler invocation to the next. + /// When their result is needed, it is recomputed. They are useful for fine-grained + /// dependency tracking, and caching within one compiler invocation. + pub is_anon: bool, + + /// Eval-always queries do not track their dependencies, and are always recomputed, even if + /// their inputs have not changed since the last compiler invocation. The result is still + /// cached within one compiler invocation. + pub is_eval_always: bool, + + /// Whether the query key can be recovered from the hashed fingerprint. + /// See [DepNodeParams] trait for the behaviour of each key type. + pub fingerprint_style: FingerprintStyle, + + /// The red/green evaluation system will try to mark a specific DepNode in the + /// dependency graph as green by recursively trying to mark the dependencies of + /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` + /// where we don't know if it is red or green and we therefore actually have + /// to recompute its value in order to find out. Since the only piece of + /// information that we have at that point is the `DepNode` we are trying to + /// re-evaluate, we need some way to re-run a query from just that. This is what + /// `force_from_dep_node()` implements. + /// + /// In the general case, a `DepNode` consists of a `DepKind` and an opaque + /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint + /// is usually constructed by computing a stable hash of the query-key that the + /// `DepNode` corresponds to. Consequently, it is not in general possible to go + /// back from hash to query-key (since hash functions are not reversible). For + /// this reason `force_from_dep_node()` is expected to fail from time to time + /// because we just cannot find out, from the `DepNode` alone, what the + /// corresponding query-key is and therefore cannot re-run the query. + /// + /// The system deals with this case letting `try_mark_green` fail which forces + /// the root query to be re-evaluated. + /// + /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. + /// Fortunately, we can use some contextual information that will allow us to + /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we + /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a + /// valid `DefPathHash`. Since we also always build a huge table that maps every + /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have + /// everything we need to re-run the query. + /// + /// Take the `mir_promoted` query as an example. Like many other queries, it + /// just has a single parameter: the `DefId` of the item it will compute the + /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` + /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` + /// is actually a `DefPathHash`, and can therefore just look up the corresponding + /// `DefId` in `tcx.def_path_hash_to_def_id`. + pub force_from_dep_node: Option<fn(tcx: CTX, dep_node: DepNode<CTX::DepKind>) -> bool>, + + /// Invoke a query to put the on-disk cached value in memory. + pub try_load_from_on_disk_cache: Option<fn(CTX, DepNode<CTX::DepKind>)>, +} + /// A "work product" corresponds to a `.o` (or other) file that we /// save in between runs. These IDs do not have a `DefId` but rather /// some independent path or string that persists between runs without diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 6f3bd776216..5003a14b910 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -4,7 +4,7 @@ mod graph; mod query; mod serialized; -pub use dep_node::{DepNode, DepNodeParams, WorkProductId}; +pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId}; pub use graph::{ hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct, }; @@ -34,16 +34,43 @@ pub trait DepContext: Copy { /// Access the compiler session. fn sess(&self) -> &Session; - /// Return whether this kind always require evaluation. - fn is_eval_always(&self, kind: Self::DepKind) -> bool; + fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct<Self>; - fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle; + #[inline(always)] + fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle { + let data = self.dep_kind_info(kind); + if data.is_anon { + return FingerprintStyle::Opaque; + } + data.fingerprint_style + } + + #[inline(always)] + /// Return whether this kind always require evaluation. + fn is_eval_always(&self, kind: Self::DepKind) -> bool { + self.dep_kind_info(kind).is_eval_always + } /// Try to force a dep node to execute and see if it's green. - fn try_force_from_dep_node(&self, dep_node: DepNode<Self::DepKind>) -> bool; + fn try_force_from_dep_node(self, dep_node: DepNode<Self::DepKind>) -> bool { + debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); + + let cb = self.dep_kind_info(dep_node.kind); + if let Some(f) = cb.force_from_dep_node { + f(self, dep_node); + true + } else { + false + } + } /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(&self, dep_node: DepNode<Self::DepKind>); + fn try_load_from_on_disk_cache(self, dep_node: DepNode<Self::DepKind>) { + let cb = self.dep_kind_info(dep_node.kind); + if let Some(f) = cb.try_load_from_on_disk_cache { + f(self, dep_node) + } + } } pub trait HasDepContext: Copy { @@ -67,8 +94,6 @@ impl<T: DepContext> HasDepContext for T { pub enum FingerprintStyle { /// The fingerprint is actually a DefPathHash. DefPathHash, - /// The fingerprint is actually a HirId. - HirId, /// Query key was `()` or equivalent, so fingerprint is just zero. Unit, /// Some opaque hash. @@ -79,9 +104,7 @@ impl FingerprintStyle { #[inline] pub fn reconstructible(self) -> bool { match self { - FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => { - true - } + FingerprintStyle::DefPathHash | FingerprintStyle::Unit => true, FingerprintStyle::Opaque => false, } } diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index a09b8ca30e1..8140c243453 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -41,7 +41,10 @@ pub struct StableHashingContext<'a> { pub(super) enum BodyResolver<'tcx> { Forbidden, Ignore, - Traverse { owner: LocalDefId, bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>> }, + Traverse { + owner: hir::OwnerId, + bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>, + }, } impl<'a> StableHashingContext<'a> { @@ -103,7 +106,7 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn with_hir_bodies( &mut self, - owner: LocalDefId, + owner: hir::OwnerId, bodies: &SortedMap<hir::ItemLocalId, &hir::Body<'_>>, f: impl FnOnce(&mut StableHashingContext<'_>), ) { diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs index 9b1111c02c7..d806441716f 100644 --- a/compiler/rustc_resolve/src/access_levels.rs +++ b/compiler/rustc_resolve/src/access_levels.rs @@ -1,4 +1,3 @@ -use crate::imports::ImportKind; use crate::NameBinding; use crate::NameBindingKind; use crate::Resolver; @@ -54,15 +53,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { // sets the rest of the `use` chain to `AccessLevel::Exported` until // we hit the actual exported item. let set_import_binding_access_level = - |this: &mut Self, mut binding: &NameBinding<'a>, mut access_level| { + |this: &mut Self, mut binding: &NameBinding<'a>, mut access_level, ns| { while let NameBindingKind::Import { binding: nested_binding, import, .. } = binding.kind { - this.set_access_level(import.id, access_level); - if let ImportKind::Single { additional_ids, .. } = import.kind { - this.set_access_level(additional_ids.0, access_level); - this.set_access_level(additional_ids.1, access_level); - } + this.set_access_level(this.r.import_id_for_ns(import, ns), access_level); access_level = Some(AccessLevel::Exported); binding = nested_binding; @@ -72,11 +67,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> { let module = self.r.get_module(module_id.to_def_id()).unwrap(); let resolutions = self.r.resolutions(module); - for (.., name_resolution) in resolutions.borrow().iter() { + for (key, name_resolution) in resolutions.borrow().iter() { if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() { let access_level = match binding.is_import() { true => { - set_import_binding_access_level(self, binding, module_level); + set_import_binding_access_level(self, binding, module_level, key.ns); Some(AccessLevel::Exported) }, false => module_level, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 3f88f44ff21..7e83f2a7221 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -1,6 +1,5 @@ use crate::{ImplTraitContext, Resolver}; use rustc_ast::visit::{self, FnKind}; -use rustc_ast::walk_list; use rustc_ast::*; use rustc_expand::expand::AstFragment; use rustc_hir::def_id::LocalDefId; @@ -148,8 +147,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { self.with_parent(return_impl_trait_id, |this| { this.visit_fn_ret_ty(&sig.decl.output) }); - let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); - self.with_parent(closure_def, |this| walk_list!(this, visit_block, body)); + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); + self.with_parent(closure_def, |this| this.visit_block(body)); + } return; } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c133c272bac..5bdb4274781 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -2,7 +2,7 @@ use crate::diagnostics::Suggestion; use crate::Determinacy::{self, *}; -use crate::Namespace::{MacroNS, TypeNS}; +use crate::Namespace::{self, *}; use crate::{module_to_string, names_to_string}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; @@ -371,6 +371,31 @@ impl<'a> Resolver<'a> { self.used_imports.insert(import.id); } } + + /// Take primary and additional node IDs from an import and select one that corresponds to the + /// given namespace. The logic must match the corresponding logic from `fn lower_use_tree` that + /// assigns resolutons to IDs. + pub(crate) fn import_id_for_ns(&self, import: &Import<'_>, ns: Namespace) -> NodeId { + if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind { + if let Some(resolutions) = self.import_res_map.get(&import.id) { + assert!(resolutions[ns].is_some(), "incorrectly finalized import"); + return match ns { + TypeNS => import.id, + ValueNS => match resolutions.type_ns { + Some(_) => id1, + None => import.id, + }, + MacroNS => match (resolutions.type_ns, resolutions.value_ns) { + (Some(_), Some(_)) => id2, + (Some(_), None) | (None, Some(_)) => id1, + (None, None) => import.id, + }, + }; + } + } + + import.id + } } /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0aea90bb5aa..558db003867 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -805,7 +805,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { sig.decl.has_self(), sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), &sig.decl.output, - ) + ); + + this.record_lifetime_params_for_async( + fn_id, + sig.header.asyncness.opt_return_id(), + ); }, ); return; @@ -847,41 +852,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { }, ); - // Construct the list of in-scope lifetime parameters for async lowering. - // We include all lifetime parameters, either named or "Fresh". - // The order of those parameters does not matter, as long as it is - // deterministic. - if let Some((async_node_id, _)) = async_node_id { - let mut extra_lifetime_params = this - .r - .extra_lifetime_params_map - .get(&fn_id) - .cloned() - .unwrap_or_default(); - for rib in this.lifetime_ribs.iter().rev() { - extra_lifetime_params.extend( - rib.bindings - .iter() - .map(|(&ident, &(node_id, res))| (ident, node_id, res)), - ); - match rib.kind { - LifetimeRibKind::Item => break, - LifetimeRibKind::AnonymousCreateParameter { - binder, .. - } => { - if let Some(earlier_fresh) = - this.r.extra_lifetime_params_map.get(&binder) - { - extra_lifetime_params.extend(earlier_fresh); - } - } - _ => {} - } - } - this.r - .extra_lifetime_params_map - .insert(async_node_id, extra_lifetime_params); - } + this.record_lifetime_params_for_async(fn_id, async_node_id); if let Some(body) = body { // Ignore errors in function bodies if this is rustdoc @@ -3926,6 +3897,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { Some((ident.name, ns)), ) } + + /// Construct the list of in-scope lifetime parameters for async lowering. + /// We include all lifetime parameters, either named or "Fresh". + /// The order of those parameters does not matter, as long as it is + /// deterministic. + fn record_lifetime_params_for_async( + &mut self, + fn_id: NodeId, + async_node_id: Option<(NodeId, Span)>, + ) { + if let Some((async_node_id, _)) = async_node_id { + let mut extra_lifetime_params = + self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); + for rib in self.lifetime_ribs.iter().rev() { + extra_lifetime_params.extend( + rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)), + ); + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { + if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) { + extra_lifetime_params.extend(earlier_fresh); + } + } + _ => {} + } + } + self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); + } + } } struct LifetimeCountVisitor<'a, 'b> { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4d970461712..9fb1af20ac9 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -339,24 +339,25 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime /// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner /// other than the trait itself (like the trait methods or associated types), then we just use the regular /// `resolve_lifetimes`. -fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes { - let item_id = item_for(tcx, def_id); - if item_id == def_id { - let item = tcx.hir().item(hir::ItemId { def_id: item_id }); +fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes { + let item_id = item_for(tcx, def_id.def_id); + let local_def_id = item_id.def_id.def_id; + if item_id.def_id == def_id { + let item = tcx.hir().item(item_id); match item.kind { - hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id), - _ => tcx.resolve_lifetimes(item_id), + hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id), + _ => tcx.resolve_lifetimes(local_def_id), } } else { - tcx.resolve_lifetimes(item_id) + tcx.resolve_lifetimes(local_def_id) } } /// Finds the `Item` that contains the given `LocalDefId` -fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { +fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> hir::ItemId { match tcx.hir().find_by_def_id(local_def_id) { Some(Node::Item(item)) => { - return item.def_id; + return item.item_id(); } _ => {} } @@ -366,7 +367,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { loop { let node = parent_iter.next().map(|n| n.1); match node { - Some(hir::Node::Item(item)) => break item.def_id, + Some(hir::Node::Item(item)) => break item.item_id(), Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."), _ => {} } @@ -566,13 +567,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // their owner, we can keep going until we find the Item that owns that. We then // conservatively add all resolved lifetimes. Otherwise we run into problems in // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`. - for (_hir_id, node) in - self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id)) - { + for (_hir_id, node) in self.tcx.hir().parent_iter(item.def_id.into()) { match node { hir::Node::Item(parent_item) => { - let resolved_lifetimes: &ResolveLifetimes = - self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id)); + let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes( + item_for(self.tcx, parent_item.def_id.def_id).def_id.def_id, + ); // We need to add *all* deps, since opaque tys may want them from *us* for (&owner, defs) in resolved_lifetimes.defs.iter() { defs.iter().for_each(|(&local_id, region)| { @@ -1315,7 +1315,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // regular fns. if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name - && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner) + && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { rustc_session::parse::feature_err( diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 8bd42d8d216..adbc119387d 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -345,14 +345,14 @@ impl<'tcx> DumpVisitor<'tcx> { body: hir::BodyId, ) { let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { let body = map.body(body); if let Some(fn_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(fn_data, DefData, item.span); v.process_formals(body.params, &fn_data.qualname); v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id()); - v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), fn_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id.def_id), fn_data); } for arg in decl.inputs { @@ -373,10 +373,10 @@ impl<'tcx> DumpVisitor<'tcx> { typ: &'tcx hir::Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) { - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { if let Some(var_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(var_data, DefData, item.span); - v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id), var_data); + v.dumper.dump_def(&access_from!(v.save_ctxt, item.def_id.def_id), var_data); } v.visit_ty(&typ); v.visit_expr(expr); @@ -473,7 +473,7 @@ impl<'tcx> DumpVisitor<'tcx> { let span = self.span_from_span(item.ident.span); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id), + &access_from!(self.save_ctxt, item.def_id.def_id), Def { kind, id: id_from_def_id(item.def_id.to_def_id()), @@ -491,7 +491,7 @@ impl<'tcx> DumpVisitor<'tcx> { ); } - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { for field in def.fields() { v.process_struct_field_def(field, item.hir_id()); v.visit_ty(&field.ty); @@ -513,7 +513,7 @@ impl<'tcx> DumpVisitor<'tcx> { }; down_cast_data!(enum_data, DefData, item.span); - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); for variant in enum_definition.variants { let name = variant.ident.name.to_string(); @@ -612,7 +612,7 @@ impl<'tcx> DumpVisitor<'tcx> { } let map = self.tcx.hir(); - self.nest_typeck_results(item.def_id, |v| { + self.nest_typeck_results(item.def_id.def_id, |v| { v.visit_ty(&impl_.self_ty); if let Some(trait_ref) = &impl_.of_trait { v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path)); @@ -648,7 +648,7 @@ impl<'tcx> DumpVisitor<'tcx> { methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect(); let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id), + &access_from!(self.save_ctxt, item.def_id.def_id), Def { kind: DefKind::Trait, id, @@ -710,7 +710,7 @@ impl<'tcx> DumpVisitor<'tcx> { fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) { if let Some(mod_data) = self.save_ctxt.get_item_data(item) { down_cast_data!(mod_data, DefData, item.span); - self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id), mod_data); + self.dumper.dump_def(&access_from!(self.save_ctxt, item.def_id.def_id), mod_data); } } @@ -980,7 +980,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = body.map(|b| self.tcx.hir().body(b).value); let attrs = self.tcx.hir().attrs(trait_item.hir_id()); self.process_assoc_const( - trait_item.def_id, + trait_item.def_id.def_id, trait_item.ident, &ty, body, @@ -994,7 +994,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, body, - trait_item.def_id, + trait_item.def_id.def_id, trait_item.ident, &trait_item.generics, trait_item.span, @@ -1050,7 +1050,7 @@ impl<'tcx> DumpVisitor<'tcx> { let body = self.tcx.hir().body(body); let attrs = self.tcx.hir().attrs(impl_item.hir_id()); self.process_assoc_const( - impl_item.def_id, + impl_item.def_id.def_id, impl_item.ident, &ty, Some(&body.value), @@ -1062,7 +1062,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.process_method( sig, Some(body), - impl_item.def_id, + impl_item.def_id.def_id, impl_item.ident, &impl_item.generics, impl_item.span, @@ -1136,10 +1136,10 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { hir::ItemKind::Use(path, hir::UseKind::Single) => { let sub_span = path.segments.last().unwrap().ident.span; if !self.span.filter_generated(sub_span) { - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); self.dumper.import( &access, Import { @@ -1157,16 +1157,16 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::ItemKind::Use(path, hir::UseKind::Glob) => { // Make a comma-separated list of names of imported modules. - let names = self.tcx.names_imported_by_glob_use(item.def_id); + let names = self.tcx.names_imported_by_glob_use(item.def_id.def_id); let names: Vec<_> = names.iter().map(|n| n.to_string()).collect(); // Otherwise it's a span with wrong macro expansion info, which // we don't want to track anyway, since it's probably macro-internal `use` if let Some(sub_span) = self.span.sub_span_of_star(item.span) { if !self.span.filter_generated(item.span) { - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); let span = self.span_from_span(sub_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); self.dumper.import( &access, Import { @@ -1187,7 +1187,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let name_span = item.ident.span; if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let parent = self.save_ctxt.tcx.local_parent(item.def_id); + let parent = self.save_ctxt.tcx.local_parent(item.def_id.def_id); self.dumper.import( &Access { public: false, reachable: false }, Import { @@ -1235,7 +1235,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { let attrs = self.tcx.hir().attrs(item.hir_id()); self.dumper.dump_def( - &access_from!(self.save_ctxt, item.def_id), + &access_from!(self.save_ctxt, item.def_id.def_id), Def { kind: DefKind::Type, id, @@ -1323,7 +1323,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } hir::TyKind::OpaqueDef(item_id, _, _) => { let item = self.tcx.hir().item(item_id); - self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item)); + self.nest_typeck_results(item_id.def_id.def_id, |v| v.visit_item(item)); } _ => intravisit::walk_ty(self, t), } @@ -1430,7 +1430,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { - let access = access_from!(self.save_ctxt, item.def_id); + let access = access_from!(self.save_ctxt, item.def_id.def_id); match item.kind { hir::ForeignItemKind::Fn(decl, _, ref generics) => { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index ce03c2a8ad0..1a3511a1dc8 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -622,7 +622,7 @@ impl<'tcx> SaveContext<'tcx> { hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { // #75962: `self.typeck_results` may be different from the `hir_id`'s result. if self.tcx.has_typeck_results(hir_id.owner.to_def_id()) { - self.tcx.typeck(hir_id.owner).qpath_res(qpath, hir_id) + self.tcx.typeck(hir_id.owner.def_id).qpath_res(qpath, hir_id) } else { Res::Err } @@ -1041,7 +1041,7 @@ fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_>) -> rls_data::Id { // crate (very unlikely to actually happen). rls_data::Id { krate: LOCAL_CRATE.as_u32(), - index: id.owner.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(), + index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(), } }) } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d7f1bc0be84..486c514a4f5 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1409,8 +1409,6 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), - new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED], - "use new LLVM pass manager (default: no)"), nll_facts: bool = (false, parse_bool, [UNTRACKED], "dump facts from NLL analysis into side files (default: no)"), nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED], diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 9d89c9c52b2..c8c6fe2bf85 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -26,19 +26,19 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); for id in crate_items.items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } for id in crate_items.trait_items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } for id in crate_items.impl_items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } for id in crate_items.foreign_items() { - symbol_names.process_attrs(id.def_id); + symbol_names.process_attrs(id.def_id.def_id); } }) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index d62b399c1b5..b0cabc6275f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1898,7 +1898,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // FIXME(compiler-errors): This could be generalized, both to // be more granular, and probably look past other `#[fundamental]` // types, too. - self.tcx.visibility(def.did()).is_accessible_from(body_id.owner, self.tcx) + self.tcx + .visibility(def.did()) + .is_accessible_from(body_id.owner.def_id, self.tcx) } else { true } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d90b77fc556..fff26547be0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -659,7 +659,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => {} } - hir_id = self.tcx.hir().local_def_id_to_hir_id(self.tcx.hir().get_parent_item(hir_id)); + hir_id = self.tcx.hir().get_parent_item(hir_id).into(); } } @@ -2712,7 +2712,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let parent_id = hir.get_parent_item(arg_hir_id); let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results { Some(t) if t.hir_owner == parent_id => t, - _ => self.tcx.typeck(parent_id), + _ => self.tcx.typeck(parent_id.def_id), }; let expr = expr.peel_blocks(); let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()); diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index a4b54018228..3008dfcadde 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -46,7 +46,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> { /// Note that this may cause outlives obligations to be injected /// into the inference context with this body-id. /// - `ty`, the type that we are supposed to assume is WF. - #[instrument(level = "debug", skip(self, param_env, body_id))] + #[instrument(level = "debug", skip(self, param_env, body_id), ret)] fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, @@ -71,6 +71,7 @@ impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> { let TypeOpOutput { output, constraints, .. } = result; if let Some(constraints) = constraints { + debug!(?constraints); // Instantiation may have produced new inference variables and constraints on those // variables. Process these constraints. let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index e08f03a270c..27fbfb6dd21 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1224,6 +1224,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Foreign(_) => {} + // `ManuallyDrop` is trivially drop + ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {} + // These types are built-in, so we can fast-track by registering // nested predicates for their constituent type(s) ty::Array(ty, _) | ty::Slice(ty) => { diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index e3e78f70b15..32aca4a8a3f 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -49,7 +49,8 @@ fn compute_implied_outlives_bounds<'tcx>( let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default(); let mut wf_args = vec![ty.into()]; - let mut implied_bounds = vec![]; + let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> = + vec![]; let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx); @@ -65,30 +66,17 @@ fn compute_implied_outlives_bounds<'tcx>( // than the ultimate set. (Note: normally there won't be // unresolved inference variables here anyway, but there might be // during typeck under some circumstances.) + // + // FIXME(@lcnr): It's not really "always fine", having fewer implied + // bounds can be backward incompatible, e.g. #101951 was caused by + // us not dealing with inference vars in `TypeOutlives` predicates. let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP) .unwrap_or_default(); - // N.B., all of these predicates *ought* to be easily proven - // true. In fact, their correctness is (mostly) implied by - // other parts of the program. However, in #42552, we had - // an annoying scenario where: - // - // - Some `T::Foo` gets normalized, resulting in a - // variable `_1` and a `T: Trait<Foo=_1>` constraint - // (not sure why it couldn't immediately get - // solved). This result of `_1` got cached. - // - These obligations were dropped on the floor here, - // rather than being registered. - // - Then later we would get a request to normalize - // `T::Foo` which would result in `_1` being used from - // the cache, but hence without the `T: Trait<Foo=_1>` - // constraint. As a result, `_1` never gets resolved, - // and we get an ICE (in dropck). - // - // Therefore, we register any predicates involving - // inference variables. We restrict ourselves to those - // involving inference variables both for efficiency and - // to avoids duplicate errors that otherwise show up. + // While these predicates should all be implied by other parts of + // the program, they are still relevant as they may constrain + // inference variables, which is necessary to add the correct + // implied bounds in some cases, mostly when dealing with projections. fulfill_cx.register_predicate_obligations( infcx, obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(), @@ -96,10 +84,10 @@ fn compute_implied_outlives_bounds<'tcx>( // From the full set of obligations, just filter down to the // region relationships. - implied_bounds.extend(obligations.into_iter().flat_map(|obligation| { + outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| { assert!(!obligation.has_escaping_bound_vars()); match obligation.predicate.kind().no_bound_vars() { - None => vec![], + None => None, Some(pred) => match pred { ty::PredicateKind::Trait(..) | ty::PredicateKind::Subtype(..) @@ -109,21 +97,18 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![], + | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::WellFormed(arg) => { wf_args.push(arg); - vec![] + None } ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => { - vec![OutlivesBound::RegionSubRegion(r_b, r_a)] + Some(ty::OutlivesPredicate(r_a.into(), r_b)) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => { - let ty_a = infcx.resolve_vars_if_possible(ty_a); - let mut components = smallvec![]; - push_outlives_components(tcx, ty_a, &mut components); - implied_bounds_from_components(r_b, components) + Some(ty::OutlivesPredicate(ty_a.into(), r_b)) } }, } @@ -133,9 +118,27 @@ fn compute_implied_outlives_bounds<'tcx>( // Ensure that those obligations that we had to solve // get solved *here*. match fulfill_cx.select_all_or_error(infcx).as_slice() { - [] => Ok(implied_bounds), - _ => Err(NoSolution), + [] => (), + _ => return Err(NoSolution), } + + // We lazily compute the outlives components as + // `select_all_or_error` constrains inference variables. + let implied_bounds = outlives_bounds + .into_iter() + .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() { + ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)], + ty::GenericArgKind::Type(ty_a) => { + let ty_a = infcx.resolve_vars_if_possible(ty_a); + let mut components = smallvec![]; + push_outlives_components(tcx, ty_a, &mut components); + implied_bounds_from_components(r_b, components) + } + ty::GenericArgKind::Const(_) => unreachable!(), + }) + .collect(); + + Ok(implied_bounds) } /// When we have an implied bound that `T: 'a`, we can further break @@ -153,6 +156,9 @@ fn implied_bounds_from_components<'tcx>( Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)), Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)), Component::Projection(p) => Some(OutlivesBound::RegionSubProjection(sub_region, p)), + Component::Opaque(def_id, substs) => { + Some(OutlivesBound::RegionSubOpaque(sub_region, def_id, substs)) + } Component::EscapingProjection(_) => // If the projection has escaping regions, don't // try to infer any implied bounds even for its diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 515a73ead77..3e2553c425e 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -42,7 +42,7 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_def_id = tcx.hir().get_parent_item(id); - let parent_item = tcx.hir().expect_item(parent_def_id); + let parent_item = tcx.hir().expect_item(parent_def_id.def_id); match parent_item.kind { hir::ItemKind::Impl(ref impl_) => { if let Some(impl_item_ref) = diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 5432fdbb5e8..b3cbb606c72 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -365,7 +365,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // here and so associated type bindings will be handled regardless of whether there are any // non-`Self` generic parameters. if generics.params.is_empty() { - return (tcx.intern_substs(&[]), arg_count); + return (tcx.intern_substs(parent_substs), arg_count); } struct SubstsForAstPathCtxt<'a, 'tcx> { @@ -586,7 +586,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub(crate) fn create_substs_for_associated_item( &self, - tcx: TyCtxt<'tcx>, span: Span, item_def_id: DefId, item_segment: &hir::PathSegment<'_>, @@ -596,22 +595,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}", span, item_def_id, item_segment ); - if tcx.generics_of(item_def_id).params.is_empty() { - self.prohibit_generics(slice::from_ref(item_segment).iter(), |_| {}); - - parent_substs - } else { - self.create_substs_for_ast_path( - span, - item_def_id, - parent_substs, - item_segment, - item_segment.args(), - item_segment.infer_args, - None, - ) - .0 - } + self.create_substs_for_ast_path( + span, + item_def_id, + parent_substs, + item_segment, + item_segment.args(), + item_segment.infer_args, + None, + ) + .0 } /// Instantiates the path for the given trait reference, assuming that it's @@ -1121,7 +1114,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( - tcx, path_span, assoc_item.def_id, &item_segment, @@ -2100,7 +2092,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false); let item_substs = self.create_substs_for_associated_item( - tcx, span, item_def_id, item_segment, @@ -3003,7 +2994,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Make sure that we are in the condition to suggest the blanket implementation. fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) { let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 27329f8eab4..201927091a6 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(ret) = self .tcx .hir() - .find_by_def_id(self.body_id.owner) + .find_by_def_id(self.body_id.owner.def_id) .and_then(|owner| owner.fn_decl()) .map(|decl| decl.output.span()) else { return; }; @@ -495,7 +495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .typeck_results .borrow() .liberated_fn_sigs() - .get(hir::HirId::make_owner(self.body_id.owner))?; + .get(hir::HirId::make_owner(self.body_id.owner.def_id))?; let substs = sig.output().walk().find_map(|arg| { if let ty::GenericArgKind::Type(ty) = arg.unpack() diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index d6fa74c8730..d82ee8f48c5 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -782,19 +782,19 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { let _indenter = indenter(); match tcx.def_kind(id.def_id) { DefKind::Static(..) => { - tcx.ensure().typeck(id.def_id); - maybe_check_static_with_link_section(tcx, id.def_id); - check_static_inhabited(tcx, id.def_id); + tcx.ensure().typeck(id.def_id.def_id); + maybe_check_static_with_link_section(tcx, id.def_id.def_id); + check_static_inhabited(tcx, id.def_id.def_id); } DefKind::Const => { - tcx.ensure().typeck(id.def_id); + tcx.ensure().typeck(id.def_id.def_id); } DefKind::Enum => { let item = tcx.hir().item(id); let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else { return; }; - check_enum(tcx, &enum_definition.variants, item.def_id); + check_enum(tcx, &enum_definition.variants, item.def_id.def_id); } DefKind::Fn => {} // entirely within check_item_body DefKind::Impl => { @@ -807,7 +807,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { check_impl_items_against_trait( tcx, it.span, - it.def_id, + it.def_id.def_id, impl_trait_ref, &impl_.items, ); @@ -845,10 +845,10 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } DefKind::Struct => { - check_struct(tcx, id.def_id); + check_struct(tcx, id.def_id.def_id); } DefKind::Union => { - check_union(tcx, id.def_id); + check_union(tcx, id.def_id.def_id); } DefKind::OpaqueTy => { let item = tcx.hir().item(id); @@ -861,7 +861,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { // See https://github.com/rust-lang/rust/issues/75100 if !tcx.sess.opts.actually_rustdoc { let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id()); - check_opaque(tcx, item.def_id, substs, &origin); + check_opaque(tcx, item.def_id.def_id, substs, &origin); } } DefKind::TyAlias => { @@ -888,7 +888,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } } else { for item in items { - let def_id = item.id.def_id; + let def_id = item.id.def_id.def_id; let generics = tcx.generics_of(def_id); let own_counts = generics.own_counts(); if generics.params.len() - own_counts.lifetimes != 0 { diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index def592c46c2..d738e563256 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1683,7 +1683,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, can_suggest, - fcx.tcx.hir().local_def_id_to_hir_id(fcx.tcx.hir().get_parent_item(id)), + fcx.tcx.hir().get_parent_item(id).into(), ); } if !pointing_at_return_type { @@ -1692,7 +1692,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } let parent_id = fcx.tcx.hir().get_parent_item(id); - let parent_item = fcx.tcx.hir().get_by_def_id(parent_id); + let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id); if let (Some(expr), Some(_), Some((fn_decl, _, _))) = (expression, blk_id, fcx.get_node_fn_decl(parent_item)) @@ -1704,7 +1704,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expected, found, id, - fcx.tcx.hir().local_def_id_to_hir_id(parent_id), + parent_id.into(), ); } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 7c0b815e42a..ae98a8f6209 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -140,6 +140,7 @@ pub(crate) fn compare_impl_method<'tcx>( /// /// Finally we register each of these predicates as an obligation and check that /// they hold. +#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))] fn compare_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &AssocItem, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e1d55ff82cb..264df8b914b 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -375,7 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_is_local = sole_field.did.is_local(); let field_is_accessible = - sole_field.vis.is_accessible_from(expr.hir_id.owner, self.tcx) + sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) // Skip suggestions for unstable public fields (for example `Pin::pointer`) && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked); @@ -417,6 +417,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::def::CtorKind::Const => unreachable!(), }; + // Suggest constructor as deep into the block tree as possible. + // This fixes https://github.com/rust-lang/rust/issues/101065, + // and also just helps make the most minimal suggestions. + let mut expr = expr; + while let hir::ExprKind::Block(block, _) = &expr.kind + && let Some(expr_) = &block.expr + { + expr = expr_ + } + vec![ (expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")), (expr.span.shrink_to_hi(), close.to_owned()), diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 23fadff3248..48a4f40780b 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -752,7 +752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::ImplItemKind::Fn(..), span: encl_fn_span, .. - })) = self.tcx.hir().find_by_def_id(encl_item_id) + })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id) { // We are inside a function body, so reporting "return statement // outside of function body" needs an explanation. @@ -761,7 +761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this didn't hold, we would not have to report an error in // the first place. - assert_ne!(encl_item_id, encl_body_owner_id); + assert_ne!(encl_item_id.def_id, encl_body_owner_id); let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); let encl_body = self.tcx.hir().body(encl_body_id); @@ -2338,7 +2338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() { def.non_enum_variant().fields.iter().any(|field| { field.ident(self.tcx) == ident - && field.vis.is_accessible_from(expr.hir_id.owner, self.tcx) + && field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) }) } else if let ty::Tuple(tys) = output_ty.kind() && let Ok(idx) = ident.as_str().parse::<usize>() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 311fcaadaa9..64e7fa1a42b 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1543,7 +1543,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn parent_item_span(&self, id: hir::HirId) -> Option<Span> { - let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id)); + let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id); match node { Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { @@ -1559,7 +1559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise. fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> { - let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id)); + let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id); self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident)) } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 0e22971d3aa..d929a3e6548 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -276,7 +276,6 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item( self, - self.tcx, span, item_def_id, item_segment, diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 2d459b2cc0e..0e77ed0a4fe 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -2077,7 +2077,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Colon, Nothing, } - let ast_generics = hir.get_generics(id.owner).unwrap(); + let ast_generics = hir.get_generics(id.owner.def_id).unwrap(); let (sp, mut introducer) = if let Some(span) = ast_generics.bounds_span_for_suggestions(def_id) { diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 1a4c888a5a4..593a9776bde 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -519,7 +519,7 @@ fn get_owner_return_paths<'tcx>( def_id: LocalDefId, ) -> Option<(LocalDefId, ReturnsVisitor<'tcx>)> { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_id = tcx.hir().get_parent_item(hir_id).def_id; tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| { let body = tcx.hir().body(body_id); let mut visitor = ReturnsVisitor::default(); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index e4124185d15..7965ec1b43f 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -116,7 +116,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( }) } -fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { +fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { let node = tcx.hir().expect_owner(def_id); match node { hir::OwnerNode::Crate(_) => {} @@ -148,7 +148,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { /// the types first. #[instrument(skip(tcx), level = "debug")] fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { - let def_id = item.def_id; + let def_id = item.def_id.def_id; debug!( ?item.def_id, @@ -175,7 +175,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // for `T` hir::ItemKind::Impl(ref impl_) => { let is_auto = tcx - .impl_trait_ref(item.def_id) + .impl_trait_ref(def_id) .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); @@ -211,13 +211,13 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } } hir::ItemKind::Fn(ref sig, ..) => { - check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl); + check_item_fn(tcx, def_id, item.ident, item.span, sig.decl); } hir::ItemKind::Static(ty, ..) => { - check_item_type(tcx, item.def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, false); } hir::ItemKind::Const(ty, ..) => { - check_item_type(tcx, item.def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, false); } hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]); @@ -247,7 +247,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { - let def_id = item.def_id; + let def_id = item.def_id.def_id; debug!( ?item.def_id, @@ -256,15 +256,15 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { match item.kind { hir::ForeignItemKind::Fn(decl, ..) => { - check_item_fn(tcx, item.def_id, item.ident, item.span, decl) + check_item_fn(tcx, def_id, item.ident, item.span, decl) } - hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true), + hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true), hir::ForeignItemKind::Type => (), } } fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { - let def_id = trait_item.def_id; + let def_id = trait_item.def_id.def_id; let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -272,7 +272,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { _ => (None, trait_item.span), }; check_object_unsafe_self_trait_by_name(tcx, trait_item); - check_associated_item(tcx, trait_item.def_id, span, method_sig); + check_associated_item(tcx, def_id, span, method_sig); let encl_trait_def_id = tcx.local_parent(def_id); let encl_trait = tcx.hir().expect_item(encl_trait_def_id); @@ -393,7 +393,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe // We also assume that all of the function signature's parameter types // are well formed. &sig.inputs().iter().copied().collect(), - gat_def_id, + gat_def_id.def_id, gat_generics, ) } @@ -416,7 +416,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe .copied() .collect::<Vec<_>>(), &FxHashSet::default(), - gat_def_id, + gat_def_id.def_id, gat_generics, ) } @@ -456,7 +456,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe } for (gat_def_id, required_bounds) in required_bounds_by_item { - let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id); + let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id.def_id); debug!(?required_bounds); let param_env = tcx.param_env(gat_def_id); let gat_hir = gat_item_hir.hir_id(); @@ -786,7 +786,7 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { /// When this is done, suggest using `Self` instead. fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { let (trait_name, trait_def_id) = - match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id())) { + match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { hir::ItemKind::Trait(..) => (item.ident, item.def_id), _ => return, @@ -796,18 +796,18 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem let mut trait_should_be_self = vec![]; match &item.kind { hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty)) - if could_be_self(trait_def_id, ty) => + if could_be_self(trait_def_id.def_id, ty) => { trait_should_be_self.push(ty.span) } hir::TraitItemKind::Fn(sig, _) => { for ty in sig.decl.inputs { - if could_be_self(trait_def_id, ty) { + if could_be_self(trait_def_id.def_id, ty) { trait_should_be_self.push(ty.span); } } match sig.decl.output { - hir::FnRetTy::Return(ty) if could_be_self(trait_def_id, ty) => { + hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => { trait_should_be_self.push(ty.span); } _ => {} @@ -836,8 +836,6 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem } fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { - let def_id = impl_item.def_id; - let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`. @@ -845,7 +843,7 @@ fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) { _ => (None, impl_item.span), }; - check_associated_item(tcx, def_id, span, method_sig); + check_associated_item(tcx, impl_item.def_id.def_id, span, method_sig); } fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { @@ -1045,7 +1043,7 @@ fn check_type_defn<'tcx, F>( ) where F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>, { - enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { let variants = lookup_fields(wfcx); let packed = tcx.adt_def(item.def_id).repr().packed(); @@ -1124,7 +1122,7 @@ fn check_type_defn<'tcx, F>( } } - check_where_clauses(wfcx, item.span, item.def_id); + check_where_clauses(wfcx, item.span, item.def_id.def_id); }); } @@ -1132,11 +1130,12 @@ fn check_type_defn<'tcx, F>( fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { debug!(?item.def_id); - let trait_def = tcx.trait_def(item.def_id); + let def_id = item.def_id.def_id; + let trait_def = tcx.trait_def(def_id); if trait_def.is_marker || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker) { - for associated_def_id in &*tcx.associated_item_def_ids(item.def_id) { + for associated_def_id in &*tcx.associated_item_def_ids(def_id) { struct_span_err!( tcx.sess, tcx.def_span(*associated_def_id), @@ -1147,8 +1146,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { } } - enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { - check_where_clauses(wfcx, item.span, item.def_id) + enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| { + check_where_clauses(wfcx, item.span, def_id) }); // Only check traits, don't check trait aliases @@ -1242,7 +1241,7 @@ fn check_impl<'tcx>( ast_trait_ref: &Option<hir::TraitRef<'_>>, constness: hir::Constness, ) { - enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item.span, item.def_id.def_id, |wfcx| { match *ast_trait_ref { Some(ref ast_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and @@ -1273,18 +1272,18 @@ fn check_impl<'tcx>( let self_ty = tcx.type_of(item.def_id); let self_ty = wfcx.normalize( item.span, - Some(WellFormedLoc::Ty(item.hir_id().expect_owner())), + Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty, ); wfcx.register_wf_obligation( ast_self_ty.span, - Some(WellFormedLoc::Ty(item.hir_id().expect_owner())), + Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); } } - check_where_clauses(wfcx, item.span, item.def_id); + check_where_clauses(wfcx, item.span, item.def_id.def_id); }); } diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 52aad636fd8..308ad5d5fc2 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -105,7 +105,7 @@ impl<'tcx> InherentCollect<'tcx> { } if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) { - self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); + self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id.def_id); } else { bug!("unexpected self type: {:?}", self_ty); } @@ -220,7 +220,9 @@ impl<'tcx> InherentCollect<'tcx> { | ty::Ref(..) | ty::Never | ty::FnPtr(_) - | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span), + | ty::Tuple(..) => { + self.check_primitive_impl(item.def_id.def_id, self_ty, items, ty.span) + } ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => { let mut err = struct_span_err!( self.tcx.sess, diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 87961890f53..7d15e5a7f3c 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -42,7 +42,7 @@ fn do_orphan_check_impl<'tcx>( ) -> Result<(), ErrorGuaranteed> { let trait_def_id = trait_ref.def_id; - let item = tcx.hir().item(hir::ItemId { def_id }); + let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!("{:?} is not an impl: {:?}", def_id, item); }; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 359a79e9979..e7deae2b557 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -28,7 +28,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::weak_lang_items; use rustc_hir::{GenericParamKind, HirId, Node}; @@ -430,7 +430,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item( self, - self.tcx, span, item_def_id, item_segment, @@ -449,8 +448,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { match self.node() { hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => { - let item = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id())); + let item = self + .tcx + .hir() + .expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id); match &item.kind { hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) @@ -728,7 +729,7 @@ impl<'tcx> ItemCtxt<'tcx> { fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir().item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id()); - let def_id = item_id.def_id; + let def_id = item_id.def_id.def_id; match it.kind { // These don't define types. @@ -840,20 +841,21 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let trait_item = tcx.hir().trait_item(trait_item_id); - tcx.ensure().generics_of(trait_item_id.def_id); + let def_id = trait_item_id.def_id; + tcx.ensure().generics_of(def_id); match trait_item.kind { hir::TraitItemKind::Fn(..) => { - tcx.ensure().type_of(trait_item_id.def_id); - tcx.ensure().fn_sig(trait_item_id.def_id); + tcx.ensure().type_of(def_id); + tcx.ensure().fn_sig(def_id); } hir::TraitItemKind::Const(.., Some(_)) => { - tcx.ensure().type_of(trait_item_id.def_id); + tcx.ensure().type_of(def_id); } hir::TraitItemKind::Const(hir_ty, _) => { - tcx.ensure().type_of(trait_item_id.def_id); + tcx.ensure().type_of(def_id); // Account for `const C: _;`. let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); @@ -863,8 +865,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } hir::TraitItemKind::Type(_, Some(_)) => { - tcx.ensure().item_bounds(trait_item_id.def_id); - tcx.ensure().type_of(trait_item_id.def_id); + tcx.ensure().item_bounds(def_id); + tcx.ensure().type_of(def_id); // Account for `type T = _;`. let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); @@ -872,7 +874,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } hir::TraitItemKind::Type(_, None) => { - tcx.ensure().item_bounds(trait_item_id.def_id); + tcx.ensure().item_bounds(def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. let mut visitor = HirPlaceholderCollector::default(); @@ -882,7 +884,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } }; - tcx.ensure().predicates_of(trait_item_id.def_id); + tcx.ensure().predicates_of(def_id); } fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { @@ -1595,7 +1597,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { let parent_id = tcx.hir().get_parent_item(hir_id); - assert_ne!(parent_id, CRATE_DEF_ID); + assert_ne!(parent_id, hir::CRATE_OWNER_ID); debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); // Opaque types are always nested within another item, and // inherit the generics of the item. @@ -3386,7 +3388,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: let node = tcx.hir().get(hir_id); if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node { let parent_id = tcx.hir().get_parent_item(hir_id); - let parent_item = tcx.hir().expect_item(parent_id); + let parent_item = tcx.hir().expect_item(parent_id.def_id); if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind { tcx.sess .struct_span_err( diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 70e259b46bf..24fb0b1fd26 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -569,22 +569,22 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T fn visit_item(&mut self, it: &'tcx Item<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { trace!(?it.def_id); - self.check(it.def_id); + self.check(it.def_id.def_id); intravisit::walk_trait_item(self, it); } } @@ -688,22 +688,22 @@ fn find_opaque_ty_constraints_for_rpit( fn visit_item(&mut self, it: &'tcx Item<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_item(self, it); } } fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { trace!(?it.def_id); // The opaque type itself or its children are not within its reveal scope. - if it.def_id != self.def_id { - self.check(it.def_id); + if it.def_id.def_id != self.def_id { + self.check(it.def_id.def_id); intravisit::walk_impl_item(self, it); } } fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { trace!(?it.def_id); - self.check(it.def_id); + self.check(it.def_id.def_id); intravisit::walk_trait_item(self, it); } } diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 9fee1eaaec9..c499364056f 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -58,10 +58,10 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { let module = tcx.hir_module_items(module_def_id); for id in module.items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { - enforce_impl_params_are_constrained(tcx, id.def_id); - enforce_impl_items_are_distinct(tcx, id.def_id); + enforce_impl_params_are_constrained(tcx, id.def_id.def_id); + enforce_impl_items_are_distinct(tcx, id.def_id.def_id); if min_specialization { - check_min_specialization(tcx, id.def_id); + check_min_specialization(tcx, id.def_id.def_id); } } } diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index ced919f66db..39610e3ae38 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -265,6 +265,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) } + #[instrument(level = "debug", skip(self, previous))] fn cat_expr_adjusted_with<F>( &self, expr: &hir::Expr<'_>, @@ -274,7 +275,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { where F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>, { - debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); let target = self.resolve_vars_if_possible(adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { @@ -299,6 +299,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] pub(crate) fn cat_expr_unadjusted( &self, expr: &hir::Expr<'_>, @@ -387,6 +388,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self, span))] pub(crate) fn cat_res( &self, hir_id: hir::HirId, @@ -394,8 +396,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr_ty: Ty<'tcx>, res: Res, ) -> McResult<PlaceWithHirId<'tcx>> { - debug!("cat_res: id={:?} expr={:?} def={:?}", hir_id, expr_ty, res); - match res { Res::Def( DefKind::Ctor(..) @@ -475,13 +475,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ret } + #[instrument(level = "debug", skip(self))] fn cat_overloaded_place( &self, expr: &hir::Expr<'_>, base: &hir::Expr<'_>, ) -> McResult<PlaceWithHirId<'tcx>> { - debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base); - // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. @@ -497,13 +496,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_deref(expr, base) } + #[instrument(level = "debug", skip(self, node))] fn cat_deref( &self, node: &impl HirNode, base_place: PlaceWithHirId<'tcx>, ) -> McResult<PlaceWithHirId<'tcx>> { - debug!("cat_deref: base_place={:?}", base_place); - let base_curr_ty = base_place.place.ty(); let deref_ty = match base_curr_ty.builtin_deref(true) { Some(mt) => mt.ty, diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs index 3e8d023fb55..0409c7081dc 100644 --- a/compiler/rustc_typeck/src/outlives/utils.rs +++ b/compiler/rustc_typeck/src/outlives/utils.rs @@ -96,6 +96,23 @@ pub(crate) fn insert_outlives_predicate<'tcx>( .or_insert(span); } + Component::Opaque(def_id, substs) => { + // This would arise from something like: + // + // ```rust + // type Opaque<T> = impl Sized; + // fn defining<T>() -> Opaque<T> {} + // struct Ss<'a, T>(&'a Opaque<T>); + // ``` + // + // Here we want to have an implied bound `Opaque<T>: 'a` + + let ty = tcx.mk_opaque(def_id, substs); + required_predicates + .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) + .or_insert(span); + } + Component::EscapingProjection(_) => { // As above, but the projection involves // late-bound regions. Therefore, the WF diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index cacbd54b6c2..3018d1c9125 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -580,7 +580,7 @@ impl<K, V> BTreeMap<K, V> { /// map.insert(1, "a"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_stable(feature = "const_btree_new", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub const fn new() -> BTreeMap<K, V> { BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData } @@ -2392,7 +2392,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn len(&self) -> usize { self.length } @@ -2413,7 +2413,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 2cfc0807409..3caaf521240 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -343,7 +343,7 @@ impl<T> BTreeSet<T> { /// let mut set: BTreeSet<i32> = BTreeSet::new(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_stable(feature = "const_btree_new", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub const fn new() -> BTreeSet<T> { BTreeSet { map: BTreeMap::new() } @@ -1174,7 +1174,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn len(&self) -> usize { self.map.len() } @@ -1193,7 +1193,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + #[rustc_const_unstable(feature = "const_btree_len", issue = "71835")] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e3f4deb0875..2a57dad89a7 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -12,11 +12,17 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::iter::{repeat_with, FromIterator}; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::{Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice; +// This is used in a bunch of intra-doc links. +// FIXME: For some reason, `#[cfg(doc)]` wasn't sufficient, resulting in +// failures in linkchecker even though rustdoc built the docs just fine. +#[allow(unused_imports)] +use core::mem; + use crate::alloc::{Allocator, Global}; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; @@ -177,7 +183,7 @@ impl<T, A: Allocator> VecDeque<T, A> { /// Marginally more convenient #[inline] fn cap(&self) -> usize { - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // For zero sized types, we are always at maximum capacity MAXIMUM_ZST_CAPACITY } else { @@ -3038,7 +3044,7 @@ impl<T, A: Allocator> From<Vec<T, A>> for VecDeque<T, A> { /// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated. fn from(mut other: Vec<T, A>) -> Self { let len = other.len(); - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // There's no actual allocation for ZSTs to worry about capacity, // but `VecDeque` can't handle as much length as `Vec`. assert!(len < MAXIMUM_ZST_CAPACITY, "capacity overflow"); @@ -3124,7 +3130,7 @@ impl<T, const N: usize> From<[T; N]> for VecDeque<T> { fn from(arr: [T; N]) -> Self { let mut deq = VecDeque::with_capacity(N); let arr = ManuallyDrop::new(arr); - if mem::size_of::<T>() != 0 { + if !<T>::IS_ZST { // SAFETY: VecDeque::with_capacity ensures that there is enough capacity. unsafe { ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 6b3b1c22222..de58f22daae 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -99,7 +99,7 @@ #![feature(coerce_unsized)] #![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] #![feature(const_box)] -#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))] +#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] #![feature(const_cow_is_borrowed)] #![feature(const_convert)] #![feature(const_size_of_val)] @@ -139,6 +139,7 @@ #![feature(receiver_trait)] #![feature(saturating_int_impl)] #![feature(set_ptr_value)] +#![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] #![feature(slice_group_by)] #![feature(slice_ptr_get)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index b0f4529abdf..5a10121bbbe 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -3,7 +3,7 @@ use core::alloc::LayoutError; use core::cmp; use core::intrinsics; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; @@ -168,7 +168,7 @@ impl<T, A: Allocator> RawVec<T, A> { #[cfg(not(no_global_oom_handling))] fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. - if mem::size_of::<T>() == 0 || capacity == 0 { + if T::IS_ZST || capacity == 0 { Self::new_in(alloc) } else { // We avoid `unwrap_or_else` here because it bloats the amount of @@ -229,7 +229,7 @@ impl<T, A: Allocator> RawVec<T, A> { /// This will always be `usize::MAX` if `T` is zero-sized. #[inline(always)] pub fn capacity(&self) -> usize { - if mem::size_of::<T>() == 0 { usize::MAX } else { self.cap } + if T::IS_ZST { usize::MAX } else { self.cap } } /// Returns a shared reference to the allocator backing this `RawVec`. @@ -238,7 +238,7 @@ impl<T, A: Allocator> RawVec<T, A> { } fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> { - if mem::size_of::<T>() == 0 || self.cap == 0 { + if T::IS_ZST || self.cap == 0 { None } else { // We have an allocated chunk of memory, so we can bypass runtime @@ -380,7 +380,7 @@ impl<T, A: Allocator> RawVec<T, A> { // This is ensured by the calling contexts. debug_assert!(additional > 0); - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // Since we return a capacity of `usize::MAX` when `elem_size` is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow.into()); @@ -406,7 +406,7 @@ impl<T, A: Allocator> RawVec<T, A> { // `grow_amortized`, but this method is usually instantiated less often so // it's less critical. fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // Since we return a capacity of `usize::MAX` when the type size is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow.into()); diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 8c9783fe194..a5e7bf2a1a9 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -16,9 +16,7 @@ use core::borrow::{Borrow, BorrowMut}; #[cfg(not(no_global_oom_handling))] use core::cmp::Ordering::{self, Less}; #[cfg(not(no_global_oom_handling))] -use core::mem; -#[cfg(not(no_global_oom_handling))] -use core::mem::size_of; +use core::mem::{self, SizedTypeProperties}; #[cfg(not(no_global_oom_handling))] use core::ptr; @@ -1018,7 +1016,7 @@ where const MIN_RUN: usize = 10; // Sorting has no meaningful behavior on zero-sized types. - if size_of::<T>() == 0 { + if T::IS_ZST { return; } diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 5b73906a1c9..541f99bcfab 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -1,7 +1,7 @@ use crate::alloc::{Allocator, Global}; use core::fmt; use core::iter::{FusedIterator, TrustedLen}; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, SizedTypeProperties}; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -202,7 +202,7 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> { let mut vec = self.vec; - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount. // this can be achieved by manipulating the Vec length instead of moving values out from `iter`. unsafe { diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index b211421b202..a3f8fe40fd5 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -135,7 +135,7 @@ //! vec.truncate(write_idx); //! ``` use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce}; -use core::mem::{self, ManuallyDrop}; +use core::mem::{self, ManuallyDrop, SizedTypeProperties}; use core::ptr::{self}; use super::{InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; @@ -154,7 +154,7 @@ where default fn from_iter(mut iterator: I) -> Self { // See "Layout constraints" section in the module documentation. We rely on const // optimization here since these conditions currently cannot be expressed as trait bounds - if mem::size_of::<T>() == 0 + if T::IS_ZST || mem::size_of::<T>() != mem::size_of::<<<I as SourceIter>::Source as AsVecIntoIter>::Item>() || mem::align_of::<T>() diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index b4157fd5895..d74e77637bd 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -8,7 +8,7 @@ use core::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; #[cfg(not(no_global_oom_handling))] use core::ops::Deref; use core::ptr::{self, NonNull}; @@ -149,7 +149,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { fn next(&mut self) -> Option<T> { if self.ptr == self.end { None - } else if mem::size_of::<T>() == 0 { + } else if T::IS_ZST { // purposefully don't use 'ptr.offset' because for // vectors with 0-size elements this would return the // same pointer. @@ -167,7 +167,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let exact = if mem::size_of::<T>() == 0 { + let exact = if T::IS_ZST { self.end.addr().wrapping_sub(self.ptr.addr()) } else { unsafe { self.end.sub_ptr(self.ptr) } @@ -179,7 +179,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { fn advance_by(&mut self, n: usize) -> Result<(), usize> { let step_size = self.len().min(n); let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size); - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound // effectively results in unsigned pointers representing positions 0..usize::MAX, // which is valid for ZSTs. @@ -209,7 +209,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { let len = self.len(); - if mem::size_of::<T>() == 0 { + if T::IS_ZST { if len < N { self.forget_remaining_elements(); // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct @@ -253,7 +253,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> { // that `T: Copy` so reading elements from the buffer doesn't invalidate // them for `Drop`. unsafe { - if mem::size_of::<T>() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } + if T::IS_ZST { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } } } } @@ -264,7 +264,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { fn next_back(&mut self) -> Option<T> { if self.end == self.ptr { None - } else if mem::size_of::<T>() == 0 { + } else if T::IS_ZST { // See above for why 'ptr.offset' isn't used self.end = self.end.wrapping_byte_sub(1); @@ -280,7 +280,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { let step_size = self.len().min(n); - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // SAFETY: same as for advance_by() self.end = self.end.wrapping_byte_sub(step_size); } else { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 60b36af5e67..d6d986905e6 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -64,7 +64,7 @@ use core::iter; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; @@ -2347,7 +2347,7 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> { #[unstable(feature = "slice_flatten", issue = "95629")] pub fn into_flattened(self) -> Vec<T, A> { let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); - let (new_len, new_cap) = if mem::size_of::<T>() == 0 { + let (new_len, new_cap) = if T::IS_ZST { (len.checked_mul(N).expect("vec len overflow"), usize::MAX) } else { // SAFETY: @@ -2677,7 +2677,7 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> { let mut me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); let begin = me.as_mut_ptr(); - let end = if mem::size_of::<T>() == 0 { + let end = if T::IS_ZST { begin.wrapping_byte_add(me.len()) } else { begin.add(me.len()) as *const T diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 490c0d8f76c..55aced5106c 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -32,7 +32,7 @@ #![feature(slice_group_by)] #![feature(slice_partition_dedup)] #![feature(string_remove_matches)] -#![feature(const_btree_new)] +#![feature(const_btree_len)] #![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(const_str_from_utf8)] diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs index 0abe20e4ca3..4b40485d207 100644 --- a/library/core/benches/iter.rs +++ b/library/core/benches/iter.rs @@ -364,6 +364,13 @@ fn bench_partial_cmp(b: &mut Bencher) { } #[bench] +fn bench_chain_partial_cmp(b: &mut Bencher) { + b.iter(|| { + (0..50000).chain(50000..100000).map(black_box).partial_cmp((0..100000).map(black_box)) + }) +} + +#[bench] fn bench_lt(b: &mut Bencher) { b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box))) } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 165b9d24d93..36e89a95fd2 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -434,7 +434,8 @@ impl<T: Copy> SpecArrayClone for T { macro_rules! array_impl_default { {$n:expr, $t:ident $($ts:ident)*} => { #[stable(since = "1.4.0", feature = "array_default")] - impl<T> Default for [T; $n] where T: Default { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl<T> const Default for [T; $n] where T: ~const Default { fn default() -> [T; $n] { [$t::default(), $($ts::default()),*] } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 50b8264bac7..f0fa2e1d2c1 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -22,6 +22,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; use crate::marker::StructuralPartialEq; @@ -1222,7 +1223,12 @@ pub const fn min<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn min_by<T, F: ~const FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, +{ match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v1, Ordering::Greater => v2, @@ -1244,8 +1250,24 @@ pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { - min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn min_by_key<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, + K: ~const Destruct, +{ + const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>( + f: &mut F, + (v1, v2): (&T, &T), + ) -> Ordering + where + T: ~const Destruct, + K: ~const Destruct, + { + f(v1).cmp(&f(v2)) + } + min_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) } /// Compares and returns the maximum of two values. @@ -1286,7 +1308,12 @@ pub const fn max<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T { +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn max_by<T, F: ~const FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, +{ match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v2, Ordering::Greater => v1, @@ -1308,8 +1335,24 @@ pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[stable(feature = "cmp_min_max_by", since = "1.53.0")] -pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { - max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +pub const fn max_by_key<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T +where + T: ~const Destruct, + F: ~const Destruct, + K: ~const Destruct, +{ + const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>( + f: &mut F, + (v1, v2): (&T, &T), + ) -> Ordering + where + T: ~const Destruct, + K: ~const Destruct, + { + f(v1).cmp(&f(v2)) + } + max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp)) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs new file mode 100644 index 00000000000..d2e80e8e7e5 --- /dev/null +++ b/library/core/src/const_closure.rs @@ -0,0 +1,63 @@ +use crate::marker::Destruct; + +/// Struct representing a closure with mutably borrowed data. +/// +/// Example: +/// ```no_build +/// #![feature(const_mut_refs)] +/// use crate::const_closure::ConstFnMutClosure; +/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 { +/// *state += arg; +/// *state +/// } +/// let mut i = 5; +/// let mut cl = ConstFnMutClosure::new(&mut i, imp); +/// +/// assert!(7 == cl(2)); +/// assert!(8 == cl(1)); +/// ``` +pub(crate) struct ConstFnMutClosure<'a, CapturedData: ?Sized, Function> { + data: &'a mut CapturedData, + func: Function, +} + +impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<'a, CapturedData, Function> { + /// Function for creating a new closure. + /// + /// `data` is the a mutable borrow of data that is captured from the environment. + /// + /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure + /// and return the return value of the closure. + pub(crate) const fn new<ClosureArguments, ClosureReturnValue>( + data: &'a mut CapturedData, + func: Function, + ) -> Self + where + Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue, + { + Self { data, func } + } +} + +impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const + FnOnce<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function> +where + Function: + ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue + ~const Destruct, +{ + type Output = ClosureReturnValue; + + extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { + self.call_mut(args) + } +} + +impl<'a, CapturedData: ?Sized, ClosureArguments, Function, ClosureReturnValue> const + FnMut<ClosureArguments> for ConstFnMutClosure<'a, CapturedData, Function> +where + Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue, +{ + extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { + (self.func)(self.data, args) + } +} diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 25789d37c26..d8365ae9bf9 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -211,7 +211,7 @@ macro_rules! impl_Display { fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::<u8>::uninit(); 39]; - let mut curr = buf.len() as isize; + let mut curr = buf.len(); let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); @@ -228,7 +228,7 @@ macro_rules! impl_Display { // eagerly decode 4 characters at a time while n >= 10000 { - let rem = (n % 10000) as isize; + let rem = (n % 10000) as usize; n /= 10000; let d1 = (rem / 100) << 1; @@ -238,29 +238,29 @@ macro_rules! impl_Display { // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since // otherwise `curr < 0`. But then `n` was originally at least `10000^10` // which is `10^40 > 2^128 > n`. - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2); } // if we reach here numbers are <= 9999, so at most 4 chars long - let mut n = n as isize; // possibly reduce 64bit math + let mut n = n as usize; // possibly reduce 64bit math // decode 2 more chars, if > 2 chars if n >= 100 { let d1 = (n % 100) << 1; n /= 100; curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); } // decode last 1 or 2 chars if n < 10 { curr -= 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; + *buf_ptr.add(curr) = (n as u8) + b'0'; } else { let d1 = n << 1; curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); } } @@ -268,7 +268,7 @@ macro_rules! impl_Display { // UTF-8 since `DEC_DIGITS_LUT` is let buf_slice = unsafe { str::from_utf8_unchecked( - slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)) + slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) }; f.pad_integral(is_nonnegative, "", buf_slice) } @@ -339,18 +339,18 @@ macro_rules! impl_Exp { // Since `curr` always decreases by the number of digits copied, this means // that `curr >= 0`. let mut buf = [MaybeUninit::<u8>::uninit(); 40]; - let mut curr = buf.len() as isize; //index for buf + let mut curr = buf.len(); //index for buf let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); // decode 2 chars at a time while n >= 100 { - let d1 = ((n % 100) as isize) << 1; + let d1 = ((n % 100) as usize) << 1; curr -= 2; // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since // `DEC_DIGITS_LUT` has a length of 200. unsafe { - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); } n /= 100; exponent += 2; @@ -362,7 +362,7 @@ macro_rules! impl_Exp { curr -= 1; // SAFETY: Safe since `40 > curr >= 0` (see comment) unsafe { - *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0'; + *buf_ptr.add(curr) = (n as u8 % 10_u8) + b'0'; } n /= 10; exponent += 1; @@ -372,7 +372,7 @@ macro_rules! impl_Exp { curr -= 1; // SAFETY: Safe since `40 > curr >= 0` unsafe { - *buf_ptr.offset(curr) = b'.'; + *buf_ptr.add(curr) = b'.'; } } @@ -380,10 +380,10 @@ macro_rules! impl_Exp { let buf_slice = unsafe { // decode last character curr -= 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; + *buf_ptr.add(curr) = (n as u8) + b'0'; let len = buf.len() - curr as usize; - slice::from_raw_parts(buf_ptr.offset(curr), len) + slice::from_raw_parts(buf_ptr.add(curr), len) }; // stores 'e' (or 'E') and the up to 2-digit exponent @@ -392,13 +392,13 @@ macro_rules! impl_Exp { // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]` // is contained within `exp_buf` since `len <= 3`. let exp_slice = unsafe { - *exp_ptr.offset(0) = if upper { b'E' } else { b'e' }; + *exp_ptr.add(0) = if upper { b'E' } else { b'e' }; let len = if exponent < 10 { - *exp_ptr.offset(1) = (exponent as u8) + b'0'; + *exp_ptr.add(1) = (exponent as u8) + b'0'; 2 } else { let off = exponent << 1; - ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2); + ptr::copy_nonoverlapping(lut_ptr.add(off), exp_ptr.add(1), 2); 3 }; slice::from_raw_parts(exp_ptr, len) @@ -479,7 +479,7 @@ mod imp { impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128); /// Helper function for writing a u64 into `buf` going from last to first, with `curr`. -fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut isize) { +fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut usize) { let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); assert!(*curr > 19); @@ -505,14 +505,14 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu *curr -= 16; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d5 as usize), buf_ptr.add(*curr + 8), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d6 as usize), buf_ptr.add(*curr + 10), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d7 as usize), buf_ptr.add(*curr + 12), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d8 as usize), buf_ptr.add(*curr + 14), 2); } if n >= 1e8 as u64 { let to_parse = n % 1e8 as u64; @@ -525,10 +525,10 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu let d4 = ((to_parse / 1e0 as u64) % 100) << 1; *curr -= 8; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2); } // `n` < 1e8 < (1 << 32) let mut n = n as u32; @@ -540,8 +540,8 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu let d2 = (to_parse % 100) << 1; *curr -= 4; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2); } // `n` < 1e4 < (1 << 16) @@ -550,17 +550,17 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu let d1 = (n % 100) << 1; n /= 100; *curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2); } // decode last 1 or 2 chars if n < 10 { *curr -= 1; - *buf_ptr.offset(*curr) = (n as u8) + b'0'; + *buf_ptr.add(*curr) = (n as u8) + b'0'; } else { let d1 = n << 1; *curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2); + ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2); } } } @@ -593,21 +593,21 @@ impl fmt::Display for i128 { fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::<u8>::uninit(); 39]; - let mut curr = buf.len() as isize; + let mut curr = buf.len(); let (n, rem) = udiv_1e19(n); parse_u64_into(rem, &mut buf, &mut curr); if n != 0 { // 0 pad up to point - let target = (buf.len() - 19) as isize; + let target = buf.len() - 19; // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space // remaining since it has length 39 unsafe { ptr::write_bytes( - MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target), + MaybeUninit::slice_as_mut_ptr(&mut buf).add(target), b'0', - (curr - target) as usize, + curr - target, ); } curr = target; @@ -616,16 +616,16 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R parse_u64_into(rem, &mut buf, &mut curr); // Should this following branch be annotated with unlikely? if n != 0 { - let target = (buf.len() - 38) as isize; + let target = buf.len() - 38; // The raw `buf_ptr` pointer is only valid until `buf` is used the next time, // buf `buf` is not used in this scope so we are good. let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); // SAFETY: At this point we wrote at most 38 bytes, pad up to that point, // There can only be at most 1 digit remaining. unsafe { - ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize); + ptr::write_bytes(buf_ptr.add(target), b'0', curr - target); curr = target - 1; - *buf_ptr.offset(curr) = (n as u8) + b'0'; + *buf_ptr.add(curr) = (n as u8) + b'0'; } } } @@ -634,8 +634,8 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R // UTF-8 since `DEC_DIGITS_LUT` is let buf_slice = unsafe { str::from_utf8_unchecked(slice::from_raw_parts( - MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr), - buf.len() - curr as usize, + MaybeUninit::slice_as_mut_ptr(&mut buf).add(curr), + buf.len() - curr, )) }; f.pad_integral(is_nonnegative, "", buf_slice) diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 9b479a9f8ad..489fb13c0dc 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -1,4 +1,5 @@ use crate::array; +use crate::const_closure::ConstFnMutClosure; use crate::iter::{ByRefSized, FusedIterator, Iterator}; use crate::ops::{ControlFlow, NeverShortCircuit, Try}; @@ -82,12 +83,12 @@ where } } - fn fold<B, F>(mut self, init: B, f: F) -> B + fn fold<B, F>(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_fold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0 } } @@ -126,12 +127,12 @@ where try { acc } } - fn rfold<B, F>(mut self, init: B, f: F) -> B + fn rfold<B, F>(mut self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + self.try_rfold(init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)).0 } } diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 477e7117c3e..1945e402ff5 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,4 +1,7 @@ -use crate::ops::{NeverShortCircuit, Try}; +use crate::{ + const_closure::ConstFnMutClosure, + ops::{NeverShortCircuit, Try}, +}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -36,12 +39,13 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> { } #[inline] - fn fold<B, F>(self, init: B, f: F) -> B + fn fold<B, F>(self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `fold` needs ownership, so this can't forward directly. - I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)) + .0 } #[inline] @@ -72,12 +76,17 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> { } #[inline] - fn rfold<B, F>(self, init: B, f: F) -> B + fn rfold<B, F>(self, init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { // `rfold` needs ownership, so this can't forward directly. - I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 + I::try_rfold( + self.0, + init, + ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp), + ) + .0 } #[inline] diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index bf4fabad32a..de3a534f81b 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,3 +1,4 @@ +use crate::const_closure::ConstFnMutClosure; use crate::iter::{InPlaceIterable, Iterator}; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try}; @@ -203,12 +204,12 @@ where .into_try() } - fn fold<B, F>(mut self, init: B, fold: F) -> B + fn fold<B, F>(mut self, init: B, mut fold: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 + self.try_fold(init, ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp)).0 } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index b2d08f4b0f6..e26920b25cc 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2906,14 +2906,14 @@ pub trait Iterator { /// Stopping at the first `true`: /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [-1, 2, 3, 4]; /// /// let mut iter = a.iter(); /// - /// assert_eq!(iter.rposition(|&x| x == 2), Some(1)); + /// assert_eq!(iter.rposition(|&x| x >= 2), Some(3)); /// /// // we can still use `iter`, as there are more elements. - /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&-1)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -3461,36 +3461,27 @@ pub trait Iterator { /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn cmp_by<I, F>(mut self, other: I, mut cmp: F) -> Ordering + fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> Ordering, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => { - if other.next().is_none() { - return Ordering::Equal; - } else { - return Ordering::Less; - } - } - Some(val) => val, - }; - - let y = match other.next() { - None => return Ordering::Greater, - Some(val) => val, - }; - - match cmp(x, y) { - Ordering::Equal => (), - non_eq => return non_eq, + #[inline] + fn compare<X, Y, F>(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow<Ordering> + where + F: FnMut(X, Y) -> Ordering, + { + move |x, y| match cmp(x, y) { + Ordering::Equal => ControlFlow::CONTINUE, + non_eq => ControlFlow::Break(non_eq), } } + + match iter_compare(self, other.into_iter(), compare(cmp)) { + ControlFlow::Continue(ord) => ord, + ControlFlow::Break(ord) => ord, + } } /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those @@ -3546,36 +3537,27 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn partial_cmp_by<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering> + fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering> where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> Option<Ordering>, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => { - if other.next().is_none() { - return Some(Ordering::Equal); - } else { - return Some(Ordering::Less); - } - } - Some(val) => val, - }; - - let y = match other.next() { - None => return Some(Ordering::Greater), - Some(val) => val, - }; - - match partial_cmp(x, y) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, + #[inline] + fn compare<X, Y, F>(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow<Option<Ordering>> + where + F: FnMut(X, Y) -> Option<Ordering>, + { + move |x, y| match partial_cmp(x, y) { + Some(Ordering::Equal) => ControlFlow::CONTINUE, + non_eq => ControlFlow::Break(non_eq), } } + + match iter_compare(self, other.into_iter(), compare(partial_cmp)) { + ControlFlow::Continue(ord) => Some(ord), + ControlFlow::Break(ord) => ord, + } } /// Determines if the elements of this [`Iterator`] are equal to those of @@ -3613,29 +3595,26 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn eq_by<I, F>(mut self, other: I, mut eq: F) -> bool + fn eq_by<I, F>(self, other: I, eq: F) -> bool where Self: Sized, I: IntoIterator, F: FnMut(Self::Item, I::Item) -> bool, { - let mut other = other.into_iter(); - - loop { - let x = match self.next() { - None => return other.next().is_none(), - Some(val) => val, - }; - - let y = match other.next() { - None => return false, - Some(val) => val, - }; - - if !eq(x, y) { - return false; + #[inline] + fn compare<X, Y, F>(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()> + where + F: FnMut(X, Y) -> bool, + { + move |x, y| { + if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } } + + match iter_compare(self, other.into_iter(), compare(eq)) { + ControlFlow::Continue(ord) => ord == Ordering::Equal, + ControlFlow::Break(()) => false, + } } /// Determines if the elements of this [`Iterator`] are unequal to those of @@ -3860,6 +3839,46 @@ pub trait Iterator { } } +/// Compares two iterators element-wise using the given function. +/// +/// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next +/// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and +/// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements, +/// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of +/// the iterators. +/// +/// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by), +/// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by). +#[inline] +fn iter_compare<A, B, F, T>(mut a: A, mut b: B, f: F) -> ControlFlow<T, Ordering> +where + A: Iterator, + B: Iterator, + F: FnMut(A::Item, B::Item) -> ControlFlow<T>, +{ + #[inline] + fn compare<'a, B, X, T>( + b: &'a mut B, + mut f: impl FnMut(X, B::Item) -> ControlFlow<T> + 'a, + ) -> impl FnMut(X) -> ControlFlow<ControlFlow<T, Ordering>> + 'a + where + B: Iterator, + { + move |x| match b.next() { + None => ControlFlow::Break(ControlFlow::Continue(Ordering::Greater)), + Some(y) => f(x, y).map_break(ControlFlow::Break), + } + } + + match a.try_for_each(compare(&mut b, f)) { + ControlFlow::Continue(()) => ControlFlow::Continue(match b.next() { + None => Ordering::Equal, + Some(_) => Ordering::Less, + }), + ControlFlow::Break(x) => x, + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<I: Iterator + ?Sized> Iterator for &mut I { type Item = I::Item; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 21775c0a6ab..a48290ea08e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -138,6 +138,7 @@ #![feature(const_size_of_val)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_ptr_len)] +#![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_swap)] #![feature(const_trait_impl)] @@ -356,6 +357,8 @@ mod bool; mod tuple; mod unit; +mod const_closure; + #[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index d2dd2941d59..66fca2fd281 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1178,3 +1178,44 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> { pub const fn variant_count<T>() -> usize { intrinsics::variant_count::<T>() } + +/// Provides associated constants for various useful properties of types, +/// to give them a canonical form in our code and make them easier to read. +/// +/// This is here only to simplify all the ZST checks we need in the library. +/// It's not on a stabilization track right now. +#[doc(hidden)] +#[unstable(feature = "sized_type_properties", issue = "none")] +pub trait SizedTypeProperties: Sized { + /// `true` if this type requires no storage. + /// `false` if its [size](size_of) is greater than zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(sized_type_properties)] + /// use core::mem::SizedTypeProperties; + /// + /// fn do_something_with<T>() { + /// if T::IS_ZST { + /// // ... special approach ... + /// } else { + /// // ... the normal thing ... + /// } + /// } + /// + /// struct MyUnit; + /// assert!(MyUnit::IS_ZST); + /// + /// // For negative checks, consider using UFCS to emphasize the negation + /// assert!(!<i32>::IS_ZST); + /// // As it can sometimes hide in the type otherwise + /// assert!(!String::IS_ZST); + /// ``` + #[doc(hidden)] + #[unstable(feature = "sized_type_properties", issue = "none")] + const IS_ZST: bool = size_of::<Self>() == 0; +} +#[doc(hidden)] +#[unstable(feature = "sized_type_properties", issue = "none")] +impl<T> SizedTypeProperties for T {} diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index fd567a8c684..72ebe653caf 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -126,7 +126,8 @@ impl<B, C> const ops::FromResidual for ControlFlow<B, C> { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> { type TryType = ControlFlow<B, C>; } diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index dfde0b37acf..4d0d4e12adb 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -129,7 +129,7 @@ use crate::ops::ControlFlow; #[doc(alias = "?")] #[lang = "Try"] #[const_trait] -pub trait Try: FromResidual { +pub trait Try: ~const FromResidual { /// The type of the value produced by `?` when *not* short-circuiting. #[unstable(feature = "try_trait_v2", issue = "84277")] type Output; @@ -438,10 +438,11 @@ where /// and in the other direction, /// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] +#[const_trait] pub trait Residual<O> { /// The "return" type of this meta-function. #[unstable(feature = "try_trait_v2_residual", issue = "91285")] - type TryType: Try<Output = O, Residual = Self>; + type TryType: ~const Try<Output = O, Residual = Self>; } #[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] @@ -460,14 +461,17 @@ pub(crate) struct NeverShortCircuit<T>(pub T); impl<T> NeverShortCircuit<T> { /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. #[inline] - pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { - move |a, b| NeverShortCircuit(f(a, b)) + pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>( + f: &mut F, + (a, b): (A, B), + ) -> NeverShortCircuit<T> { + NeverShortCircuit(f(a, b)) } } pub(crate) enum NeverShortCircuitResidual {} -impl<T> Try for NeverShortCircuit<T> { +impl<T> const Try for NeverShortCircuit<T> { type Output = T; type Residual = NeverShortCircuitResidual; @@ -482,14 +486,14 @@ impl<T> Try for NeverShortCircuit<T> { } } -impl<T> FromResidual for NeverShortCircuit<T> { +impl<T> const FromResidual for NeverShortCircuit<T> { #[inline] fn from_residual(never: NeverShortCircuitResidual) -> Self { match never {} } } -impl<T> Residual<T> for NeverShortCircuitResidual { +impl<T> const Residual<T> for NeverShortCircuitResidual { type TryType = NeverShortCircuit<T>; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 93417586363..ed7703befcf 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -842,6 +842,7 @@ impl<T> Option<T> { /// ``` /// let good_year_from_input = "1909"; /// let bad_year_from_input = "190blarg"; + /// // Result::ok() converts a Result<T> to an Option<T> /// let good_year = good_year_from_input.parse().ok().unwrap_or_default(); /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); /// @@ -2321,7 +2322,8 @@ impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -impl<T> ops::Residual<T> for Option<convert::Infallible> { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl<T> const ops::Residual<T> for Option<convert::Infallible> { type TryType = Option<T>; } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 76eaa191f78..dc90e90402c 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -2116,6 +2116,7 @@ impl<T, E, F: From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> { } #[unstable(feature = "try_trait_v2_residual", issue = "91285")] -impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl<T, E> const ops::Residual<T> for Result<convert::Infallible, E> { type TryType = Result<T, E>; } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 395c5678451..ad39ce38319 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -9,7 +9,7 @@ use crate::fmt; use crate::intrinsics::{assume, exact_div, unchecked_sub}; use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::marker::{PhantomData, Send, Sized, Sync}; -use crate::mem; +use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZeroUsize; use crate::ptr::NonNull; @@ -91,11 +91,8 @@ impl<'a, T> Iter<'a, T> { unsafe { assume(!ptr.is_null()); - let end = if mem::size_of::<T>() == 0 { - ptr.wrapping_byte_add(slice.len()) - } else { - ptr.add(slice.len()) - }; + let end = + if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) }; Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData } } @@ -227,11 +224,8 @@ impl<'a, T> IterMut<'a, T> { unsafe { assume(!ptr.is_null()); - let end = if mem::size_of::<T>() == 0 { - ptr.wrapping_byte_add(slice.len()) - } else { - ptr.add(slice.len()) - }; + let end = + if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) }; Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData } } diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index 6c9e7574e17..ce51d48e3e5 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -100,7 +100,7 @@ macro_rules! iterator { // Unsafe because the offset must not exceed `self.len()`. #[inline(always)] unsafe fn pre_dec_end(&mut self, offset: usize) -> * $raw_mut T { - if mem::size_of::<T>() == 0 { + if T::IS_ZST { zst_shrink!(self, offset); self.ptr.as_ptr() } else { @@ -140,7 +140,7 @@ macro_rules! iterator { // since we check if the iterator is empty first. unsafe { assume(!self.ptr.as_ptr().is_null()); - if mem::size_of::<T>() != 0 { + if !<T>::IS_ZST { assume(!self.end.is_null()); } if is_empty!(self) { @@ -166,7 +166,7 @@ macro_rules! iterator { fn nth(&mut self, n: usize) -> Option<$elem> { if n >= len!(self) { // This iterator is now empty. - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // We have to do it this way as `ptr` may never be 0, but `end` // could be (due to wrapping). self.end = self.ptr.as_ptr(); @@ -355,7 +355,7 @@ macro_rules! iterator { // empty first. unsafe { assume(!self.ptr.as_ptr().is_null()); - if mem::size_of::<T>() != 0 { + if !<T>::IS_ZST { assume(!self.end.is_null()); } if is_empty!(self) { diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 7de1f48e6c9..c848c2e18e9 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -141,8 +141,8 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> { // SAFETY: offset starts at len - suffix.len(), as long as it is greater than // min_aligned_offset (prefix.len()) the remaining distance is at least 2 * chunk_bytes. unsafe { - let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk); - let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk); + let u = *(ptr.add(offset - 2 * chunk_bytes) as *const Chunk); + let v = *(ptr.add(offset - chunk_bytes) as *const Chunk); // Break if there is a matching byte. let zu = contains_zero_byte(u ^ repeated_x); diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ff601137ff6..cd04fa00442 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -9,7 +9,7 @@ use crate::cmp::Ordering::{self, Greater, Less}; use crate::intrinsics::{assert_unsafe_precondition, exact_div}; use crate::marker::Copy; -use crate::mem; +use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZeroUsize; use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds}; use crate::option::Option; @@ -1580,7 +1580,8 @@ impl<T> [T] { #[inline] #[track_caller] #[must_use] - pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] + pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which // fulfills the requirements of `from_raw_parts_mut`. @@ -1679,9 +1680,10 @@ impl<T> [T] { /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] + #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] #[inline] #[must_use] - pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { + pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { let len = self.len(); let ptr = self.as_mut_ptr(); @@ -2643,9 +2645,10 @@ impl<T> [T] { /// less than or equal to any value at a position `j > index`. Additionally, this reordering is /// unstable (i.e. any number of equal elements may end up at position `index`), in-place /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth - /// element" in other libraries. It returns a triplet of the following values: all elements less - /// than the one at the given index, the value at the given index, and all elements greater than - /// the one at the given index. + /// element" in other libraries. It returns a triplet of the following from the reordered slice: + /// the subslice prior to `index`, the element at `index`, and the subslice after `index`; + /// accordingly, the values in those two subslices will respectively all be less-than-or-equal-to + /// and greater-than-or-equal-to the value of the element at `index`. /// /// # Current implementation /// @@ -2689,10 +2692,11 @@ impl<T> [T] { /// less than or equal to any value at a position `j > index` using the comparator function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function - /// is also known as "kth element" in other libraries. It returns a triplet of the following - /// values: all elements less than the one at the given index, the value at the given index, - /// and all elements greater than the one at the given index, using the provided comparator - /// function. + /// is also known as "kth element" in other libraries. It returns a triplet of the following from + /// the slice reordered according to the provided comparator function: the subslice prior to + /// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in + /// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to + /// the value of the element at `index`. /// /// # Current implementation /// @@ -2740,10 +2744,11 @@ impl<T> [T] { /// less than or equal to any value at a position `j > index` using the key extraction function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function - /// is also known as "kth element" in other libraries. It returns a triplet of the following - /// values: all elements less than the one at the given index, the value at the given index, and - /// all elements greater than the one at the given index, using the provided key extraction - /// function. + /// is also known as "kth element" in other libraries. It returns a triplet of the following from + /// the slice reordered according to the provided key extraction function: the subslice prior to + /// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in + /// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to + /// the value of the element at `index`. /// /// # Current implementation /// @@ -3456,7 +3461,7 @@ impl<T> [T] { #[must_use] pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) { // Note that most of this function will be constant-evaluated, - if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 { + if U::IS_ZST || T::IS_ZST { // handle ZSTs specially, which is – don't handle them at all. return (self, &[], &[]); } @@ -3517,7 +3522,7 @@ impl<T> [T] { #[must_use] pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) { // Note that most of this function will be constant-evaluated, - if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 { + if U::IS_ZST || T::IS_ZST { // handle ZSTs specially, which is – don't handle them at all. return (self, &mut [], &mut []); } @@ -4063,7 +4068,7 @@ impl<T, const N: usize> [[T; N]] { /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] pub fn flatten(&self) -> &[T] { - let len = if crate::mem::size_of::<T>() == 0 { + let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { // SAFETY: `self.len() * N` cannot overflow because `self` is @@ -4101,7 +4106,7 @@ impl<T, const N: usize> [[T; N]] { /// ``` #[unstable(feature = "slice_flatten", issue = "95629")] pub fn flatten_mut(&mut self) -> &mut [T] { - let len = if crate::mem::size_of::<T>() == 0 { + let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") } else { // SAFETY: `self.len() * N` cannot overflow because `self` is diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index 4589c6c0f04..fa8c238f8e7 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -1,5 +1,5 @@ use crate::cmp; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::ptr; /// Rotates the range `[mid-left, mid+right)` such that the element at `mid` becomes the first @@ -63,7 +63,7 @@ use crate::ptr; /// when `left < right` the swapping happens from the left instead. pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) { type BufType = [usize; 32]; - if mem::size_of::<T>() == 0 { + if T::IS_ZST { return; } loop { diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index c6c03c0b0db..87f77b7f21d 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -7,7 +7,7 @@ //! stable sorting implementation. use crate::cmp; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, MaybeUninit, SizedTypeProperties}; use crate::ptr; /// When dropped, copies from `src` into `dest`. @@ -813,7 +813,7 @@ where F: FnMut(&T, &T) -> bool, { // Sorting has no meaningful behavior on zero-sized types. - if mem::size_of::<T>() == 0 { + if T::IS_ZST { return; } @@ -898,7 +898,7 @@ where panic!("partition_at_index index {} greater than length of slice {}", index, v.len()); } - if mem::size_of::<T>() == 0 { + if T::IS_ZST { // Sorting has no meaningful behavior on zero-sized types. Do nothing. } else if index == v.len() - 1 { // Find max element and place it in the last position of the array. We're free to use diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index a7519ab5ab6..c65c275000c 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -100,6 +100,7 @@ impl<T: Sized> Exclusive<T> { /// Wrap a value in an `Exclusive` #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn new(t: T) -> Self { Self { inner: t } } @@ -107,6 +108,7 @@ impl<T: Sized> Exclusive<T> { /// Unwrap the value contained in the `Exclusive` #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn into_inner(self) -> T { self.inner } @@ -116,6 +118,7 @@ impl<T: ?Sized> Exclusive<T> { /// Get exclusive access to the underlying value. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn get_mut(&mut self) -> &mut T { &mut self.inner } @@ -128,6 +131,7 @@ impl<T: ?Sized> Exclusive<T> { /// produce _pinned_ access to the underlying value. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned // `Pin::map_unchecked_mut` is not const, so we do this conversion manually @@ -139,6 +143,7 @@ impl<T: ?Sized> Exclusive<T> { /// building an `Exclusive` with [`Exclusive::new`]. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> { // SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic unsafe { &mut *(r as *mut T as *mut Exclusive<T>) } @@ -149,6 +154,7 @@ impl<T: ?Sized> Exclusive<T> { /// building an `Exclusive` with [`Exclusive::new`]. #[unstable(feature = "exclusive_wrapper", issue = "98407")] #[must_use] + #[inline] pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> { // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned // `Pin::map_unchecked_mut` is not const, so we do this conversion manually @@ -158,6 +164,7 @@ impl<T: ?Sized> Exclusive<T> { #[unstable(feature = "exclusive_wrapper", issue = "98407")] impl<T> From<T> for Exclusive<T> { + #[inline] fn from(t: T) -> Self { Self::new(t) } @@ -166,7 +173,7 @@ impl<T> From<T> for Exclusive<T> { #[unstable(feature = "exclusive_wrapper", issue = "98407")] impl<T: Future + ?Sized> Future for Exclusive<T> { type Output = T::Output; - + #[inline] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { self.get_pin_mut().poll(cx) } diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index aa8a2425bf4..fc91fe468cc 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -93,7 +93,8 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] - impl<$($T:Default),+> Default for ($($T,)+) { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl<$($T: ~const Default),+> const Default for ($($T,)+) { #[inline] fn default() -> ($($T,)+) { ($({ let x: $T = Default::default(); x},)+) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 38dcf6cbf7d..4b07b393a2f 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -300,7 +300,7 @@ pub mod panic_count { thread_local! { static LOCAL_PANIC_COUNT: Cell<usize> = const { Cell::new(0) } } // Sum of panic counts from all threads. The purpose of this is to have - // a fast path in `is_zero` (which is used by `panicking`). In any particular + // a fast path in `count_is_zero` (which is used by `panicking`). In any particular // thread, if that thread currently views `GLOBAL_PANIC_COUNT` as being zero, // then `LOCAL_PANIC_COUNT` in that thread is zero. This invariant holds before // and after increase and decrease, but not necessarily during their execution. @@ -369,7 +369,7 @@ pub mod panic_count { } // Slow path is in a separate function to reduce the amount of code - // inlined from `is_zero`. + // inlined from `count_is_zero`. #[inline(never)] #[cold] fn is_zero_slow_path() -> bool { diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 5409bd1777c..0d934318c22 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -316,9 +316,9 @@ where // | small1 | Chunk smaller than 8 bytes // +--------+ fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) { - let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 }; - let small1_size = (len - small0_size as usize) % 8; - let big_size = len - small0_size as usize - small1_size as usize; + let small0_size = if ptr.is_aligned_to(8) { 0 } else { 8 - ptr.addr() % 8 }; + let small1_size = (len - small0_size) % 8; + let big_size = len - small0_size - small1_size; (small0_size, big_size, small1_size) } @@ -364,8 +364,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) mfence lfence ", - val = in(reg_byte) *src.offset(off as isize), - dst = in(reg) dst.offset(off as isize), + val = in(reg_byte) *src.add(off), + dst = in(reg) dst.add(off), seg_sel = in(reg) &mut seg_sel, options(nostack, att_syntax) ); @@ -378,8 +378,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) assert!(is_enclave_range(src, len)); assert!(is_user_range(dst, len)); assert!(len < isize::MAX as usize); - assert!(!(src as usize).overflowing_add(len).1); - assert!(!(dst as usize).overflowing_add(len).1); + assert!(!src.addr().overflowing_add(len).1); + assert!(!dst.addr().overflowing_add(len).1); if len < 8 { // Can't align on 8 byte boundary: copy safely byte per byte @@ -404,17 +404,17 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) unsafe { // Copy small0 - copy_bytewise_to_userspace(src, dst, small0_size as _); + copy_bytewise_to_userspace(src, dst, small0_size); // Copy big - let big_src = src.offset(small0_size as _); - let big_dst = dst.offset(small0_size as _); - copy_quadwords(big_src as _, big_dst, big_size); + let big_src = src.add(small0_size); + let big_dst = dst.add(small0_size); + copy_quadwords(big_src, big_dst, big_size); // Copy small1 - let small1_src = src.offset(big_size as isize + small0_size as isize); - let small1_dst = dst.offset(big_size as isize + small0_size as isize); - copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _); + let small1_src = src.add(big_size + small0_size); + let small1_dst = dst.add(big_size + small0_size); + copy_bytewise_to_userspace(small1_src, small1_dst, small1_size); } } } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 3c3770708b1..7c70ddbd9b9 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -125,7 +125,9 @@ pub fn error_string(errno: i32) -> String { } let p = p as *const _; - str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() + // We can't always expect a UTF-8 environment. When we don't get that luxury, + // it's better to give a low-quality error message than none at all. + String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into() } } diff --git a/library/std/src/sys/unsupported/locks/condvar.rs b/library/std/src/sys/unsupported/locks/condvar.rs index e703fd0d269..527a26a12bc 100644 --- a/library/std/src/sys/unsupported/locks/condvar.rs +++ b/library/std/src/sys/unsupported/locks/condvar.rs @@ -7,6 +7,7 @@ pub type MovableCondvar = Condvar; impl Condvar { #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Condvar { Condvar {} } diff --git a/library/std/src/sys/unsupported/locks/mutex.rs b/library/std/src/sys/unsupported/locks/mutex.rs index 2be0b34b985..87ea475c6e3 100644 --- a/library/std/src/sys/unsupported/locks/mutex.rs +++ b/library/std/src/sys/unsupported/locks/mutex.rs @@ -12,6 +12,7 @@ unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Mutex { Mutex { locked: Cell::new(false) } } diff --git a/library/std/src/sys/unsupported/locks/rwlock.rs b/library/std/src/sys/unsupported/locks/rwlock.rs index aca5fb7152c..5292691b955 100644 --- a/library/std/src/sys/unsupported/locks/rwlock.rs +++ b/library/std/src/sys/unsupported/locks/rwlock.rs @@ -12,6 +12,7 @@ unsafe impl Sync for RwLock {} // no threads on this platform impl RwLock { #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> RwLock { RwLock { mode: Cell::new(0) } } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 89d0ab59be8..c61a7e7d1e4 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -279,7 +279,6 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _; pub const STATUS_PENDING: NTSTATUS = 0x103 as _; pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; -pub const STATUS_NOT_SUPPORTED: NTSTATUS = 0xC00000BB_u32 as _; // Equivalent to the `NT_SUCCESS` C preprocessor macro. // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values @@ -289,6 +288,7 @@ pub fn nt_success(status: NTSTATUS) -> bool { // "RNG\0" pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0]; +pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; #[repr(C)] pub struct UNICODE_STRING { @@ -817,10 +817,6 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link(name = "advapi32")] extern "system" { - // Forbidden when targeting UWP - #[link_name = "SystemFunction036"] - pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; - // Allowed but unused by UWP pub fn OpenProcessToken( ProcessHandle: HANDLE, diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs index d6cd8f80271..b5a49489d3f 100644 --- a/library/std/src/sys/windows/rand.rs +++ b/library/std/src/sys/windows/rand.rs @@ -13,15 +13,12 @@ //! but significant number of users to experience panics caused by a failure of //! this function. See [#94098]. //! -//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE` -//! [Pseudo-handle], which gets the default RNG algorithm without querying the -//! system preference thus hopefully avoiding the previous issue. -//! This is only supported on Windows 10+ so a fallback is used for older versions. +//! The current version falls back to using `BCryptOpenAlgorithmProvider` if +//! `BCRYPT_USE_SYSTEM_PREFERRED_RNG` fails for any reason. //! //! [#94098]: https://github.com/rust-lang/rust/issues/94098 //! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom //! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom -//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles use crate::mem; use crate::ptr; use crate::sys::c; @@ -33,37 +30,35 @@ use crate::sys::c; /// [`HashMap`]: crate::collections::HashMap /// [`RandomState`]: crate::collections::hash_map::RandomState pub fn hashmap_random_keys() -> (u64, u64) { - Rng::open().and_then(|rng| rng.gen_random_keys()).unwrap_or_else(fallback_rng) + Rng::SYSTEM.gen_random_keys().unwrap_or_else(fallback_rng) } -struct Rng(c::BCRYPT_ALG_HANDLE); +struct Rng { + algorithm: c::BCRYPT_ALG_HANDLE, + flags: u32, +} impl Rng { - #[cfg(miri)] - fn open() -> Result<Self, c::NTSTATUS> { - const BCRYPT_RNG_ALG_HANDLE: c::BCRYPT_ALG_HANDLE = ptr::invalid_mut(0x81); - let _ = ( - c::BCryptOpenAlgorithmProvider, - c::BCryptCloseAlgorithmProvider, - c::BCRYPT_RNG_ALGORITHM, - c::STATUS_NOT_SUPPORTED, - ); - Ok(Self(BCRYPT_RNG_ALG_HANDLE)) + const SYSTEM: Self = unsafe { Self::new(ptr::null_mut(), c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) }; + + /// Create the RNG from an existing algorithm handle. + /// + /// # Safety + /// + /// The handle must either be null or a valid algorithm handle. + const unsafe fn new(algorithm: c::BCRYPT_ALG_HANDLE, flags: u32) -> Self { + Self { algorithm, flags } } - #[cfg(not(miri))] - // Open a handle to the RNG algorithm. + + /// Open a handle to the RNG algorithm. fn open() -> Result<Self, c::NTSTATUS> { use crate::sync::atomic::AtomicPtr; use crate::sync::atomic::Ordering::{Acquire, Release}; - const ERROR_VALUE: c::LPVOID = ptr::invalid_mut(usize::MAX); // An atomic is used so we don't need to reopen the handle every time. static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(ptr::null_mut()); let mut handle = HANDLE.load(Acquire); - // We use a sentinel value to designate an error occurred last time. - if handle == ERROR_VALUE { - Err(c::STATUS_NOT_SUPPORTED) - } else if handle.is_null() { + if handle.is_null() { let status = unsafe { c::BCryptOpenAlgorithmProvider( &mut handle, @@ -80,13 +75,12 @@ impl Rng { unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) }; handle = previous_handle; } - Ok(Self(handle)) + Ok(unsafe { Self::new(handle, 0) }) } else { - HANDLE.store(ERROR_VALUE, Release); Err(status) } } else { - Ok(Self(handle)) + Ok(unsafe { Self::new(handle, 0) }) } } @@ -94,33 +88,19 @@ impl Rng { let mut v = (0, 0); let status = unsafe { let size = mem::size_of_val(&v).try_into().unwrap(); - c::BCryptGenRandom(self.0, ptr::addr_of_mut!(v).cast(), size, 0) + c::BCryptGenRandom(self.algorithm, ptr::addr_of_mut!(v).cast(), size, self.flags) }; if c::nt_success(status) { Ok(v) } else { Err(status) } } } -/// Generate random numbers using the fallback RNG function (RtlGenRandom) -#[cfg(not(target_vendor = "uwp"))] +/// Generate random numbers using the fallback RNG function #[inline(never)] fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) { - let mut v = (0, 0); - let ret = - unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) }; - - if ret != 0 { - v - } else { - panic!( - "RNG broken: {rng_status:#x}, fallback RNG broken: {}", - crate::io::Error::last_os_error() - ) + match Rng::open().and_then(|rng| rng.gen_random_keys()) { + Ok(keys) => keys, + Err(status) => { + panic!("RNG broken: {rng_status:#x}, fallback RNG broken: {status:#x}") + } } } - -/// We can't use RtlGenRandom with UWP, so there is no fallback -#[cfg(target_vendor = "uwp")] -#[inline(never)] -fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) { - panic!("RNG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP"); -} diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs index f3ac1061b89..8bc5b24115d 100644 --- a/library/std/src/sys_common/condvar.rs +++ b/library/std/src/sys_common/condvar.rs @@ -15,6 +15,7 @@ pub struct Condvar { impl Condvar { /// Creates a new condition variable for use. #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() } } diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs index ce8f3670487..4ac9e62bf86 100644 --- a/library/std/src/sys_common/condvar/check.rs +++ b/library/std/src/sys_common/condvar/check.rs @@ -50,6 +50,7 @@ pub struct NoCheck; #[allow(dead_code)] impl NoCheck { + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self } diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs index 48479f5bdb3..7b9f7ef5487 100644 --- a/library/std/src/sys_common/mutex.rs +++ b/library/std/src/sys_common/mutex.rs @@ -61,6 +61,7 @@ unsafe impl Sync for MovableMutex {} impl MovableMutex { /// Creates a new mutex. #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self(imp::MovableMutex::new()) } diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs index 36d721fcbcb..042981dac60 100644 --- a/library/std/src/sys_common/rwlock.rs +++ b/library/std/src/sys_common/rwlock.rs @@ -15,6 +15,7 @@ pub struct MovableRwLock(imp::MovableRwLock); impl MovableRwLock { /// Creates a new reader-writer lock for use. #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] pub const fn new() -> Self { Self(imp::MovableRwLock::new()) } diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs index ab34d5c1e55..cd1f418028c 100644 --- a/src/bootstrap/build.rs +++ b/src/bootstrap/build.rs @@ -1,43 +1,7 @@ -use env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use std::env; -use std::ffi::OsString; -use std::path::PathBuf; - -/// Given an executable called `name`, return the filename for the -/// executable for a particular target. -pub fn exe(name: &PathBuf) -> PathBuf { - if EXE_EXTENSION != "" && name.extension() != Some(EXE_EXTENSION.as_ref()) { - let mut name: OsString = name.clone().into(); - name.push(EXE_SUFFIX); - name.into() - } else { - name.clone() - } -} fn main() { let host = env::var("HOST").unwrap(); println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-env-changed=RUSTC"); println!("cargo:rustc-env=BUILD_TRIPLE={}", host); - - // This may not be a canonicalized path. - let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap()); - - if rustc.is_relative() { - println!("cargo:rerun-if-env-changed=PATH"); - for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { - let absolute = dir.join(&exe(&rustc)); - if absolute.exists() { - rustc = absolute; - break; - } - } - } - assert!(rustc.is_absolute()); - - // FIXME: if the path is not utf-8, this is going to break. Unfortunately - // Cargo doesn't have a way for us to specify non-utf-8 paths easily, so - // we'll need to invent some encoding scheme if this becomes a problem. - println!("cargo:rustc-env=RUSTC={}", rustc.to_str().unwrap()); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bc6283ef467..415774d7255 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -724,6 +724,7 @@ impl<'a> Builder<'a> { dist::Miri, dist::LlvmTools, dist::RustDev, + dist::Bootstrap, dist::Extended, // It seems that PlainSourceTarball somehow changes how some of the tools // perceive their dependencies (see #93033) which would invalidate fingerprints @@ -1556,13 +1557,12 @@ impl<'a> Builder<'a> { match mode { Mode::ToolBootstrap => { // Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally. - // HACK: because anyhow does feature detection in build.rs, we need to allow the backtrace feature too. - rustflags.arg("-Zallow-features=binary-dep-depinfo,backtrace"); + rustflags.arg("-Zallow-features=binary-dep-depinfo"); } Mode::ToolStd => { // Right now this is just compiletest and a few other tools that build on stable. // Allow them to use `feature(test)`, but nothing else. - rustflags.arg("-Zallow-features=binary-dep-depinfo,test,backtrace,proc_macro_internals,proc_macro_diagnostic,proc_macro_span"); + rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span"); } Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {} } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 7c062460c4f..74530dec97b 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -772,21 +772,20 @@ impl Config { // set by build.rs config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); // Undo `src/bootstrap` config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned(); config.out = PathBuf::from("build"); - config.initial_cargo = PathBuf::from(env!("CARGO")); - config.initial_rustc = PathBuf::from(env!("RUSTC")); - config } pub fn parse(args: &[String]) -> Config { let flags = Flags::parse(&args); - let mut config = Config::default_opts(); + + // Set flags. config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect(); config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; @@ -805,7 +804,49 @@ impl Config { config.llvm_profile_use = flags.llvm_profile_use; config.llvm_profile_generate = flags.llvm_profile_generate; + // Infer the rest of the configuration. + + // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, + // running on a completely machine from where it was compiled. + let mut cmd = Command::new("git"); + // NOTE: we cannot support running from outside the repository because the only path we have available + // is set at compile time, which can be wrong if bootstrap was downloaded from source. + // We still support running outside the repository if we find we aren't in a git directory. + cmd.arg("rev-parse").arg("--show-toplevel"); + // Discard stderr because we expect this to fail when building from a tarball. + let output = cmd + .stderr(std::process::Stdio::null()) + .output() + .ok() + .and_then(|output| if output.status.success() { Some(output) } else { None }); + if let Some(output) = output { + let git_root = String::from_utf8(output.stdout).unwrap(); + // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes. + let git_root = PathBuf::from(git_root.trim()).canonicalize().unwrap(); + let s = git_root.to_str().unwrap(); + + // Bootstrap is quite bad at handling /? in front of paths + config.src = match s.strip_prefix("\\\\?\\") { + Some(p) => PathBuf::from(p), + None => PathBuf::from(git_root), + }; + } else { + // We're building from a tarball, not git sources. + // We don't support pre-downloaded bootstrap in this case. + } + + if cfg!(test) { + // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly. + config.out = Path::new( + &env::var_os("CARGO_TARGET_DIR").expect("cargo test directly is not supported"), + ) + .parent() + .unwrap() + .to_path_buf(); + } + let stage0_json = t!(std::fs::read(&config.src.join("src").join("stage0.json"))); + config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json)); #[cfg(test)] @@ -861,7 +902,6 @@ impl Config { let build = toml.build.unwrap_or_default(); - set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from))); // NOTE: Bootstrap spawns various commands with different working directories. // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. @@ -870,6 +910,16 @@ impl Config { config.out = crate::util::absolute(&config.out); } + config.initial_rustc = build + .rustc + .map(PathBuf::from) + .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc")); + config.initial_cargo = build + .cargo + .map(PathBuf::from) + .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/cargo")); + + // NOTE: it's important this comes *after* we set `initial_rustc` just above. if config.dry_run { let dir = config.out.join("tmp-dry-run"); t!(fs::create_dir_all(&dir)); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b7bc96cc86d..f387496883b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1424,7 +1424,7 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); - for tool in &["rust-demangler", "rust-analyzer", "rustfmt"] { + for tool in &["rust-demangler"] { if !built_tools.contains(tool) { contents = filter(&contents, tool); } @@ -1465,7 +1465,8 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("miri"); - for tool in &["rust-docs", "rust-demangler", "rust-analyzer"] { + prepare("rust-analyzer"); + for tool in &["rust-docs", "rust-demangler"] { if built_tools.contains(tool) { prepare(tool); } @@ -1525,7 +1526,8 @@ impl Step for Extended { prepare("rust-std"); prepare("clippy"); prepare("miri"); - for tool in &["rust-demangler", "rust-analyzer"] { + prepare("rust-analyzer"); + for tool in &["rust-demangler"] { if built_tools.contains(tool) { prepare(tool); } @@ -1609,25 +1611,23 @@ impl Step for Extended { .arg("-out") .arg(exe.join("StdGroup.wxs")), ); - if built_tools.contains("rust-analyzer") { - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-analyzer") - .args(&heat_flags) - .arg("-cg") - .arg("RustAnalyzerGroup") - .arg("-dr") - .arg("RustAnalyzer") - .arg("-var") - .arg("var.RustAnalyzerDir") - .arg("-out") - .arg(exe.join("RustAnalyzerGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")), - ); - } + builder.run( + Command::new(&heat) + .current_dir(&exe) + .arg("dir") + .arg("rust-analyzer") + .args(&heat_flags) + .arg("-cg") + .arg("RustAnalyzerGroup") + .arg("-dr") + .arg("RustAnalyzer") + .arg("-var") + .arg("var.RustAnalyzerDir") + .arg("-out") + .arg(exe.join("RustAnalyzerGroup.wxs")) + .arg("-t") + .arg(etc.join("msi/remove-duplicates.xsl")), + ); builder.run( Command::new(&heat) .current_dir(&exe) @@ -1879,7 +1879,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir let mut cmd = Command::new(llvm_config); cmd.arg("--libfiles"); builder.verbose(&format!("running {:?}", cmd)); - let files = output(&mut cmd); + let files = if builder.config.dry_run { "".into() } else { output(&mut cmd) }; let build_llvm_out = &builder.llvm_out(builder.config.build); let target_llvm_out = &builder.llvm_out(target); for file in files.trim_end().split(' ') { @@ -2026,6 +2026,7 @@ impl Step for RustDev { "llvm-dwp", "llvm-nm", "llvm-dwarfdump", + "llvm-dis", ] { tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); } @@ -2056,6 +2057,41 @@ impl Step for RustDev { } } +// Tarball intended for internal consumption to ease rustc/std development. +// +// Should not be considered stable by end users. +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Bootstrap { + pub target: TargetSelection, +} + +impl Step for Bootstrap { + type Output = Option<GeneratedTarball>; + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("bootstrap") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Bootstrap { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> { + let target = self.target; + + let tarball = Tarball::new(builder, "bootstrap", &target.triple); + + let bootstrap_outdir = &builder.bootstrap_out; + for file in &["bootstrap", "llvm-config-wrapper", "rustc", "rustdoc", "sccache-plus-cl"] { + tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755); + } + + Some(tarball.generate()) + } +} + /// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the /// release process to avoid cloning the monorepo and building stuff. /// diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 19504a51a58..2e11cf19c3f 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/96867 +Last change is for: https://github.com/rust-lang/rust/pull/97550 diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index b421ebc2d01..572adeb6420 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -458,19 +458,18 @@ impl Build { .expect("failed to read src/version"); let version = version.trim(); - let bootstrap_out = if std::env::var("BOOTSTRAP_PYTHON").is_ok() { - out.join("bootstrap").join("debug") - } else { - let workspace_target_dir = std::env::var("CARGO_TARGET_DIR") - .map(PathBuf::from) - .unwrap_or_else(|_| src.join("target")); - let bootstrap_out = workspace_target_dir.join("debug"); - if !bootstrap_out.join("rustc").exists() && !cfg!(test) { - // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented - panic!("run `cargo build --bins` before `cargo run`") - } - bootstrap_out - }; + let bootstrap_out = std::env::current_exe() + .expect("could not determine path to running process") + .parent() + .unwrap() + .to_path_buf(); + if !bootstrap_out.join(exe("rustc", config.build)).exists() && !cfg!(test) { + // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented + panic!( + "`rustc` not found in {}, run `cargo build --bins` before `cargo run`", + bootstrap_out.display() + ) + } let mut build = Build { initial_rustc: config.initial_rustc.clone(), diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 1617875ec23..01f4cacd771 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -520,7 +520,7 @@ impl Step for Miri { cargo.arg("--").arg("miri").arg("setup"); // Tell `cargo miri setup` where to find the sources. - cargo.env("XARGO_RUST_SRC", builder.src.join("library")); + cargo.env("MIRI_LIB_SRC", builder.src.join("library")); // Tell it where to find Miri. cargo.env("MIRI", &miri); // Debug things. diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 973c43072bf..b960239807a 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -82,7 +82,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ - build-manifest + build-manifest bootstrap ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang # This is the only builder which will create source tarballs diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 2774f8587f4..142464bf22b 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.10.0 \ No newline at end of file +0.11.0 \ No newline at end of file diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index f020c31079e..9f401779900 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -462,7 +462,7 @@ jobs: - name: dist-x86_64-apple env: - SCRIPT: ./x.py dist --host=x86_64-apple-darwin --target=x86_64-apple-darwin + SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -474,7 +474,7 @@ jobs: - name: dist-apple-various env: - SCRIPT: ./x.py dist --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim + SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -485,7 +485,7 @@ jobs: - name: dist-x86_64-apple-alt env: - SCRIPT: ./x.py dist + SCRIPT: ./x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.7 @@ -515,7 +515,7 @@ jobs: # This target only needs to support 11.0 and up as nothing else supports the hardware - name: dist-aarch64-apple env: - SCRIPT: ./x.py dist --stage 2 + SCRIPT: ./x.py dist bootstrap --include-default-paths --stage 2 RUST_CONFIGURE_ARGS: >- --build=x86_64-apple-darwin --host=aarch64-apple-darwin @@ -659,7 +659,7 @@ jobs: --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist + SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-xl @@ -671,7 +671,7 @@ jobs: --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-xl @@ -682,7 +682,7 @@ jobs: --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 # Hack around this SDK version, because it doesn't work with clang. # See https://github.com/rust-lang/rust/issues/88796 @@ -699,14 +699,14 @@ jobs: # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths CUSTOM_MINGW: 1 DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-xl - name: dist-x86_64-mingw env: - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-gnu --enable-full-tools @@ -722,7 +722,7 @@ jobs: - name: dist-x86_64-msvc-alt env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist + SCRIPT: python x.py dist bootstrap --include-default-paths <<: *job-windows-xl try: diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 4fbfd3a4cec..06883ddd58b 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -24,6 +24,7 @@ - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) + - [\*-android and \*-androideabi](platform-support/android.md) - [\*-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index f05ff3f1b6b..79cdfb82e41 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -270,6 +270,11 @@ This flag will set which lints should be set to the [warn level](lints/levels.md _Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information. +<a id="option-force-warn"></a> +## `--force-warn`: force a lint to warn + +This flag sets the given lint to the [forced warn level](lints/levels.md#force-warn) and the level cannot be overridden, even ignoring the [lint caps](lints/levels.md#capping-lints). + <a id="option-a-allow"></a> ## `-A`: set lint allowed @@ -381,6 +386,12 @@ are: - `always` — Always use colors. - `never` — Never colorize output. +<a id="option-diagnostic-width"></a> +## `--diagnostic-width`: specify the terminal width for diagnostics + +This flag takes a number that specifies the width of the terminal in characters. +Formatting of diagnostics will take the width into consideration to make them better fit on the screen. + <a id="option-remap-path-prefix"></a> ## `--remap-path-prefix`: remap source names in output diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 37b530dcb06..ea2792c218b 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -125,17 +125,17 @@ target | std | notes `aarch64-apple-ios` | ✓ | ARM64 iOS [`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64 `aarch64-fuchsia` | ✓ | ARM64 Fuchsia -`aarch64-linux-android` | ✓ | ARM64 Android +[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat -`arm-linux-androideabi` | ✓ | ARMv7 Android +[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat `armebv7r-none-eabi` | * | Bare ARMv7-R, Big Endian `armebv7r-none-eabihf` | * | Bare ARMv7-R, Big Endian, hardfloat `armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23) `armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL -`armv7-linux-androideabi` | ✓ | ARMv7a Android +[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7a Android `armv7-unknown-linux-gnueabi` | ✓ |ARMv7 Linux (kernel 4.15, glibc 2.27) `armv7-unknown-linux-musleabi` | ✓ |ARMv7 Linux with MUSL `armv7-unknown-linux-musleabihf` | ✓ | ARMv7 Linux with MUSL, hardfloat @@ -146,7 +146,7 @@ target | std | notes `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23) `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL -`i686-linux-android` | ✓ | 32-bit x86 Android +[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL @@ -165,7 +165,7 @@ target | std | notes `thumbv7em-none-eabi` | * | Bare Cortex-M4, M7 `thumbv7em-none-eabihf` | * | Bare Cortex-M4F, M7F, FPU, hardfloat `thumbv7m-none-eabi` | * | Bare Cortex-M3 -`thumbv7neon-linux-androideabi` | ✓ | Thumb2-mode ARMv7a Android with NEON +[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7a Android with NEON `thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23) `thumbv8m.base-none-eabi` | * | ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | ARMv8-M Mainline @@ -176,7 +176,7 @@ target | std | notes `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | 64-bit Fuchsia -`x86_64-linux-android` | ✓ | 64-bit x86 Android +[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md new file mode 100644 index 00000000000..b2c8e5d4df7 --- /dev/null +++ b/src/doc/rustc/src/platform-support/android.md @@ -0,0 +1,45 @@ +# *-linux-android and *-linux-androideabi + +**Tier: 2** + +[Android] is a mobile operating system built on top of the Linux kernel. + +[Android]: https://source.android.com/ + +## Target maintainers + +- Chris Wailes ([@chriswailes](https://github.com/chriswailes)) +- Matthew Maurer ([@maurer](https://github.com/maurer)) +- Martin Geisler ([@mgeisler](https://github.com/mgeisler)) + +## Requirements + +This target is cross-compiled from a host environment. Development may be done +from the [source tree] or using the Android NDK. + +[source tree]: https://source.android.com/docs/setup/build/downloading + +Android targets support std. Generated binaries use the ELF file format. + +## NDK/API Update Policy + +Rust will support the most recent Long Term Support (LTS) Android Native +Development Kit (NDK). By default Rust will support all API levels supported +by the NDK, but a higher minimum API level may be required if deemed necessary. + +## Building the target + +To build Rust binaries for Android you'll need a copy of the most recent LTS +edition of the [Android NDK]. Supported Android targets are: + +* aarch64-linux-android +* arm-linux-androideabi +* armv7-linux-androideabi +* i686-linux-android +* thumbv7neon-linux-androideabi +* x86_64-linux-android + +[Android NDK]: https://developer.android.com/ndk/downloads + +A list of all supported targets can be found +[here](https://doc.rust-lang.org/rustc/platform-support.html) diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md index 3ce18743be5..3e644f786f6 100644 --- a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md +++ b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md @@ -41,7 +41,7 @@ $ rustc -Zself-profile -Zself-profile-events=default,args - `llvm` - Adds tracing information about LLVM passes and codegeneration. - - Disabled by default because this only works when `-Znew-llvm-pass-manager` is enabled. + - Disabled by default because this significantly increases the trace file size. ## Event synonyms diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 375737e9bc4..bd68dffb823 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1080,7 +1080,7 @@ pub(crate) fn clean_impl_item<'tcx>( let mut what_rustc_thinks = Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx); - let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id)); + let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id.def_id)); // Trait impl items always inherit the impl's visibility -- // we don't want to show `pub`. @@ -1325,7 +1325,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type segments: trait_segments.iter().map(|x| clean_path_segment(x, cx)).collect(), }; register_res(cx, trait_.res); - let self_def_id = DefId::local(qself.hir_id.owner.local_def_index); + let self_def_id = DefId::local(qself.hir_id.owner.def_id.local_def_index); let self_type = clean_ty(qself, cx); let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type); Type::QPath(Box::new(QPathData { @@ -2037,7 +2037,7 @@ fn clean_extern_crate<'tcx>( cx: &mut DocContext<'tcx>, ) -> Vec<Item> { // this is the ID of the `extern crate` statement - let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE); + let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id.def_id).unwrap_or(LOCAL_CRATE); // this is the ID of the crate itself let crate_def_id = cnum.as_def_id(); let attrs = cx.tcx.hir().attrs(krate.hir_id()); @@ -2099,7 +2099,7 @@ fn clean_use_statement<'tcx>( let attrs = cx.tcx.hir().attrs(import.hir_id()); let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); let pub_underscore = visibility.is_public() && name == kw::Underscore; - let current_mod = cx.tcx.parent_module_from_def_id(import.def_id); + let current_mod = cx.tcx.parent_module_from_def_id(import.def_id.def_id); // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1c4e666cd94..75ac11a3a88 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1790,7 +1790,7 @@ pub(crate) fn render_impl_summary( write!(w, "<section id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases); render_rightside(w, cx, &i.impl_item, containing_item, RenderMode::Normal); write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); - write!(w, "<h3 class=\"code-header in-band\">"); + write!(w, "<h3 class=\"code-header\">"); if let Some(use_absolute) = use_absolute { write!(w, "{}", inner_impl.print(use_absolute, cx)); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e17165440d1..28dc4bf3010 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -176,8 +176,8 @@ h4.code-header { border-bottom-style: none; margin: 0; padding: 0; - margin-top: 0.6em; - margin-bottom: 0.4em; + margin-top: 0.6rem; + margin-bottom: 0.4rem; } .impl, .impl-items .method, @@ -411,7 +411,7 @@ img { .sidebar { font-size: 0.875rem; - width: 250px; + width: 200px; min-width: 200px; overflow-y: scroll; position: sticky; @@ -658,18 +658,17 @@ h2.location a { overflow-x: auto; } -.content .out-of-band { +.out-of-band { flex-grow: 0; font-size: 1.125rem; font-weight: normal; - float: right; } .method > .code-header, .trait-impl > .code-header { display: block; } -.content .in-band { +.in-band { flex-grow: 1; margin: 0px; padding: 0px; @@ -682,10 +681,6 @@ h2.location a { background-color: var(--main-background-color); } -.in-band > code, .in-band > .code-header { - display: inline-block; -} - .docblock code, .docblock-short code, pre, .rustdoc.source .example-wrap { background-color: var(--code-block-background-color); @@ -1130,10 +1125,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ font-size: 1rem; } -.summary { - padding-right: 0px; -} - pre.rust .question-mark { font-weight: bold; } @@ -1412,7 +1403,6 @@ pre.rust { } #source-sidebar { width: 100%; - z-index: 1; overflow: auto; } #source-sidebar > .title { @@ -1736,13 +1726,13 @@ in storage.js plus the media query with (min-width: 701px) flex-direction: column; } - .content .out-of-band { + .out-of-band { text-align: left; margin-left: initial; padding: initial; } - .content .out-of-band .since::before { + .out-of-band .since::before { content: "Since "; } @@ -1918,14 +1908,6 @@ in storage.js plus the media query with (min-width: 701px) border-bottom: 1px solid; } - #source-sidebar { - z-index: 11; - } - - #main-content > .line-numbers { - margin-top: 0; - } - .notable-traits .notable-traits-tooltiptext { left: 0; top: 100%; @@ -1982,7 +1964,7 @@ in storage.js plus the media query with (min-width: 701px) } @media print { - nav.sidebar, nav.sub, .content .out-of-band, a.srclink, #copy-path, + nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path, details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before, details.rustdoc-toggle.top-doc > summary { display: none; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 5fbe540c320..c9674f11a5e 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -555,7 +555,6 @@ function loadCss(cssFileName) { const code = document.createElement("h3"); code.innerHTML = struct[TEXT_IDX]; addClass(code, "code-header"); - addClass(code, "in-band"); onEachLazy(code.getElementsByTagName("a"), elem => { const href = elem.getAttribute("href"); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 14d695582b0..23ad0c30f21 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -461,7 +461,7 @@ fn opts() -> Vec<RustcOptGroup> { "human|json|short", ) }), - unstable("diagnostic-width", |o| { + stable("diagnostic-width", |o| { o.optopt( "", "diagnostic-width", diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 765f7c61bd3..de3a4b33905 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { let expected_parent = hir.get_parent_item(hir_id); // If parents are different, it means that `item` is a reexport and we need // to compute the actual `cfg` by iterating through its "real" parents. - if self.parent == Some(expected_parent) { + if self.parent == Some(expected_parent.def_id) { return; } } diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index ca86ac89e85..dfa6ba38b88 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -143,14 +143,14 @@ where // then we need to exit before calling typeck (which will panic). See // test/run-make/rustdoc-scrape-examples-invalid-expr for an example. let hir = tcx.hir(); - if hir.maybe_body_owned_by(ex.hir_id.owner).is_none() { + if hir.maybe_body_owned_by(ex.hir_id.owner.def_id).is_none() { return; } // Get type of function if expression is a function call let (ty, call_span, ident_span) = match ex.kind { hir::ExprKind::Call(f, _) => { - let types = tcx.typeck(ex.hir_id.owner); + let types = tcx.typeck(ex.hir_id.owner.def_id); if let Some(ty) = types.node_type_opt(f.hir_id) { (ty, ex.span, f.span) @@ -160,7 +160,7 @@ where } } hir::ExprKind::MethodCall(path, _, _, call_span) => { - let types = tcx.typeck(ex.hir_id.owner); + let types = tcx.typeck(ex.hir_id.owner.def_id); let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else { trace!("type_dependent_def_id({}) = None", ex.hir_id); return; @@ -183,9 +183,8 @@ where // If the enclosing item has a span coming from a proc macro, then we also don't want to include // the example. - let enclosing_item_span = tcx - .hir() - .span_with_body(tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(ex.hir_id))); + let enclosing_item_span = + tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into()); if enclosing_item_span.from_expansion() { trace!("Rejecting expr ({call_span:?}) from macro item: {enclosing_item_span:?}"); return; diff --git a/src/test/rustdoc-gui/check-stab-in-docblock.goml b/src/test/rustdoc-gui/check-stab-in-docblock.goml index 7f965ada594..afe25195100 100644 --- a/src/test/rustdoc-gui/check-stab-in-docblock.goml +++ b/src/test/rustdoc-gui/check-stab-in-docblock.goml @@ -7,15 +7,21 @@ size: (786, 600) // Confirms that there 3 paragraphs. assert-count: (".top-doc .docblock p", 3) // Checking that there is no scrollable content. +store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(1)", "clientHeight") +store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(1)", "clientWidth") assert-property: ( ".top-doc .docblock p:nth-of-type(1)", - {"scrollHeight": "120", "clientHeight": "120", "scrollWidth": "502", "clientWidth": "502"}, + {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|}, ) +store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(2)", "clientHeight") +store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(2)", "clientWidth") assert-property: ( ".top-doc .docblock p:nth-of-type(2)", - {"scrollHeight": "48", "clientHeight": "48", "scrollWidth": "502", "clientWidth": "502"}, + {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|}, ) +store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(3)", "clientHeight") +store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(3)", "clientWidth") assert-property: ( ".top-doc .docblock p:nth-of-type(3)", - {"scrollHeight": "48", "clientHeight": "48", "scrollWidth": "502", "clientWidth": "502"}, + {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|}, ) diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml index f93f3f0aefc..ee4dad444e9 100644 --- a/src/test/rustdoc-gui/code-blocks-overflow.goml +++ b/src/test/rustdoc-gui/code-blocks-overflow.goml @@ -5,4 +5,4 @@ size: (1080, 600) assert-count: (".docblock > .example-wrap", 2) assert: ".docblock > .example-wrap > .language-txt" assert: ".docblock > .example-wrap > .rust-example-rendered" -assert-css: (".docblock > .example-wrap > pre", {"width": "785.25px", "overflow-x": "auto"}, ALL) +assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL) diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml index 7f97cf220cc..ef0d37c902e 100644 --- a/src/test/rustdoc-gui/docblock-table-overflow.goml +++ b/src/test/rustdoc-gui/docblock-table-overflow.goml @@ -4,7 +4,7 @@ goto: file://|DOC_PATH|/lib2/long_table/struct.Foo.html size: (1100, 800) // Logically, the ".docblock" and the "<p>" should have the same scroll width. compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"]) -assert-property: (".top-doc .docblock", {"scrollWidth": "801"}) +assert-property: (".top-doc .docblock", {"scrollWidth": "816"}) // However, since there is overflow in the <table>, its scroll width is bigger. assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"}) @@ -16,6 +16,6 @@ compare-elements-property: ( "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "801"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "816"}) // However, since there is overflow in the <table>, its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index a47a9c8a14c..4f01f1a1624 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -19,7 +19,7 @@ assert-css: ( ) assert-css: ( ".impl .code-header", - {"color": "rgb(230, 225, 207)", "background-color": "rgb(15, 20, 25)"}, + {"color": "rgb(230, 225, 207)", "background-color": "rgba(0, 0, 0, 0)"}, ALL, ) @@ -58,7 +58,7 @@ assert-css: ( ) assert-css: ( ".impl .code-header", - {"color": "rgb(221, 221, 221)", "background-color": "rgb(53, 53, 53)"}, + {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ALL, ) @@ -95,7 +95,7 @@ assert-css: ( ) assert-css: ( ".impl .code-header", - {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, + {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ALL, ) diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index 666a6e1253d..2fcbee27147 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -8,23 +8,23 @@ assert-count: ("#implementors-list .impl", 2) assert: ("#implementors-list .impl:nth-child(1) > a.anchor") assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever-for-Struct"}) assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever-for-Struct"}) -assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band" +assert: "#implementors-list .impl:nth-child(1) > .code-header" assert: ("#implementors-list .impl:nth-child(2) > a.anchor") assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"}) assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"}) -assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band" +assert: "#implementors-list .impl:nth-child(2) > .code-header" goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html compare-elements-position-near-false: ( "#impl-EmptyTrait1-for-HasEmptyTraits", "#impl-EmptyTrait2-for-HasEmptyTraits", - {"y": 30}, + {"y": 34}, ) compare-elements-position-near: ( "#impl-EmptyTrait3-for-HasEmptyTraits h3", "#impl-EmptyTrait3-for-HasEmptyTraits .item-info", - {"y": 30}, + {"y": 34}, ) // Now check that re-exports work correctly. diff --git a/src/test/rustdoc-gui/item-info-overflow.goml b/src/test/rustdoc-gui/item-info-overflow.goml index 17478da4fea..bc3addd33dd 100644 --- a/src/test/rustdoc-gui/item-info-overflow.goml +++ b/src/test/rustdoc-gui/item-info-overflow.goml @@ -4,7 +4,7 @@ goto: file://|DOC_PATH|/lib2/struct.LongItemInfo.html size: (1200, 870) // Logically, the "item-decl" and the "item-info" should have the same scroll width. compare-elements-property: (".item-decl", ".item-info", ["scrollWidth"]) -assert-property: (".item-info", {"scrollWidth": "890"}) +assert-property: (".item-info", {"scrollWidth": "940"}) // Just to be sure we're comparing the correct "item-info": assert-text: ( ".item-info", @@ -21,7 +21,7 @@ compare-elements-property: ( ) assert-property: ( "#impl-SimpleTrait-for-LongItemInfo2 .item-info", - {"scrollWidth": "866"}, + {"scrollWidth": "916"}, ) // Just to be sure we're comparing the correct "item-info": assert-text: ( diff --git a/src/test/rustdoc-gui/item-info.goml b/src/test/rustdoc-gui/item-info.goml index 50c45b76bd6..8750d5c5360 100644 --- a/src/test/rustdoc-gui/item-info.goml +++ b/src/test/rustdoc-gui/item-info.goml @@ -4,9 +4,9 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html // We set a fixed size so there is no chance of "random" resize. size: (1100, 800) // We check that ".item-info" is bigger than its content. -assert-css: (".item-info", {"width": "790px"}) +assert-css: (".item-info", {"width": "840px"}) assert-css: (".item-info .stab", {"width": "289px"}) -assert-position: (".item-info .stab", {"x": 295}) +assert-position: (".item-info .stab", {"x": 245}) // Now we ensure that they're not rendered on the same line. goto: file://|DOC_PATH|/lib2/trait.Trait.html diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml index 7eb00d825a5..20a129f9d9d 100644 --- a/src/test/rustdoc-gui/notable-trait.goml +++ b/src/test/rustdoc-gui/notable-trait.goml @@ -18,11 +18,11 @@ compare-elements-position-false: ( // The `i` should be *after* the type. assert-position: ( "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", - {"x": 692}, + {"x": 677}, ) assert-position: ( "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']", - {"x": 966}, + {"x": 951}, ) diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index efbbfb925bd..e33693e27ea 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -7,7 +7,7 @@ press-key: 'Enter' wait-for: "#crate-search" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... -assert-css: (".search-results div.desc", {"width": "293px"}) +assert-css: (".search-results div.desc", {"width": "318px"}) size: (600, 100) // As counter-intuitive as it may seem, in this width, the width is "100%", which is why // when computed it's larger. diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 32fe3334f36..ea7bcc66994 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -1,5 +1,6 @@ // Checks multiple things on the sidebar display (width of its elements, colors, etc). goto: file://|DOC_PATH|/test_docs/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) show-text: true local-storage: {"rustdoc-theme": "light"} // We reload the page so the local storage settings are being used. @@ -39,11 +40,13 @@ assert-property: ("html", {"scrollTop": "0"}) // We now go back to the crate page to click on the "lib2" crate link. goto: file://|DOC_PATH|/test_docs/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-css: (".sidebar-elems .crate > ul > li:first-child > a", {"color": "rgb(53, 109, 164)"}) click: ".sidebar-elems .crate > ul > li:first-child > a" // PAGE: lib2/index.html goto: file://|DOC_PATH|/lib2/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .location", "Crate lib2") // We check that we have the crates list and that the "current" on is now "lib2". assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2") @@ -65,11 +68,13 @@ assert-text: (".sidebar .sidebar-elems .location", "In lib2") assert-false: ".sidebar-elems > .crate" goto: ./module/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .location", "Module module") // We check that we don't have the crate list. assert-false: ".sidebar-elems > .crate" goto: ./sub_module/sub_sub_module/index.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-text: (".sidebar > .location", "Module sub_sub_module") // We check that we don't have the crate list. assert-false: ".sidebar-elems .crate" @@ -78,11 +83,21 @@ assert-text: ("#functions + .item-table .item-left > a", "foo") // Links to trait implementations in the sidebar should not wrap even if they are long. goto: file://|DOC_PATH|/lib2/struct.HasALongTraitWithParams.html +assert-property: (".sidebar", {"clientWidth": "200"}) assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29}) // Test that clicking on of the "In <module>" headings in the sidebar links to the // appropriate anchor in index.html. goto: file://|DOC_PATH|/test_docs/struct.Foo.html +assert-property: (".sidebar", {"clientWidth": "200"}) click: ".block.mod h3 a" // PAGE: index.html assert-css: ("#modules", {"background-color": "rgb(253, 255, 211)"}) + +// Finally, assert that the `[+]/[−]` toggle doesn't affect sidebar width. +click: "#toggle-all-docs" +assert-text: ("#toggle-all-docs", "[+]") +assert-property: (".sidebar", {"clientWidth": "200"}) +click: "#toggle-all-docs" +assert-text: ("#toggle-all-docs", "[−]") +assert-property: (".sidebar", {"clientWidth": "200"}) \ No newline at end of file diff --git a/src/test/rustdoc-gui/src-font-size.goml b/src/test/rustdoc-gui/src-font-size.goml index 0c01e254554..9797f196c55 100644 --- a/src/test/rustdoc-gui/src-font-size.goml +++ b/src/test/rustdoc-gui/src-font-size.goml @@ -5,7 +5,7 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html show-text: true // Check the impl headers. assert-css: (".impl.has-srclink .srclink", {"font-size": "16px"}, ALL) -assert-css: (".impl.has-srclink .code-header.in-band", {"font-size": "18px"}, ALL) +assert-css: (".impl.has-srclink .code-header", {"font-size": "18px"}, ALL) // Check the impl items. assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL) assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL) diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index 9a46908f933..505874fa010 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -15,7 +15,7 @@ assert-property: (".item-table .struct", {"offsetWidth": "684"}) goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html assert-property: ("body", {"scrollWidth": "1100"}) // We now check that the section width hasn't grown because of it. -assert-property: ("#main-content", {"scrollWidth": "825"}) +assert-property: ("#main-content", {"scrollWidth": "840"}) // And now checking that it has scrollable content. assert-property: (".item-decl pre", {"scrollWidth": "1103"}) @@ -24,7 +24,7 @@ assert-property: (".item-decl pre", {"scrollWidth": "1103"}) goto: file://|DOC_PATH|/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html assert-property: ("body", {"scrollWidth": "1100"}) // We now check that the section width hasn't grown because of it. -assert-property: ("#main-content", {"scrollWidth": "825"}) +assert-property: ("#main-content", {"scrollWidth": "840"}) // And now checking that it has scrollable content. assert-property: (".item-decl pre", {"scrollWidth": "950"}) @@ -32,6 +32,6 @@ assert-property: (".item-decl pre", {"scrollWidth": "950"}) size: (600, 600) goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html // It shouldn't have an overflow in the topbar either. -assert-property: (".mobile-topbar .location", {"scrollWidth": "500"}) -assert-property: (".mobile-topbar .location", {"clientWidth": "500"}) +store-property: (scrollWidth, ".mobile-topbar .location", "scrollWidth") +assert-property: (".mobile-topbar .location", {"clientWidth": |scrollWidth|}) assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"}) diff --git a/src/test/rustdoc-ui/diagnostic-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs index 61961d5ec71..290d9db775b 100644 --- a/src/test/rustdoc-ui/diagnostic-width.rs +++ b/src/test/rustdoc-ui/diagnostic-width.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunstable-options --diagnostic-width=10 +// compile-flags: --diagnostic-width=10 #![deny(rustdoc::bare_urls)] /// This is a long line that contains a http://link.com diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 749abe36419..25d5c6e4ad2 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -82,7 +82,6 @@ -Z mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds) -Z move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted -Z mutable-noalias=val -- emit noalias metadata for mutable references (default: yes) - -Z new-llvm-pass-manager=val -- use new LLVM pass manager (default: no) -Z nll-facts=val -- dump facts from NLL analysis into side files (default: no) -Z nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`) -Z no-analysis=val -- parse and expand the source, but run no analysis diff --git a/src/test/rustdoc/anonymous-lifetime.rs b/src/test/rustdoc/anonymous-lifetime.rs index f5a7d225847..390ed5a1f93 100644 --- a/src/test/rustdoc/anonymous-lifetime.rs +++ b/src/test/rustdoc/anonymous-lifetime.rs @@ -12,7 +12,7 @@ pub trait Stream { } // @has 'foo/trait.Stream.html' -// @has - '//*[@class="code-header in-band"]' 'impl<S: ?Sized + Stream + Unpin> Stream for &mut S' +// @has - '//*[@class="code-header"]' 'impl<S: ?Sized + Stream + Unpin> Stream for &mut S' impl<S: ?Sized + Stream + Unpin> Stream for &mut S { type Item = S::Item; diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs index 97b7739b4c9..a3e10ee5555 100644 --- a/src/test/rustdoc/assoc-consts.rs +++ b/src/test/rustdoc/assoc-consts.rs @@ -13,7 +13,7 @@ pub trait Foo { pub struct Bar; impl Foo for Bar { - // @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Foo for Bar' + // @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Foo for Bar' // @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize' const FOO: usize = 12; // @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool' @@ -81,7 +81,7 @@ pub trait Qux { const QUX_DEFAULT2: u32 = 3; } -// @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Qux for Bar' +// @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Qux for Bar' impl Qux for Bar { // @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8' // @has - '//*[@class="docblock"]' "Docs for QUX0 in trait." diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs index 676d656dabf..437f0001fcf 100644 --- a/src/test/rustdoc/blanket-reexport-item.rs +++ b/src/test/rustdoc/blanket-reexport-item.rs @@ -1,6 +1,6 @@ #![crate_name = "foo"] -// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T' +// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header"]' 'impl<T, U> Into<U> for T' pub struct S2 {} mod m { pub struct S {} diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs index 59113952345..6cbae9abebb 100644 --- a/src/test/rustdoc/const-generics/add-impl.rs +++ b/src/test/rustdoc/const-generics/add-impl.rs @@ -7,7 +7,7 @@ pub struct Simd<T, const WIDTH: usize> { inner: T, } -// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>' +// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>' impl Add for Simd<u8, 16> { type Output = Self; diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs index 87d2f29e260..5bf76e3c469 100644 --- a/src/test/rustdoc/const-generics/const-generics-docs.rs +++ b/src/test/rustdoc/const-generics/const-generics-docs.rs @@ -19,10 +19,10 @@ pub use extern_crate::WTrait; // @has foo/trait.Trait.html '//pre[@class="rust trait"]' \ // 'pub trait Trait<const N: usize>' -// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1> for u8' -// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2> for u8' -// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8' -// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8' +// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8' +// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<{1 + 2}> for u8' +// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header"]' \ // 'impl<const N: usize> Trait<N> for [u8; N]' pub trait Trait<const N: usize> {} impl Trait<1> for u8 {} @@ -36,7 +36,7 @@ pub struct Foo<const N: usize> where u8: Trait<N>; // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)' pub struct Bar<T, const N: usize>([T; N]); -// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>' +// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>' impl<const M: usize> Foo<M> where u8: Trait<M> { // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' pub const FOO_ASSOC: usize = M + 13; @@ -47,7 +47,7 @@ impl<const M: usize> Foo<M> where u8: Trait<M> { } } -// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>' +// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Bar<u8, M>' impl<const M: usize> Bar<u8, M> { // @has - '//*[@id="method.hey"]' \ // 'pub fn hey<const N: usize>(&self) -> Foo<N>where u8: Trait<N>' diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index f1181d54ac8..75ee84279be 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -9,20 +9,20 @@ pub enum Order { } // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>' -// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>' -// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header in-band"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>' +// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>' +// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>' pub struct VSet<T, const ORDER: Order> { inner: Vec<T>, } -// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Sorted }>' +// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Sorted }>' impl<T> VSet<T, { Order::Sorted }> { pub fn new() -> Self { Self { inner: Vec::new() } } } -// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header in-band"]' 'impl<T> VSet<T, { Order::Unsorted }>' +// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Unsorted }>' impl<T> VSet<T, { Order::Unsorted }> { pub fn new() -> Self { Self { inner: Vec::new() } @@ -31,7 +31,7 @@ impl<T> VSet<T, { Order::Unsorted }> { pub struct Escape<const S: &'static str>; -// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header in-band"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>' +// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>' impl Escape<r#"<script>alert("Escape");</script>"#> { pub fn f() {} } diff --git a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs index 4eac8e31e45..310e89a35c4 100644 --- a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs +++ b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs @@ -12,7 +12,7 @@ pub struct Hasher<T> { unsafe impl<T: Default> Send for Hasher<T> {} // @has foo/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foo' +// @has - '//h3[@class="code-header"]' 'impl Send for Foo' pub struct Foo { hasher: Hasher<[u8; 3]>, } diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs index 84c9e4ac0cd..c1f95ac91c3 100644 --- a/src/test/rustdoc/duplicate_impls/issue-33054.rs +++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs @@ -1,12 +1,12 @@ // ignore-tidy-linelength // @has issue_33054/impls/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl Foo' -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' +// @has - '//h3[@class="code-header"]' 'impl Foo' +// @has - '//h3[@class="code-header"]' 'impl Bar for Foo' // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 // @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl has-srclink"]' 1 // @has issue_33054/impls/bar/trait.Bar.html -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo' +// @has - '//h3[@class="code-header"]' 'impl Bar for Foo' // @count - '//*[@class="struct"]' 1 pub mod impls; diff --git a/src/test/rustdoc/empty-impl-block.rs b/src/test/rustdoc/empty-impl-block.rs index 6a2a254f63a..95d4db06b31 100644 --- a/src/test/rustdoc/empty-impl-block.rs +++ b/src/test/rustdoc/empty-impl-block.rs @@ -16,5 +16,5 @@ pub struct Another; pub trait Bar {} // @has 'foo/struct.Another.html' -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Another' +// @has - '//h3[@class="code-header"]' 'impl Bar for Another' impl Bar for Another {} diff --git a/src/test/rustdoc/extern-impl.rs b/src/test/rustdoc/extern-impl.rs index f357d65df94..fd1bc214008 100644 --- a/src/test/rustdoc/extern-impl.rs +++ b/src/test/rustdoc/extern-impl.rs @@ -19,9 +19,9 @@ impl Foo { // @has foo/trait.Bar.html pub trait Bar {} -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for fn()' +// @has - '//h3[@class="code-header"]' 'impl Bar for fn()' impl Bar for fn() {} -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "C" fn()' +// @has - '//h3[@class="code-header"]' 'impl Bar for extern "C" fn()' impl Bar for extern fn() {} -// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "system" fn()' +// @has - '//h3[@class="code-header"]' 'impl Bar for extern "system" fn()' impl Bar for extern "system" fn() {} diff --git a/src/test/rustdoc/fn-bound.rs b/src/test/rustdoc/fn-bound.rs index 4c4ffddc8a6..9e060ff2026 100644 --- a/src/test/rustdoc/fn-bound.rs +++ b/src/test/rustdoc/fn-bound.rs @@ -11,7 +11,7 @@ pub struct ConditionalIterator<F> { } -// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header in-band"]' 'impl<F: Fn(&i32)> Iterator for ConditionalIterator<F>' +// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header"]' 'impl<F: Fn(&i32)> Iterator for ConditionalIterator<F>' impl<F: Fn(&i32)> Iterator for ConditionalIterator<F> { type Item = (); diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs index c6beed70abe..6f68b157499 100644 --- a/src/test/rustdoc/generic-impl.rs +++ b/src/test/rustdoc/generic-impl.rs @@ -5,7 +5,7 @@ use std::fmt; // @!has foo/struct.Bar.html '//*[@id="impl-ToString-for-Bar"]' '' pub struct Bar; -// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' +// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header"]' 'impl<T> ToString for T' pub struct Foo; // @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-Foo"]' 'ToString' diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs index 59b5b6e5797..3493ae6d2bb 100644 --- a/src/test/rustdoc/higher-ranked-trait-bounds.rs +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -49,7 +49,7 @@ impl<'a> Foo<'a> { // @has foo/trait.B.html pub trait B<'x> {} -// @has - '//h3[@class="code-header in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>" +// @has - '//h3[@class="code-header"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>" impl<'a> B<'a> for dyn for<'b> Trait<'b> {} // @has foo/struct.Bar.html diff --git a/src/test/rustdoc/impl-disambiguation.rs b/src/test/rustdoc/impl-disambiguation.rs index d1d39ccff32..bb978dc0f3e 100644 --- a/src/test/rustdoc/impl-disambiguation.rs +++ b/src/test/rustdoc/impl-disambiguation.rs @@ -4,13 +4,13 @@ pub trait Foo {} pub struct Bar<T> { field: T } -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl Foo for Bar<u8>" impl Foo for Bar<u8> {} -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl Foo for Bar<u16>" impl Foo for Bar<u16> {} -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl<'a> Foo for &'a Bar<u8>" impl<'a> Foo for &'a Bar<u8> {} @@ -22,9 +22,9 @@ pub mod mod2 { pub enum Baz {} } -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl Foo for foo::mod1::Baz" impl Foo for mod1::Baz {} -// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl<'a> Foo for &'a foo::mod2::Baz" impl<'a> Foo for &'a mod2::Baz {} diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs index b1481e1f279..0a8c2c8d2a9 100644 --- a/src/test/rustdoc/impl-parts.rs +++ b/src/test/rustdoc/impl-parts.rs @@ -5,8 +5,8 @@ pub auto trait AnAutoTrait {} pub struct Foo<T> { field: T } -// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync," -// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ +// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header"]' \ // "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync," impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {} diff --git a/src/test/rustdoc/inline_cross/issue-31948-1.rs b/src/test/rustdoc/inline_cross/issue-31948-1.rs index be8585dd16e..6e89167b3a4 100644 --- a/src/test/rustdoc/inline_cross/issue-31948-1.rs +++ b/src/test/rustdoc/inline_cross/issue-31948-1.rs @@ -5,22 +5,22 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948_1/struct.Wobble.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' pub use rustdoc_nonreachable_impls::hidden::Wobble; // @has issue_31948_1/trait.Bark.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @has - '//h3[@class="code-header in-band"]' 'for Wobble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @has - '//h3[@class="code-header"]' 'for Wobble' +// @!has - '//h3[@class="code-header"]' 'for Wibble' pub use rustdoc_nonreachable_impls::Bark; // @has issue_31948_1/trait.Woof.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @has - '//h3[@class="code-header in-band"]' 'for Wobble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @has - '//h3[@class="code-header"]' 'for Wobble' +// @!has - '//h3[@class="code-header"]' 'for Wibble' pub use rustdoc_nonreachable_impls::Woof; // @!has issue_31948_1/trait.Bar.html diff --git a/src/test/rustdoc/inline_cross/issue-31948-2.rs b/src/test/rustdoc/inline_cross/issue-31948-2.rs index 7aa994f19d6..141e07656a0 100644 --- a/src/test/rustdoc/inline_cross/issue-31948-2.rs +++ b/src/test/rustdoc/inline_cross/issue-31948-2.rs @@ -5,15 +5,15 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948_2/struct.Wobble.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Qux for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for' pub use rustdoc_nonreachable_impls::hidden::Wobble; // @has issue_31948_2/trait.Qux.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @has - '//h3[@class="code-header in-band"]' 'for Wobble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @has - '//h3[@class="code-header"]' 'for Wobble' pub use rustdoc_nonreachable_impls::hidden::Qux; // @!has issue_31948_2/trait.Bar.html diff --git a/src/test/rustdoc/inline_cross/issue-31948.rs b/src/test/rustdoc/inline_cross/issue-31948.rs index 7bf4110d32a..96fc6ca47e7 100644 --- a/src/test/rustdoc/inline_cross/issue-31948.rs +++ b/src/test/rustdoc/inline_cross/issue-31948.rs @@ -5,22 +5,22 @@ extern crate rustdoc_nonreachable_impls; // @has issue_31948/struct.Foo.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for' -// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bar for' -// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Qux for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for' +// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bar for' +// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for' pub use rustdoc_nonreachable_impls::Foo; // @has issue_31948/trait.Bark.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wobble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @!has - '//h3[@class="code-header"]' 'for Wibble' +// @!has - '//h3[@class="code-header"]' 'for Wobble' pub use rustdoc_nonreachable_impls::Bark; // @has issue_31948/trait.Woof.html -// @has - '//h3[@class="code-header in-band"]' 'for Foo' -// @!has - '//h3[@class="code-header in-band"]' 'for Wibble' -// @!has - '//h3[@class="code-header in-band"]' 'for Wobble' +// @has - '//h3[@class="code-header"]' 'for Foo' +// @!has - '//h3[@class="code-header"]' 'for Wibble' +// @!has - '//h3[@class="code-header"]' 'for Wobble' pub use rustdoc_nonreachable_impls::Woof; // @!has issue_31948/trait.Bar.html diff --git a/src/test/rustdoc/inline_cross/issue-32881.rs b/src/test/rustdoc/inline_cross/issue-32881.rs index 8052339a83b..183fd15abbe 100644 --- a/src/test/rustdoc/inline_cross/issue-32881.rs +++ b/src/test/rustdoc/inline_cross/issue-32881.rs @@ -5,7 +5,7 @@ extern crate rustdoc_trait_object_impl; // @has issue_32881/trait.Bar.html -// @has - '//h3[@class="code-header in-band"]' "impl<'a> dyn Bar" -// @has - '//h3[@class="code-header in-band"]' "impl<'a> Debug for dyn Bar" +// @has - '//h3[@class="code-header"]' "impl<'a> dyn Bar" +// @has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar" pub use rustdoc_trait_object_impl::Bar; diff --git a/src/test/rustdoc/inline_cross/issue-33113.rs b/src/test/rustdoc/inline_cross/issue-33113.rs index c60859bbcea..d954707facf 100644 --- a/src/test/rustdoc/inline_cross/issue-33113.rs +++ b/src/test/rustdoc/inline_cross/issue-33113.rs @@ -5,6 +5,6 @@ extern crate bar; // @has issue_33113/trait.Bar.html -// @has - '//h3[@class="code-header in-band"]' "for &'a char" -// @has - '//h3[@class="code-header in-band"]' "for Foo" +// @has - '//h3[@class="code-header"]' "for &'a char" +// @has - '//h3[@class="code-header"]' "for Foo" pub use bar::Bar; diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs index 363c52a336e..b646babacc5 100644 --- a/src/test/rustdoc/inline_cross/trait-vis.rs +++ b/src/test/rustdoc/inline_cross/trait-vis.rs @@ -3,5 +3,5 @@ extern crate inner; // @has trait_vis/struct.SomeStruct.html -// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct' +// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct' pub use inner::SomeStruct; diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs index e7b08088f40..19b69da1513 100644 --- a/src/test/rustdoc/inline_local/trait-vis.rs +++ b/src/test/rustdoc/inline_local/trait-vis.rs @@ -13,6 +13,6 @@ mod asdf { } // @has trait_vis/struct.SomeStruct.html -// @has - '//h3[@class="code-header in-band"]' 'impl ThisTrait for SomeStruct' -// @!has - '//h3[@class="code-header in-band"]' 'impl PrivateTrait for SomeStruct' +// @has - '//h3[@class="code-header"]' 'impl ThisTrait for SomeStruct' +// @!has - '//h3[@class="code-header"]' 'impl PrivateTrait for SomeStruct' pub use asdf::SomeStruct; diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs index 134821e1ef3..01ae4438500 100644 --- a/src/test/rustdoc/issue-29503.rs +++ b/src/test/rustdoc/issue-29503.rs @@ -5,7 +5,7 @@ pub trait MyTrait { fn my_string(&self) -> String; } -// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for Twhere T: Debug" +// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header']" "impl<T> MyTrait for Twhere T: Debug" impl<T> MyTrait for T where T: fmt::Debug, diff --git a/src/test/rustdoc/issue-33592.rs b/src/test/rustdoc/issue-33592.rs index 815439db9bf..7a128f0b897 100644 --- a/src/test/rustdoc/issue-33592.rs +++ b/src/test/rustdoc/issue-33592.rs @@ -6,8 +6,8 @@ pub struct Bar; pub struct Baz; -// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl Foo<i32> for Bar' +// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl Foo<i32> for Bar' impl Foo<i32> for Bar {} -// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl<T> Foo<T> for Baz' +// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl<T> Foo<T> for Baz' impl<T> Foo<T> for Baz {} diff --git a/src/test/rustdoc/issue-46727.rs b/src/test/rustdoc/issue-46727.rs index 00e9127a34d..8cfc4827a7f 100644 --- a/src/test/rustdoc/issue-46727.rs +++ b/src/test/rustdoc/issue-46727.rs @@ -3,5 +3,5 @@ extern crate issue_46727; // @has issue_46727/trait.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl<T> Foo for Bar<[T; 3]>' +// @has - '//h3[@class="code-header"]' 'impl<T> Foo for Bar<[T; 3]>' pub use issue_46727::{Foo, Bar}; diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs index 43fb705f589..04bc4f304d6 100644 --- a/src/test/rustdoc/issue-50159.rs +++ b/src/test/rustdoc/issue-50159.rs @@ -11,8 +11,8 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> { } // @has issue_50159/struct.Switch.html -// @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync' +// @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send' +// @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Switch<B: Signal> { diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs index aa5890a8451..1c7aa9c7eef 100644 --- a/src/test/rustdoc/issue-51236.rs +++ b/src/test/rustdoc/issue-51236.rs @@ -7,7 +7,7 @@ pub mod traits { } // @has issue_51236/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> Send for Owned<T>where <T as Owned<'static>>::Reader: Send" pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> { marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>, diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs index ce0f85d25da..7b7290ab4b7 100644 --- a/src/test/rustdoc/issue-54705.rs +++ b/src/test/rustdoc/issue-54705.rs @@ -1,10 +1,10 @@ pub trait ScopeHandle<'scope> {} // @has issue_54705/struct.ScopeFutureContents.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync" pub struct ScopeFutureContents<'scope, S> where S: ScopeHandle<'scope>, diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs index ee2420d86d2..22a18ef90e1 100644 --- a/src/test/rustdoc/issue-55321.rs +++ b/src/test/rustdoc/issue-55321.rs @@ -1,9 +1,9 @@ #![feature(negative_impls)] // @has issue_55321/struct.A.html -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for A" -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Sync for A" pub struct A(); @@ -11,8 +11,8 @@ impl !Send for A {} impl !Sync for A {} // @has issue_55321/struct.B.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> !Send for B<T>" -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> !Sync for B<T>" pub struct B<T: ?Sized>(A, Box<T>); diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs index aef6ddd8d23..b4eef344b5f 100644 --- a/src/test/rustdoc/issue-56822.rs +++ b/src/test/rustdoc/issue-56822.rs @@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> { } // @has issue_56822/struct.Parser.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'a> Send for Parser<'a>" pub struct Parser<'a> { field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs index 167f0f039c1..fbb0f82ae39 100644 --- a/src/test/rustdoc/issue-60726.rs +++ b/src/test/rustdoc/issue-60726.rs @@ -26,9 +26,9 @@ where {} // @has issue_60726/struct.IntoIter.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> !Send for IntoIter<T>" -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> !Sync for IntoIter<T>" pub struct IntoIter<T>{ hello:DynTrait<FooInterface<T>>, diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs index ac97b94fb35..3b11059a755 100644 --- a/src/test/rustdoc/issue-75588.rs +++ b/src/test/rustdoc/issue-75588.rs @@ -10,8 +10,8 @@ extern crate realcore; extern crate real_gimli; // issue #74672 -// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice' +// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header"]' 'impl Deref for EndianSlice' pub use realcore::Deref; -// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo' +// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header"]' 'impl Join for Foo' pub use realcore::Join; diff --git a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs index 515e617b4f4..62fbc2444db 100644 --- a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs +++ b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs @@ -31,7 +31,7 @@ impl<T: Trait3> Trait3 for Vec<T> { pub struct Struct1 {} // @has issue_80233_normalize_auto_trait/struct.Question.html -// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Question<T>' +// @has - '//h3[@class="code-header"]' 'impl<T> Send for Question<T>' pub struct Question<T: Trait1> { pub ins: <<Vec<T> as Trait3>::Type3 as Trait2>::Type2, } diff --git a/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs b/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs index 8999e6a889b..adf4d111a6c 100644 --- a/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs +++ b/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs @@ -1,14 +1,14 @@ use std::convert::AsRef; pub struct Local; -// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header in-band"]' 'impl AsRef<str> for Local' +// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header"]' 'impl AsRef<str> for Local' impl AsRef<str> for Local { fn as_ref(&self) -> &str { todo!() } } -// @has - '//h3[@class="code-header in-band"]' 'impl AsRef<Local> for str' +// @has - '//h3[@class="code-header"]' 'impl AsRef<Local> for str' impl AsRef<Local> for str { fn as_ref(&self) -> &Local { todo!() diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs index a8841f137fe..d50268509b2 100644 --- a/src/test/rustdoc/issue-98697.rs +++ b/src/test/rustdoc/issue-98697.rs @@ -12,6 +12,6 @@ extern crate issue_98697_reexport_with_anonymous_lifetime; // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' pub use issue_98697_reexport_with_anonymous_lifetime::repro; -// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl MyTrait<&Extra> for Extra' -// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl<' +// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra' +// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl<' pub use issue_98697_reexport_with_anonymous_lifetime::Extra; diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs index 61a23986862..af19c784d6d 100644 --- a/src/test/rustdoc/negative-impl.rs +++ b/src/test/rustdoc/negative-impl.rs @@ -5,10 +5,10 @@ pub struct Alpha; // @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo<B>" pub struct Bravo<B>(B); -// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl !Send for Alpha" impl !Send for Alpha {} -// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' "\ +// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' "\ // impl<B> !Send for Bravo<B>" impl<B> !Send for Bravo<B> {} diff --git a/src/test/rustdoc/primitive-reference.rs b/src/test/rustdoc/primitive-reference.rs index 5c119340609..431c9aa79c7 100644 --- a/src/test/rustdoc/primitive-reference.rs +++ b/src/test/rustdoc/primitive-reference.rs @@ -14,7 +14,7 @@ // There should be only one implementation listed. // @count - '//*[@class="impl has-srclink"]' 1 -// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header in-band"]' \ +// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header"]' \ // 'impl<A, B> Foo<&A> for &B' #[doc(primitive = "reference")] /// this is a test! diff --git a/src/test/rustdoc/primitive/primitive-generic-impl.rs b/src/test/rustdoc/primitive/primitive-generic-impl.rs index eebb2cf5a35..7b336b39810 100644 --- a/src/test/rustdoc/primitive/primitive-generic-impl.rs +++ b/src/test/rustdoc/primitive/primitive-generic-impl.rs @@ -1,7 +1,7 @@ #![feature(rustdoc_internals)] #![crate_name = "foo"] -// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T' +// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header"]' 'impl<T> ToString for T' #[doc(primitive = "i32")] /// Some useless docs, wouhou! diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs index 2ab9d44be6d..aa38485c445 100644 --- a/src/test/rustdoc/recursive-deref.rs +++ b/src/test/rustdoc/recursive-deref.rs @@ -9,7 +9,7 @@ impl C { pub fn c(&self) {} } -// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A' +// @has recursive_deref/struct.A.html '//h3[@class="code-header"]' 'impl Deref for A' // @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)' impl Deref for A { type Target = B; @@ -19,7 +19,7 @@ impl Deref for A { } } -// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B' +// @has recursive_deref/struct.B.html '//h3[@class="code-header"]' 'impl Deref for B' // @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)' impl Deref for B { type Target = C; @@ -29,7 +29,7 @@ impl Deref for B { } } -// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C' +// @has recursive_deref/struct.C.html '//h3[@class="code-header"]' 'impl Deref for C' impl Deref for C { type Target = B; @@ -49,7 +49,7 @@ impl G { pub fn g() {} } -// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D' +// @has recursive_deref/struct.D.html '//h3[@class="code-header"]' 'impl Deref for D' // We also check that `G::g` method isn't rendered because there is no `self` argument. // @!has '-' '//*[@id="deref-methods-G"]' '' impl Deref for D { @@ -60,7 +60,7 @@ impl Deref for D { } } -// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E' +// @has recursive_deref/struct.E.html '//h3[@class="code-header"]' 'impl Deref for E' // We also check that `G::g` method isn't rendered because there is no `self` argument. // @!has '-' '//*[@id="deref-methods-G"]' '' impl Deref for E { @@ -71,7 +71,7 @@ impl Deref for E { } } -// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F' +// @has recursive_deref/struct.F.html '//h3[@class="code-header"]' 'impl Deref for F' // We also check that `G::g` method isn't rendered because there is no `self` argument. // @!has '-' '//*[@id="deref-methods-G"]' '' impl Deref for F { @@ -82,7 +82,7 @@ impl Deref for F { } } -// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G' +// @has recursive_deref/struct.G.html '//h3[@class="code-header"]' 'impl Deref for G' impl Deref for G { type Target = E; @@ -100,7 +100,7 @@ impl I { pub fn i() {} } -// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H' +// @has recursive_deref/struct.H.html '//h3[@class="code-header"]' 'impl Deref for H' // @!has '-' '//*[@id="deref-methods-I"]' '' impl Deref for H { type Target = I; @@ -110,7 +110,7 @@ impl Deref for H { } } -// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I' +// @has recursive_deref/struct.I.html '//h3[@class="code-header"]' 'impl Deref for I' impl Deref for I { type Target = H; diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs index f3e211e3017..8bd402291aa 100644 --- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs +++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs @@ -30,10 +30,10 @@ pub trait Tr<T> { } // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]' '' -// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone' -// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const' -// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone' +// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]' '~const' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Clone' +// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const' +// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone' impl<T: ~const Clone + ~const Destruct> const Tr<T> for T where Option<T>: ~const Clone + ~const Destruct, diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs index 15515039659..6712af527a3 100644 --- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs +++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs @@ -6,9 +6,9 @@ // @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types' // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32' -// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header in-band"]' 'impl Foo for u32' +// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32' // @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str" -// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header in-band"]' "impl<'a> Foo for &'a str" +// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header"]' "impl<'a> Foo for &'a str" pub trait Foo {} impl Foo for u32 {} diff --git a/src/test/rustdoc/sized_trait.rs b/src/test/rustdoc/sized_trait.rs index 36718ebe1a6..feef4de8d57 100644 --- a/src/test/rustdoc/sized_trait.rs +++ b/src/test/rustdoc/sized_trait.rs @@ -11,7 +11,7 @@ pub struct Bar { pub struct Foo<T: ?Sized>(T); // @has foo/struct.Unsized.html -// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header in-band"]' 'impl !Sized for Unsized' +// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header"]' 'impl !Sized for Unsized' pub struct Unsized { data: [u8], } diff --git a/src/test/rustdoc/src-links-auto-impls.rs b/src/test/rustdoc/src-links-auto-impls.rs index 313a4b11893..953563833c9 100644 --- a/src/test/rustdoc/src-links-auto-impls.rs +++ b/src/test/rustdoc/src-links-auto-impls.rs @@ -1,11 +1,11 @@ #![crate_name = "foo"] // @has foo/struct.Unsized.html -// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header in-band"]' 'impl !Sized for Unsized' +// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header"]' 'impl !Sized for Unsized' // @!has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="srclink"]' 'source' -// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized' +// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized' // @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="srclink"]' 'source' -// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header in-band"]' 'impl<T> Any for T' +// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header"]' 'impl<T> Any for T' // @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink rightside"]' 'source' pub struct Unsized { data: [u8], diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs index 19138fd1ace..7c6a388653c 100644 --- a/src/test/rustdoc/synthetic_auto/basic.rs +++ b/src/test/rustdoc/synthetic_auto/basic.rs @@ -1,6 +1,6 @@ // @has basic/struct.Foo.html -// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T>where T: Send' -// @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T>where T: Sync' +// @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send' +// @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync' // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 pub struct Foo<T> { diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs index 39f78983da2..43393c21fdd 100644 --- a/src/test/rustdoc/synthetic_auto/complex.rs +++ b/src/test/rustdoc/synthetic_auto/complex.rs @@ -20,7 +20,7 @@ mod foo { } // @has complex/struct.NotOuter.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \ // -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static" diff --git a/src/test/rustdoc/synthetic_auto/crate-local.rs b/src/test/rustdoc/synthetic_auto/crate-local.rs index 58b787dfafc..ed01f63f998 100644 --- a/src/test/rustdoc/synthetic_auto/crate-local.rs +++ b/src/test/rustdoc/synthetic_auto/crate-local.rs @@ -3,7 +3,7 @@ pub auto trait Banana {} // @has crate_local/struct.Peach.html -// @has - '//h3[@class="code-header in-band"]' 'impl Banana for Peach' -// @has - '//h3[@class="code-header in-band"]' 'impl Send for Peach' -// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Peach' +// @has - '//h3[@class="code-header"]' 'impl Banana for Peach' +// @has - '//h3[@class="code-header"]' 'impl Send for Peach' +// @has - '//h3[@class="code-header"]' 'impl Sync for Peach' pub struct Peach; diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs index 0c94850e786..33170a84435 100644 --- a/src/test/rustdoc/synthetic_auto/lifetimes.rs +++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs @@ -9,10 +9,10 @@ where {} // @has lifetimes/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Sync for Foo<'c, K>where K: Sync" pub struct Foo<'c, K: 'c> { inner_field: Inner<'c, K>, diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs index 35047e3e8c0..77c04ad2ad9 100644 --- a/src/test/rustdoc/synthetic_auto/manual.rs +++ b/src/test/rustdoc/synthetic_auto/manual.rs @@ -1,8 +1,8 @@ // @has manual/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl<T> Sync for Foo<T>where T: Sync' // -// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl<T> Send for Foo<T>' // // @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1 diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs index 66e749ac38d..2c2c848a5e0 100644 --- a/src/test/rustdoc/synthetic_auto/negative.rs +++ b/src/test/rustdoc/synthetic_auto/negative.rs @@ -3,10 +3,10 @@ pub struct Inner<T: Copy> { } // @has negative/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> !Send for Outer<T>" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> !Sync for Outer<T>" pub struct Outer<T: Copy> { inner_field: Inner<T>, diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs index 09587bcc30f..423bf115ab1 100644 --- a/src/test/rustdoc/synthetic_auto/nested.rs +++ b/src/test/rustdoc/synthetic_auto/nested.rs @@ -9,10 +9,10 @@ where } // @has nested/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl<T> Send for Foo<T>where T: Copy' // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // 'impl<T> Sync for Foo<T>where T: Sync' pub struct Foo<T> { inner_field: Inner<T>, diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs index 41375decc8a..59f33623322 100644 --- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs +++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs @@ -9,7 +9,7 @@ where } // @has no_redundancy/struct.Outer.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> Send for Outer<T>where T: Send + Copy" pub struct Outer<T> { inner_field: Inner<T>, diff --git a/src/test/rustdoc/synthetic_auto/overflow.rs b/src/test/rustdoc/synthetic_auto/overflow.rs index c132ab6fb1b..35a487c764d 100644 --- a/src/test/rustdoc/synthetic_auto/overflow.rs +++ b/src/test/rustdoc/synthetic_auto/overflow.rs @@ -21,7 +21,7 @@ enum TyData<I: Interner> { struct VariableKind<I: Interner>(I::InternedType); // @has overflow/struct.BoundVarsCollector.html -// @has - '//h3[@class="code-header in-band"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>" +// @has - '//h3[@class="code-header"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>" pub struct BoundVarsCollector<'tcx> { val: VariableKind<RustInterner<'tcx>> } diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs index e80b1b1dc9b..558ff2add40 100644 --- a/src/test/rustdoc/synthetic_auto/project.rs +++ b/src/test/rustdoc/synthetic_auto/project.rs @@ -23,10 +23,10 @@ where } // @has project/struct.Foo.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Send for Foo<'c, K>where K: MyTrait<MyItem = bool>, 'c: 'static" // -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \ // 'c: 'static," pub struct Foo<'c, K: 'c> { diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs index d15a8de7d2f..c6ae96de776 100644 --- a/src/test/rustdoc/synthetic_auto/self-referential.rs +++ b/src/test/rustdoc/synthetic_auto/self-referential.rs @@ -23,7 +23,7 @@ impl<T> Pattern for Wrapper<T> { // @has self_referential/struct.WriteAndThen.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<P1> Send for WriteAndThen<P1>where <P1 as Pattern>::Value: Send" pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value) where P1: Pattern; diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs index 08e9567313e..1a76cb919c2 100644 --- a/src/test/rustdoc/synthetic_auto/static-region.rs +++ b/src/test/rustdoc/synthetic_auto/static-region.rs @@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> { } // @has static_region/struct.Owned.html -// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<T> Send for Owned<T>where <T as OwnedTrait<'static>>::Reader: Send" pub struct Owned<T> where T: OwnedTrait<'static> { marker: <T as OwnedTrait<'static>>::Reader, diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs index 6d450a625d0..a65dd7a546c 100644 --- a/src/test/rustdoc/traits-in-bodies.rs +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -4,7 +4,7 @@ pub struct Bounded<T: Clone>(T); // @has traits_in_bodies/struct.SomeStruct.html -// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct' +// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct' pub struct SomeStruct; fn asdf() -> Bounded<SomeStruct> { @@ -18,7 +18,7 @@ fn asdf() -> Bounded<SomeStruct> { } // @has traits_in_bodies/struct.Point.html -// @has - '//h3[@class="code-header in-band"]' 'impl Copy for Point' +// @has - '//h3[@class="code-header"]' 'impl Copy for Point' #[derive(Clone)] pub struct Point { x: i32, @@ -31,7 +31,7 @@ const _FOO: () = { }; // @has traits_in_bodies/struct.Inception.html -// @has - '//h3[@class="code-header in-band"]' 'impl Clone for Inception' +// @has - '//h3[@class="code-header"]' 'impl Clone for Inception' pub struct Inception; static _BAR: usize = { diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs index b68ec4557ad..d5dfa948489 100644 --- a/src/test/rustdoc/typedef.rs +++ b/src/test/rustdoc/typedef.rs @@ -9,8 +9,8 @@ impl MyStruct { } // @has typedef/type.MyAlias.html -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyAlias' -// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyTrait for MyAlias' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyAlias' +// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias' // @hasraw - 'Alias docstring' // @has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias' // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods' diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 68a146bfa55..8b5bce28f5a 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -13,7 +13,7 @@ pub fn charlie<C>() where C: MyTrait {} pub struct Delta<D>(D); -// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<D> Delta<D>where D: MyTrait" impl<D> Delta<D> where D: MyTrait { pub fn delta() {} @@ -43,17 +43,17 @@ pub trait TraitWhere { { todo!() } } -// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<E> MyTrait for Echo<E>where E: MyTrait" -// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \ // "impl<E> MyTrait for Echo<E>where E: MyTrait" impl<E> MyTrait for Echo<E>where E: MyTrait {} pub enum Foxtrot<F> { Foxtrot1(F) } -// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ +// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \ // "impl<F> MyTrait for Foxtrot<F>where F: MyTrait" -// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ +// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \ // "impl<F> MyTrait for Foxtrot<F>where F: MyTrait" impl<F> MyTrait for Foxtrot<F>where F: MyTrait {} diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 03ad3ca8261..03da804bd1c 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass { ) { let item = match cx.tcx.hir().get(id) { Node::Item(item) => item, - _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)), + _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id), }; let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr"); diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 80ea9082881..ad481c14bab 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -76,13 +76,15 @@ struct InvalidNestedStructAttr1 {} #[derive(Diagnostic)] #[diag(nonsense = "...", code = "E0123", slug = "foo")] //~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr2 {} #[derive(Diagnostic)] #[diag(nonsense = 4, code = "E0123", slug = "foo")] //~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr3 {} #[derive(Diagnostic)] @@ -217,6 +219,7 @@ struct Suggest { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithoutCode { #[suggestion(typeck::suggestion)] + //~^ ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -225,6 +228,7 @@ struct SuggestWithoutCode { struct SuggestWithBadKey { #[suggestion(nonsense = "bar")] //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute + //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -233,6 +237,7 @@ struct SuggestWithBadKey { struct SuggestWithShorthandMsg { #[suggestion(msg = "bar")] //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute + //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -269,16 +274,16 @@ struct SuggestWithSpanOnly { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateSpanAndApplicability { #[suggestion(typeck::suggestion, code = "This is suggested code")] - //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span` suggestion: (Span, Span, Applicability), + //~^ ERROR specified multiple times } #[derive(Diagnostic)] #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateApplicabilityAndSpan { #[suggestion(typeck::suggestion, code = "This is suggested code")] - //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one suggestion: (Applicability, Applicability, Span), + //~^ ERROR specified multiple times } #[derive(Diagnostic)] @@ -294,7 +299,7 @@ struct WrongKindOfAnnotation { struct OptionsInErrors { #[label(typeck::label)] label: Option<Span>, - #[suggestion(typeck::suggestion)] + #[suggestion(typeck::suggestion, code = "...")] opt_sugg: Option<(Span, Applicability)>, } @@ -436,7 +441,7 @@ struct ErrorWithNoteCustomWrongOrder { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ApplicabilityInBoth { #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] - //~^ ERROR applicability cannot be set in both the field and attribute + //~^ ERROR specified multiple times suggestion: (Span, Applicability), } @@ -507,7 +512,7 @@ struct OptUnitField { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelWithTrailingPath { #[label(typeck::label, foo)] - //~^ ERROR `#[label(...)]` is not a valid attribute + //~^ ERROR `#[label(foo)]` is not a valid attribute span: Span, } @@ -515,7 +520,7 @@ struct LabelWithTrailingPath { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelWithTrailingNameValue { #[label(typeck::label, foo = "...")] - //~^ ERROR `#[label(...)]` is not a valid attribute + //~^ ERROR `#[label(foo = ...)]` is not a valid attribute span: Span, } @@ -523,7 +528,7 @@ struct LabelWithTrailingNameValue { #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelWithTrailingList { #[label(typeck::label, foo("..."))] - //~^ ERROR `#[label(...)]` is not a valid attribute + //~^ ERROR `#[label(foo(...))]` is not a valid attribute span: Span, } @@ -581,3 +586,68 @@ struct LintAttributeOnSessionDiag {} //~| ERROR diagnostic slug not specified //~| ERROR cannot find attribute `lint` in this scope struct LintAttributeOnLintDiag {} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct DuplicatedSuggestionCode { + #[suggestion(typeck::suggestion, code = "...", code = ",,,")] + //~^ ERROR specified multiple times + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct InvalidTypeInSuggestionTuple { + #[suggestion(typeck::suggestion, code = "...")] + suggestion: (Span, usize), + //~^ ERROR wrong types for suggestion +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct MissingApplicabilityInSuggestionTuple { + #[suggestion(typeck::suggestion, code = "...")] + suggestion: (Span,), + //~^ ERROR wrong types for suggestion +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct MissingCodeInSuggestion { + #[suggestion(typeck::suggestion)] + //~^ ERROR suggestion without `code = "..."` + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[multipart_suggestion(typeck::suggestion)] +//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute +//~| ERROR cannot find attribute `multipart_suggestion` in this scope +#[multipart_suggestion()] +//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute +//~| ERROR cannot find attribute `multipart_suggestion` in this scope +struct MultipartSuggestion { + #[multipart_suggestion(typeck::suggestion)] + //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute + //~| ERROR cannot find attribute `multipart_suggestion` in this scope + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[suggestion(typeck::suggestion, code = "...")] +//~^ ERROR `#[suggestion(...)]` is not a valid attribute +struct SuggestionOnStruct { + #[primary_span] + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[label] +//~^ ERROR `#[label]` is not a valid attribute +struct LabelOnStruct { + #[primary_span] + suggestion: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index c3972beb512..9919b12beaf 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -20,8 +20,6 @@ error: `#[nonsense(...)]` is not a valid attribute | LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: only `diag`, `help`, `note` and `warning` are valid attributes error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:53:1 @@ -41,7 +39,7 @@ error: `#[diag("...")]` is not a valid attribute LL | #[diag("E0123")] | ^^^^^^^ | - = help: first argument of the attribute should be the diagnostic slug + = help: a diagnostic slug is required as the first argument error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:60:1 @@ -60,7 +58,7 @@ error: `#[diag(nonsense(...))]` is not a valid attribute LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^ | - = help: first argument of the attribute should be the diagnostic slug + = help: a diagnostic slug is required as the first argument error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:71:1 @@ -79,7 +77,15 @@ error: `#[diag(nonsense = ...)]` is not a valid attribute LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: first argument of the attribute should be the diagnostic slug + = help: only `code` is a valid nested attributes following the slug + +error: `#[diag(slug = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:77:42 + | +LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ + | + = help: only `code` is a valid nested attributes following the slug error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:77:1 @@ -87,32 +93,40 @@ error: diagnostic slug not specified LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] LL | | LL | | +LL | | LL | | struct InvalidNestedStructAttr2 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:83:8 + --> $DIR/diagnostic-derive.rs:84:8 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ + +error: `#[diag(slug = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:84:38 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ + | + = help: only `code` is a valid nested attributes following the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:83:1 + --> $DIR/diagnostic-derive.rs:84:1 | LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] LL | | LL | | +LL | | LL | | struct InvalidNestedStructAttr3 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:89:58 + --> $DIR/diagnostic-derive.rs:91:58 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ @@ -120,55 +134,57 @@ LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] = help: only `code` is a valid nested attributes following the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:96:5 + --> $DIR/diagnostic-derive.rs:98:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:103:1 + --> $DIR/diagnostic-derive.rs:105:8 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:102:1 + --> $DIR/diagnostic-derive.rs:104:8 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:103:49 + --> $DIR/diagnostic-derive.rs:105:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:102:49 + --> $DIR/diagnostic-derive.rs:104:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:65 + --> $DIR/diagnostic-derive.rs:111:65 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:109:49 + --> $DIR/diagnostic-derive.rs:111:49 | LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] | ^^^^^^^ error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:114:42 + --> $DIR/diagnostic-derive.rs:116:42 | LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: diagnostic slug must be the first argument error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:119:1 + --> $DIR/diagnostic-derive.rs:121:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +192,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:122:1 + --> $DIR/diagnostic-derive.rs:124:1 | LL | / #[diag(code = "E0456")] LL | | @@ -186,33 +202,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:133:5 + --> $DIR/diagnostic-derive.rs:135:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:141:5 + --> $DIR/diagnostic-derive.rs:143:5 | LL | #[nonsense] | ^^^^^^^^^^^ - | - = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:158:5 + --> $DIR/diagnostic-derive.rs:160:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:166:45 + --> $DIR/diagnostic-derive.rs:168:45 | LL | #[suggestion(typeck::suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:171:16 + --> $DIR/diagnostic-derive.rs:173:16 | LL | #[derive(Diagnostic)] | - ^ expected `'}'` in format string @@ -223,7 +237,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:181:15 + --> $DIR/diagnostic-derive.rs:183:15 | LL | #[derive(Diagnostic)] | ^ unmatched `}` in format string @@ -232,29 +246,47 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:201:5 + --> $DIR/diagnostic-derive.rs:203:5 | LL | #[label(typeck::label)] | ^^^^^^^^^^^^^^^^^^^^^^^ +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:221:5 + | +LL | #[suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:226:18 + --> $DIR/diagnostic-derive.rs:229:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ | - = help: only `message`, `code` and `applicability` are valid field attributes + = help: only `code` and `applicability` are valid nested attributes + +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:229:5 + | +LL | #[suggestion(nonsense = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:234:18 + --> $DIR/diagnostic-derive.rs:238:18 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ | - = help: only `message`, `code` and `applicability` are valid field attributes + = help: only `code` and `applicability` are valid nested attributes + +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:238:5 + | +LL | #[suggestion(msg = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:256:5 + --> $DIR/diagnostic-derive.rs:261:5 | LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | @@ -263,60 +295,76 @@ LL | | suggestion: Applicability, | = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` -error: type of field annotated with `#[suggestion(...)]` contains more than one `Span` - --> $DIR/diagnostic-derive.rs:271:5 +error: specified multiple times + --> $DIR/diagnostic-derive.rs:277:24 | -LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] -LL | | -LL | | suggestion: (Span, Span, Applicability), - | |___________________________________________^ +LL | suggestion: (Span, Span, Applicability), + | ^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:277:18 + | +LL | suggestion: (Span, Span, Applicability), + | ^^^^ -error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability - --> $DIR/diagnostic-derive.rs:279:5 +error: specified multiple times + --> $DIR/diagnostic-derive.rs:285:33 | -LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] -LL | | -LL | | suggestion: (Applicability, Applicability, Span), - | |____________________________________________________^ +LL | suggestion: (Applicability, Applicability, Span), + | ^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:285:18 + | +LL | suggestion: (Applicability, Applicability, Span), + | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:287:5 + --> $DIR/diagnostic-derive.rs:292:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ -error: applicability cannot be set in both the field and attribute - --> $DIR/diagnostic-derive.rs:438:52 +error: specified multiple times + --> $DIR/diagnostic-derive.rs:443:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:445:24 + | +LL | suggestion: (Span, Applicability), + | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:446:52 + --> $DIR/diagnostic-derive.rs:451:52 | LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:509:5 +error: `#[label(foo)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:514:28 | LL | #[label(typeck::label, foo)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ + | + = help: a diagnostic slug must be the first argument to the attribute -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:517:5 +error: `#[label(foo = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:522:28 | LL | #[label(typeck::label, foo = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:525:5 +error: `#[label(foo(...))]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:530:28 | LL | #[label(typeck::label, foo("..."))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:538:5 + --> $DIR/diagnostic-derive.rs:543:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -324,15 +372,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:558:1 + --> $DIR/diagnostic-derive.rs:563:1 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:558:1 + --> $DIR/diagnostic-derive.rs:563:1 | LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -344,15 +390,13 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:565:1 + --> $DIR/diagnostic-derive.rs:570:1 | LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `warn_` have been replaced by `warning` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:565:1 + --> $DIR/diagnostic-derive.rs:570:1 | LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -364,15 +408,13 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:572:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:572:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -384,15 +426,13 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:579:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:579:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | @@ -403,6 +443,80 @@ LL | | struct LintAttributeOnLintDiag {} | = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]` +error: specified multiple times + --> $DIR/diagnostic-derive.rs:593:52 + | +LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] + | ^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive.rs:593:38 + | +LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")] + | ^^^^^^^^^^^^ + +error: wrong types for suggestion + --> $DIR/diagnostic-derive.rs:602:24 + | +LL | suggestion: (Span, usize), + | ^^^^^ + | + = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` + +error: wrong types for suggestion + --> $DIR/diagnostic-derive.rs:610:17 + | +LL | suggestion: (Span,), + | ^^^^^^^ + | + = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` + +error: suggestion without `code = "..."` + --> $DIR/diagnostic-derive.rs:617:5 + | +LL | #[suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:624:1 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider creating a `Subdiagnostic` instead + +error: `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:627:1 + | +LL | #[multipart_suggestion()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider creating a `Subdiagnostic` instead + +error: `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:631:5 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider creating a `Subdiagnostic` instead + +error: `#[suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:639:1 + | +LL | #[suggestion(typeck::suggestion, code = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[label]` and `#[suggestion]` can only be applied to fields + +error: `#[label]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:648:1 + | +LL | #[label] + | ^^^^^^^^ + | + = help: `#[label]` and `#[suggestion]` can only be applied to fields + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:53:3 | @@ -410,35 +524,53 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:141:7 + --> $DIR/diagnostic-derive.rs:143:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:558:3 + --> $DIR/diagnostic-derive.rs:563:3 | LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:565:3 + --> $DIR/diagnostic-derive.rs:570:3 | LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:572:3 + --> $DIR/diagnostic-derive.rs:577:3 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:579:3 + --> $DIR/diagnostic-derive.rs:584:3 | LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive.rs:624:3 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive.rs:627:3 + | +LL | #[multipart_suggestion()] + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive.rs:631:7 + | +LL | #[multipart_suggestion(typeck::suggestion)] + | ^^^^^^^^^^^^^^^^^^^^ + error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent` --> $DIR/diagnostic-derive.rs:66:8 | @@ -446,7 +578,7 @@ LL | #[diag(nonsense, code = "E0123")] | ^^^^^^^^ not found in `rustc_errors::fluent` error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:331:10 + --> $DIR/diagnostic-derive.rs:336:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -459,7 +591,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 55 previous errors +error: aborting due to 72 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 9fbe7b1f4c8..606b3b5e5eb 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -52,7 +52,7 @@ struct C { #[derive(Subdiagnostic)] #[label] -//~^ ERROR `#[label]` is not a valid attribute +//~^ ERROR diagnostic slug must be first argument struct D { #[primary_span] span: Span, @@ -81,6 +81,7 @@ struct F { #[derive(Subdiagnostic)] #[label(bug = "...")] //~^ ERROR `#[label(bug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct G { #[primary_span] span: Span, @@ -90,6 +91,7 @@ struct G { #[derive(Subdiagnostic)] #[label("...")] //~^ ERROR `#[label("...")]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct H { #[primary_span] span: Span, @@ -99,6 +101,7 @@ struct H { #[derive(Subdiagnostic)] #[label(slug = 4)] //~^ ERROR `#[label(slug = ...)]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct J { #[primary_span] span: Span, @@ -108,6 +111,7 @@ struct J { #[derive(Subdiagnostic)] #[label(slug("..."))] //~^ ERROR `#[label(slug(...))]` is not a valid attribute +//~| ERROR diagnostic slug must be first argument struct K { #[primary_span] span: Span, @@ -135,7 +139,7 @@ struct M { #[derive(Subdiagnostic)] #[label(parser::add_paren, code = "...")] -//~^ ERROR `code` is not a valid nested attribute of a `label` attribute +//~^ ERROR `#[label(code = ...)]` is not a valid attribute struct N { #[primary_span] span: Span, @@ -144,7 +148,7 @@ struct N { #[derive(Subdiagnostic)] #[label(parser::add_paren, applicability = "machine-applicable")] -//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute +//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute struct O { #[primary_span] span: Span, @@ -216,6 +220,7 @@ enum T { enum U { #[label(code = "...")] //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute + //~| ERROR `#[label(code = ...)]` is not a valid attribute A { #[primary_span] span: Span, @@ -531,7 +536,7 @@ struct BA { #[derive(Subdiagnostic)] #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields -//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute +//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute struct BBa { var: String, } @@ -612,10 +617,9 @@ struct BG { #[derive(Subdiagnostic)] #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] -//~^ NOTE previously specified here struct BH { #[applicability] - //~^ ERROR specified multiple times + //~^ ERROR `#[applicability]` has no effect appl: Applicability, #[suggestion_part(code = "(")] first: Span, diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 0a0247e8980..171b89e657d 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -8,7 +8,7 @@ LL | | var: String, LL | | } | |_^ -error: `#[label]` is not a valid attribute +error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:54:1 | LL | #[label] @@ -31,101 +31,123 @@ error: `#[label(bug = ...)]` is not a valid attribute | LL | #[label(bug = "...")] | ^^^^^^^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:82:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label(bug = "...")] + | ^^^^^^^^^^^^^^^^^^^^^ error: `#[label("...")]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:91:9 + --> $DIR/subdiagnostic-derive.rs:92:9 | LL | #[label("...")] | ^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:92:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label("...")] + | ^^^^^^^^^^^^^^^ error: `#[label(slug = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:100:9 + --> $DIR/subdiagnostic-derive.rs:102:9 | LL | #[label(slug = 4)] | ^^^^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:102:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label(slug = 4)] + | ^^^^^^^^^^^^^^^^^^ error: `#[label(slug(...))]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:109:9 + --> $DIR/subdiagnostic-derive.rs:112:9 | LL | #[label(slug("..."))] | ^^^^^^^^^^^ + +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:112:1 | - = help: first argument of the attribute should be the diagnostic slug +LL | #[label(slug("..."))] + | ^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:128:1 + --> $DIR/subdiagnostic-derive.rs:132:1 | LL | #[label()] | ^^^^^^^^^^ -error: `code` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:137:28 +error: `#[label(code = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:141:28 | LL | #[label(parser::add_paren, code = "...")] | ^^^^^^^^^^^^ -error: `applicability` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:146:28 +error: `#[label(applicability = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:150:28 | LL | #[label(parser::add_paren, applicability = "machine-applicable")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:155:1 + --> $DIR/subdiagnostic-derive.rs:159:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:169:5 + --> $DIR/subdiagnostic-derive.rs:173:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:181:5 + --> $DIR/subdiagnostic-derive.rs:185:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:193:5 + --> $DIR/subdiagnostic-derive.rs:197:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:205:5 + --> $DIR/subdiagnostic-derive.rs:209:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ +error: `#[label(code = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:221:13 + | +LL | #[label(code = "...")] + | ^^^^^^^^^^^^ + error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:217:5 + --> $DIR/subdiagnostic-derive.rs:221:5 | LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:234:5 + --> $DIR/subdiagnostic-derive.rs:239:5 | LL | B { | ^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:246:5 + --> $DIR/subdiagnostic-derive.rs:251:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:243:1 + --> $DIR/subdiagnostic-derive.rs:248:1 | LL | / #[label(parser::add_paren)] LL | | @@ -137,13 +159,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:256:5 + --> $DIR/subdiagnostic-derive.rs:261:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:266:5 + --> $DIR/subdiagnostic-derive.rs:271:5 | LL | #[bar] | ^^^^^^ @@ -151,13 +173,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:277:5 + --> $DIR/subdiagnostic-derive.rs:282:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:288:5 + --> $DIR/subdiagnostic-derive.rs:293:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ @@ -165,7 +187,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:304:1 + --> $DIR/subdiagnostic-derive.rs:309:1 | LL | / union AC { LL | | @@ -175,7 +197,7 @@ LL | | } | |_^ error: `#[label(parser::add_paren)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:319:28 + --> $DIR/subdiagnostic-derive.rs:324:28 | LL | #[label(parser::add_paren, parser::add_paren)] | ^^^^^^^^^^^^^^^^^ @@ -183,67 +205,67 @@ LL | #[label(parser::add_paren, parser::add_paren)] = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:332:5 + --> $DIR/subdiagnostic-derive.rs:337:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:329:5 + --> $DIR/subdiagnostic-derive.rs:334:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:338:8 + --> $DIR/subdiagnostic-derive.rs:343:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:375:47 + --> $DIR/subdiagnostic-derive.rs:380:47 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:375:33 + --> $DIR/subdiagnostic-derive.rs:380:33 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:393:5 + --> $DIR/subdiagnostic-derive.rs:398:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:390:5 + --> $DIR/subdiagnostic-derive.rs:395:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:403:5 + --> $DIR/subdiagnostic-derive.rs:408:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:416:1 + --> $DIR/subdiagnostic-derive.rs:421:1 | LL | #[suggestion(parser::add_paren)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:426:46 + --> $DIR/subdiagnostic-derive.rs:431:46 | LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] | ^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:444:1 + --> $DIR/subdiagnostic-derive.rs:449:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -253,25 +275,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:458:1 + --> $DIR/subdiagnostic-derive.rs:463:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:478:39 + --> $DIR/subdiagnostic-derive.rs:483:39 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:497:43 + --> $DIR/subdiagnostic-derive.rs:502:43 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:520:5 + --> $DIR/subdiagnostic-derive.rs:525:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -279,7 +301,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:523:5 + --> $DIR/subdiagnostic-derive.rs:528:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -287,7 +309,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:517:1 + --> $DIR/subdiagnostic-derive.rs:522:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -298,14 +320,16 @@ LL | | var: String, LL | | } | |_^ -error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute - --> $DIR/subdiagnostic-derive.rs:532:43 +error: `#[multipart_suggestion(code = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:537:43 | LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] | ^^^^^^^^^^^^ + | + = help: only `applicability` is a valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:532:1 + --> $DIR/subdiagnostic-derive.rs:537:1 | LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] LL | | @@ -316,19 +340,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:542:5 + --> $DIR/subdiagnostic-derive.rs:547:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:550:5 + --> $DIR/subdiagnostic-derive.rs:555:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:559:5 + --> $DIR/subdiagnostic-derive.rs:564:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -336,7 +360,7 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:556:1 + --> $DIR/subdiagnostic-derive.rs:561:1 | LL | / #[multipart_suggestion(parser::add_paren)] LL | | @@ -348,19 +372,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:567:5 + --> $DIR/subdiagnostic-derive.rs:572:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:570:5 + --> $DIR/subdiagnostic-derive.rs:575:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(foo = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:573:23 + --> $DIR/subdiagnostic-derive.rs:578:23 | LL | #[suggestion_part(foo = "bar")] | ^^^^^^^^^^^ @@ -368,40 +392,34 @@ LL | #[suggestion_part(foo = "bar")] = help: `code` is the only valid nested attribute error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:576:5 + --> $DIR/subdiagnostic-derive.rs:581:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:579:5 + --> $DIR/subdiagnostic-derive.rs:584:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:587:37 + --> $DIR/subdiagnostic-derive.rs:592:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:587:23 + --> $DIR/subdiagnostic-derive.rs:592:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ -error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:617:5 +error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` + --> $DIR/subdiagnostic-derive.rs:621:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:614:43 - | -LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 @@ -410,59 +428,59 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:155:3 + --> $DIR/subdiagnostic-derive.rs:159:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:169:7 + --> $DIR/subdiagnostic-derive.rs:173:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:181:7 + --> $DIR/subdiagnostic-derive.rs:185:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:193:7 + --> $DIR/subdiagnostic-derive.rs:197:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:205:7 + --> $DIR/subdiagnostic-derive.rs:209:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:266:7 + --> $DIR/subdiagnostic-derive.rs:271:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:277:7 + --> $DIR/subdiagnostic-derive.rs:282:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:288:7 + --> $DIR/subdiagnostic-derive.rs:293:7 | LL | #[bar("...")] | ^^^ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` - --> $DIR/subdiagnostic-derive.rs:118:9 + --> $DIR/subdiagnostic-derive.rs:122:9 | LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 63 previous errors +error: aborting due to 68 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/async-await/in-trait/issue-102138.rs b/src/test/ui/async-await/in-trait/issue-102138.rs new file mode 100644 index 00000000000..f61b34ed99e --- /dev/null +++ b/src/test/ui/async-await/in-trait/issue-102138.rs @@ -0,0 +1,46 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +async fn yield_now() {} + +trait AsyncIterator { + type Item; + async fn next(&mut self) -> Option<Self::Item>; +} + +struct YieldingRange { + counter: u32, + stop: u32, +} + +impl AsyncIterator for YieldingRange { + type Item = u32; + + async fn next(&mut self) -> Option<Self::Item> { + if self.counter == self.stop { + None + } else { + let c = self.counter; + self.counter += 1; + yield_now().await; + Some(c) + } + } +} + +async fn async_main() { + let mut x = YieldingRange { counter: 0, stop: 10 }; + + while let Some(v) = x.next().await { + println!("Hi: {v}"); + } +} + +fn main() { + let _ = async_main(); +} diff --git a/src/test/ui/async-await/in-trait/issue-102219.rs b/src/test/ui/async-await/in-trait/issue-102219.rs new file mode 100644 index 00000000000..9a35f6515cb --- /dev/null +++ b/src/test/ui/async-await/in-trait/issue-102219.rs @@ -0,0 +1,10 @@ +// compile-flags:--crate-type=lib +// edition:2021 +// check-pass + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait T { + async fn foo(); +} diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs new file mode 100644 index 00000000000..31eba074008 --- /dev/null +++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs @@ -0,0 +1,26 @@ +// Tests the suggestion to reborrow the first move site +// when we move then borrow a `&mut` ref. + +struct State; + +impl IntoIterator for &mut State { + type IntoIter = std::vec::IntoIter<()>; + type Item = (); + + fn into_iter(self) -> Self::IntoIter { + vec![].into_iter() + } +} + +fn once(f: impl FnOnce()) {} + +fn fill_memory_blocks_mt(state: &mut State) { + for _ in state {} + //~^ HELP consider creating a fresh reborrow of `state` here + fill_segment(state); + //~^ ERROR borrow of moved value: `state` +} + +fn fill_segment(state: &mut State) {} + +fn main() {} diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr new file mode 100644 index 00000000000..13a2005e2ef --- /dev/null +++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr @@ -0,0 +1,24 @@ +error[E0382]: borrow of moved value: `state` + --> $DIR/reborrow-sugg-move-then-borrow.rs:20:18 + | +LL | fn fill_memory_blocks_mt(state: &mut State) { + | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait +LL | for _ in state {} + | ----- `state` moved due to this implicit call to `.into_iter()` +LL | +LL | fill_segment(state); + | ^^^^^ value borrowed here after move + | +note: this function takes ownership of the receiver `self`, which moves `state` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider creating a fresh reborrow of `state` here + | +LL | for _ in &mut *state {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/check-static-values-constraints.rs b/src/test/ui/check-static-values-constraints.rs index eb4ecd8baca..f6a577d0d9c 100644 --- a/src/test/ui/check-static-values-constraints.rs +++ b/src/test/ui/check-static-values-constraints.rs @@ -63,7 +63,7 @@ static STATIC8: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, // This example should fail because field1 in the base struct is not safe static STATIC9: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, ..SafeStruct{field1: SafeEnum::Variant3(WithDtor), -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of field2: SafeEnum::Variant1}}; struct UnsafeStruct; diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr index 3c193ca34ac..31939f7f6db 100644 --- a/src/test/ui/check-static-values-constraints.stderr +++ b/src/test/ui/check-static-values-constraints.stderr @@ -1,4 +1,4 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `SafeStruct` cannot be evaluated at compile-time --> $DIR/check-static-values-constraints.rs:65:43 | LL | ..SafeStruct{field1: SafeEnum::Variant3(WithDtor), @@ -7,7 +7,7 @@ LL | | LL | | field2: SafeEnum::Variant1}}; | | ^- value is dropped here | |________________________________________________________________________________| - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics error[E0010]: allocations are not allowed in statics --> $DIR/check-static-values-constraints.rs:79:33 diff --git a/src/test/ui/command/command-pre-exec.rs b/src/test/ui/command/command-pre-exec.rs index 61914e22930..d366c5ffbfd 100644 --- a/src/test/ui/command/command-pre-exec.rs +++ b/src/test/ui/command/command-pre-exec.rs @@ -6,6 +6,7 @@ // ignore-windows - this is a unix-specific test // ignore-emscripten no processes // ignore-sgx no processes +// ignore-fuchsia no execvp syscall #![feature(process_exec, rustc_private)] extern crate libc; diff --git a/src/test/ui/command/command-uid-gid.rs b/src/test/ui/command/command-uid-gid.rs index e1eb4b1405b..aa4e2f5b893 100644 --- a/src/test/ui/command/command-uid-gid.rs +++ b/src/test/ui/command/command-uid-gid.rs @@ -2,6 +2,7 @@ // ignore-android // ignore-emscripten // ignore-sgx +// ignore-fuchsia no '/bin/sh', '/bin/ls' #![feature(rustc_private)] diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs index 18692dbced6..1e2bcc55b6b 100644 --- a/src/test/ui/consts/const-eval/const_let.rs +++ b/src/test/ui/consts/const-eval/const_let.rs @@ -14,16 +14,16 @@ const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x }; // error const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of // error const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of // error const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of // error const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr index 47f39b703e4..63442f55718 100644 --- a/src/test/ui/consts/const-eval/const_let.stderr +++ b/src/test/ui/consts/const-eval/const_let.stderr @@ -1,34 +1,34 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time --> $DIR/const_let.rs:16:32 | LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time --> $DIR/const_let.rs:20:33 | LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<FakeNeedsDrop>` cannot be evaluated at compile-time --> $DIR/const_let.rs:24:21 | LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<FakeNeedsDrop>` cannot be evaluated at compile-time --> $DIR/const_let.rs:28:22 | LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; | ^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs index 2518e4ed40b..e6639826cb2 100644 --- a/src/test/ui/consts/const-eval/issue-65394.rs +++ b/src/test/ui/consts/const-eval/issue-65394.rs @@ -4,7 +4,7 @@ // We will likely have to change this behavior before we allow `&mut` in a `const`. const _: Vec<i32> = { - let mut x = Vec::<i32>::new(); //~ ERROR destructors cannot be evaluated at compile-time + let mut x = Vec::<i32>::new(); //~ ERROR destructor of let r = &mut x; //~ ERROR mutable references are not allowed in constants let y = x; y diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr index ec229d7f53a..ae6f0e93716 100644 --- a/src/test/ui/consts/const-eval/issue-65394.stderr +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -7,11 +7,11 @@ LL | let r = &mut x; = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Vec<i32>` cannot be evaluated at compile-time --> $DIR/issue-65394.rs:7:9 | LL | let mut x = Vec::<i32>::new(); - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here diff --git a/src/test/ui/consts/const-eval/livedrop.rs b/src/test/ui/consts/const-eval/livedrop.rs index 66b7d058080..543f1f0ecee 100644 --- a/src/test/ui/consts/const-eval/livedrop.rs +++ b/src/test/ui/consts/const-eval/livedrop.rs @@ -1,6 +1,6 @@ const _: Option<Vec<i32>> = { let mut never_returned = Some(Vec::new()); - let mut always_returned = None; //~ ERROR destructors cannot be evaluated at compile-time + let mut always_returned = None; //~ ERROR destructor of let mut i = 0; loop { diff --git a/src/test/ui/consts/const-eval/livedrop.stderr b/src/test/ui/consts/const-eval/livedrop.stderr index 1e8b4230c6f..d04fdb70ed3 100644 --- a/src/test/ui/consts/const-eval/livedrop.stderr +++ b/src/test/ui/consts/const-eval/livedrop.stderr @@ -1,8 +1,8 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time --> $DIR/livedrop.rs:3:9 | LL | let mut always_returned = None; - | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | always_returned = never_returned; | --------------- value is dropped here diff --git a/src/test/ui/consts/control-flow/drop-fail.precise.stderr b/src/test/ui/consts/control-flow/drop-fail.precise.stderr index 0b0b2443a4a..93b5f257efb 100644 --- a/src/test/ui/consts/control-flow/drop-fail.precise.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.precise.stderr @@ -1,14 +1,14 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:8:9 | LL | let x = Some(Vec::new()); - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:39:9 | LL | let mut tmp = None; - | ^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^ the destructor for this type cannot be evaluated in constants error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/control-flow/drop-fail.rs b/src/test/ui/consts/control-flow/drop-fail.rs index efa5a11c941..41341f3121e 100644 --- a/src/test/ui/consts/control-flow/drop-fail.rs +++ b/src/test/ui/consts/control-flow/drop-fail.rs @@ -6,7 +6,7 @@ const _: Option<Vec<i32>> = { let y: Option<Vec<i32>> = None; let x = Some(Vec::new()); - //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time + //[stock,precise]~^ ERROR destructor of if true { x @@ -19,7 +19,7 @@ const _: Option<Vec<i32>> = { // existing analysis. const _: Vec<i32> = { let vec_tuple = (Vec::new(),); - //[stock]~^ ERROR destructors cannot be evaluated at compile-time + //[stock]~^ ERROR destructor of vec_tuple.0 }; @@ -27,7 +27,7 @@ const _: Vec<i32> = { // This applies to single-field enum variants as well. const _: Vec<i32> = { let x: Result<_, Vec<i32>> = Ok(Vec::new()); - //[stock]~^ ERROR destructors cannot be evaluated at compile-time + //[stock]~^ ERROR destructor of match x { Ok(x) | Err(x) => x, @@ -37,7 +37,7 @@ const _: Vec<i32> = { const _: Option<Vec<i32>> = { let mut some = Some(Vec::new()); let mut tmp = None; - //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time + //[stock,precise]~^ ERROR destructor of let mut i = 0; while i < 10 { diff --git a/src/test/ui/consts/control-flow/drop-fail.stock.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr index 72ca4fa08bc..2cc8568026e 100644 --- a/src/test/ui/consts/control-flow/drop-fail.stock.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr @@ -1,35 +1,35 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:8:9 | LL | let x = Some(Vec::new()); - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Vec<i32>,)` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:21:9 | LL | let vec_tuple = (Vec::new(),); - | ^^^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Result<Vec<i32>, Vec<i32>>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:29:9 | LL | let x: Result<_, Vec<i32>> = Ok(Vec::new()); - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time --> $DIR/drop-fail.rs:39:9 | LL | let mut tmp = None; - | ^^^^^^^ constants cannot evaluate destructors + | ^^^^^^^ the destructor for this type cannot be evaluated in constants ... LL | }; | - value is dropped here diff --git a/src/test/ui/consts/drop_box.rs b/src/test/ui/consts/drop_box.rs index 58a373a9673..67997413078 100644 --- a/src/test/ui/consts/drop_box.rs +++ b/src/test/ui/consts/drop_box.rs @@ -1,4 +1,4 @@ const fn f<T>(_: Box<T>) {} -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of fn main() {} diff --git a/src/test/ui/consts/drop_box.stderr b/src/test/ui/consts/drop_box.stderr index b9d6581e8ec..62324939b08 100644 --- a/src/test/ui/consts/drop_box.stderr +++ b/src/test/ui/consts/drop_box.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Box<T>` cannot be evaluated at compile-time --> $DIR/drop_box.rs:1:15 | LL | const fn f<T>(_: Box<T>) {} | ^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error: aborting due to previous error diff --git a/src/test/ui/consts/drop_zst.stderr b/src/test/ui/consts/drop_zst.stderr index d4be5aa56d9..37758a4cbda 100644 --- a/src/test/ui/consts/drop_zst.stderr +++ b/src/test/ui/consts/drop_zst.stderr @@ -1,8 +1,8 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `S` cannot be evaluated at compile-time --> $DIR/drop_zst.rs:14:9 | LL | let s = S; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions error: aborting due to previous error diff --git a/src/test/ui/consts/issue-88071.rs b/src/test/ui/consts/issue-88071.rs index 1c38c43e6c0..f58cdb5945e 100644 --- a/src/test/ui/consts/issue-88071.rs +++ b/src/test/ui/consts/issue-88071.rs @@ -2,8 +2,6 @@ // // regression test for #88071 -#![feature(const_btree_new)] - use std::collections::BTreeMap; pub struct CustomMap<K, V>(BTreeMap<K, V>); diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 0bafaf2e81f..c2891488c7f 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -34,7 +34,7 @@ const fn foo35(a: bool, b: bool) -> bool { a ^ b } struct Foo<T: ?Sized>(T); impl<T> Foo<T> { const fn new(t: T) -> Self { Foo(t) } - const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated + const fn into_inner(self) -> T { self.0 } //~ destructor of const fn get(&self) -> &T { &self.0 } const fn get_mut(&mut self) -> &mut T { &mut self.0 } //~^ mutable references @@ -43,7 +43,7 @@ impl<T> Foo<T> { } impl<'a, T> Foo<T> { const fn new_lt(t: T) -> Self { Foo(t) } - const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated + const fn into_inner_lt(self) -> T { self.0 } //~ destructor of const fn get_lt(&'a self) -> &T { &self.0 } const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~^ mutable references @@ -52,7 +52,7 @@ impl<'a, T> Foo<T> { } impl<T: Sized> Foo<T> { const fn new_s(t: T) -> Self { Foo(t) } - const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors + const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructor const fn get_s(&self) -> &T { &self.0 } const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } //~^ mutable references diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 4ad17602c84..11c79e8e2d6 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | LL | const fn into_inner(self) -> T { self.0 } | ^^^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:39:22 @@ -33,13 +33,13 @@ LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:46:28 | LL | const fn into_inner_lt(self) -> T { self.0 } | ^^^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:48:25 @@ -68,13 +68,13 @@ LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:55:27 | LL | const fn into_inner_s(self) -> T { self.0 } | ^^^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error[E0658]: mutable references are not allowed in constant functions --> $DIR/min_const_fn.rs:57:24 @@ -191,21 +191,21 @@ LL | const fn inc(x: &mut i32) { *x += 1 } = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `AlanTuring<impl std::fmt::Debug>` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:122:19 | LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {} | ^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:124:18 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions error: aborting due to 24 previous errors diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs index 8b17f6885ad..4466f097ef4 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs @@ -8,7 +8,7 @@ trait Foo<T> { } trait Bar<T, U: Foo<T>> { - const F: u32 = (U::X, 42).1; //~ ERROR destructors cannot be evaluated at compile-time + const F: u32 = (U::X, 42).1; //~ ERROR destructor of } impl Foo<u32> for () { diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index 0b6cb2fab46..c91c72d1fbf 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(T, u32)` cannot be evaluated at compile-time --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:11:20 | LL | const F: u32 = (U::X, 42).1; | ^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to previous error diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.rs b/src/test/ui/consts/qualif-indirect-mutation-fail.rs index f74a25a346f..a6d2934044a 100644 --- a/src/test/ui/consts/qualif-indirect-mutation-fail.rs +++ b/src/test/ui/consts/qualif-indirect-mutation-fail.rs @@ -6,13 +6,13 @@ // Mutable borrow of a field with drop impl. pub const fn f() { - let mut a: (u32, Option<String>) = (0, None); //~ ERROR destructors cannot be evaluated + let mut a: (u32, Option<String>) = (0, None); //~ ERROR destructor of let _ = &mut a.1; } // Mutable borrow of a type with drop impl. pub const A1: () = { - let mut x = None; //~ ERROR destructors cannot be evaluated + let mut x = None; //~ ERROR destructor of let mut y = Some(String::new()); let a = &mut x; let b = &mut y; @@ -28,12 +28,12 @@ pub const A2: () = { let b = &mut y; std::mem::swap(a, b); std::mem::forget(y); - let _z = x; //~ ERROR destructors cannot be evaluated + let _z = x; //~ ERROR destructor of }; // Shared borrow of a type that might be !Freeze and Drop. pub const fn g1<T>() { - let x: Option<T> = None; //~ ERROR destructors cannot be evaluated + let x: Option<T> = None; //~ ERROR destructor of let _ = x.is_some(); } @@ -41,24 +41,24 @@ pub const fn g1<T>() { pub const fn g2<T>() { let x: Option<T> = None; let _ = x.is_some(); - let _y = x; //~ ERROR destructors cannot be evaluated + let _y = x; //~ ERROR destructor of } // Mutable raw reference to a Drop type. pub const fn address_of_mut() { - let mut x: Option<String> = None; //~ ERROR destructors cannot be evaluated + let mut x: Option<String> = None; //~ ERROR destructor of &raw mut x; - let mut y: Option<String> = None; //~ ERROR destructors cannot be evaluated + let mut y: Option<String> = None; //~ ERROR destructor of std::ptr::addr_of_mut!(y); } // Const raw reference to a Drop type. Conservatively assumed to allow mutation // until resolution of https://github.com/rust-lang/rust/issues/56604. pub const fn address_of_const() { - let x: Option<String> = None; //~ ERROR destructors cannot be evaluated + let x: Option<String> = None; //~ ERROR destructor of &raw const x; - let y: Option<String> = None; //~ ERROR destructors cannot be evaluated + let y: Option<String> = None; //~ ERROR destructor of std::ptr::addr_of!(y); } diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr index 713df12b7a5..6379c00e4b4 100644 --- a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr +++ b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr @@ -1,56 +1,56 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(u32, Option<String>)` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:9:9 | LL | let mut a: (u32, Option<String>) = (0, None); - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:15:9 | LL | let mut x = None; - | ^^^^^ constants cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:31:9 | LL | let _z = x; - | ^^ constants cannot evaluate destructors + | ^^ the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:36:9 | LL | let x: Option<T> = None; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:44:9 | LL | let _y = x; - | ^^ constant functions cannot evaluate destructors + | ^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:52:9 | LL | let mut y: Option<String> = None; - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:49:9 | LL | let mut x: Option<String> = None; - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:62:9 | LL | let y: Option<String> = None; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time --> $DIR/qualif-indirect-mutation-fail.rs:59:9 | LL | let x: Option<String> = None; - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions error: aborting due to 9 previous errors diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs index 2b970390f03..7cd3dbec931 100644 --- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs +++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs @@ -11,7 +11,7 @@ impl<T> Either<T, T> { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "foo", since = "1.0.0")] pub const fn unwrap(self) -> T { - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of match self { Self::Left(t) => t, Self::Right(t) => t, diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr b/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr index a3f513541dd..5f70391eec2 100644 --- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr +++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr @@ -1,8 +1,8 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Either<T, T>` cannot be evaluated at compile-time --> $DIR/stable-precise-live-drops-in-libcore.rs:13:25 | LL | pub const fn unwrap(self) -> T { - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs index b9e7e1405f9..ca4ed8f0b47 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.rs +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs @@ -15,8 +15,8 @@ impl<T> Opt<T> { #[rustc_const_unstable(feature = "foo", issue = "none")] #[stable(feature = "rust1", since = "1.0.0")] const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { - //~^ ERROR destructors cannot be evaluated at compile-time - //~| ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of + //~| ERROR destructor of match self { Opt::Some(t) => t, Opt::None => f(), diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr index fee74bd0a6c..e5b00dd07ab 100644 --- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,17 +1,17 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:17:60 | LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { - | ^ constant functions cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `Opt<T>` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:17:54 | LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { - | ^^^^ constant functions cannot evaluate destructors + | ^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs index 59d5ef20205..3cfacea5e17 100644 --- a/src/test/ui/drop/repeat-drop-2.rs +++ b/src/test/ui/drop/repeat-drop-2.rs @@ -5,7 +5,7 @@ fn borrowck_catch() { } const _: [String; 0] = [String::new(); 0]; -//~^ ERROR destructors cannot be evaluated at compile-time [E0493] +//~^ ERROR destructor of `String` cannot be evaluated at compile-time [E0493] fn must_be_init() { let x: u8; diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr index 48fa2bfa975..adfaed73973 100644 --- a/src/test/ui/drop/repeat-drop-2.stderr +++ b/src/test/ui/drop/repeat-drop-2.stderr @@ -8,13 +8,13 @@ LL | let _bar = foo; LL | let _baz = [foo; 0]; | ^^^ value used here after move -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/repeat-drop-2.rs:7:25 | LL | const _: [String; 0] = [String::new(); 0]; | -^^^^^^^^^^^^^---- | || - | |constants cannot evaluate destructors + | |the destructor for this type cannot be evaluated in constants | value is dropped here error[E0381]: used binding `x` isn't initialized diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs index 23457b8e062..9b646060adf 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs @@ -3,11 +3,9 @@ #![deny(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` #![allow(non_exhaustive_omitted_patterns)] //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` -//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` fn main() { enum Foo { @@ -19,8 +17,6 @@ fn main() { //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` match Foo::A { Foo::A => {} Foo::B => {} @@ -35,5 +31,4 @@ fn main() { } //~^^^ WARNING unknown lint: `non_exhaustive_omitted_patterns` //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` - //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` } diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr index 29023858e4f..3de08e215da 100644 --- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr +++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -10,7 +10,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 | LL | #![allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -30,7 +30,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:33:9 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | #![deny(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 | LL | #![allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | #![allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -80,7 +80,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 | LL | #[allow(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[allow(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:33:9 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,13 +100,13 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable error[E0004]: non-exhaustive patterns: `Foo::C` not covered - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:24:11 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11 | LL | match Foo::A { | ^^^^^^ pattern `Foo::C` not covered | note: `Foo` defined here - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:14:15 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:12:15 | LL | enum Foo { | --- @@ -119,56 +119,6 @@ LL ~ Foo::B => {} LL + Foo::C => todo!() | -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 - | -LL | #![deny(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:7:1 - | -LL | #![allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:17:5 - | -LL | #[allow(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -warning: unknown lint: `non_exhaustive_omitted_patterns` - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:33:9 - | -LL | #[warn(non_exhaustive_omitted_patterns)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the `non_exhaustive_omitted_patterns` lint is unstable - = note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information - = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable - -error: aborting due to previous error; 15 warnings emitted +error: aborting due to previous error; 10 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr deleted file mode 100644 index de1b464a41d..00000000000 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime - --> $DIR/issue-86218.rs:22:28 - | -LL | type InnerStream<'s> = impl Stream<Item = i32> + 's; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: type must outlive the lifetime `'s` as defined here as required by this binding - --> $DIR/issue-86218.rs:22:22 - | -LL | type InnerStream<'s> = impl Stream<Item = i32> + 's; - | ^^ - -error: unconstrained opaque type - --> $DIR/issue-86218.rs:22:28 - | -LL | type InnerStream<'s> = impl Stream<Item = i32> + 's; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `InnerStream` must be used in combination with a concrete type within the same module - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0477`. diff --git a/src/test/ui/generic-associated-types/issue-86218-2.rs b/src/test/ui/generic-associated-types/issue-86218-2.rs new file mode 100644 index 00000000000..63c839ea871 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-86218-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay<AdditionalValue> { + type InnerStream<'s>: Stream<Item = i32> + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl<T> Yay<T> for () { + type InnerStream<'s> = impl Stream<Item = i32> + 's; + fn foo<'s>() -> Self::InnerStream<'s> { () } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/issue-86218.rs index 3a2d758e7d6..b2c3071f06b 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs +++ b/src/test/ui/generic-associated-types/issue-86218.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #86218 - -// This should pass, but seems to run into a TAIT issue. +// check-pass #![feature(type_alias_impl_trait)] @@ -20,7 +17,8 @@ trait Yay<AdditionalValue> { impl<'a> Yay<&'a ()> for () { type InnerStream<'s> = impl Stream<Item = i32> + 's; - fn foo<'s>() -> Self::InnerStream<'s> { todo!() } + //^ ERROR does not fulfill the required lifetime + fn foo<'s>() -> Self::InnerStream<'s> { () } } fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/issue-102140.rs b/src/test/ui/impl-trait/in-trait/issue-102140.rs new file mode 100644 index 00000000000..be1e012acb1 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/issue-102140.rs @@ -0,0 +1,30 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Marker {} +impl Marker for u32 {} + +trait MyTrait { + fn foo(&self) -> impl Marker + where + Self: Sized; +} + +struct Outer; + +impl MyTrait for Outer { + fn foo(&self) -> impl Marker { + 42 + } +} + +impl dyn MyTrait { + fn other(&self) -> impl Marker { + MyTrait::foo(&self) + //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/in-trait/issue-102140.stderr b/src/test/ui/impl-trait/in-trait/issue-102140.stderr new file mode 100644 index 00000000000..08602185f50 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/issue-102140.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:22 + | +LL | MyTrait::foo(&self) + | ------------ -^^^^ + | | | + | | the trait `MyTrait` is not implemented for `&dyn MyTrait` + | | help: consider removing the leading `&`-reference + | required by a bound introduced by this call + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs index 90d1cd3798a..9ee1ba3d3b4 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.rs +++ b/src/test/ui/impl-trait/issues/issue-78722.rs @@ -12,7 +12,7 @@ struct Bug { } let f: F = async { 1 }; //~^ ERROR `async` blocks are not allowed in constants - //~| ERROR destructors cannot be evaluated at compile-time + //~| ERROR destructor of 1 }], } diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr index 9a0ffbc89d9..a96994f5a7f 100644 --- a/src/test/ui/impl-trait/issues/issue-78722.stderr +++ b/src/test/ui/impl-trait/issues/issue-78722.stderr @@ -7,11 +7,11 @@ LL | let f: F = async { 1 }; = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/issue-78722.rs:13:13 | LL | let f: F = async { 1 }; - | ^ constants cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in constants ... LL | }], | - value is dropped here diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.fixed b/src/test/ui/impl-trait/unactionable_diagnostic.fixed new file mode 100644 index 00000000000..6c2505177fe --- /dev/null +++ b/src/test/ui/impl-trait/unactionable_diagnostic.fixed @@ -0,0 +1,25 @@ +// run-rustfix + +pub trait Trait {} + +pub struct Foo; + +impl Trait for Foo {} + +fn foo<'x, P>( + _post: P, + x: &'x Foo, +) -> &'x impl Trait { + x +} + +pub fn bar<'t, T: 't>( + //~^ HELP: consider adding an explicit lifetime bound... + post: T, + x: &'t Foo, +) -> &'t impl Trait { + foo(post, x) + //~^ ERROR: the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.rs b/src/test/ui/impl-trait/unactionable_diagnostic.rs new file mode 100644 index 00000000000..bce35cbdd0d --- /dev/null +++ b/src/test/ui/impl-trait/unactionable_diagnostic.rs @@ -0,0 +1,25 @@ +// run-rustfix + +pub trait Trait {} + +pub struct Foo; + +impl Trait for Foo {} + +fn foo<'x, P>( + _post: P, + x: &'x Foo, +) -> &'x impl Trait { + x +} + +pub fn bar<'t, T>( + //~^ HELP: consider adding an explicit lifetime bound... + post: T, + x: &'t Foo, +) -> &'t impl Trait { + foo(post, x) + //~^ ERROR: the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.stderr b/src/test/ui/impl-trait/unactionable_diagnostic.stderr new file mode 100644 index 00000000000..a32004cda1a --- /dev/null +++ b/src/test/ui/impl-trait/unactionable_diagnostic.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/unactionable_diagnostic.rs:21:5 + | +LL | foo(post, x) + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | pub fn bar<'t, T: 't>( + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/implied-bounds/issue-101951.rs b/src/test/ui/implied-bounds/issue-101951.rs new file mode 100644 index 00000000000..108fef8a15f --- /dev/null +++ b/src/test/ui/implied-bounds/issue-101951.rs @@ -0,0 +1,50 @@ +// Taken directly from that issue. +// +// This test detected that we didn't correctly resolve +// inference variables when computing implied bounds. +// +// check-pass +pub trait BuilderFn<'a> { + type Output; +} + +impl<'a, F, Out> BuilderFn<'a> for F +where + F: FnOnce(&'a mut ()) -> Out, +{ + type Output = Out; +} + +pub trait ConstructionFirm { + type Builder: for<'a> BuilderFn<'a>; +} + +pub trait Campus<T> +where + T: ConstructionFirm, +{ + fn add_building( + &mut self, + building: &mut <<T as ConstructionFirm>::Builder as BuilderFn<'_>>::Output, + ); +} + +struct ArchitectsInc {} + +impl ConstructionFirm for ArchitectsInc { + type Builder = fn(&mut ()) -> PrettyCondo<'_>; +} + +struct PrettyCondo<'a> { + _marker: &'a mut (), +} + +struct CondoEstate {} + +impl Campus<ArchitectsInc> for CondoEstate { + fn add_building(&mut self, _building: &mut PrettyCondo<'_>) { + todo!() + } +} + +fn main() {} diff --git a/src/test/ui/invalid/invalid-llvm-passes.rs b/src/test/ui/invalid/invalid-llvm-passes.rs index ca3c6230af0..ee28f5eb6d6 100644 --- a/src/test/ui/invalid/invalid-llvm-passes.rs +++ b/src/test/ui/invalid/invalid-llvm-passes.rs @@ -1,4 +1,4 @@ // build-fail -// compile-flags: -Cpasses=unknown-pass -Z new-llvm-pass-manager=yes +// compile-flags: -Cpasses=unknown-pass fn main() {} diff --git a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr index 5942fa8aeb4..06befcbb511 100644 --- a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr +++ b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: requested on the command line with `--force-warn while-true` + warning: unused variable: `x` --> $DIR/force_warn_expected_lints_fulfilled.rs:20:9 | @@ -28,13 +36,5 @@ LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*"; | = note: requested on the command line with `--force-warn unused-mut` -warning: denote infinite loops with `loop { ... }` - --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 - | -LL | while true { - | ^^^^^^^^^^ help: use `loop` - | - = note: requested on the command line with `--force-warn while-true` - warning: 5 warnings emitted diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs index fc7341a563b..624b464ecef 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -3,9 +3,9 @@ static A: () = { let a: [String; 1]; - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of a[0] = String::new(); - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of //~| ERROR binding `a` isn't initialized }; @@ -14,9 +14,9 @@ struct B<T>([T; 1]); impl<T> B<T> { pub const fn f(mut self, other: T) -> Self { let _this = self; - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of self.0[0] = other; - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of //~| ERROR use of moved value self } diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr index d8154f8d2cb..c06a6238a90 100644 --- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -1,17 +1,17 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 | LL | a[0] = String::new(); | ^^^^ | | - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics | value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `[String; 1]` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:5:9 | LL | let a: [String; 1]; - | ^ statics cannot evaluate destructors + | ^ the destructor for this type cannot be evaluated in statics ... LL | }; | - value is dropped here @@ -25,20 +25,20 @@ LL | LL | a[0] = String::new(); | ^^^^ `a` used here but it isn't initialized -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 | LL | self.0[0] = other; | ^^^^^^^^^ | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions | value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `B<T>` cannot be evaluated at compile-time --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 | LL | let _this = self; - | ^^^^^ constant functions cannot evaluate destructors + | ^^^^^ the destructor for this type cannot be evaluated in constant functions ... LL | } | - value is dropped here diff --git a/src/test/ui/parser/issues/issue-101540.rs b/src/test/ui/parser/issues/issue-101540.rs new file mode 100644 index 00000000000..328ec6f906b --- /dev/null +++ b/src/test/ui/parser/issues/issue-101540.rs @@ -0,0 +1,7 @@ +struct S1 { + struct S2 { + //~^ ERROR structs are not allowed in struct definitions + } +} + +fn main() {} diff --git a/src/test/ui/parser/issues/issue-101540.stderr b/src/test/ui/parser/issues/issue-101540.stderr new file mode 100644 index 00000000000..53c7c9590e6 --- /dev/null +++ b/src/test/ui/parser/issues/issue-101540.stderr @@ -0,0 +1,10 @@ +error: structs are not allowed in struct definitions + --> $DIR/issue-101540.rs:2:5 + | +LL | struct S2 { + | ^^^^^^^^^ + | + = help: consider creating a new `struct` definition instead of nesting + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs index aa718ab9254..bf94d980678 100644 --- a/src/test/ui/privacy/access_levels.rs +++ b/src/test/ui/privacy/access_levels.rs @@ -55,8 +55,21 @@ mod outer { //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(sel } } -pub use outer::inner1; +#[rustc_effective_visibility] +pub use outer::inner1; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} } +mod half_public_import { + #[rustc_effective_visibility] + pub type HalfPublicImport = u8; //~ ERROR Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + #[rustc_effective_visibility] + #[allow(non_upper_case_globals)] + pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) +} + +#[rustc_effective_visibility] +pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + //~^ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + fn main() {} diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr index 2ed6c330a2f..81514d1fbab 100644 --- a/src/test/ui/privacy/access_levels.stderr +++ b/src/test/ui/privacy/access_levels.stderr @@ -88,6 +88,36 @@ error: Public: pub(self), Exported: pub(self), Reachable: pub, ReachableFromImpl LL | pub a: u8, | ^^^^^^^^^ +error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:59:9 + | +LL | pub use outer::inner1; + | ^^^^^^^^^^^^^ + +error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:65:5 + | +LL | pub type HalfPublicImport = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:68:5 + | +LL | pub(crate) const HalfPublicImport: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub + --> $DIR/access_levels.rs:72:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self) + --> $DIR/access_levels.rs:72:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: pub --> $DIR/access_levels.rs:14:13 | @@ -100,5 +130,5 @@ error: Public: pub(self), Exported: pub, Reachable: pub, ReachableFromImplTrait: LL | type B; | ^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 22 previous errors diff --git a/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs new file mode 100644 index 00000000000..fba4ffa1c6e --- /dev/null +++ b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs @@ -0,0 +1,11 @@ +// check-pass +// This is currently stable behavior, which was almost accidentally made an +// error in #102161 since there is no test exercising it. I am not sure if +// this _should_ be the desired behavior, but at least we should know if it +// changes. + +fn main() {} + +trait Foo { + fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32); +} diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index 1542c7f3118..33e18e35522 100644 --- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -7,7 +7,7 @@ // // no-prefer-dynamic // revisions: opt0 opt1 -// compile-flags: -Znew-llvm-pass-manager=yes -Zsanitizer=address -Clto=thin +// compile-flags: -Zsanitizer=address -Clto=thin //[opt0]compile-flags: -Copt-level=0 //[opt1]compile-flags: -Copt-level=1 // run-fail diff --git a/src/test/ui/span/E0493.rs b/src/test/ui/span/E0493.rs index ad4100205f2..625da25a7c2 100644 --- a/src/test/ui/span/E0493.rs +++ b/src/test/ui/span/E0493.rs @@ -15,7 +15,7 @@ impl Drop for Bar { } const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; -//~^ destructors cannot be evaluated at compile-time +//~^ ERROR destructor of fn main() { } diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr index 29d1b000943..9db627562d6 100644 --- a/src/test/ui/span/E0493.stderr +++ b/src/test/ui/span/E0493.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Foo, Foo)` cannot be evaluated at compile-time --> $DIR/E0493.rs:17:17 | LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to previous error diff --git a/src/test/ui/static/static-drop-scope.rs b/src/test/ui/static/static-drop-scope.rs index e7ea8663d5a..34afa9873a3 100644 --- a/src/test/ui/static/static-drop-scope.rs +++ b/src/test/ui/static/static-drop-scope.rs @@ -5,33 +5,33 @@ impl Drop for WithDtor { } static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of //~| ERROR temporary value dropped while borrowed const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of //~| ERROR temporary value dropped while borrowed static EARLY_DROP_S: i32 = (WithDtor, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const EARLY_DROP_C: i32 = (WithDtor, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const fn const_drop<T>(_: T) {} -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const fn const_drop2<T>(x: T) { (x, ()).1 - //~^ ERROR destructors cannot be evaluated at compile-time + //~^ ERROR destructor of } const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of const HELPER: Option<WithDtor> = Some(WithDtor); const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; -//~^ ERROR destructors cannot be evaluated at compile-time +//~^ ERROR destructor of fn main () {} diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr index ac32f217fd7..112bfc00304 100644 --- a/src/test/ui/static/static-drop-scope.stderr +++ b/src/test/ui/static/static-drop-scope.stderr @@ -1,10 +1,10 @@ -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:7:60 | LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:7:60 @@ -16,13 +16,13 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | | creates a temporary which is freed while still in use | using this value as a static requires that borrow lasts for `'static` -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:11:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed --> $DIR/static-drop-scope.rs:11:59 @@ -34,54 +34,54 @@ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | | creates a temporary which is freed while still in use | using this value as a constant requires that borrow lasts for `'static` -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:15:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here | | - | statics cannot evaluate destructors + | the destructor for this type cannot be evaluated in statics -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:18:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:21:24 | LL | const fn const_drop<T>(_: T) {} | ^ - value is dropped here | | - | constant functions cannot evaluate destructors + | the destructor for this type cannot be evaluated in constant functions -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:25:5 | LL | (x, ()).1 - | ^^^^^^^ constant functions cannot evaluate destructors + | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions LL | LL | } | - value is dropped here -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Option<WithDtor>, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:29:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | ^^^^^^^^^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants -error[E0493]: destructors cannot be evaluated at compile-time +error[E0493]: destructor of `(Option<WithDtor>, i32)` cannot be evaluated at compile-time --> $DIR/static-drop-scope.rs:34:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | ^^^^^^^^^^^ - value is dropped here | | - | constants cannot evaluate destructors + | the destructor for this type cannot be evaluated in constants error: aborting due to 10 previous errors diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs index f88572f8419..2dd7174a9be 100644 --- a/src/test/ui/structs/struct-path-associated-type.rs +++ b/src/test/ui/structs/struct-path-associated-type.rs @@ -13,7 +13,7 @@ fn f<T: Tr>() { //~^ ERROR expected struct, variant or union type, found associated type let z = T::A::<u8> {}; //~^ ERROR expected struct, variant or union type, found associated type - //~| ERROR type arguments are not allowed on this type + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied match S { T::A {} => {} //~^ ERROR expected struct, variant or union type, found associated type @@ -22,7 +22,7 @@ fn f<T: Tr>() { fn g<T: Tr<A = S>>() { let s = T::A {}; // OK - let z = T::A::<u8> {}; //~ ERROR type arguments are not allowed on this type + let z = T::A::<u8> {}; //~ ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied match S { T::A {} => {} // OK } diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr index bdce0e1b331..abb445214f3 100644 --- a/src/test/ui/structs/struct-path-associated-type.stderr +++ b/src/test/ui/structs/struct-path-associated-type.stderr @@ -4,13 +4,19 @@ error[E0071]: expected struct, variant or union type, found associated type LL | let s = T::A {}; | ^^^^ not a struct -error[E0109]: type arguments are not allowed on this type - --> $DIR/struct-path-associated-type.rs:14:20 +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/struct-path-associated-type.rs:14:16 | LL | let z = T::A::<u8> {}; - | - ^^ type argument not allowed + | ^------ help: remove these generics | | - | not allowed on this type + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/struct-path-associated-type.rs:4:10 + | +LL | type A; + | ^ error[E0071]: expected struct, variant or union type, found associated type --> $DIR/struct-path-associated-type.rs:14:13 @@ -24,13 +30,19 @@ error[E0071]: expected struct, variant or union type, found associated type LL | T::A {} => {} | ^^^^ not a struct -error[E0109]: type arguments are not allowed on this type - --> $DIR/struct-path-associated-type.rs:25:20 +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/struct-path-associated-type.rs:25:16 | LL | let z = T::A::<u8> {}; - | - ^^ type argument not allowed + | ^------ help: remove these generics | | - | not allowed on this type + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/struct-path-associated-type.rs:4:10 + | +LL | type A; + | ^ error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 @@ -52,5 +64,5 @@ LL | S::A {} => {} error: aborting due to 8 previous errors -Some errors have detailed explanations: E0071, E0109, E0223. +Some errors have detailed explanations: E0071, E0107, E0223. For more information about an error, try `rustc --explain E0071`. diff --git a/src/test/ui/suggestions/issue-101065.fixed b/src/test/ui/suggestions/issue-101065.fixed new file mode 100644 index 00000000000..88c716cc86c --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.fixed @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult<T> { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(FakeResult::Ok(())) //~ERROR E0308 + }; +} diff --git a/src/test/ui/suggestions/issue-101065.rs b/src/test/ui/suggestions/issue-101065.rs new file mode 100644 index 00000000000..2715f102708 --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.rs @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult<T> { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(()) //~ERROR E0308 + }; +} diff --git a/src/test/ui/suggestions/issue-101065.stderr b/src/test/ui/suggestions/issue-101065.stderr new file mode 100644 index 00000000000..6f7ecd24ca4 --- /dev/null +++ b/src/test/ui/suggestions/issue-101065.stderr @@ -0,0 +1,23 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-101065.rs:12:9 + | +LL | let _x = if true { + | ______________- +LL | | FakeResult::Ok(FakeResult::Ok(())) + | | ---------------------------------- expected because of this +LL | | } else { +LL | | FakeResult::Ok(()) + | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + | + = note: expected enum `FakeResult<FakeResult<()>>` + found enum `FakeResult<()>` +help: try wrapping the expression in `FakeResult::Ok` + | +LL | FakeResult::Ok(FakeResult::Ok(())) + | +++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout index 5fcdfca18d6..7fb90581f8a 100644 --- a/src/test/ui/thir-tree.stdout +++ b/src/test/ui/thir-tree.stdout @@ -33,7 +33,9 @@ Thir { region_scope: Node(2), lint_level: Explicit( HirId { - owner: DefId(0:3 ~ thir_tree[8f1d]::main), + owner: OwnerId { + def_id: DefId(0:3 ~ thir_tree[8f1d]::main), + }, local_id: 2, }, ), diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds.rs b/src/test/ui/type-alias-impl-trait/implied_bounds.rs new file mode 100644 index 00000000000..53cbf8d2290 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime<'a> = impl Equals<SelfType = ()>; +fn _defining_use<'a>() -> WithLifetime<'a> {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<'a>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<'a>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<'a>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl<S> Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds.stderr new file mode 100644 index 00000000000..6f11b66634b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs new file mode 100644 index 00000000000..b4c4c013cd2 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type Ty<'a, A> = impl Sized + 'a; +fn defining<'a, A>() -> Ty<'a, A> {} +fn assert_static<T: 'static>() {} +fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::<Ty<'a, A>>() } + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds3.rs b/src/test/ui/type-alias-impl-trait/implied_bounds3.rs new file mode 100644 index 00000000000..e39c613281d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds3.rs @@ -0,0 +1,18 @@ +// check-pass + +fn foo<F>(_: F) +where + F: 'static, +{ +} + +fn from<F: Send>(f: F) -> impl Send { + f +} + +fn bar<T>() { + foo(from(|| ())) +} + +fn main() { +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs new file mode 100644 index 00000000000..4cf35f95190 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs @@ -0,0 +1,31 @@ +trait StaticDefaultRef: 'static { + fn default_ref() -> &'static Self; +} + +impl StaticDefaultRef for str { + fn default_ref() -> &'static str { + "" + } +} + +fn into_impl(x: &str) -> &(impl ?Sized + AsRef<str> + StaticDefaultRef + '_) { + x +} + +fn extend_lifetime<'a>(x: &'a str) -> &'static str { + let t = into_impl(x); + helper(|_| t) //~ ERROR lifetime may not live long enough +} + +fn helper<T: ?Sized + AsRef<str> + StaticDefaultRef>(f: impl FnOnce(&T) -> &T) -> &'static str { + f(T::default_ref()).as_ref() +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr new file mode 100644 index 00000000000..151564c3b45 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_closure.rs:17:16 + | +LL | fn extend_lifetime<'a>(x: &'a str) -> &'static str { + | -- lifetime `'a` defined here +LL | let t = into_impl(x); +LL | helper(|_| t) + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs new file mode 100644 index 00000000000..8023cd24f0b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime<T> = impl Equals<SelfType = ()>; +fn _defining_use<T>() -> WithLifetime<T> {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<&'a ()>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<&'a ()>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<&'a ()>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl<S> Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr new file mode 100644 index 00000000000..cbc5e607318 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_from_types.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs new file mode 100644 index 00000000000..b6a7264a529 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs @@ -0,0 +1,27 @@ +#![feature(type_alias_impl_trait)] + +// known-bug: #99840 +// this should not compile +// check-pass + +type Alias = impl Sized; + +fn constrain() -> Alias { + 1i32 +} + +trait HideIt { + type Assoc; +} + +impl HideIt for () { + type Assoc = Alias; +} + +pub trait Yay {} + +impl Yay for <() as HideIt>::Assoc {} +// impl Yay for i32 {} // this already errors +// impl Yay for u32 {} // this also already errors + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs new file mode 100644 index 00000000000..6e5b8f491ea --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs @@ -0,0 +1,43 @@ +#![feature(type_alias_impl_trait)] + +mod test_lifetime_param { + type Ty<'a> = impl Sized; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_higher_kinded_lifetime_param { + type Ty<'a> = impl Sized; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_higher_kinded_lifetime_param2 { + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_type_param { + type Ty<A> = impl Sized; + fn defining<A>(s: A) -> Ty<A> { s } + fn assert_static<A: 'static>() {} + fn test<A>() where Ty<A>: 'static { assert_static::<A>() } + //~^ ERROR: parameter type `A` may not live long enough +} + +mod test_implied_from_fn_sig { + type Opaque<T: 'static> = impl Sized; + fn defining<T: 'static>() -> Opaque<T> {} + fn assert_static<T: 'static>() {} + fn test<T>(_: Opaque<T>) { assert_static::<T>(); } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr new file mode 100644 index 00000000000..887620a4d50 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -0,0 +1,58 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:6:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:15:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:22:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:8:43 + | +LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:17:46 + | +LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:24:21 + | +LL | fn test<'a>() { assert_static::<'a>() } + | -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | | + | lifetime `'a` defined here + +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:32:41 + | +LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() } + | ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() } + | +++++++++ + +error: aborting due to 4 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs new file mode 100644 index 00000000000..ac32dbde04b --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +mod test_type_param_static { + type Ty<A> = impl Sized + 'static; + //~^ ERROR: the parameter type `A` may not live long enough + fn defining<A: 'static>(s: A) -> Ty<A> { s } + fn assert_static<A: 'static>() {} + fn test<A>() where Ty<A>: 'static { assert_static::<A>() } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr new file mode 100644 index 00000000000..47bc31e78c3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:4:18 + | +LL | type Ty<A> = impl Sized + 'static; + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | type Ty<A: 'static> = impl Sized + 'static; + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs index f20ddf02071..477b61390ed 100644 --- a/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs +++ b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs @@ -16,7 +16,7 @@ fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> { } } -pub type RandGeneratorWithIndirection<'a> = impl Generator<Return = (), Yield = u64> + 'a; +pub type RandGeneratorWithIndirection<'c> = impl Generator<Return = (), Yield = u64> + 'c; pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> { fn helper<'b>(rng: &'b ()) -> impl 'b + Generator<Return = (), Yield = u64> { move || { diff --git a/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs b/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs new file mode 100644 index 00000000000..27ca7d0fdc9 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generators, generator_trait)] +#![feature(type_alias_impl_trait)] + +trait Trait {} + +impl<T> Trait for T {} + +type Foo<'c> = impl Trait + 'c; +fn foo<'a>(rng: &'a ()) -> Foo<'a> { + fn helper<'b>(rng: &'b ()) -> impl 'b + Trait { + rng + } + + helper(rng) +} + +fn main() { +} diff --git a/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs new file mode 100644 index 00000000000..f43ad7dce1d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +type Opaque<T> = impl Sized; +fn defining<T>() -> Opaque<T> {} +struct Ss<'a, T>(&'a Opaque<T>); + + +fn test<'a, T>(_: Ss<'a, T>) { + // test that we have an implied bound `Opaque<T>: 'a` from fn signature + None::<&'a Opaque<T>>; +} + +fn main() {} diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 501f9ef78ae..e54d71fc8e4 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -704,7 +704,7 @@ fn walk_parents<'tcx>( span, .. }) if span.ctxt() == ctxt => { - let ty = cx.tcx.type_of(def_id); + let ty = cx.tcx.type_of(def_id.def_id); Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx)) }, diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs index eb158d850fa..f48ba526d51 100644 --- a/src/tools/clippy/clippy_lints/src/doc.rs +++ b/src/tools/clippy/clippy_lints/src/doc.rs @@ -233,11 +233,11 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { cx, - typeck_results: cx.tcx.typeck(item.def_id), + typeck_results: cx.tcx.typeck(item.def_id.def_id), panic_span: None, }; fpu.visit_expr(body.value); - lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); + lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); } }, hir::ItemKind::Impl(impl_) => { @@ -268,7 +268,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let headers = check_attrs(cx, &self.valid_idents, attrs); if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if !in_external_macro(cx.tcx.sess, item.span) { - lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, None, None); + lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, None, None); } } } @@ -283,11 +283,11 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown { let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { cx, - typeck_results: cx.tcx.typeck(item.def_id), + typeck_results: cx.tcx.typeck(item.def_id.def_id), panic_span: None, }; fpu.visit_expr(body.value); - lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); + lint_for_missing_headers(cx, item.def_id.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span); } } } diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs index cd36f9fcd72..c39a909b3cc 100644 --- a/src/tools/clippy/clippy_lints/src/enum_variants.rs +++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs @@ -297,7 +297,7 @@ impl LateLintPass<'_> for EnumVariantNames { } } if let ItemKind::Enum(ref def, _) = item.kind { - if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id)) { + if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id.def_id)) { check_variant(cx, self.threshold, def, item_name, item.span); } } diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 327865e4c85..a6ddb26e2de 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { } } - let parent_id = cx.tcx.hir().get_parent_item(hir_id); + let parent_id = cx.tcx.hir().get_parent_item(hir_id).def_id; let parent_node = cx.tcx.hir().find_by_def_id(parent_id); let mut trait_self_ty = None; diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index 173d41b4b05..f3d9ebc5f12 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -73,7 +73,7 @@ impl LateLintPass<'_> for ExhaustiveItems { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if_chain! { if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind; - if cx.access_levels.is_exported(item.def_id); + if cx.access_levels.is_exported(item.def_id.def_id); let attrs = cx.tcx.hir().attrs(item.hir_id()); if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); then { diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs index cbf52d19334..407dd1b3957 100644 --- a/src/tools/clippy/clippy_lints/src/exit.rs +++ b/src/tools/clippy/clippy_lints/src/exit.rs @@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit { if let ExprKind::Path(ref path) = path_expr.kind; if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::EXIT); - let parent = cx.tcx.hir().get_parent_item(e.hir_id); + let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id; if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent); // If the next item up is a function we check if it is an entry point // and only then emit a linter warning diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 1f69f34a229..ef24a5d06ad 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -107,7 +107,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h let body = cx.tcx.hir().body(body_id); let mut fpu = FindPanicUnwrap { lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.id.def_id), + typeck_results: cx.tcx.typeck(impl_item.id.def_id.def_id), result: Vec::new(), }; fpu.visit_expr(body.value); diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 00a4937763e..d6d33bda173 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -21,7 +21,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id); + let is_public = cx.access_levels.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); @@ -31,7 +31,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> sig.decl, cx.tcx.hir().body(*body_id), item.span, - item.def_id, + item.def_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this function could have a `#[must_use]` attribute", ); @@ -41,19 +41,19 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id); + let is_public = cx.access_levels.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); - } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id).is_none() { + } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id.def_id).is_none() { check_must_use_candidate( cx, sig.decl, cx.tcx.hir().body(*body_id), item.span, - item.def_id, + item.def_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this method could have a `#[must_use]` attribute", ); @@ -63,7 +63,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { - let is_public = cx.access_levels.is_exported(item.def_id); + let is_public = cx.access_levels.is_exported(item.def_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); @@ -78,7 +78,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr sig.decl, body, item.span, - item.def_id, + item.def_id.def_id, item.span.with_hi(sig.decl.output.span().hi()), "this method could have a `#[must_use]` attribute", ); @@ -171,7 +171,7 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet) return false; // ignore `_` patterns } if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) { - is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys) + is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), pat.span, tys) } else { false } @@ -218,7 +218,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) && is_mutable_ty( self.cx, - self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), + self.cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), arg.span, &mut tys, ) @@ -236,7 +236,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> { if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id()) && is_mutable_ty( self.cx, - self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg), + self.cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg), arg.span, &mut tys, ) diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 3bbfa52e810..0b50431fbaa 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -28,7 +28,7 @@ pub(super) fn check_fn<'tcx>( pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind { let body = cx.tcx.hir().body(eid); - check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id); + check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id.def_id); } } diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 9591405cb06..113c4e9f509 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -34,9 +34,9 @@ fn result_err_ty<'tcx>( pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) { if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind - && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) + && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { - if cx.access_levels.is_exported(item.def_id) { + if cx.access_levels.is_exported(item.def_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -47,10 +47,10 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, l pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) { // Don't lint if method is a trait's implementation, we can't do anything about those if let hir::ImplItemKind::Fn(ref sig, _) = item.kind - && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) - && trait_ref_of_method(cx, item.def_id).is_none() + && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) + && trait_ref_of_method(cx, item.def_id.def_id).is_none() { - if cx.access_levels.is_exported(item.def_id) { + if cx.access_levels.is_exported(item.def_id.def_id) { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); check_result_unit_err(cx, err_ty, fn_header_span); } @@ -61,8 +61,8 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) { if let hir::TraitItemKind::Fn(ref sig, _) = item.kind { let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); - if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) { - if cx.access_levels.is_exported(item.def_id) { + if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id.def_id, item.span) { + if cx.access_levels.is_exported(item.def_id.def_id) { check_result_unit_err(cx, err_ty, fn_header_span); } check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 4f9680f60fe..804fdc2da08 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { } } - if !cx.access_levels.is_exported(item.def_id) { + if !cx.access_levels.is_exported(item.def_id.def_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs index 17d867aacb5..cb6c2ec0fb9 100644 --- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String); // Filters instances of to_string which are required by a trait - if trait_ref_of_method(cx, impl_item.def_id).is_none(); + if trait_ref_of_method(cx, impl_item.def_id.def_id).is_none(); then { show_lint(cx, impl_item); diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index b56d87c5348..2027c23d328 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { let name = item.ident.name.as_str(); if matches!(name, "iter" | "iter_mut") { if let TraitItemKind::Fn(fn_sig, _) = &item.kind { - check_sig(cx, name, fn_sig, item.def_id); + check_sig(cx, name, fn_sig, item.def_id.def_id); } } } @@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { ) { if let ImplItemKind::Fn(fn_sig, _) = &item.kind { - check_sig(cx, name, fn_sig, item.def_id); + check_sig(cx, name, fn_sig, item.def_id.def_id); } } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 7ae8ef830fa..7d15dd4cb21 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { if item.ident.name == sym::len; if let ImplItemKind::Fn(sig, _) = &item.kind; if sig.decl.implicit_self.has_implicit_self(); - if cx.access_levels.is_exported(item.def_id); + if cx.access_levels.is_exported(item.def_id.def_id); if matches!(sig.decl.output, FnRetTy::Return(_)); if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()); if imp.of_trait.is_none(); @@ -210,7 +210,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items } } - if cx.access_levels.is_exported(visited_trait.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) + if cx.access_levels.is_exported(visited_trait.def_id.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len)) { let mut current_and_super_traits = DefIdSet::default(); fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx); diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 643a7cfd577..399a03187d9 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { if let ImplItemKind::Fn(ref sig, id) = item.kind { - let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id).is_none(); + let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id.def_id).is_none(); check_fn_inner( cx, sig.decl, @@ -276,7 +276,7 @@ fn could_use_elision<'tcx>( let mut checker = BodyLifetimeChecker { lifetimes_used_in_body: false, }; - checker.visit_expr(body.value); + checker.visit_expr(&body.value); if checker.lifetimes_used_in_body { return false; } diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index fce2d54639c..be7f96e9bb0 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -69,7 +69,7 @@ fn check_for_mutation<'tcx>( ExprUseVisitor::new( &mut delegate, &infcx, - body.hir_id.owner, + body.hir_id.owner.def_id, cx.param_env, cx.typeck_results(), ) diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 2b04475c7a9..53e7565bd33 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -166,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { if let Some((id, span)) = iter.next() && iter.next().is_none() { - self.potential_enums.push((item.def_id, id, item.span, span)); + self.potential_enums.push((item.def_id.def_id, id, item.span, span)); } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index cdde4c54d63..ddb6d1ca26c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3250,7 +3250,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { return; } let name = impl_item.ident.name.as_str(); - let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(parent); let self_ty = cx.tcx.type_of(item.def_id); @@ -3259,7 +3259,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind; if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next(); - let method_sig = cx.tcx.fn_sig(impl_item.def_id); + let method_sig = cx.tcx.fn_sig(impl_item.def_id.def_id); let method_sig = cx.tcx.erase_late_bound_regions(method_sig); let first_arg_ty = method_sig.inputs().iter().next(); @@ -3269,7 +3269,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { then { // if this impl block implements a trait, lint in trait definition instead - if !implements_trait && cx.access_levels.is_exported(impl_item.def_id) { + if !implements_trait && cx.access_levels.is_exported(impl_item.def_id.def_id) { // check missing trait implementations for method_config in &TRAIT_METHODS { if name == method_config.method_name && @@ -3301,7 +3301,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if sig.decl.implicit_self.has_implicit_self() && !(self.avoid_breaking_exported_api - && cx.access_levels.is_exported(impl_item.def_id)) + && cx.access_levels.is_exported(impl_item.def_id.def_id)) { wrong_self_convention::check( cx, diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index bc304c081b9..f24b41411c8 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { // Const fns are not allowed as methods in a trait. { - let parent = cx.tcx.hir().get_parent_item(hir_id); + let parent = cx.tcx.hir().get_parent_item(hir_id).def_id; if parent != CRATE_DEF_ID { if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent) { if let hir::ItemKind::Trait(..) = &item.kind { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 3701fdb4adb..47219556676 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { hir::ItemKind::Fn(..) => { // ignore main() if it.ident.name == sym::main { - let at_root = cx.tcx.local_parent(it.def_id) == CRATE_DEF_ID; + let at_root = cx.tcx.local_parent(it.def_id.def_id) == CRATE_DEF_ID; if at_root { return; } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 07bc2ca5d3c..9d5764ac092 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { return; } - if !cx.access_levels.is_exported(it.def_id) { + if !cx.access_levels.is_exported(it.def_id.def_id) { return; } match it.kind { @@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } // If the item being implemented is not exported, then we don't need #[inline] - if !cx.access_levels.is_exported(impl_item.def_id) { + if !cx.access_levels.is_exported(impl_item.def_id.def_id) { return; } @@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { }; if let Some(trait_def_id) = trait_def_id { - if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id) { + if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id.def_id) { // If a trait is being implemented for an item, and the // trait is not exported, we don't need #[inline] return; diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index 4db103bbc13..25d6ca83a94 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) { if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind { - if trait_ref_of_method(cx, item.def_id).is_none() { + if trait_ref_of_method(cx, item.def_id.def_id).is_none() { check_sig(cx, item.hir_id(), sig.decl); } } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 5c45ee6d94a..357a71693d2 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // can't be implemented for unsafe new return; } - if cx.tcx.is_doc_hidden(impl_item.def_id) { + if cx.tcx.is_doc_hidden(impl_item.def_id.def_id) { // shouldn't be implemented when it is hidden in docs return; } @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if_chain! { if sig.decl.inputs.is_empty(); if name == sym::new; - if cx.access_levels.is_reachable(impl_item.def_id); + if cx.access_levels.is_reachable(impl_item.def_id.def_id); let self_def_id = cx.tcx.hir().get_parent_item(id); let self_ty = cx.tcx.type_of(self_def_id); if self_ty == return_ty(cx, id); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index b1588452732..616ef9e2f86 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind { - let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(item_def_id); match &item.kind { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 6217110a1f3..d64a9cf71e1 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -243,7 +243,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { .. })) => { #[allow(trivial_casts)] - if let Some(Node::Item(item)) = get_parent_node(cx.tcx, cx.tcx.hir().local_def_id_to_hir_id(def_id)) + if let Some(Node::Item(item)) = get_parent_node(cx.tcx, def_id.into()) && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.def_id) && let Some(trait_item_id) = cx.tcx.associated_item(def_id).trait_item_def_id { diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs index 945a09a647c..2c22c8b3d08 100644 --- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( if_chain! { if let Some((_, lang_item)) = binop_traits(op.node); if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item); - let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id); + let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id; if trait_ref_of_method(cx, parent_fn) .map_or(true, |t| t.path.res.def_id() != trait_id); if implements_trait(cx, ty, trait_id, &[rty.into()]); diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 0960b050c24..6b2eea48932 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind { - self.check_poly_fn(cx, item.def_id, method_sig.decl, None); + self.check_poly_fn(cx, item.def_id.def_id, method_sig.decl, None); } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 323326381d4..3c6ca9d9897 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -46,8 +46,8 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]); impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if_chain! { - if cx.tcx.visibility(item.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); - if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false); + if cx.tcx.visibility(item.def_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id()); + if !cx.access_levels.is_exported(item.def_id.def_id) && self.is_exported.last() == Some(&false); if is_not_macro_export(item); then { let span = item.span.with_hi(item.ident.span.hi()); @@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } if let ItemKind::Mod { .. } = item.kind { - self.is_exported.push(cx.access_levels.is_exported(item.def_id)); + self.is_exported.push(cx.access_levels.is_exported(item.def_id.def_id)); } } diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 60be6bd335f..16d702a3868 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) { if let TraitItemKind::Fn(ref sig, _) = item.kind { - check_method(cx, sig.decl, item.def_id, item.span, item.hir_id()); + check_method(cx, sig.decl, item.def_id.def_id, item.span, item.hir_id()); } } } diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 9cea4d88067..1ac538f4c7c 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { _ => return, } - let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let item = cx.tcx.hir().expect_item(parent); let self_ty = cx.tcx.type_of(item.def_id); let ret_ty = return_ty(cx, impl_item.hir_id()); diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index 6add20c1fb7..d47ed459387 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -64,11 +64,11 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl { // Check for more than one binary operation in the implemented function // Linting when multiple operations are involved can result in false positives - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn); if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind; let body = cx.tcx.hir().body(body_id); - let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn); let trait_id = trait_ref.path.res.def_id(); if ![binop_trait_id, op_assign_trait_id].contains(&trait_id); diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs index 8bdadf24402..8e90d20265c 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs @@ -42,7 +42,7 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>( /// messages. This function will panic if that occurs. fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option<CastKind> { let hir_id = e.hir_id; - let local_def_id = hir_id.owner; + let local_def_id = hir_id.owner.def_id; Inherited::build(cx.tcx, local_def_id).enter(|inherited| { let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 94945b2e1a9..1268c23206a 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -104,7 +104,7 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did); if let GenericParamKind::Type { synthetic, .. } = generic_param.kind; if synthetic; - if let Some(generics) = cx.tcx.hir().get_generics(id.owner); + if let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id); if let Some(pred) = generics.bounds_for_param(did.expect_local()).next(); then { Some(pred.bounds) diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 353a6f6b899..aca55817c52 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -313,7 +313,7 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO impl<'tcx> LateLintPass<'tcx> for Types { fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) { let is_in_trait_impl = - if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id)) { + if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id).def_id) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { false @@ -333,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - let is_exported = cx.access_levels.is_exported(item.def_id); + let is_exported = cx.access_levels.is_exported(item.def_id.def_id); match item.kind { ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty( @@ -353,7 +353,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { match item.kind { ImplItemKind::Const(ty, _) => { let is_in_trait_impl = if let Some(hir::Node::Item(item)) = - cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id())) + cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(item.hir_id()).def_id) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { @@ -390,7 +390,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) { - let is_exported = cx.access_levels.is_exported(item.def_id); + let is_exported = cx.access_levels.is_exported(item.def_id.def_id); let context = CheckTyContext { is_exported, diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 51c65d898cf..713fe06bad4 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -54,14 +54,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { if impl_item.span.from_expansion() { return; } - let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()); + let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id; let parent_item = cx.tcx.hir().expect_item(parent); let assoc_item = cx.tcx.associated_item(impl_item.def_id); if_chain! { if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind; if assoc_item.fn_has_self_parameter; if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; - if !cx.access_levels.is_exported(impl_item.def_id) || !self.avoid_breaking_exported_api; + if !cx.access_levels.is_exported(impl_item.def_id.def_id) || !self.avoid_breaking_exported_api; let body = cx.tcx.hir().body(*body_id); if let [self_param, ..] = body.params; if !is_local_used(cx, body, self_param.pat.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs index 46020adcaa2..baa53ba664f 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs @@ -111,7 +111,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tc let body = cx.tcx.hir().body(body_id); let mut fpu = FindExpectUnwrap { lcx: cx, - typeck_results: cx.tcx.typeck(impl_item.def_id), + typeck_results: cx.tcx.typeck(impl_item.def_id.def_id), result: Vec::new(), }; fpu.visit_expr(body.value); diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 02bf09ed506..2c71f35d490 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -105,7 +105,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms { fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) { // do not lint public items or in macros if in_external_macro(cx.sess(), it.span) - || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id)) + || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id.def_id)) { return; } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 44ab9bca795..ce51cb693fc 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { if !is_from_proc_macro(cx, item); // expensive, should be last check then { StackItem::Check { - impl_id: item.def_id, + impl_id: item.def_id.def_id, in_body: 0, types_to_skip: std::iter::once(self_ty.hir_id).collect(), } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4003fff27c0..1df3135c962 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -140,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for Author { fn check_item(cx: &LateContext<'_>, hir_id: HirId) { let hir = cx.tcx.hir(); - if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) { + if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner().def_id) { check_node(cx, hir_id, |v| { v.expr(&v.bind("expr", hir.body(body_id).value)); }); diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 5418eca382d..2604b1ee7c5 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -120,14 +120,14 @@ impl LateLintPass<'_> for WildcardImports { if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } - let module = cx.tcx.parent_module_from_def_id(item.def_id); - if cx.tcx.visibility(item.def_id) != ty::Visibility::Restricted(module.to_def_id()) { + let module = cx.tcx.parent_module_from_def_id(item.def_id.def_id); + if cx.tcx.visibility(item.def_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) { return; } if_chain! { if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(item, use_path.segments); - let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id); + let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id.def_id); if !used_imports.is_empty(); // Already handled by `unused_imports` then { let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index 8dc43c0e294..386f3c527f1 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -72,7 +72,7 @@ fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool { let second_parent_id = cx .tcx .hir() - .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(parent_id)); + .get_parent_item(parent_id.into()).def_id; if let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(second_parent_id) { if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind { return true; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 62da850a15e..9343cf457b3 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -78,7 +78,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; @@ -212,7 +212,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option< /// } /// ``` pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool { - let parent_id = cx.tcx.hir().get_parent_item(id); + let parent_id = cx.tcx.hir().get_parent_item(id).def_id; match cx.tcx.hir().get_by_def_id(parent_id) { Node::Item(&Item { kind: ItemKind::Const(..) | ItemKind::Static(..), @@ -597,8 +597,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) -> let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); let parent_impl = cx.tcx.hir().get_parent_item(hir_id); if_chain! { - if parent_impl != CRATE_DEF_ID; - if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl); + if parent_impl != hir::CRATE_OWNER_ID; + if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id); if let hir::ItemKind::Impl(impl_) = &item.kind; then { return impl_.of_trait.as_ref(); @@ -1104,7 +1104,7 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { /// Gets the name of the item the expression is in, if available. pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> { - let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id); + let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id; match cx.tcx.hir().find_by_def_id(parent_id) { Some( Node::Item(Item { ident, .. }) @@ -1648,7 +1648,7 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool return true; } prev_enclosing_node = Some(enclosing_node); - enclosing_node = map.local_def_id_to_hir_id(map.get_parent_item(enclosing_node)); + enclosing_node = map.get_parent_item(enclosing_node).into(); } false diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 405f0228683..f7ce7191772 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -367,10 +367,21 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<RustcVersion>) -> bo // Checking MSRV is manually necessary because `rustc` has no such concept. This entire // function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`. // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. + + // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver` doesn't accept + // the `-dev` version number so we have to strip it off. + let short_version = since + .as_str() + .split('-') + .next() + .expect("rustc_attr::StabilityLevel::Stable::since` is empty"); + + let since = rustc_span::Symbol::intern(short_version); + crate::meets_msrv( msrv, RustcVersion::parse(since.as_str()) - .expect("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted"), + .unwrap_or_else(|err| panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}")), ) } else { // Unstable const fn with the feature enabled. diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs index 3af5dfb62f9..a7c08839f52 100644 --- a/src/tools/clippy/clippy_utils/src/usage.rs +++ b/src/tools/clippy/clippy_utils/src/usage.rs @@ -21,7 +21,7 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> ExprUseVisitor::new( &mut delegate, &infcx, - expr.hir_id.owner, + expr.hir_id.owner.def_id, cx.param_env, cx.typeck_results(), ) diff --git a/src/tools/clippy/tests/ui/crashes/ice-7126.rs b/src/tools/clippy/tests/ui/crashes/ice-7126.rs index ca563ba0978..b2dc2248b55 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7126.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-7126.rs @@ -1,13 +1,13 @@ // This test requires a feature gated const fn and will stop working in the future. -#![feature(const_btree_new)] +#![feature(const_btree_len)] use std::collections::BTreeMap; -struct Foo(BTreeMap<i32, i32>); +struct Foo(usize); impl Foo { fn new() -> Self { - Self(BTreeMap::new()) + Self(BTreeMap::len(&BTreeMap::<u8, u8>::new())) } } |
