From b2bfa1049fe6ca6ad903e947547e230ee54b1a34 Mon Sep 17 00:00:00 2001 From: NotLebedev Date: Tue, 27 May 2025 11:12:05 +0300 Subject: [PATCH 01/28] Add discriminant_for_variant to AdtDef --- compiler/rustc_smir/src/rustc_smir/context.rs | 16 ++++++++++++++-- .../src/stable_mir/compiler_interface.rs | 9 +++++++-- compiler/rustc_smir/src/stable_mir/ty.rs | 9 +++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index bac5c9066f1f6..a803961276a4c 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -22,9 +22,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty, - TyConst, TyKind, UintTy, VariantDef, + TyConst, TyKind, UintTy, VariantDef, VariantIdx, }; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; @@ -440,6 +440,18 @@ impl<'tcx> SmirCtxt<'tcx> { def.internal(&mut *tables, tcx).variants().len() } + /// Discriminant for a given variant index of AdtDef + pub fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + + let discr = adt + .internal(&mut *tables, tcx) + .discriminant_for_variant(tcx, variant.internal(&mut *tables, tcx)); + + Discr { val: discr.val, ty: discr.ty.stable(&mut *tables) } + } + /// The name of a variant. pub fn variant_name(&self, def: VariantDef) -> Symbol { let mut tables = self.0.borrow_mut(); diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs index bb35e23a72884..510ee699be0fc 100644 --- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs +++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs @@ -13,10 +13,10 @@ use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::MachineInfo; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, - TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, + TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, }; use stable_mir::{ AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, @@ -225,6 +225,11 @@ impl<'tcx> SmirInterface<'tcx> { self.cx.adt_variants_len(def) } + /// Discriminant for a given variant index of AdtDef + pub(crate) fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + self.cx.adt_discr_for_variant(adt, variant) + } + /// The name of a variant. pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol { self.cx.variant_name(def) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index e331e5934716a..d439142f5fde1 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -818,6 +818,15 @@ impl AdtDef { pub fn variant(&self, idx: VariantIdx) -> Option { (idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self }) } + + pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr { + with(|cx| cx.adt_discr_for_variant(*self, idx)) + } +} + +pub struct Discr { + pub val: u128, + pub ty: Ty, } /// Definition of a variant, which can be either a struct / union field or an enum variant. From a2d5942e3693ca534ba40c28c7c655574ff475d3 Mon Sep 17 00:00:00 2001 From: NotLebedev Date: Tue, 27 May 2025 11:18:37 +0300 Subject: [PATCH 02/28] Add discriminant_for_variant to CoroutineDef --- compiler/rustc_smir/src/rustc_smir/context.rs | 28 ++++++++++++++++--- .../src/stable_mir/compiler_interface.rs | 18 +++++++++--- compiler/rustc_smir/src/stable_mir/ty.rs | 6 ++++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index a803961276a4c..ebf91a3e370d8 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -12,7 +12,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ - GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, + CoroutineArgsExt, GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, + ValTree, }; use rustc_middle::{mir, ty}; use rustc_span::def_id::LOCAL_CRATE; @@ -22,9 +23,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Discr, FieldDef, FnDef, ForeignDef, - ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty, - TyConst, TyKind, UintTy, VariantDef, VariantIdx, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, + ForeignDef, ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, + Span, Ty, TyConst, TyKind, UintTy, VariantDef, VariantIdx, }; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; @@ -452,6 +453,25 @@ impl<'tcx> SmirCtxt<'tcx> { Discr { val: discr.val, ty: discr.ty.stable(&mut *tables) } } + /// Discriminant for a given variand index and args of a coroutine + pub fn coroutine_discr_for_variant( + &self, + coroutine: CoroutineDef, + args: &GenericArgs, + variant: VariantIdx, + ) -> Discr { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + + let discr = args.internal(&mut *tables, tcx).as_coroutine().discriminant_for_variant( + coroutine.def_id().internal(&mut *tables, tcx), + tcx, + variant.internal(&mut *tables, tcx), + ); + + Discr { val: discr.val, ty: discr.ty.stable(&mut *tables) } + } + /// The name of a variant. pub fn variant_name(&self, def: VariantDef) -> Symbol { let mut tables = self.0.borrow_mut(); diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs index 510ee699be0fc..18313f11c460c 100644 --- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs +++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs @@ -13,10 +13,10 @@ use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::MachineInfo; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Discr, FieldDef, FnDef, ForeignDef, - ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, - ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, - TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, + ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, + Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, + TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, }; use stable_mir::{ AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, @@ -230,6 +230,16 @@ impl<'tcx> SmirInterface<'tcx> { self.cx.adt_discr_for_variant(adt, variant) } + /// Discriminant for a given variand index and args of a coroutine + pub(crate) fn coroutine_discr_for_variant( + &self, + coroutine: CoroutineDef, + args: &GenericArgs, + variant: VariantIdx, + ) -> Discr { + self.cx.coroutine_discr_for_variant(coroutine, args, variant) + } + /// The name of a variant. pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol { self.cx.variant_name(def) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index d439142f5fde1..6976a6e8c6bad 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -747,6 +747,12 @@ crate_def! { pub CoroutineDef; } +impl CoroutineDef { + pub fn discriminant_for_variant(&self, args: &GenericArgs, idx: VariantIdx) -> Discr { + with(|cx| cx.coroutine_discr_for_variant(*self, args, idx)) + } +} + crate_def! { #[derive(Serialize)] pub CoroutineClosureDef; From 7d13f8d470c25f68e3ba81a930dfccea5a9210bd Mon Sep 17 00:00:00 2001 From: NotLebedev Date: Thu, 27 Mar 2025 22:20:42 +0300 Subject: [PATCH 03/28] Implement Stable for Discr --- compiler/rustc_smir/src/rustc_smir/context.rs | 21 +++++++------------ .../rustc_smir/src/rustc_smir/convert/ty.rs | 8 +++++++ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index ebf91a3e370d8..7d9679cd67d74 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -445,12 +445,9 @@ impl<'tcx> SmirCtxt<'tcx> { pub fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; - - let discr = adt - .internal(&mut *tables, tcx) - .discriminant_for_variant(tcx, variant.internal(&mut *tables, tcx)); - - Discr { val: discr.val, ty: discr.ty.stable(&mut *tables) } + let adt = adt.internal(&mut *tables, tcx); + let variant = variant.internal(&mut *tables, tcx); + adt.discriminant_for_variant(tcx, variant).stable(&mut *tables) } /// Discriminant for a given variand index and args of a coroutine @@ -462,14 +459,10 @@ impl<'tcx> SmirCtxt<'tcx> { ) -> Discr { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; - - let discr = args.internal(&mut *tables, tcx).as_coroutine().discriminant_for_variant( - coroutine.def_id().internal(&mut *tables, tcx), - tcx, - variant.internal(&mut *tables, tcx), - ); - - Discr { val: discr.val, ty: discr.ty.stable(&mut *tables) } + let coroutine = coroutine.def_id().internal(&mut *tables, tcx); + let args = args.internal(&mut *tables, tcx); + let variant = variant.internal(&mut *tables, tcx); + args.as_coroutine().discriminant_for_variant(coroutine, tcx, variant).stable(&mut *tables) } /// The name of a variant. diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 8bcac4c4678e4..a5a90549157c0 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -959,3 +959,11 @@ impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { } } } + +impl<'tcx> Stable<'tcx> for rustc_middle::ty::util::Discr<'tcx> { + type T = stable_mir::ty::Discr; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables) } + } +} From becdd21b77398496970951a41492ac236ecdfc9b Mon Sep 17 00:00:00 2001 From: NotLebedev Date: Wed, 4 Jun 2025 13:28:48 +0300 Subject: [PATCH 04/28] Add test for `AdtDef::discriminant_for_variant` --- tests/ui-fulldeps/stable-mir/check_variant.rs | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/ui-fulldeps/stable-mir/check_variant.rs diff --git a/tests/ui-fulldeps/stable-mir/check_variant.rs b/tests/ui-fulldeps/stable-mir/check_variant.rs new file mode 100644 index 0000000000000..61dc3c4e4b396 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_variant.rs @@ -0,0 +1,154 @@ +//@ run-pass +//! Test that users are able to use stable mir APIs to retrieve type information from a crate item +//! definition. + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ edition: 2024 + +#![feature(rustc_private)] +#![feature(assert_matches)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use std::io::Write; +use std::ops::ControlFlow; + +use stable_mir::CrateItem; +use stable_mir::crate_def::CrateDef; +use stable_mir::mir::{AggregateKind, Rvalue, Statement, StatementKind}; +use stable_mir::ty::{IntTy, RigidTy, Ty}; + +const CRATE_NAME: &str = "crate_variant_ty"; + +/// Test if we can retrieve discriminant info for different types. +fn test_def_tys() -> ControlFlow<()> { + check_adt_mono(); + check_adt_poly(); + + ControlFlow::Continue(()) +} + +fn check_adt_mono() { + let mono = get_fn("mono").expect_body(); + + check_statement_is_aggregate_assign( + &mono.blocks[0].statements[0], + 0, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &mono.blocks[1].statements[0], + 1, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &mono.blocks[2].statements[0], + 2, + RigidTy::Int(IntTy::Isize), + ); +} + +fn check_adt_poly() { + let poly = get_fn("poly").expect_body(); + + check_statement_is_aggregate_assign( + &poly.blocks[0].statements[0], + 0, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[1].statements[0], + 1, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[2].statements[0], + 2, + RigidTy::Int(IntTy::Isize), + ); +} + +fn get_fn(name: &str) -> CrateItem { + stable_mir::all_local_items().into_iter().find(|it| it.name().eq(name)).unwrap() +} + +fn check_statement_is_aggregate_assign( + statement: &Statement, + expected_discr_val: u128, + expected_discr_ty: RigidTy, +) { + if let Statement { kind: StatementKind::Assign(_, rvalue), .. } = statement + && let Rvalue::Aggregate(aggregate, _) = rvalue + && let AggregateKind::Adt(adt_def, variant_idx, ..) = aggregate + { + let discr = adt_def.discriminant_for_variant(*variant_idx); + + assert_eq!(discr.val, expected_discr_val); + assert_eq!(discr.ty, Ty::from_rigid_kind(expected_discr_ty)); + } else { + unreachable!("Unexpected statement"); + } +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "defs_ty_input.rs"; + generate_input(&path).unwrap(); + let args = &[ + "rustc".to_string(), + "-Cpanic=abort".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_def_tys).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + use std::hint::black_box; + + enum Mono {{ + A, + B(i32), + C {{ a: i32, b: u32 }}, + }} + + enum Poly {{ + A, + B(T), + C {{ t: T }}, + }} + + pub fn main() {{ + mono(); + }} + + fn mono() {{ + black_box(Mono::A); + black_box(Mono::B(6)); + black_box(Mono::C {{a: 1, b: 10 }}); + }} + + fn poly() {{ + black_box(Poly::::A); + black_box(Poly::B(1i32)); + black_box(Poly::C {{ t: 1i32 }}); + }} + "# + )?; + Ok(()) +} From a39e98fe1da2772baa55b27eef7e56e55ac09675 Mon Sep 17 00:00:00 2001 From: NotLebedev Date: Wed, 4 Jun 2025 14:25:37 +0300 Subject: [PATCH 05/28] Add test for `AdtDef::discriminant_for_variant` polymorphic over parameter --- tests/ui-fulldeps/stable-mir/check_variant.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/ui-fulldeps/stable-mir/check_variant.rs b/tests/ui-fulldeps/stable-mir/check_variant.rs index 61dc3c4e4b396..412fb8be35751 100644 --- a/tests/ui-fulldeps/stable-mir/check_variant.rs +++ b/tests/ui-fulldeps/stable-mir/check_variant.rs @@ -31,6 +31,7 @@ const CRATE_NAME: &str = "crate_variant_ty"; fn test_def_tys() -> ControlFlow<()> { check_adt_mono(); check_adt_poly(); + check_adt_poly2(); ControlFlow::Continue(()) } @@ -75,6 +76,26 @@ fn check_adt_poly() { ); } +fn check_adt_poly2() { + let poly = get_fn("poly2").expect_body(); + + check_statement_is_aggregate_assign( + &poly.blocks[0].statements[0], + 0, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[1].statements[0], + 1, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[2].statements[0], + 2, + RigidTy::Int(IntTy::Isize), + ); +} + fn get_fn(name: &str) -> CrateItem { stable_mir::all_local_items().into_iter().find(|it| it.name().eq(name)).unwrap() } @@ -135,6 +156,8 @@ fn generate_input(path: &str) -> std::io::Result<()> { pub fn main() {{ mono(); + poly(); + poly2::(1); }} fn mono() {{ @@ -148,6 +171,12 @@ fn generate_input(path: &str) -> std::io::Result<()> { black_box(Poly::B(1i32)); black_box(Poly::C {{ t: 1i32 }}); }} + + fn poly2(t: T) {{ + black_box(Poly::::A); + black_box(Poly::B(t)); + black_box(Poly::C {{ t: t }}); + }} "# )?; Ok(()) From 443e45ca01511a4a86314becd443f6735ee2554e Mon Sep 17 00:00:00 2001 From: NotLebedev Date: Fri, 6 Jun 2025 15:25:32 +0300 Subject: [PATCH 06/28] Fix test description --- tests/ui-fulldeps/stable-mir/check_variant.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui-fulldeps/stable-mir/check_variant.rs b/tests/ui-fulldeps/stable-mir/check_variant.rs index 412fb8be35751..b0de3369830b2 100644 --- a/tests/ui-fulldeps/stable-mir/check_variant.rs +++ b/tests/ui-fulldeps/stable-mir/check_variant.rs @@ -1,6 +1,6 @@ //@ run-pass -//! Test that users are able to use stable mir APIs to retrieve type information from a crate item -//! definition. +//! Test that users are able to use stable mir APIs to retrieve +//! discriminant value and type for AdtDef and Coroutine variants //@ ignore-stage1 //@ ignore-cross-compile From 3fce086d79afd9bc5b52a13e051934694cf196c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Jun 2025 21:10:27 +0000 Subject: [PATCH 07/28] Make E0621 missing lifetime suggestion verbose ``` error[E0621]: explicit lifetime required in the type of `x` --> $DIR/42701_one_named_and_one_anonymous.rs:10:9 | LL | &*x | ^^^ lifetime `'a` required | help: add explicit lifetime `'a` to the type of `x` | LL | fn foo2<'a>(a: &'a Foo, x: &'a i32) -> &'a i32 { | ++ ``` --- compiler/rustc_trait_selection/src/errors.rs | 12 ++++++++---- ...hout-precise-captures-we-are-powerless.stderr | 16 ++++++++++------ tests/ui/async-await/issues/issue-63388-1.stderr | 9 ++++++--- .../must_outlive_least_region_or_bound.stderr | 9 ++++++--- tests/ui/issues/issue-13058.stderr | 8 +++++--- tests/ui/issues/issue-14285.stderr | 8 ++++++-- tests/ui/issues/issue-15034.stderr | 7 +++++-- tests/ui/issues/issue-3154.stderr | 7 +++++-- tests/ui/issues/issue-40288-2.stderr | 16 ++++++++++------ .../42701_one_named_and_one_anonymous.stderr | 8 +++++--- ...ne-existing-name-early-bound-in-struct.stderr | 8 +++++--- ...ex1-return-one-existing-name-if-else-2.stderr | 7 +++++-- ...ex1-return-one-existing-name-if-else-3.stderr | 7 +++++-- ...one-existing-name-if-else-using-impl-2.stderr | 7 +++++-- ...one-existing-name-if-else-using-impl-3.stderr | 7 +++++-- .../ex1-return-one-existing-name-if-else.stderr | 7 +++++-- .../ex2a-push-one-existing-name-2.stderr | 7 +++++-- ...x2a-push-one-existing-name-early-bound.stderr | 8 +++++--- .../ex2a-push-one-existing-name.stderr | 7 +++++-- tests/ui/lifetimes/noisy-follow-up-erro.stderr | 9 ++++++--- ...object-lifetime-default-from-box-error.stderr | 8 +++++--- tests/ui/regions/regions-glb-free-free.stderr | 7 +++++-- .../regions/regions-infer-at-fn-not-param.stderr | 9 ++++++--- .../missing-lifetimes-in-signature.stderr | 8 +++++--- tests/ui/variance/variance-trait-matching.stderr | 8 +++++--- 25 files changed, 143 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 06f81ac554e62..7bf49056e2991 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -759,7 +759,8 @@ pub enum ExplicitLifetimeRequired<'a> { #[suggestion( trait_selection_explicit_lifetime_required_sugg_with_ident, code = "{new_ty}", - applicability = "unspecified" + applicability = "unspecified", + style = "verbose" )] new_ty_span: Span, #[skip_arg] @@ -774,7 +775,8 @@ pub enum ExplicitLifetimeRequired<'a> { #[suggestion( trait_selection_explicit_lifetime_required_sugg_with_param_type, code = "{new_ty}", - applicability = "unspecified" + applicability = "unspecified", + style = "verbose" )] new_ty_span: Span, #[skip_arg] @@ -1462,7 +1464,8 @@ pub enum SuggestAccessingField<'a> { #[suggestion( trait_selection_suggest_accessing_field, code = "{snippet}.{name}", - applicability = "maybe-incorrect" + applicability = "maybe-incorrect", + style = "verbose" )] Safe { #[primary_span] @@ -1474,7 +1477,8 @@ pub enum SuggestAccessingField<'a> { #[suggestion( trait_selection_suggest_accessing_field, code = "unsafe {{ {snippet}.{name} }}", - applicability = "maybe-incorrect" + applicability = "maybe-incorrect", + style = "verbose" )] Unsafe { #[primary_span] diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr index 329cec6dad3a3..b7259074bf64b 100644 --- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr +++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr @@ -106,11 +106,13 @@ LL | } error[E0621]: explicit lifetime required in the type of `x` --> $DIR/without-precise-captures-we-are-powerless.rs:38:5 | -LL | fn through_field_and_ref<'a>(x: &S<'a>) { - | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` -... LL | outlives::<'a>(call_once(c)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn through_field_and_ref<'a>(x: &'a S<'a>) { + | ++ error[E0597]: `c` does not live long enough --> $DIR/without-precise-captures-we-are-powerless.rs:43:20 @@ -131,11 +133,13 @@ LL | } error[E0621]: explicit lifetime required in the type of `x` --> $DIR/without-precise-captures-we-are-powerless.rs:44:5 | -LL | fn through_field_and_ref_move<'a>(x: &S<'a>) { - | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` -... LL | outlives::<'a>(call_once(c)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn through_field_and_ref_move<'a>(x: &'a S<'a>) { + | ++ error: aborting due to 10 previous errors diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index 277f7fa6f63ed..a59fe7dbc20e6 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -1,11 +1,14 @@ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:14:9 | -LL | &'a self, foo: &dyn Foo - | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` -... LL | foo | ^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `foo` + | +LL - &'a self, foo: &dyn Foo +LL + &'a self, foo: &'a (dyn Foo + 'a) + | error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index ba7d7770e5038..53c5568660417 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -65,9 +65,12 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/must_outlive_least_region_or_bound.rs:15:41 | LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } - | ---- ^ lifetime `'a` required - | | - | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` + | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn foo<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ++ error: lifetime may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:30:55 diff --git a/tests/ui/issues/issue-13058.stderr b/tests/ui/issues/issue-13058.stderr index 7cc2860eb5086..4f4108fa18254 100644 --- a/tests/ui/issues/issue-13058.stderr +++ b/tests/ui/issues/issue-13058.stderr @@ -1,11 +1,13 @@ error[E0621]: explicit lifetime required in the type of `cont` --> $DIR/issue-13058.rs:14:21 | -LL | fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool - | -- help: add explicit lifetime `'r` to the type of `cont`: `&'r T` -LL | { LL | let cont_iter = cont.iter(); | ^^^^^^^^^^^ lifetime `'r` required + | +help: add explicit lifetime `'r` to the type of `cont` + | +LL | fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &'r T) -> bool + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-14285.stderr b/tests/ui/issues/issue-14285.stderr index 4f89ae51157b8..edd139eecba4d 100644 --- a/tests/ui/issues/issue-14285.stderr +++ b/tests/ui/issues/issue-14285.stderr @@ -1,10 +1,14 @@ error[E0621]: explicit lifetime required in the type of `a` --> $DIR/issue-14285.rs:12:5 | -LL | fn foo<'a>(a: &dyn Foo) -> B<'a> { - | -------- help: add explicit lifetime `'a` to the type of `a`: `&'a (dyn Foo + 'a)` LL | B(a) | ^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `a` + | +LL - fn foo<'a>(a: &dyn Foo) -> B<'a> { +LL + fn foo<'a>(a: &'a (dyn Foo + 'a)) -> B<'a> { + | error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/issues/issue-15034.stderr index 587a5c85e924a..7db8ade2e482c 100644 --- a/tests/ui/issues/issue-15034.stderr +++ b/tests/ui/issues/issue-15034.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `lexer` --> $DIR/issue-15034.rs:17:9 | -LL | pub fn new(lexer: &'a mut Lexer) -> Parser<'a> { - | ------------- help: add explicit lifetime `'a` to the type of `lexer`: `&'a mut Lexer<'a>` LL | Parser { lexer: lexer } | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `lexer` + | +LL | pub fn new(lexer: &'a mut Lexer<'a>) -> Parser<'a> { + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-3154.stderr b/tests/ui/issues/issue-3154.stderr index 3106aaddc4a1c..c17e59f7fc3d6 100644 --- a/tests/ui/issues/issue-3154.stderr +++ b/tests/ui/issues/issue-3154.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/issue-3154.rs:6:5 | -LL | fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> { - | -- help: add explicit lifetime `'a` to the type of `x`: `&'a Q` LL | Thing { x: x } | ^^^^^^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn thing<'a,Q>(x: &'a Q) -> Thing<'a,Q> { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-40288-2.stderr b/tests/ui/issues/issue-40288-2.stderr index 2c64856b08f8d..81cb7cdd51ff6 100644 --- a/tests/ui/issues/issue-40288-2.stderr +++ b/tests/ui/issues/issue-40288-2.stderr @@ -1,20 +1,24 @@ error[E0621]: explicit lifetime required in the type of `y` --> $DIR/issue-40288-2.rs:9:5 | -LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { - | -- help: add explicit lifetime `'a` to the type of `y`: `&'a T` -... LL | out[0] | ^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &'a T) -> &'a T { + | ++ error[E0621]: explicit lifetime required in the type of `y` --> $DIR/issue-40288-2.rs:24:5 | -LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { - | -- help: add explicit lifetime `'a` to the type of `y`: `&'a T` -... LL | out.head | ^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &'a T) -> &'a T { + | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr index af22078aff590..c524aabfacb86 100644 --- a/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr +++ b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr @@ -1,11 +1,13 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/42701_one_named_and_one_anonymous.rs:10:9 | -LL | fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 { - | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -... LL | &*x | ^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn foo2<'a>(a: &'a Foo, x: &'a i32) -> &'a i32 { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr index e202c31214d37..44a542eeeeb6a 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr @@ -1,11 +1,13 @@ error[E0621]: explicit lifetime required in the type of `other` --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:11:21 | -LL | fn bar(&self, other: Foo) -> Foo<'a> { - | --- help: add explicit lifetime `'a` to the type of `other`: `Foo<'a>` -... LL | other | ^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `other` + | +LL | fn bar(&self, other: Foo<'a>) -> Foo<'a> { + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr index 5518ded0106d9..52cf8595448d9 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-2.rs:2:16 | -LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { - | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` LL | if x > y { x } else { y } | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr index c689fa9884a76..fbd9695e85fab 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in parameter type --> $DIR/ex1-return-one-existing-name-if-else-3.rs:2:27 | -LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { - | --------------- help: add explicit lifetime `'a` to type: `(&'a i32, &'a i32)` LL | if x > y { x } else { y } | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to type + | +LL | fn foo<'a>((x, y): (&'a i32, &'a i32)) -> &'a i32 { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr index 3da50cfbb1d08..c875381c615fc 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:4:15 | -LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { - | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` LL | if x > y { x } else { y } | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 071bda24ef8de..83cd11baf3916 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:7:36 | -LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { - | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` LL | if true { &self.field } else { x } | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn foo<'a>(&'a self, x: &'a i32) -> &i32 { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr index 1df0776a51b58..bf09bd26359c5 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex1-return-one-existing-name-if-else.rs:2:27 | -LL | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { - | ---- help: add explicit lifetime `'a` to the type of `y`: `&'a i32` LL | if x > y { x } else { y } | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr index 25a2f4b96f40d..f37e1ba00e7e7 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex2a-push-one-existing-name-2.rs:6:5 | -LL | fn foo<'a>(x: Ref, y: &mut Vec>) { - | -------- help: add explicit lifetime `'a` to the type of `x`: `Ref<'a, i32>` LL | y.push(x); | ^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `x` + | +LL | fn foo<'a>(x: Ref<'a, i32>, y: &mut Vec>) { + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr index e2725977d8370..c25b4c9921f8e 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr @@ -1,11 +1,13 @@ error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex2a-push-one-existing-name-early-bound.rs:8:5 | -LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T) - | -- help: add explicit lifetime `'a` to the type of `y`: `&'a T` -... LL | x.push(y); | ^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &'a T) + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr index 1025581d5acf5..8c7bee4bfc400 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -1,10 +1,13 @@ error[E0621]: explicit lifetime required in the type of `y` --> $DIR/ex2a-push-one-existing-name.rs:6:5 | -LL | fn foo<'a>(x: &mut Vec>, y: Ref) { - | -------- help: add explicit lifetime `'a` to the type of `y`: `Ref<'a, i32>` LL | x.push(y); | ^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | fn foo<'a>(x: &mut Vec>, y: Ref<'a, i32>) { + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/noisy-follow-up-erro.stderr b/tests/ui/lifetimes/noisy-follow-up-erro.stderr index 04863badbd1ef..eb52147dba4bb 100644 --- a/tests/ui/lifetimes/noisy-follow-up-erro.stderr +++ b/tests/ui/lifetimes/noisy-follow-up-erro.stderr @@ -15,11 +15,14 @@ LL | struct Foo<'c, 'd>(&'c (), &'d ()); error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/noisy-follow-up-erro.rs:14:9 | -LL | fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> { - | -------------------- help: add explicit lifetime `'a` to the type of `foo`: `&mut Foo<'_, 'a>` -LL | LL | self.bar().map_err(|()| foo.acc(self))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `foo` + | +LL - fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> { +LL + fn boom(&self, foo: &mut Foo<'_, 'a>) -> Result<(), &'a ()> { + | error: aborting due to 2 previous errors diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 15b36925c47b5..05eb611081a41 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -21,11 +21,13 @@ LL | ss.r error[E0621]: explicit lifetime required in the type of `ss` --> $DIR/object-lifetime-default-from-box-error.rs:33:5 | -LL | fn store1<'b>(ss: &mut SomeStruct, b: Box) { - | --------------- help: add explicit lifetime `'b` to the type of `ss`: `&mut SomeStruct<'b>` -... LL | ss.r = b; | ^^^^ lifetime `'b` required + | +help: add explicit lifetime `'b` to the type of `ss` + | +LL | fn store1<'b>(ss: &mut SomeStruct<'b>, b: Box) { + | ++++ error: aborting due to 3 previous errors diff --git a/tests/ui/regions/regions-glb-free-free.stderr b/tests/ui/regions/regions-glb-free-free.stderr index 727669f26835e..6ea09e3e1d76d 100644 --- a/tests/ui/regions/regions-glb-free-free.stderr +++ b/tests/ui/regions/regions-glb-free-free.stderr @@ -1,8 +1,6 @@ error[E0621]: explicit lifetime required in the type of `s` --> $DIR/regions-glb-free-free.rs:15:13 | -LL | pub fn set_desc(self, s: &str) -> Flag<'a> { - | ---- help: add explicit lifetime `'a` to the type of `s`: `&'a str` LL | / Flag { LL | | name: self.name, LL | | desc: s, @@ -10,6 +8,11 @@ LL | | max_count: self.max_count, LL | | value: self.value LL | | } | |_____________^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `s` + | +LL | pub fn set_desc(self, s: &'a str) -> Flag<'a> { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-infer-at-fn-not-param.stderr b/tests/ui/regions/regions-infer-at-fn-not-param.stderr index 4c7660276f2dd..58ff2586a82c1 100644 --- a/tests/ui/regions/regions-infer-at-fn-not-param.stderr +++ b/tests/ui/regions/regions-infer-at-fn-not-param.stderr @@ -2,9 +2,12 @@ error[E0621]: explicit lifetime required in the type of `p` --> $DIR/regions-infer-at-fn-not-param.rs:13:57 | LL | fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p } - | -------------- ^ lifetime `'a` required - | | - | help: add explicit lifetime `'a` to the type of `p`: `Parameterized1<'a>` + | ^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `p` + | +LL | fn take1<'a>(p: Parameterized1<'a>) -> Parameterized1<'a> { p } + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 41cb2ee46bb5a..0aa33d3b6fb17 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -101,15 +101,17 @@ LL + fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + 'b error[E0621]: explicit lifetime required in the type of `dest` --> $DIR/missing-lifetimes-in-signature.rs:73:5 | -LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` -... LL | / move || { LL | | LL | | LL | | *dest = g.get(); LL | | } | |_____^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `dest` + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a + | ++ error[E0309]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:85:5 diff --git a/tests/ui/variance/variance-trait-matching.stderr b/tests/ui/variance/variance-trait-matching.stderr index 9c72fe239dde9..495669668c552 100644 --- a/tests/ui/variance/variance-trait-matching.stderr +++ b/tests/ui/variance/variance-trait-matching.stderr @@ -1,11 +1,13 @@ error[E0621]: explicit lifetime required in the type of `get` --> $DIR/variance-trait-matching.rs:24:5 | -LL | fn get<'a, G>(get: &G) -> i32 - | -- help: add explicit lifetime `'a` to the type of `get`: `&'a G` -... LL | pick(get, &22) | ^^^^^^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `get` + | +LL | fn get<'a, G>(get: &'a G) -> i32 + | ++ error: aborting due to 1 previous error From 643a9d233b4f1547220134daea4bcca809302d40 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 6 Jun 2025 15:19:08 -0700 Subject: [PATCH 08/28] tests: Change "fastcall" to "system" in some tests Lets the test still work on different architectures. --- tests/debuginfo/type-names.rs | 4 ++-- tests/incremental/hashes/trait_defs.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/debuginfo/type-names.rs b/tests/debuginfo/type-names.rs index 3c7eab7e8d718..ac61fef48fe16 100644 --- a/tests/debuginfo/type-names.rs +++ b/tests/debuginfo/type-names.rs @@ -19,7 +19,7 @@ // gdb-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdb-check:type = type_names::GenericStruct usize> +// gdb-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct // gdb-check:type = type_names::mod1::Struct2 @@ -379,7 +379,7 @@ fn main() { let simple_struct = Struct1; let generic_struct1: GenericStruct = GenericStruct(PhantomData); - let generic_struct2: GenericStruct usize> = + let generic_struct2: GenericStruct usize> = GenericStruct(PhantomData); let mod_struct = mod1::Struct2; diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index cb8716d90b07f..7141ddb0d7ed8 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -440,7 +440,7 @@ trait TraitAddExternModifier { // Change extern "C" to extern "stdcall" #[cfg(any(cfail1,cfail4))] -trait TraitChangeExternCToRustIntrinsic { +trait TraitChangeExternCToExternSystem { // -------------------------------------------------------------- // ------------------------- // -------------------------------------------------------------- @@ -458,7 +458,7 @@ trait TraitChangeExternCToRustIntrinsic { #[rustc_clean(cfg="cfail3")] #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] - extern "stdcall" fn method(); + extern "system" fn method(); } From 518eb0d5dd9ba822795fc5bc8e434e7139b0acbd Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 2 Jun 2025 07:20:42 -0700 Subject: [PATCH 09/28] rustdoc-json: Rearrange deck chairs in ABI testing We move the vectorcall ABI tests into their own file which is now only run on x86-64, while replacing them with rust-cold ABI tests so that aarch64 hosts continue to test an unstable ABI. A better solution might be cross-compiling or something but I really don't have time for that right now. --- tests/rustdoc-json/fn_pointer/abi.rs | 9 +++------ tests/rustdoc-json/fns/abi.rs | 9 +++------ tests/rustdoc-json/methods/abi.rs | 17 +++++------------ tests/rustdoc-json/vectorcall.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 tests/rustdoc-json/vectorcall.rs diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs index 34150c0fe89e0..ec76e0f66362a 100644 --- a/tests/rustdoc-json/fn_pointer/abi.rs +++ b/tests/rustdoc-json/fn_pointer/abi.rs @@ -1,4 +1,4 @@ -#![feature(abi_vectorcall)] +#![feature(rust_cold_cc)] //@ is "$.index[?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\" pub type AbiRust = fn(); @@ -15,8 +15,5 @@ pub type AbiCUnwind = extern "C-unwind" fn(); //@ is "$.index[?(@.name=='AbiSystemUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": true}}' pub type AbiSystemUnwind = extern "system-unwind" fn(); -//@ is "$.index[?(@.name=='AbiVecorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""' -pub type AbiVecorcall = extern "vectorcall" fn(); - -//@ is "$.index[?(@.name=='AbiVecorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' -pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn(); +//@ is "$.index[?(@.name=='AbiRustCold')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"rust-cold\""' +pub type AbiRustCold = extern "rust-cold" fn(); diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs index 7277bb1f59a40..3373d135c89d6 100644 --- a/tests/rustdoc-json/fns/abi.rs +++ b/tests/rustdoc-json/fns/abi.rs @@ -1,4 +1,4 @@ -#![feature(abi_vectorcall)] +#![feature(rust_cold_cc)] //@ is "$.index[?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\" pub fn abi_rust() {} @@ -15,8 +15,5 @@ pub extern "C-unwind" fn abi_c_unwind() {} //@ is "$.index[?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' pub extern "system-unwind" fn abi_system_unwind() {} -//@ is "$.index[?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' -pub extern "vectorcall" fn abi_vectorcall() {} - -//@ is "$.index[?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' -pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} +//@ is "$.index[?(@.name=='abi_rust_cold')].inner.function.header.abi.Other" '"\"rust-cold\""' +pub extern "rust-cold" fn abi_rust_cold() {} diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs index fa2387ddf67a8..be6a11784f55d 100644 --- a/tests/rustdoc-json/methods/abi.rs +++ b/tests/rustdoc-json/methods/abi.rs @@ -1,5 +1,4 @@ -#![feature(abi_vectorcall)] - +#![feature(rust_cold_cc)] //@ has "$.index[?(@.name=='Foo')]" pub struct Foo; @@ -19,11 +18,8 @@ impl Foo { //@ is "$.index[?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' pub extern "system-unwind" fn abi_system_unwind() {} - //@ is "$.index[?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' - pub extern "vectorcall" fn abi_vectorcall() {} - - //@ is "$.index[?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' - pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} + //@ is "$.index[?(@.name=='abi_rust_cold')].inner.function.header.abi.Other" '"\"rust-cold\""' + pub extern "rust-cold" fn abi_rust_cold() {} } pub trait Bar { @@ -42,9 +38,6 @@ pub trait Bar { //@ is "$.index[?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' extern "system-unwind" fn trait_abi_system_unwind() {} - //@ is "$.index[?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' - extern "vectorcall" fn trait_abi_vectorcall() {} - - //@ is "$.index[?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' - extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {} + //@ is "$.index[?(@.name=='trait_abi_rust_cold')].inner.function.header.abi.Other" '"\"rust-cold\""' + extern "rust-cold" fn trait_abi_rust_cold() {} } diff --git a/tests/rustdoc-json/vectorcall.rs b/tests/rustdoc-json/vectorcall.rs new file mode 100644 index 0000000000000..19cac244f422f --- /dev/null +++ b/tests/rustdoc-json/vectorcall.rs @@ -0,0 +1,27 @@ +#![feature(abi_vectorcall)] +//@ only-x86_64 + +//@ is "$.index[?(@.name=='AbiVectorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""' +pub type AbiVectorcall = extern "vectorcall" fn(); + +//@ is "$.index[?(@.name=='AbiVectorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' +pub type AbiVectorcallUnwind = extern "vectorcall-unwind" fn(); + +//@ has "$.index[?(@.name=='Foo')]" +pub struct Foo; + +impl Foo { + //@ is "$.index[?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' + pub extern "vectorcall" fn abi_vectorcall() {} + + //@ is "$.index[?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' + pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} +} + +pub trait Bar { + //@ is "$.index[?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' + extern "vectorcall" fn trait_abi_vectorcall() {} + + //@ is "$.index[?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' + extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {} +} From 6cea550285de6e884eb906b1933292856969df4e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 1 Jun 2025 13:38:02 -0700 Subject: [PATCH 10/28] tests: Minicore `extern "gpu-kernel"` feature test Explicitly cross-build it for GPU targets and check it errors on hosts. --- .../feature-gate-abi_gpu_kernel.AMDGPU.stderr | 73 +++++++++++++++++++ ...> feature-gate-abi_gpu_kernel.HOST.stderr} | 28 +++---- .../feature-gate-abi_gpu_kernel.NVPTX.stderr | 73 +++++++++++++++++++ .../feature-gate-abi_gpu_kernel.rs | 19 +++-- 4 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr rename tests/ui/feature-gates/{feature-gate-abi_gpu_kernel.stderr => feature-gate-abi_gpu_kernel.HOST.stderr} (88%) create mode 100644 tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr new file mode 100644 index 0000000000000..fca32c5c1e6fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.AMDGPU.stderr @@ -0,0 +1,73 @@ +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:16:8 + | +LL | extern "gpu-kernel" fn f1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:21:12 + | +LL | extern "gpu-kernel" fn m1(_: ()); + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:23:12 + | +LL | extern "gpu-kernel" fn dm1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:31:12 + | +LL | extern "gpu-kernel" fn m1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:37:12 + | +LL | extern "gpu-kernel" fn im1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:42:18 + | +LL | type A1 = extern "gpu-kernel" fn(_: ()); + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:47:8 + | +LL | extern "gpu-kernel" {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr similarity index 88% rename from tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr rename to tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr index aa9c67f0151fc..cc81289f6b788 100644 --- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.HOST.stderr @@ -1,5 +1,5 @@ error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:11:8 + --> $DIR/feature-gate-abi_gpu_kernel.rs:16:8 | LL | extern "gpu-kernel" fn f1(_: ()) {} | ^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | extern "gpu-kernel" fn f1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:16:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:21:12 | LL | extern "gpu-kernel" fn m1(_: ()); | ^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | extern "gpu-kernel" fn m1(_: ()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:18:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:23:12 | LL | extern "gpu-kernel" fn dm1(_: ()) {} | ^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | extern "gpu-kernel" fn dm1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:26:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:31:12 | LL | extern "gpu-kernel" fn m1(_: ()) {} | ^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | extern "gpu-kernel" fn m1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:32:12 + --> $DIR/feature-gate-abi_gpu_kernel.rs:37:12 | LL | extern "gpu-kernel" fn im1(_: ()) {} | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | extern "gpu-kernel" fn im1(_: ()) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:18 + --> $DIR/feature-gate-abi_gpu_kernel.rs:42:18 | LL | type A1 = extern "gpu-kernel" fn(_: ()); | ^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | type A1 = extern "gpu-kernel" fn(_: ()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:8 + --> $DIR/feature-gate-abi_gpu_kernel.rs:47:8 | LL | extern "gpu-kernel" {} | ^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | extern "gpu-kernel" {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: the calling convention "gpu-kernel" is not supported on this target - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:11 + --> $DIR/feature-gate-abi_gpu_kernel.rs:42:11 | LL | type A1 = extern "gpu-kernel" fn(_: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,31 +79,31 @@ LL | type A1 = extern "gpu-kernel" fn(_: ()); = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:42:1 + --> $DIR/feature-gate-abi_gpu_kernel.rs:47:1 | LL | extern "gpu-kernel" {} | ^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:11:1 + --> $DIR/feature-gate-abi_gpu_kernel.rs:16:1 | LL | extern "gpu-kernel" fn f1(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:18:5 + --> $DIR/feature-gate-abi_gpu_kernel.rs:23:5 | LL | extern "gpu-kernel" fn dm1(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:26:5 + --> $DIR/feature-gate-abi_gpu_kernel.rs:31:5 | LL | extern "gpu-kernel" fn m1(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_gpu_kernel.rs:32:5 + --> $DIR/feature-gate-abi_gpu_kernel.rs:37:5 | LL | extern "gpu-kernel" fn im1(_: ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -114,7 +114,7 @@ Some errors have detailed explanations: E0570, E0658. For more information about an error, try `rustc --explain E0570`. Future incompatibility report: Future breakage diagnostic: warning: the calling convention "gpu-kernel" is not supported on this target - --> $DIR/feature-gate-abi_gpu_kernel.rs:37:11 + --> $DIR/feature-gate-abi_gpu_kernel.rs:42:11 | LL | type A1 = extern "gpu-kernel" fn(_: ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr new file mode 100644 index 0000000000000..fca32c5c1e6fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.NVPTX.stderr @@ -0,0 +1,73 @@ +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:16:8 + | +LL | extern "gpu-kernel" fn f1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:21:12 + | +LL | extern "gpu-kernel" fn m1(_: ()); + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:23:12 + | +LL | extern "gpu-kernel" fn dm1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:31:12 + | +LL | extern "gpu-kernel" fn m1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:37:12 + | +LL | extern "gpu-kernel" fn im1(_: ()) {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:42:18 + | +LL | type A1 = extern "gpu-kernel" fn(_: ()); + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change + --> $DIR/feature-gate-abi_gpu_kernel.rs:47:8 + | +LL | extern "gpu-kernel" {} + | ^^^^^^^^^^^^ + | + = note: see issue #135467 for more information + = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs index d9027b417b4d9..7b1ee681dd7ef 100644 --- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs +++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs @@ -1,5 +1,10 @@ +//@ revisions: HOST AMDGPU NVPTX //@ add-core-stubs //@ compile-flags: --crate-type=rlib +//@[AMDGPU] compile-flags: --target amdgcn-amd-amdhsa -Ctarget-cpu=gfx1100 +//@[AMDGPU] needs-llvm-components: amdgpu +//@[NVPTX] compile-flags: --target nvptx64-nvidia-cuda +//@[NVPTX] needs-llvm-components: nvptx #![feature(no_core, lang_items)] #![no_core] @@ -9,14 +14,14 @@ use minicore::*; // Functions extern "gpu-kernel" fn f1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change -//~^ ERROR is not a supported ABI +//[HOST]~^ ERROR is not a supported ABI // Methods in trait definition trait Tr { extern "gpu-kernel" fn m1(_: ()); //~ ERROR "gpu-kernel" ABI is experimental and subject to change extern "gpu-kernel" fn dm1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change - //~^ ERROR is not a supported ABI + //[HOST]~^ ERROR is not a supported ABI } struct S; @@ -24,20 +29,20 @@ struct S; // Methods in trait impl impl Tr for S { extern "gpu-kernel" fn m1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change - //~^ ERROR is not a supported ABI + //[HOST]~^ ERROR is not a supported ABI } // Methods in inherent impl impl S { extern "gpu-kernel" fn im1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change - //~^ ERROR is not a supported ABI + //[HOST]~^ ERROR is not a supported ABI } // Function pointer types type A1 = extern "gpu-kernel" fn(_: ()); //~ ERROR "gpu-kernel" ABI is experimental and subject to change -//~^ WARN the calling convention "gpu-kernel" is not supported on this target -//~^^ WARN this was previously accepted by the compiler but is being phased out +//[HOST]~^ WARNING the calling convention "gpu-kernel" is not supported on this target [unsupported_fn_ptr_calling_conventions] +//[HOST]~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! // Foreign modules extern "gpu-kernel" {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change -//~^ ERROR is not a supported ABI +//[HOST]~^ ERROR is not a supported ABI From 59069986e7446123556630a32adce7f101eeaf8d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 7 Jun 2025 11:04:40 -0700 Subject: [PATCH 11/28] tests: Copy dont-shuffle-bswaps per tested opt level --- .../autovec/dont-shuffle-bswaps-opt2.rs | 29 +++++++++++++++++++ .../dont-shuffle-bswaps-opt3.rs} | 3 +- 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs rename tests/codegen/{dont-shuffle-bswaps.rs => autovec/dont-shuffle-bswaps-opt3.rs} (94%) diff --git a/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs b/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs new file mode 100644 index 0000000000000..391cf1c639ca3 --- /dev/null +++ b/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs @@ -0,0 +1,29 @@ +//@ compile-flags: -Copt-level=2 + +#![crate_type = "lib"] +#![no_std] + +// The code is from https://github.com/rust-lang/rust/issues/122805. +// Ensure we do not generate the shufflevector instruction +// to avoid complicating the code. + +// CHECK-LABEL: define{{.*}}void @convert( +// CHECK-NOT: shufflevector +#[no_mangle] +pub fn convert(value: [u16; 8]) -> [u8; 16] { + #[cfg(target_endian = "little")] + let bswap = u16::to_be; + #[cfg(target_endian = "big")] + let bswap = u16::to_le; + let addr16 = [ + bswap(value[0]), + bswap(value[1]), + bswap(value[2]), + bswap(value[3]), + bswap(value[4]), + bswap(value[5]), + bswap(value[6]), + bswap(value[7]), + ]; + unsafe { core::mem::transmute::<_, [u8; 16]>(addr16) } +} diff --git a/tests/codegen/dont-shuffle-bswaps.rs b/tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs similarity index 94% rename from tests/codegen/dont-shuffle-bswaps.rs rename to tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs index c1dab2bc29536..e105487cccab2 100644 --- a/tests/codegen/dont-shuffle-bswaps.rs +++ b/tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs @@ -1,5 +1,4 @@ -//@ revisions: OPT2 OPT3 OPT3_S390X -//@[OPT2] compile-flags: -Copt-level=2 +//@ revisions: OPT3 OPT3_S390X //@[OPT3] compile-flags: -C opt-level=3 // some targets don't do the opt we are looking for //@[OPT3] only-64bit From cb3d074f6a21f0c5ae36d811bfbe0c10578680ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 10 Jun 2025 08:00:13 +0200 Subject: [PATCH 12/28] Only run `citool` tests on the `auto` branch --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5054a075676b..841bc39bf1e6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,12 +64,18 @@ jobs: uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8 with: workspaces: src/ci/citool + - name: Test citool + # Only test citool on the auto branch, to reduce latency of the calculate matrix job + # on PR/try builds. + if: ${{ github.ref == 'refs/heads/auto' }} + run: | + cd src/ci/citool + CARGO_INCREMENTAL=0 cargo test - name: Calculate the CI job matrix env: COMMIT_MESSAGE: ${{ github.event.head_commit.message }} run: | cd src/ci/citool - CARGO_INCREMENTAL=0 cargo test CARGO_INCREMENTAL=0 cargo run calculate-job-matrix >> $GITHUB_OUTPUT id: jobs job: From 6b0deb2161b730be16c1ec13c1ab47455c054f37 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 7 Jun 2025 11:12:38 -0700 Subject: [PATCH 13/28] tests: Revise dont-shuffle-bswaps-opt3 per tested arch Some architectures gain target-cpu minimums in doing so. --- .../autovec/dont-shuffle-bswaps-opt2.rs | 2 ++ .../autovec/dont-shuffle-bswaps-opt3.rs | 29 +++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs b/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs index 391cf1c639ca3..c354228acc50a 100644 --- a/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs +++ b/tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs @@ -3,6 +3,8 @@ #![crate_type = "lib"] #![no_std] +// This test is paired with the arch-specific -opt3.rs test. + // The code is from https://github.com/rust-lang/rust/issues/122805. // Ensure we do not generate the shufflevector instruction // to avoid complicating the code. diff --git a/tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs b/tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs index e105487cccab2..203d12005de2a 100644 --- a/tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs +++ b/tests/codegen/autovec/dont-shuffle-bswaps-opt3.rs @@ -1,28 +1,27 @@ -//@ revisions: OPT3 OPT3_S390X -//@[OPT3] compile-flags: -C opt-level=3 -// some targets don't do the opt we are looking for -//@[OPT3] only-64bit -//@[OPT3] ignore-s390x -//@[OPT3_S390X] compile-flags: -C opt-level=3 -C target-cpu=z13 -//@[OPT3_S390X] only-s390x +//@ revisions: AARCH64 X86_64 Z13 +//@ compile-flags: -Copt-level=3 +//@[AARCH64] only-aarch64 +//@[X86_64] only-x86_64 +//@[Z13] only-s390x +//@[Z13] compile-flags: -Ctarget-cpu=z13 #![crate_type = "lib"] #![no_std] +// This test is paired with the arch-neutral -opt2.rs test + // The code is from https://github.com/rust-lang/rust/issues/122805. // Ensure we do not generate the shufflevector instruction // to avoid complicating the code. + // CHECK-LABEL: define{{.*}}void @convert( // CHECK-NOT: shufflevector + // On higher opt levels, this should just be a bswap: -// OPT3: load <8 x i16> -// OPT3-NEXT: call <8 x i16> @llvm.bswap -// OPT3-NEXT: store <8 x i16> -// OPT3-NEXT: ret void -// OPT3_S390X: load <8 x i16> -// OPT3_S390X-NEXT: call <8 x i16> @llvm.bswap -// OPT3_S390X-NEXT: store <8 x i16> -// OPT3_S390X-NEXT: ret void +// CHECK: load <8 x i16> +// CHECK-NEXT: call <8 x i16> @llvm.bswap +// CHECK-NEXT: store <8 x i16> +// CHECK-NEXT: ret void #[no_mangle] pub fn convert(value: [u16; 8]) -> [u8; 16] { #[cfg(target_endian = "little")] From 3a5187aa3b9a15caf3ceeff1299dd88f6d959442 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 9 Jun 2025 23:37:55 -0700 Subject: [PATCH 14/28] tests: Do not run afoul of asm.validity.non-exhaustive in input-stats --- tests/ui/stats/input-stats.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ui/stats/input-stats.rs b/tests/ui/stats/input-stats.rs index e760e2894e318..1e880cc693e10 100644 --- a/tests/ui/stats/input-stats.rs +++ b/tests/ui/stats/input-stats.rs @@ -1,6 +1,7 @@ //@ check-pass //@ compile-flags: -Zinput-stats //@ only-64bit +//@ needs-asm-support // layout randomization affects the hir stat output //@ needs-deterministic-layouts // @@ -49,5 +50,7 @@ fn main() { _ => {} } - unsafe { asm!("mov rdi, 1"); } + // NOTE(workingjubilee): do GPUs support NOPs? remove this cfg if they do + #[cfg(not(any(target_arch = "nvptx64", target_arch = "spirv", target_arch = "amdgpu")))] + unsafe { asm!("nop"); } } From de8a91b51c3fbc60e80a75e2859e371e7de7e1ec Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Mon, 9 Jun 2025 22:29:59 +0800 Subject: [PATCH 15/28] Add supported asm types for LoongArch32 --- compiler/rustc_target/src/asm/loongarch.rs | 10 ++++++---- .../src/language-features/asm-experimental-arch.md | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs index b4ea6fc592a8c..8783d3953b161 100644 --- a/compiler/rustc_target/src/asm/loongarch.rs +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -34,11 +34,13 @@ impl LoongArchInlineAsmRegClass { pub fn supported_types( self, - _arch: InlineAsmArch, + arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option)] { - match self { - Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, - Self::freg => types! { f: F32; d: F64; }, + match (self, arch) { + (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; }, + (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F32; }, + (Self::freg, _) => types! { f: F32; d: F64; }, + _ => unreachable!("unsupported register class"), } } } diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index d9566c9f55c5c..121f949343594 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -19,6 +19,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - M68k - CSKY - SPARC +- LoongArch32 ## Register classes @@ -53,6 +54,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `freg` | `f[0-31]` | `f` | | SPARC | `reg` | `r[2-29]` | `r` | | SPARC | `yreg` | `y` | Only clobbers | +| LoongArch32 | `reg` | `$r1`, `$r[4-20]`, `$r[23,30]` | `r` | +| LoongArch32 | `freg` | `$f[0-31]` | `f` | > **Notes**: > - NVPTX doesn't have a fixed register set, so named registers are not supported. @@ -91,6 +94,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `freg` | None | `f32`, | | SPARC | `reg` | None | `i8`, `i16`, `i32`, `i64` (SPARC64 only) | | SPARC | `yreg` | N/A | Only clobbers | +| LoongArch32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| LoongArch32 | `freg` | None | `f32`, `f64` | ## Register aliases From 8ef8062d65055f2b54bd030487ae0e3388aa827a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 10 Jun 2025 22:10:10 +0800 Subject: [PATCH 16/28] Extract target no-std hack to `build_helpers` To centralize this hack in one place with a backlink to the issue tracking this hack, as this logic is also needed by compiletest to implement a `//@ needs-target-std` directive. --- src/bootstrap/src/core/config/toml/target.rs | 2 +- src/build_helper/src/lib.rs | 1 + src/build_helper/src/targets.rs | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/build_helper/src/targets.rs diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs index 7f074d1b25e08..b8fc3e74c354d 100644 --- a/src/bootstrap/src/core/config/toml/target.rs +++ b/src/bootstrap/src/core/config/toml/target.rs @@ -84,7 +84,7 @@ pub struct Target { impl Target { pub fn from_triple(triple: &str) -> Self { let mut target: Self = Default::default(); - if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") { + if !build_helper::targets::target_supports_std(triple) { target.no_std = true; } if triple.contains("emscripten") { diff --git a/src/build_helper/src/lib.rs b/src/build_helper/src/lib.rs index 1f5cf72364110..05de8fd2d42f1 100644 --- a/src/build_helper/src/lib.rs +++ b/src/build_helper/src/lib.rs @@ -6,6 +6,7 @@ pub mod fs; pub mod git; pub mod metrics; pub mod stage0_parser; +pub mod targets; pub mod util; /// The default set of crates for opt-dist to collect LLVM profiles. diff --git a/src/build_helper/src/targets.rs b/src/build_helper/src/targets.rs new file mode 100644 index 0000000000000..cccc413368bc9 --- /dev/null +++ b/src/build_helper/src/targets.rs @@ -0,0 +1,11 @@ +// FIXME(#142296): this hack is because there is no reliable way (yet) to determine whether a given +// target supports std. In the long-term, we should try to implement a way to *reliably* determine +// target (std) metadata. +// +// NOTE: this is pulled out to `build_helpers` to share this hack between `bootstrap` and +// `compiletest`. +pub fn target_supports_std(target_tuple: &str) -> bool { + !(target_tuple.contains("-none") + || target_tuple.contains("nvptx") + || target_tuple.contains("switch")) +} From e10b2f60eb04f0afb755ca22e447131043204be4 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 10 Jun 2025 22:16:09 +0800 Subject: [PATCH 17/28] Implement `//@ needs-target-std` directive in compiletest To support tests to condition their (potentially cross-compile) execution based on whether the target supports std. --- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header/needs.rs | 5 +++++ src/tools/compiletest/src/header/tests.rs | 11 +++++++++++ 3 files changed, 17 insertions(+) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 1406553c9ea7b..2ecb4fc865213 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -166,6 +166,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-subprocess", "needs-symlink", "needs-target-has-atomic", + "needs-target-std", "needs-threads", "needs-unwind", "needs-wasmtime", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 2ace40c490bf3..b1165f4bb184f 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -174,6 +174,11 @@ pub(super) fn handle_needs( condition: config.with_std_debug_assertions, ignore_reason: "ignored if std wasn't built with debug assertions", }, + Need { + name: "needs-target-std", + condition: build_helper::targets::target_supports_std(&config.target), + ignore_reason: "ignored if target does not support std", + }, ]; let (name, rest) = match ln.split_once([':', ' ']) { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index e7e5ff0ab0093..31b49b09bcdc2 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -945,3 +945,14 @@ fn test_ignore_auxiliary() { let config = cfg().build(); assert!(check_ignore(&config, "//@ ignore-auxiliary")); } + +#[test] +fn test_needs_target_std() { + // Cherry-picks two targets: + // 1. `x86_64-unknown-none`: Tier 2, intentionally never supports std. + // 2. `x86_64-unknown-linux-gnu`: Tier 1, always supports std. + let config = cfg().target("x86_64-unknown-none").build(); + assert!(check_ignore(&config, "//@ needs-target-std")); + let config = cfg().target("x86_64-unknown-linux-gnu").build(); + assert!(!check_ignore(&config, "//@ needs-target-std")); +} From c5b81235742c92adbf9343f57f92cce28a6b43d6 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 10 Jun 2025 22:17:57 +0800 Subject: [PATCH 18/28] Document `//@ needs-target-std` in rustc-dev-guide --- src/doc/rustc-dev-guide/src/tests/directives.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 2dff21ed61c28..b043c7035fe06 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -202,6 +202,7 @@ settings: `//@ needs-crate-type: cdylib, proc-macro` will cause the test to be ignored on `wasm32-unknown-unknown` target because the target does not support the `proc-macro` crate type. +- `needs-target-std` — ignores if target platform does not have std support. The following directives will check LLVM support: From 97270edc242e3c46250e05ab171f22eb89c06614 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 10 Jun 2025 22:37:36 +0800 Subject: [PATCH 19/28] Make loongarch-none target maintainers more easily pingable --- src/doc/rustc/src/platform-support/loongarch-none.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index fd90b0a27638a..7c3a7e6c8bc57 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -11,8 +11,8 @@ Freestanding/bare-metal LoongArch binaries in ELF format: firmware, kernels, etc ## Target maintainers -- [@heiher](https://github.com/heiher) -- [@xen0n](https://github.com/xen0n) +[@heiher](https://github.com/heiher) +[@xen0n](https://github.com/xen0n) ## Requirements From c558db34dc4ad66236d09ba7a2101a4c6b8cacd5 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 10 Jun 2025 22:22:52 +0800 Subject: [PATCH 20/28] Modify some run-make tests to use `//@ needs-target-std` Instead of a jumble of `ignore-$target`s, `ignore-none` and `ignore-nvptx`. --- tests/run-make/cpp-global-destructors/rmake.rs | 6 +----- tests/run-make/export-executable-symbols/rmake.rs | 3 +-- tests/run-make/incr-foreign-head-span/rmake.rs | 5 +---- tests/run-make/incr-prev-body-beyond-eof/rmake.rs | 6 +----- tests/run-make/incr-test-moved-file/rmake.rs | 5 +---- tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs | 5 +---- 6 files changed, 6 insertions(+), 24 deletions(-) diff --git a/tests/run-make/cpp-global-destructors/rmake.rs b/tests/run-make/cpp-global-destructors/rmake.rs index 9bc5c84e10db5..92aeb67c27858 100644 --- a/tests/run-make/cpp-global-destructors/rmake.rs +++ b/tests/run-make/cpp-global-destructors/rmake.rs @@ -6,15 +6,11 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -//@ ignore-none -// Reason: no-std is not supported. //@ ignore-wasm32 //@ ignore-wasm64 // Reason: compiling C++ to WASM may cause problems. -// Neither of these are tested in full CI. -//@ ignore-nvptx64-nvidia-cuda -// Reason: can't find crate "std" +// Not exercised in full CI, but sgx technically supports std. //@ ignore-sgx use run_make_support::{build_native_static_lib_cxx, run, rustc}; diff --git a/tests/run-make/export-executable-symbols/rmake.rs b/tests/run-make/export-executable-symbols/rmake.rs index 77f968189b655..dc8c59b9c742f 100644 --- a/tests/run-make/export-executable-symbols/rmake.rs +++ b/tests/run-make/export-executable-symbols/rmake.rs @@ -10,8 +10,7 @@ // (See #85673) //@ ignore-wasm32 //@ ignore-wasm64 -//@ ignore-none -// Reason: no-std is not supported +//@ needs-target-std use run_make_support::{bin_name, llvm_readobj, rustc}; diff --git a/tests/run-make/incr-foreign-head-span/rmake.rs b/tests/run-make/incr-foreign-head-span/rmake.rs index 92e2ed5f8793a..d9841b314641e 100644 --- a/tests/run-make/incr-foreign-head-span/rmake.rs +++ b/tests/run-make/incr-foreign-head-span/rmake.rs @@ -5,10 +5,7 @@ // source file from disk during compilation of a downstream crate. // See https://github.com/rust-lang/rust/issues/86480 -//@ ignore-none -// Reason: no-std is not supported -//@ ignore-nvptx64-nvidia-cuda -// Reason: can't find crate for 'std' +//@ needs-target-std use run_make_support::{rfs, rust_lib_name, rustc}; diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs index 47dce85248ab8..cfa8d5b46cd9c 100644 --- a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs +++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs @@ -7,11 +7,7 @@ // was hashed by rustc in addition to the span length, and the fix still // works. -//@ ignore-none -// reason: no-std is not supported - -//@ ignore-nvptx64-nvidia-cuda -// FIXME: can't find crate for `std` +//@ needs-target-std use run_make_support::{rfs, rustc}; diff --git a/tests/run-make/incr-test-moved-file/rmake.rs b/tests/run-make/incr-test-moved-file/rmake.rs index 0ba1b0d58feeb..dfba95d3fedbf 100644 --- a/tests/run-make/incr-test-moved-file/rmake.rs +++ b/tests/run-make/incr-test-moved-file/rmake.rs @@ -9,10 +9,7 @@ // for successful compilation. // See https://github.com/rust-lang/rust/issues/83112 -//@ ignore-none -// Reason: no-std is not supported -//@ ignore-nvptx64-nvidia-cuda -// FIXME: can't find crate for 'std' +//@ needs-target-std use run_make_support::{rfs, rustc}; diff --git a/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs b/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs index f63146e692ac4..0d96b40e8a435 100644 --- a/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs +++ b/tests/run-make/moved-src-dir-fingerprint-ice/rmake.rs @@ -12,10 +12,7 @@ // sessions. // See https://github.com/rust-lang/rust/issues/85019 -//@ ignore-none -// Reason: no-std is not supported -//@ ignore-nvptx64-nvidia-cuda -// FIXME: can't find crate for 'std' +//@ needs-target-std use run_make_support::{rfs, rust_lib_name, rustc}; From 6f487586f86a28982242dfb5ee660170c1a0f2d5 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 3 Jun 2025 22:19:30 +0800 Subject: [PATCH 21/28] Configure bootstrap backport nominations via triagebot --- triagebot.toml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 15c56f8861f5f..09a78b6a34ee3 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -729,6 +729,41 @@ don't know ] message_on_remove = "PR #{number}'s stable-nomination has been removed." +[notify-zulip."beta-nominated".bootstrap] +required_labels = ["T-bootstrap"] +zulip_stream = 507486 # #t-infra/bootstrap/backports +topic = "#{number}: beta-nominated" +message_on_add = [ + """\ +@*T-bootstrap* PR #{number} "{title}" has been nominated for beta backport. +""", + """\ +/poll Approve beta backport of #{number}? +approve +decline +don't know +""", +] +message_on_remove = "PR #{number}'s beta-nomination has been removed." + +[notify-zulip."stable-nominated".bootstrap] +required_labels = ["T-bootstrap"] +zulip_stream = 507486 # #t-infra/bootstrap/backports +topic = "#{number}: stable-nominated" +message_on_add = [ + """\ +@*T-bootstrap* PR #{number} "{title}" has been nominated for stable backport. +""", + """\ +/poll Approve stable backport of #{number}? +approve +approve (but does not justify new dot release on its own) +decline +don't know +""", +] +message_on_remove = "PR #{number}'s stable-nomination has been removed." + [notify-zulip."A-edition-2021"] required_labels = ["C-bug"] zulip_stream = 268952 # #edition From 096c29a27becb2b6034beac0998dc754a7e5acc0 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 10 Jun 2025 01:37:47 +0000 Subject: [PATCH 22/28] Update dependencies in `library/Cargo.lock` This removes the `compiler_builtins` dependency from a handful of library dependencies, which is progress toward [1]. [1]: https://github.com/rust-lang/rust/issues/142265 --- library/Cargo.lock | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 966ae72dc2ad1..5314ac327370d 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -16,11 +16,10 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" dependencies = [ - "compiler_builtins", "rustc-std-workspace-core", ] @@ -51,11 +50,10 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" dependencies = [ - "compiler_builtins", "rustc-std-workspace-core", ] @@ -81,12 +79,11 @@ dependencies = [ [[package]] name = "dlmalloc" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7" +checksum = "d01597dde41c0b9da50d5f8c219023d63d8f27f39a27095070fd191fddc83891" dependencies = [ "cfg-if", - "compiler_builtins", "libc", "rustc-std-workspace-core", "windows-sys", @@ -104,9 +101,9 @@ dependencies = [ [[package]] name = "getopts" -version = "0.2.21" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" dependencies = [ "rustc-std-workspace-core", "rustc-std-workspace-std", @@ -126,11 +123,10 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ - "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -167,12 +163,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", - "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -274,11 +269,10 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" dependencies = [ - "compiler_builtins", "rustc-std-workspace-core", ] @@ -381,11 +375,10 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.14" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" dependencies = [ - "compiler_builtins", "rustc-std-workspace-core", "rustc-std-workspace-std", ] @@ -414,11 +407,10 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" dependencies = [ - "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] From 6227acc749556a5b5e111b06ab3499da29349f49 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 10 Jun 2025 17:01:55 +0000 Subject: [PATCH 23/28] Dont unwrap and re-wrap typing envs --- compiler/rustc_middle/src/query/erase.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 7 ++----- compiler/rustc_ty_utils/src/ty.rs | 8 +++----- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 6035056baaf9d..7c998761a9d44 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -389,6 +389,7 @@ tcx_lifetime! { rustc_middle::ty::layout::FnAbiError, rustc_middle::ty::layout::LayoutError, rustc_middle::ty::ParamEnv, + rustc_middle::ty::TypingEnv, rustc_middle::ty::Predicate, rustc_middle::ty::SymbolName, rustc_middle::ty::TraitRef, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d03f01bf863ed..09e4598a67f0e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1571,7 +1571,7 @@ rustc_queries! { /// Like `param_env`, but returns the `ParamEnv` after all opaque types have been /// replaced with their hidden type. This is used in the old trait solver /// when in `PostAnalysis` mode and should not be called directly. - query param_env_normalized_for_post_analysis(def_id: DefId) -> ty::ParamEnv<'tcx> { + query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> { desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index af31f7ed33b4d..dc3f2844e5ae8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1116,10 +1116,7 @@ impl<'tcx> TypingEnv<'tcx> { } pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam) -> TypingEnv<'tcx> { - TypingEnv { - typing_mode: TypingMode::PostAnalysis, - param_env: tcx.param_env_normalized_for_post_analysis(def_id), - } + tcx.typing_env_normalized_for_post_analysis(def_id) } /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all @@ -1133,7 +1130,7 @@ impl<'tcx> TypingEnv<'tcx> { // No need to reveal opaques with the new solver enabled, // since we have lazy norm. let param_env = if tcx.next_trait_solver_globally() { - ParamEnv::new(param_env.caller_bounds()) + param_env } else { ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds())) }; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 4dc27622d235a..79ac622df32aa 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -255,10 +255,8 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { } } -fn param_env_normalized_for_post_analysis(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { - // This is a bit ugly but the easiest way to avoid code duplication. - let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id); - typing_env.with_post_analysis_normalized(tcx).param_env +fn typing_env_normalized_for_post_analysis(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TypingEnv<'_> { + ty::TypingEnv::non_body_analysis(tcx, def_id).with_post_analysis_normalized(tcx) } /// Check if a function is async. @@ -374,7 +372,7 @@ pub(crate) fn provide(providers: &mut Providers) { asyncness, adt_sized_constraint, param_env, - param_env_normalized_for_post_analysis, + typing_env_normalized_for_post_analysis, defaultness, unsizing_params_for_adt, impl_self_is_guaranteed_unsized, From d8f053bbdd20437ba8f5385fe36f30771ab69465 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 31 Jul 2024 01:59:22 -0400 Subject: [PATCH 24/28] Fix a missing fragment specifier in rustdoc tests --- .../macro/macro-generated-macro.macro_morestuff_pre.html | 4 ++-- tests/rustdoc/macro/macro-generated-macro.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html b/tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html index 28f15522a82f7..4dcc8111c6ff3 100644 --- a/tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html +++ b/tests/rustdoc/macro/macro-generated-macro.macro_morestuff_pre.html @@ -1,7 +1,7 @@ macro_rules! morestuff { ( - <= "space between most kinds of tokens" : 1 $x + @ :: >>= 'static - "no space inside paren or bracket" : (2 a) [2 a] $(2 $a:tt)* + <= "space between most kinds of tokens" : 1 $x:ident + @ :: >>= + 'static "no space inside paren or bracket" : (2 a) [2 a] $(2 $a:tt)* "space inside curly brace" : { 2 a } "no space inside empty delimiters" : () [] {} "no space before comma or semicolon" : a, (a), { a }, a; [T; 0]; diff --git a/tests/rustdoc/macro/macro-generated-macro.rs b/tests/rustdoc/macro/macro-generated-macro.rs index e77d0cf89e748..dfb152bafb62e 100644 --- a/tests/rustdoc/macro/macro-generated-macro.rs +++ b/tests/rustdoc/macro/macro-generated-macro.rs @@ -25,7 +25,7 @@ make_macro!(linebreak 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 //@ snapshot macro_morestuff_pre macro_generated_macro/macro.morestuff.html //pre/text() make_macro!(morestuff - "space between most kinds of tokens": 1 $x + @ :: >>= 'static + "space between most kinds of tokens": 1 $x:ident + @ :: >>= 'static "no space inside paren or bracket": (2 a) [2 a] $(2 $a:tt)* "space inside curly brace": { 2 a } "no space inside empty delimiters": () [] {} From 1dc388b13663eb64cca8cbe76ee97c00985e3d91 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 30 Jul 2024 23:04:23 -0400 Subject: [PATCH 25/28] Make `missing_fragment_specifier` an unconditional error This was attempted in [1] then reverted in [2] because of fallout. Recently, this was made an edition-dependent error in [3]. Make missing fragment specifiers an unconditional error again. [1]: https://github.com/rust-lang/rust/pull/75516 [2]: https://github.com/rust-lang/rust/pull/80210 [3]: https://github.com/rust-lang/rust/pull/128006 --- compiler/rustc_expand/messages.ftl | 2 +- compiler/rustc_expand/src/mbe/macro_check.rs | 25 ++---- compiler/rustc_lint/messages.ftl | 2 - compiler/rustc_lint/src/early/diagnostics.rs | 3 - compiler/rustc_lint/src/lib.rs | 5 ++ compiler/rustc_lint/src/lints.rs | 4 - compiler/rustc_lint_defs/src/builtin.rs | 46 ---------- compiler/rustc_lint_defs/src/lib.rs | 1 - tests/ui/future-incompatible-lint-group.rs | 20 ++++- .../ui/future-incompatible-lint-group.stderr | 44 +++++----- tests/ui/lint/expansion-time.rs | 4 - tests/ui/lint/expansion-time.stderr | 33 +------ tests/ui/macros/issue-39404.rs | 6 +- tests/ui/macros/issue-39404.stderr | 26 ++---- tests/ui/macros/macro-match-nonterminal.rs | 2 - .../ui/macros/macro-match-nonterminal.stderr | 39 +++------ .../macro-missing-fragment-deduplication.rs | 6 +- ...acro-missing-fragment-deduplication.stderr | 26 ++---- .../macro-missing-fragment.e2015.stderr | 85 ------------------- tests/ui/macros/macro-missing-fragment.rs | 24 ++---- ...4.stderr => macro-missing-fragment.stderr} | 14 +-- tests/ui/parser/macro/issue-33569.rs | 1 - tests/ui/parser/macro/issue-33569.stderr | 24 ++---- 23 files changed, 104 insertions(+), 338 deletions(-) delete mode 100644 tests/ui/macros/macro-missing-fragment.e2015.stderr rename tests/ui/macros/{macro-missing-fragment.e2024.stderr => macro-missing-fragment.stderr} (79%) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index f26c7c1ba0bc4..c180a1594a61f 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -112,7 +112,7 @@ expand_meta_var_expr_unrecognized_var = variable `{$key}` is not recognized in meta-variable expression expand_missing_fragment_specifier = missing fragment specifier - .note = fragment specifiers must be specified in the 2024 edition + .note = fragment specifiers must be provided .suggestion_add_fragspec = try adding a specifier here .valid = {$valid} diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 1a2db233b7a64..3cd803c3e8482 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -112,9 +112,8 @@ use rustc_ast::{DUMMY_NODE_ID, NodeId}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; use rustc_lint_defs::BuiltinLintDiag; -use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER}; +use rustc_session::lint::builtin::META_VARIABLE_MISUSE; use rustc_session::parse::ParseSess; -use rustc_span::edition::Edition; use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw}; use smallvec::SmallVec; @@ -266,23 +265,11 @@ fn check_binders( // Similarly, this can only happen when checking a toplevel macro. TokenTree::MetaVarDecl(span, name, kind) => { if kind.is_none() && node_id != DUMMY_NODE_ID { - // FIXME: Report this as a hard error eventually and remove equivalent errors from - // `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once - // as a hard error and then once as a buffered lint. - if span.edition() >= Edition::Edition2024 { - psess.dcx().emit_err(errors::MissingFragmentSpecifier { - span, - add_span: span.shrink_to_hi(), - valid: VALID_FRAGMENT_NAMES_MSG, - }); - } else { - psess.buffer_lint( - MISSING_FRAGMENT_SPECIFIER, - span, - node_id, - BuiltinLintDiag::MissingFragmentSpecifier, - ); - } + psess.dcx().emit_err(errors::MissingFragmentSpecifier { + span, + add_span: span.shrink_to_hi(), + valid: VALID_FRAGMENT_NAMES_MSG, + }); } if !macros.is_empty() { psess.dcx().span_bug(span, "unexpected MetaVarDecl in nested lhs"); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index fd2e2ba39acec..9a1db52fbd1ee 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -533,8 +533,6 @@ lint_mismatched_lifetime_syntaxes_suggestion_implicit = lint_mismatched_lifetime_syntaxes_suggestion_mixed = one option is to remove the lifetime for references and use the anonymous lifetime for paths -lint_missing_fragment_specifier = missing fragment specifier - lint_missing_unsafe_on_extern = extern blocks should be unsafe .suggestion = needs `unsafe` before the extern keyword diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 60c477dd6c749..3b0a36186b671 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -432,9 +432,6 @@ pub fn decorate_builtin_lint( BuiltinLintDiag::CfgAttrNoAttributes => { lints::CfgAttrNoAttributes.decorate_lint(diag); } - BuiltinLintDiag::MissingFragmentSpecifier => { - lints::MissingFragmentSpecifier.decorate_lint(diag); - } BuiltinLintDiag::MetaVariableStillRepeating(name) => { lints::MetaVariableStillRepeating { name }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 72bfeaddbf1a7..547539d7273c3 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -619,6 +619,11 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, \ see for more information", ); + store.register_removed( + "missing_fragment_specifier", + "converted into hard error, \ + see for more information", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 9d3c74a9a2b80..25acde53367b8 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2616,10 +2616,6 @@ pub(crate) struct DuplicateMacroAttribute; #[diag(lint_cfg_attr_no_attributes)] pub(crate) struct CfgAttrNoAttributes; -#[derive(LintDiagnostic)] -#[diag(lint_missing_fragment_specifier)] -pub(crate) struct MissingFragmentSpecifier; - #[derive(LintDiagnostic)] #[diag(lint_metavariable_still_repeating)] pub(crate) struct MetaVariableStillRepeating { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 777118e69fb15..174619e5ad9f6 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -65,7 +65,6 @@ declare_lint_pass! { MACRO_USE_EXTERN_CRATE, META_VARIABLE_MISUSE, MISSING_ABI, - MISSING_FRAGMENT_SPECIFIER, MISSING_UNSAFE_ON_EXTERN, MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, @@ -1417,51 +1416,6 @@ declare_lint! { }; } -declare_lint! { - /// The `missing_fragment_specifier` lint is issued when an unused pattern in a - /// `macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not - /// followed by a fragment specifier (e.g. `:expr`). - /// - /// This warning can always be fixed by removing the unused pattern in the - /// `macro_rules!` macro definition. - /// - /// ### Example - /// - /// ```rust,compile_fail,edition2021 - /// macro_rules! foo { - /// () => {}; - /// ($name) => { }; - /// } - /// - /// fn main() { - /// foo!(); - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// To fix this, remove the unused pattern from the `macro_rules!` macro definition: - /// - /// ```rust - /// macro_rules! foo { - /// () => {}; - /// } - /// fn main() { - /// foo!(); - /// } - /// ``` - pub MISSING_FRAGMENT_SPECIFIER, - Deny, - "detects missing fragment specifiers in unused `macro_rules!` patterns", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseError, - reference: "issue #40107 ", - report_in_deps: true, - }; -} - declare_lint! { /// The `late_bound_lifetime_arguments` lint detects generic lifetime /// arguments in path segments with late bound lifetime parameters. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 1d9b7a7fcb948..cd402c9234fd8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -778,7 +778,6 @@ pub enum BuiltinLintDiag { UnnameableTestItems, DuplicateMacroAttribute, CfgAttrNoAttributes, - MissingFragmentSpecifier, MetaVariableStillRepeating(MacroRulesNormalizedIdent), MetaVariableWrongOperator, DuplicateMatcherBinding, diff --git a/tests/ui/future-incompatible-lint-group.rs b/tests/ui/future-incompatible-lint-group.rs index ed2c47bb60907..5ce09cceec901 100644 --- a/tests/ui/future-incompatible-lint-group.rs +++ b/tests/ui/future-incompatible-lint-group.rs @@ -2,11 +2,23 @@ // lints for changes that are not tied to an edition #![deny(future_incompatible)] -// Error since this is a `future_incompatible` lint -macro_rules! m { ($i) => {} } //~ ERROR missing fragment specifier - //~| WARN this was previously accepted +enum E { V } -trait Tr { +trait Tr1 { + type V; + fn foo() -> Self::V; +} + +impl Tr1 for E { + type V = u8; + + // Error since this is a `future_incompatible` lint + fn foo() -> Self::V { 0 } + //~^ ERROR ambiguous associated item + //~| WARN this was previously accepted +} + +trait Tr2 { // Warn only since this is not a `future_incompatible` lint fn f(u8) {} //~ WARN anonymous parameters are deprecated //~| WARN this is accepted in the current edition diff --git a/tests/ui/future-incompatible-lint-group.stderr b/tests/ui/future-incompatible-lint-group.stderr index 4c867e0aab3cb..94b8803ab2fcd 100644 --- a/tests/ui/future-incompatible-lint-group.stderr +++ b/tests/ui/future-incompatible-lint-group.stderr @@ -1,20 +1,5 @@ -error: missing fragment specifier - --> $DIR/future-incompatible-lint-group.rs:6:19 - | -LL | macro_rules! m { ($i) => {} } - | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/future-incompatible-lint-group.rs:3:9 - | -LL | #![deny(future_incompatible)] - | ^^^^^^^^^^^^^^^^^^^ - = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]` - warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/future-incompatible-lint-group.rs:11:10 + --> $DIR/future-incompatible-lint-group.rs:23:10 | LL | fn f(u8) {} | ^^ help: try naming the parameter or explicitly ignoring it: `_: u8` @@ -23,21 +8,30 @@ LL | fn f(u8) {} = note: for more information, see issue #41686 = note: `#[warn(anonymous_parameters)]` on by default -error: aborting due to 1 previous error; 1 warning emitted - -Future incompatibility report: Future breakage diagnostic: -error: missing fragment specifier - --> $DIR/future-incompatible-lint-group.rs:6:19 +error: ambiguous associated item + --> $DIR/future-incompatible-lint-group.rs:16:17 | -LL | macro_rules! m { ($i) => {} } - | ^^ +LL | fn foo() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `::V` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 + = note: for more information, see issue #57644 +note: `V` could refer to the variant defined here + --> $DIR/future-incompatible-lint-group.rs:5:10 + | +LL | enum E { V } + | ^ +note: `V` could also refer to the associated type defined here + --> $DIR/future-incompatible-lint-group.rs:8:5 + | +LL | type V; + | ^^^^^^ note: the lint level is defined here --> $DIR/future-incompatible-lint-group.rs:3:9 | LL | #![deny(future_incompatible)] | ^^^^^^^^^^^^^^^^^^^ - = note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]` + = note: `#[deny(ambiguous_associated_items)]` implied by `#[deny(future_incompatible)]` + +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs index 5ffb0c7881e33..2c59bf0006514 100644 --- a/tests/ui/lint/expansion-time.rs +++ b/tests/ui/lint/expansion-time.rs @@ -5,10 +5,6 @@ macro_rules! foo { ( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator } -#[warn(missing_fragment_specifier)] -macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier - //~| WARN this was previously accepted - #[deprecated = "reason"] macro_rules! deprecated { () => {} diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr index f24d1b68a8dae..b1154d1a54c0b 100644 --- a/tests/ui/lint/expansion-time.stderr +++ b/tests/ui/lint/expansion-time.stderr @@ -12,20 +12,6 @@ note: the lint level is defined here LL | #[warn(meta_variable_misuse)] | ^^^^^^^^^^^^^^^^^^^^ -warning: missing fragment specifier - --> $DIR/expansion-time.rs:9:19 - | -LL | macro_rules! m { ($i) => {} } - | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/expansion-time.rs:8:8 - | -LL | #[warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - warning: include macro expected single expression in source --> $DIR/expansion-time-include.rs:4:1 | @@ -33,25 +19,10 @@ LL | 2 | ^ | note: the lint level is defined here - --> $DIR/expansion-time.rs:22:8 + --> $DIR/expansion-time.rs:18:8 | LL | #[warn(incomplete_include)] | ^^^^^^^^^^^^^^^^^^ -warning: 3 warnings emitted - -Future incompatibility report: Future breakage diagnostic: -warning: missing fragment specifier - --> $DIR/expansion-time.rs:9:19 - | -LL | macro_rules! m { ($i) => {} } - | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/expansion-time.rs:8:8 - | -LL | #[warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: 2 warnings emitted diff --git a/tests/ui/macros/issue-39404.rs b/tests/ui/macros/issue-39404.rs index 2229f2c3900c3..ceeb6231bc8cd 100644 --- a/tests/ui/macros/issue-39404.rs +++ b/tests/ui/macros/issue-39404.rs @@ -1,7 +1,7 @@ #![allow(unused)] -macro_rules! m { ($i) => {} } -//~^ ERROR missing fragment specifier -//~| WARN previously accepted +macro_rules! m { + ($i) => {}; //~ ERROR missing fragment specifier +} fn main() {} diff --git a/tests/ui/macros/issue-39404.stderr b/tests/ui/macros/issue-39404.stderr index 176c8e9f073c8..62d0bc1018c59 100644 --- a/tests/ui/macros/issue-39404.stderr +++ b/tests/ui/macros/issue-39404.stderr @@ -1,23 +1,15 @@ error: missing fragment specifier - --> $DIR/issue-39404.rs:3:19 + --> $DIR/issue-39404.rs:4:6 | -LL | macro_rules! m { ($i) => {} } - | ^^ +LL | ($i) => {}; + | ^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default + = note: fragment specifiers must be provided + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility +help: try adding a specifier here + | +LL | ($i:spec) => {}; + | +++++ error: aborting due to 1 previous error -Future incompatibility report: Future breakage diagnostic: -error: missing fragment specifier - --> $DIR/issue-39404.rs:3:19 - | -LL | macro_rules! m { ($i) => {} } - | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default - diff --git a/tests/ui/macros/macro-match-nonterminal.rs b/tests/ui/macros/macro-match-nonterminal.rs index 5d9eb55fee036..fa2af945a1f1b 100644 --- a/tests/ui/macros/macro-match-nonterminal.rs +++ b/tests/ui/macros/macro-match-nonterminal.rs @@ -3,8 +3,6 @@ macro_rules! test { //~^ ERROR missing fragment //~| ERROR missing fragment //~| ERROR missing fragment - //~| WARN this was previously accepted - //~| WARN this was previously accepted () }; } diff --git a/tests/ui/macros/macro-match-nonterminal.stderr b/tests/ui/macros/macro-match-nonterminal.stderr index f221f92c3cda6..8196d795c4c8f 100644 --- a/tests/ui/macros/macro-match-nonterminal.stderr +++ b/tests/ui/macros/macro-match-nonterminal.stderr @@ -3,16 +3,13 @@ error: missing fragment specifier | LL | ($a, $b) => { | ^^ - -error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:6 | -LL | ($a, $b) => { - | ^^ + = note: fragment specifiers must be provided + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility +help: try adding a specifier here | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default +LL | ($a:spec, $b) => { + | +++++ error: missing fragment specifier --> $DIR/macro-match-nonterminal.rs:2:10 @@ -20,30 +17,18 @@ error: missing fragment specifier LL | ($a, $b) => { | ^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - -error: aborting due to 3 previous errors + = note: fragment specifiers must be provided + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility +help: try adding a specifier here + | +LL | ($a, $b:spec) => { + | +++++ -Future incompatibility report: Future breakage diagnostic: error: missing fragment specifier --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default -Future breakage diagnostic: -error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:10 - | -LL | ($a, $b) => { - | ^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default +error: aborting due to 3 previous errors diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.rs b/tests/ui/macros/macro-missing-fragment-deduplication.rs index b77c51e055bff..481f08fa11199 100644 --- a/tests/ui/macros/macro-missing-fragment-deduplication.rs +++ b/tests/ui/macros/macro-missing-fragment-deduplication.rs @@ -1,10 +1,8 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes macro_rules! m { - ($name) => {} - //~^ ERROR missing fragment - //~| ERROR missing fragment - //~| WARN this was previously accepted + ($name) => {}; //~ ERROR missing fragment + //~| ERROR missing fragment } fn main() { diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.stderr b/tests/ui/macros/macro-missing-fragment-deduplication.stderr index c46712f70fd53..820f7eb3cf7fd 100644 --- a/tests/ui/macros/macro-missing-fragment-deduplication.stderr +++ b/tests/ui/macros/macro-missing-fragment-deduplication.stderr @@ -1,29 +1,21 @@ error: missing fragment specifier --> $DIR/macro-missing-fragment-deduplication.rs:4:6 | -LL | ($name) => {} +LL | ($name) => {}; | ^^^^^ - -error: missing fragment specifier - --> $DIR/macro-missing-fragment-deduplication.rs:4:6 | -LL | ($name) => {} - | ^^^^^ + = note: fragment specifiers must be provided + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility +help: try adding a specifier here | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default +LL | ($name:spec) => {}; + | +++++ -error: aborting due to 2 previous errors - -Future incompatibility report: Future breakage diagnostic: error: missing fragment specifier --> $DIR/macro-missing-fragment-deduplication.rs:4:6 | -LL | ($name) => {} +LL | ($name) => {}; | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default + +error: aborting due to 2 previous errors diff --git a/tests/ui/macros/macro-missing-fragment.e2015.stderr b/tests/ui/macros/macro-missing-fragment.e2015.stderr deleted file mode 100644 index 3d32f203d4a2e..0000000000000 --- a/tests/ui/macros/macro-missing-fragment.e2015.stderr +++ /dev/null @@ -1,85 +0,0 @@ -error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:8:20 - | -LL | ( $( any_token $field_rust_type )* ) => {}; - | ^^^^^^^^^^^^^^^^ - -warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:8:20 - | -LL | ( $( any_token $field_rust_type )* ) => {}; - | ^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:5:9 - | -LL | #![warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:18:7 - | -LL | ( $name ) => {}; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - -warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:25:7 - | -LL | ( $name ) => {}; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - -error: aborting due to 1 previous error; 3 warnings emitted - -Future incompatibility report: Future breakage diagnostic: -warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:8:20 - | -LL | ( $( any_token $field_rust_type )* ) => {}; - | ^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:5:9 - | -LL | #![warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:18:7 - | -LL | ( $name ) => {}; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:5:9 - | -LL | #![warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:25:7 - | -LL | ( $name ) => {}; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 -note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:5:9 - | -LL | #![warn(missing_fragment_specifier)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs index 42387e8dbbf4f..533aa147bcbf5 100644 --- a/tests/ui/macros/macro-missing-fragment.rs +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -1,31 +1,17 @@ -//@ revisions: e2015 e2024 -//@[e2015] edition:2015 -//@[e2024] edition:2024 - -#![warn(missing_fragment_specifier)] +//! Ensure that macros produce an error if fragment specifiers are missing. macro_rules! used_arm { - ( $( any_token $field_rust_type )* ) => {}; - //[e2015]~^ ERROR missing fragment - //[e2015]~| WARN missing fragment - //[e2015]~| WARN this was previously accepted - //[e2024]~^^^^ ERROR missing fragment - //[e2024]~| ERROR missing fragment + ( $( any_token $field_rust_type )* ) => {}; //~ ERROR missing fragment + //~| ERROR missing fragment } macro_rules! used_macro_unused_arm { () => {}; - ( $name ) => {}; - //[e2015]~^ WARN missing fragment - //[e2015]~| WARN this was previously accepted - //[e2024]~^^^ ERROR missing fragment + ( $name ) => {}; //~ ERROR missing fragment } macro_rules! unused_macro { - ( $name ) => {}; - //[e2015]~^ WARN missing fragment - //[e2015]~| WARN this was previously accepted - //[e2024]~^^^ ERROR missing fragment + ( $name ) => {}; //~ ERROR missing fragment } fn main() { diff --git a/tests/ui/macros/macro-missing-fragment.e2024.stderr b/tests/ui/macros/macro-missing-fragment.stderr similarity index 79% rename from tests/ui/macros/macro-missing-fragment.e2024.stderr rename to tests/ui/macros/macro-missing-fragment.stderr index a9195063a5b92..4a99d7d949cfe 100644 --- a/tests/ui/macros/macro-missing-fragment.e2024.stderr +++ b/tests/ui/macros/macro-missing-fragment.stderr @@ -1,10 +1,10 @@ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:8:20 + --> $DIR/macro-missing-fragment.rs:4:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ | - = note: fragment specifiers must be specified in the 2024 edition + = note: fragment specifiers must be provided = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility help: try adding a specifier here | @@ -12,12 +12,12 @@ LL | ( $( any_token $field_rust_type:spec )* ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:18:7 + --> $DIR/macro-missing-fragment.rs:10:7 | LL | ( $name ) => {}; | ^^^^^ | - = note: fragment specifiers must be specified in the 2024 edition + = note: fragment specifiers must be provided = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility help: try adding a specifier here | @@ -25,12 +25,12 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:25:7 + --> $DIR/macro-missing-fragment.rs:14:7 | LL | ( $name ) => {}; | ^^^^^ | - = note: fragment specifiers must be specified in the 2024 edition + = note: fragment specifiers must be provided = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility help: try adding a specifier here | @@ -38,7 +38,7 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:8:20 + --> $DIR/macro-missing-fragment.rs:4:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/parser/macro/issue-33569.rs b/tests/ui/parser/macro/issue-33569.rs index 069d181e96267..e0a5352ab06db 100644 --- a/tests/ui/parser/macro/issue-33569.rs +++ b/tests/ui/parser/macro/issue-33569.rs @@ -2,7 +2,6 @@ macro_rules! foo { { $+ } => { //~ ERROR expected identifier, found `+` //~^ ERROR missing fragment specifier //~| ERROR missing fragment specifier - //~| WARN this was previously accepted $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` } } diff --git a/tests/ui/parser/macro/issue-33569.stderr b/tests/ui/parser/macro/issue-33569.stderr index d1b6abfeeebfd..0d53c04c1c9f0 100644 --- a/tests/ui/parser/macro/issue-33569.stderr +++ b/tests/ui/parser/macro/issue-33569.stderr @@ -5,7 +5,7 @@ LL | { $+ } => { | ^ error: expected one of: `*`, `+`, or `?` - --> $DIR/issue-33569.rs:6:13 + --> $DIR/issue-33569.rs:5:13 | LL | $(x)(y) | ^^^ @@ -15,27 +15,19 @@ error: missing fragment specifier | LL | { $+ } => { | ^ - -error: missing fragment specifier - --> $DIR/issue-33569.rs:2:8 | -LL | { $+ } => { - | ^ + = note: fragment specifiers must be provided + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility +help: try adding a specifier here | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default +LL | { $+:spec } => { + | +++++ -error: aborting due to 4 previous errors - -Future incompatibility report: Future breakage diagnostic: error: missing fragment specifier --> $DIR/issue-33569.rs:2:8 | LL | { $+ } => { | ^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #40107 - = note: `#[deny(missing_fragment_specifier)]` on by default + +error: aborting due to 4 previous errors From 1cc4d35ea18fad2698368bf234865ea53831ba80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 28 Dec 2024 02:19:35 +0000 Subject: [PATCH 26/28] Detect when attribute is provided by missing `derive` macro ``` error: cannot find attribute `empty_helper` in this scope --> $DIR/derive-helper-legacy-limits.rs:17:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ | help: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute | LL + #[derive(Empty)] LL | struct S2; | ``` Look at proc-macro attributes when encountering unknown attribute ``` error: cannot find attribute `sede` in this scope --> src/main.rs:18:7 | 18 | #[sede(untagged)] | ^^^^ | help: the derive macros `Serialize` and `Deserialize` accept the similarly named `serde` attribute | 18 | #[serde(untagged)] | ~~~~~ error: cannot find attribute `serde` in this scope --> src/main.rs:12:7 | 12 | #[serde(untagged)] | ^^^^^ | = note: `serde` is in scope, but it is a crate, not an attribute help: `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize`, you might be missing a `derive` attribute | 10 | #[derive(Serialize, Deserialize)] | ``` --- compiler/rustc_resolve/src/diagnostics.rs | 137 +++++++++++++++++- compiler/rustc_resolve/src/ident.rs | 1 + compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 30 +++- .../diagnostic-derive.stderr | 14 ++ tests/ui/macros/auxiliary/serde.rs | 19 +++ tests/ui/macros/missing-derive-1.rs | 33 +++++ tests/ui/macros/missing-derive-1.stderr | 47 ++++++ tests/ui/macros/missing-derive-2.rs | 26 ++++ tests/ui/macros/missing-derive-2.stderr | 47 ++++++ tests/ui/macros/missing-derive-3.rs | 24 +++ tests/ui/macros/missing-derive-3.stderr | 32 ++++ .../derive-helper-legacy-limits.stderr | 6 + .../proc-macro/derive-helper-shadowing.stderr | 2 + .../proc-macro/disappearing-resolution.stderr | 6 + 16 files changed, 421 insertions(+), 7 deletions(-) create mode 100644 tests/ui/macros/auxiliary/serde.rs create mode 100644 tests/ui/macros/missing-derive-1.rs create mode 100644 tests/ui/macros/missing-derive-1.stderr create mode 100644 tests/ui/macros/missing-derive-2.rs create mode 100644 tests/ui/macros/missing-derive-2.stderr create mode 100644 tests/ui/macros/missing-derive-3.rs create mode 100644 tests/ui/macros/missing-derive-3.stderr diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 201b1c0a493bc..9c512e070e002 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -7,7 +7,7 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_attr_data_structures::{self as attr, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::unord::UnordSet; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, MultiSpan, SuggestionStyle, @@ -1054,6 +1054,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { false, false, None, + None, ) else { continue; }; @@ -1482,7 +1483,35 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope: &ParentScope<'ra>, ident: Ident, krate: &Crate, + sugg_span: Option, ) { + // Bring imported but unused `derive` macros into `macro_map` so we ensure they can be used + // for suggestions. + self.visit_scopes( + ScopeSet::Macro(MacroKind::Derive), + &parent_scope, + ident.span.ctxt(), + |this, scope, _use_prelude, _ctxt| { + let Scope::Module(m, _) = scope else { + return None; + }; + for (_, resolution) in this.resolutions(m).borrow().iter() { + let Some(binding) = resolution.borrow().binding else { + continue; + }; + let Res::Def(DefKind::Macro(MacroKind::Derive | MacroKind::Attr), def_id) = + binding.res() + else { + continue; + }; + // By doing this all *imported* macros get added to the `macro_map` even if they + // are *unused*, which makes the later suggestions find them and work. + let _ = this.get_macro_by_def_id(def_id); + } + None::<()> + }, + ); + let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind); let suggestion = self.early_lookup_typo_candidate( ScopeSet::Macro(macro_kind), @@ -1490,7 +1519,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, is_expected, ); - self.add_typo_suggestion(err, suggestion, ident.span); + if !self.add_typo_suggestion(err, suggestion, ident.span) { + self.detect_derive_attribute(err, ident, parent_scope, sugg_span); + } let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); @@ -1623,6 +1654,108 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } + /// Given an attribute macro that failed to be resolved, look for `derive` macros that could + /// provide it, either as-is or with small typos. + fn detect_derive_attribute( + &self, + err: &mut Diag<'_>, + ident: Ident, + parent_scope: &ParentScope<'ra>, + sugg_span: Option, + ) { + // Find all of the `derive`s in scope and collect their corresponding declared + // attributes. + // FIXME: this only works if the crate that owns the macro that has the helper_attr + // has already been imported. + let mut derives = vec![]; + let mut all_attrs: UnordMap> = UnordMap::default(); + // We're collecting these in a hashmap, and handle ordering the output further down. + #[allow(rustc::potential_query_instability)] + for (def_id, data) in &self.macro_map { + for helper_attr in &data.ext.helper_attrs { + let item_name = self.tcx.item_name(*def_id); + all_attrs.entry(*helper_attr).or_default().push(item_name); + if helper_attr == &ident.name { + derives.push(item_name); + } + } + } + let kind = MacroKind::Derive.descr(); + if !derives.is_empty() { + // We found an exact match for the missing attribute in a `derive` macro. Suggest it. + derives.sort(); + derives.dedup(); + let msg = match &derives[..] { + [derive] => format!(" `{derive}`"), + [start @ .., last] => format!( + "s {} and `{last}`", + start.iter().map(|d| format!("`{d}`")).collect::>().join(", ") + ), + [] => unreachable!("we checked for this to be non-empty 10 lines above!?"), + }; + let msg = format!( + "`{}` is an attribute that can be used by the {kind}{msg}, you might be \ + missing a `derive` attribute", + ident.name, + ); + let sugg_span = if let ModuleKind::Def(DefKind::Enum, id, _) = parent_scope.module.kind + { + let span = self.def_span(id); + if span.from_expansion() { + None + } else { + // For enum variants sugg_span is empty but we can get the enum's Span. + Some(span.shrink_to_lo()) + } + } else { + // For items this `Span` will be populated, everything else it'll be None. + sugg_span + }; + match sugg_span { + Some(span) => { + err.span_suggestion_verbose( + span, + msg, + format!( + "#[derive({})]\n", + derives + .iter() + .map(|d| d.to_string()) + .collect::>() + .join(", ") + ), + Applicability::MaybeIncorrect, + ); + } + None => { + err.note(msg); + } + } + } else { + // We didn't find an exact match. Look for close matches. If any, suggest fixing typo. + let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord(); + if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None) + && let Some(macros) = all_attrs.get(&best_match) + { + let msg = match ¯os[..] { + [] => return, + [name] => format!(" `{name}` accepts"), + [start @ .., end] => format!( + "s {} and `{end}` accept", + start.iter().map(|m| format!("`{m}`")).collect::>().join(", "), + ), + }; + let msg = format!("the {kind}{msg} the similarly named `{best_match}` attribute"); + err.span_suggestion_verbose( + ident.span, + msg, + best_match, + Applicability::MaybeIncorrect, + ); + } + } + } + pub(crate) fn add_typo_suggestion( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 180d6af219d11..68fbe48ebcb08 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -460,6 +460,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { true, force, ignore_import, + None, ) { Ok((Some(ext), _)) => { if ext.helper_attrs.contains(&ident.name) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3dc285fdab690..fa4b024c422f0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4509,7 +4509,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident); let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None }; if let Ok((_, res)) = - self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None) + self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None, None) { return Ok(Some(PartialRes::new(res))); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9ba70abd4d933..2ff48c503c559 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1139,7 +1139,7 @@ pub struct Resolver<'ra, 'tcx> { proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'ra>, Option>)>, + Vec<(Ident, MacroKind, ParentScope<'ra>, Option>, Option)>, multi_segment_macro_resolutions: Vec<(Vec, Span, MacroKind, ParentScope<'ra>, Option, Namespace)>, builtin_attrs: Vec<(Ident, ParentScope<'ra>)>, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index ee905065b966b..e80d4422e3748 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -12,7 +12,8 @@ use rustc_attr_data_structures::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, DiagCtxtHandle, StashKey}; use rustc_expand::base::{ - DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind, + Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, + SyntaxExtensionKind, }; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{ @@ -294,6 +295,14 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { && self.tcx.def_kind(mod_def_id) == DefKind::Mod }) .map(|&InvocationParent { parent_def: mod_def_id, .. }| mod_def_id); + let sugg_span = match &invoc.kind { + InvocationKind::Attr { item: Annotatable::Item(item), .. } + if !item.span.from_expansion() => + { + Some(item.span.shrink_to_lo()) + } + _ => None, + }; let (ext, res) = self.smart_resolve_macro_path( path, kind, @@ -304,6 +313,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { force, deleg_impl, looks_like_invoc_in_mod_inert_attr, + sugg_span, )?; let span = invoc.span(); @@ -386,6 +396,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { true, force, None, + None, ) { Ok((Some(ext), _)) => { if !ext.helper_attrs.is_empty() { @@ -528,6 +539,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { force: bool, deleg_impl: Option, invoc_in_mod_inert_attr: Option, + suggestion_span: Option, ) -> Result<(Arc, Res), Indeterminate> { let (ext, res) = match self.resolve_macro_or_delegation_path( path, @@ -538,6 +550,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { deleg_impl, invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)), None, + suggestion_span, ) { Ok((Some(ext), res)) => (ext, res), Ok((None, res)) => (self.dummy_ext(kind), res), @@ -681,6 +694,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { trace: bool, force: bool, ignore_import: Option>, + suggestion_span: Option, ) -> Result<(Option>, Res), Determinacy> { self.resolve_macro_or_delegation_path( path, @@ -691,6 +705,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, None, ignore_import, + suggestion_span, ) } @@ -704,6 +719,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { deleg_impl: Option, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, ignore_import: Option>, + suggestion_span: Option, ) -> Result<(Option>, Res), Determinacy> { let path_span = ast_path.span; let mut path = Segment::from_path(ast_path); @@ -768,6 +784,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { kind, *parent_scope, binding.ok(), + suggestion_span, )); } @@ -905,7 +922,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions); - for (ident, kind, parent_scope, initial_binding) in macro_resolutions { + for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions { match self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::Macro(kind), @@ -946,7 +963,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { expected, ident, }); - self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate); + self.unresolved_macro_suggestions( + &mut err, + kind, + &parent_scope, + ident, + krate, + sugg_span, + ); err.emit(); } } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 03fca17aa55d4..001699b2bc726 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -583,18 +583,32 @@ error: cannot find attribute `multipart_suggestion` in this scope | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ + | +help: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute + | +LL + #[derive(Subdiagnostic)] +LL | struct MultipartSuggestion { + | error: cannot find attribute `multipart_suggestion` in this scope --> $DIR/diagnostic-derive.rs:647:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ + | +help: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute + | +LL + #[derive(Subdiagnostic)] +LL | struct MultipartSuggestion { + | error: cannot find attribute `multipart_suggestion` in this scope --> $DIR/diagnostic-derive.rs:651:7 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` --> $DIR/diagnostic-derive.rs:75:8 diff --git a/tests/ui/macros/auxiliary/serde.rs b/tests/ui/macros/auxiliary/serde.rs new file mode 100644 index 0000000000000..355b650bcf390 --- /dev/null +++ b/tests/ui/macros/auxiliary/serde.rs @@ -0,0 +1,19 @@ +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_derive(Serialize, attributes(serde))] +pub fn serialize(ts: TokenStream) -> TokenStream { + quote!{} +} + +#[proc_macro_derive(Deserialize, attributes(serde))] +pub fn deserialize(ts: TokenStream) -> TokenStream { + quote!{} +} diff --git a/tests/ui/macros/missing-derive-1.rs b/tests/ui/macros/missing-derive-1.rs new file mode 100644 index 0000000000000..b5221fbca60a8 --- /dev/null +++ b/tests/ui/macros/missing-derive-1.rs @@ -0,0 +1,33 @@ +//@aux-build:serde.rs + +// derive macros imported and used + +extern crate serde; +use serde::{Serialize, Deserialize}; + +#[serde(untagged)] //~ ERROR cannot find attribute `serde` +enum A { //~ HELP `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize` + A, + B, +} + +enum B { //~ HELP `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize` + A, + #[serde(untagged)] //~ ERROR cannot find attribute `serde` + B, +} + +enum C { + A, + #[sede(untagged)] //~ ERROR cannot find attribute `sede` + B, //~^ HELP the derive macros `Deserialize` and `Serialize` accept the similarly named `serde` attribute +} + +#[derive(Serialize, Deserialize)] +#[serde(untagged)] +enum D { + A, + B, +} + +fn main() {} diff --git a/tests/ui/macros/missing-derive-1.stderr b/tests/ui/macros/missing-derive-1.stderr new file mode 100644 index 0000000000000..d7255d5937e06 --- /dev/null +++ b/tests/ui/macros/missing-derive-1.stderr @@ -0,0 +1,47 @@ +error: cannot find attribute `serde` in this scope + --> $DIR/missing-derive-1.rs:8:3 + | +LL | #[serde(untagged)] + | ^^^^^ + | +note: `serde` is imported here, but it is a crate, not an attribute + --> $DIR/missing-derive-1.rs:5:1 + | +LL | extern crate serde; + | ^^^^^^^^^^^^^^^^^^^ +help: `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize`, you might be missing a `derive` attribute + | +LL + #[derive(Serialize, Deserialize)] +LL | enum A { + | + +error: cannot find attribute `serde` in this scope + --> $DIR/missing-derive-1.rs:16:7 + | +LL | #[serde(untagged)] + | ^^^^^ + | +note: `serde` is imported here, but it is a crate, not an attribute + --> $DIR/missing-derive-1.rs:5:1 + | +LL | extern crate serde; + | ^^^^^^^^^^^^^^^^^^^ +help: `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize`, you might be missing a `derive` attribute + | +LL + #[derive(Serialize, Deserialize)] +LL | enum B { + | + +error: cannot find attribute `sede` in this scope + --> $DIR/missing-derive-1.rs:22:7 + | +LL | #[sede(untagged)] + | ^^^^ + | +help: the derive macros `Deserialize` and `Serialize` accept the similarly named `serde` attribute + | +LL | #[serde(untagged)] + | + + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/missing-derive-2.rs b/tests/ui/macros/missing-derive-2.rs new file mode 100644 index 0000000000000..754aab0287ade --- /dev/null +++ b/tests/ui/macros/missing-derive-2.rs @@ -0,0 +1,26 @@ +//@aux-build:serde.rs + +// derive macros imported but unused + +extern crate serde; +use serde::{Serialize, Deserialize}; + +#[serde(untagged)] //~ ERROR cannot find attribute `serde` +enum A { //~ HELP `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize` + A, + B, +} + +enum B { //~ HELP `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize` + A, + #[serde(untagged)] //~ ERROR cannot find attribute `serde` + B, +} + +enum C { + A, + #[sede(untagged)] //~ ERROR cannot find attribute `sede` + B, //~^ HELP the derive macros `Deserialize` and `Serialize` accept the similarly named `serde` attribute +} + +fn main() {} diff --git a/tests/ui/macros/missing-derive-2.stderr b/tests/ui/macros/missing-derive-2.stderr new file mode 100644 index 0000000000000..7234515bde2cc --- /dev/null +++ b/tests/ui/macros/missing-derive-2.stderr @@ -0,0 +1,47 @@ +error: cannot find attribute `sede` in this scope + --> $DIR/missing-derive-2.rs:22:7 + | +LL | #[sede(untagged)] + | ^^^^ + | +help: the derive macros `Deserialize` and `Serialize` accept the similarly named `serde` attribute + | +LL | #[serde(untagged)] + | + + +error: cannot find attribute `serde` in this scope + --> $DIR/missing-derive-2.rs:16:7 + | +LL | #[serde(untagged)] + | ^^^^^ + | +note: `serde` is imported here, but it is a crate, not an attribute + --> $DIR/missing-derive-2.rs:5:1 + | +LL | extern crate serde; + | ^^^^^^^^^^^^^^^^^^^ +help: `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize`, you might be missing a `derive` attribute + | +LL + #[derive(Serialize, Deserialize)] +LL | enum B { + | + +error: cannot find attribute `serde` in this scope + --> $DIR/missing-derive-2.rs:8:3 + | +LL | #[serde(untagged)] + | ^^^^^ + | +note: `serde` is imported here, but it is a crate, not an attribute + --> $DIR/missing-derive-2.rs:5:1 + | +LL | extern crate serde; + | ^^^^^^^^^^^^^^^^^^^ +help: `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize`, you might be missing a `derive` attribute + | +LL + #[derive(Serialize, Deserialize)] +LL | enum A { + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/missing-derive-3.rs b/tests/ui/macros/missing-derive-3.rs new file mode 100644 index 0000000000000..8add81988901a --- /dev/null +++ b/tests/ui/macros/missing-derive-3.rs @@ -0,0 +1,24 @@ +//@aux-build:serde.rs + +// derive macros not imported, but namespace imported. Not yet handled. +extern crate serde; + +#[serde(untagged)] //~ ERROR cannot find attribute `serde` +enum A { + A, + B, +} + +enum B { + A, + #[serde(untagged)] //~ ERROR cannot find attribute `serde` + B, +} + +enum C { + A, + #[sede(untagged)] //~ ERROR cannot find attribute `sede` + B, +} + +fn main() {} diff --git a/tests/ui/macros/missing-derive-3.stderr b/tests/ui/macros/missing-derive-3.stderr new file mode 100644 index 0000000000000..0a7ed8d08763c --- /dev/null +++ b/tests/ui/macros/missing-derive-3.stderr @@ -0,0 +1,32 @@ +error: cannot find attribute `sede` in this scope + --> $DIR/missing-derive-3.rs:20:7 + | +LL | #[sede(untagged)] + | ^^^^ + +error: cannot find attribute `serde` in this scope + --> $DIR/missing-derive-3.rs:14:7 + | +LL | #[serde(untagged)] + | ^^^^^ + | +note: `serde` is imported here, but it is a crate, not an attribute + --> $DIR/missing-derive-3.rs:4:1 + | +LL | extern crate serde; + | ^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `serde` in this scope + --> $DIR/missing-derive-3.rs:6:3 + | +LL | #[serde(untagged)] + | ^^^^^ + | +note: `serde` is imported here, but it is a crate, not an attribute + --> $DIR/missing-derive-3.rs:4:1 + | +LL | extern crate serde; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/proc-macro/derive-helper-legacy-limits.stderr b/tests/ui/proc-macro/derive-helper-legacy-limits.stderr index f5cd455435d4a..df3c5c47ddb2d 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-limits.stderr +++ b/tests/ui/proc-macro/derive-helper-legacy-limits.stderr @@ -3,6 +3,12 @@ error: cannot find attribute `empty_helper` in this scope | LL | #[empty_helper] | ^^^^^^^^^^^^ + | +help: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute + | +LL + #[derive(Empty)] +LL | struct S2; + | error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/derive-helper-shadowing.stderr b/tests/ui/proc-macro/derive-helper-shadowing.stderr index f284b1c54dd61..1206778bb2352 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.stderr +++ b/tests/ui/proc-macro/derive-helper-shadowing.stderr @@ -16,6 +16,7 @@ error: cannot find attribute `empty_helper` in this scope LL | #[derive(GenHelperUse)] | ^^^^^^^^^^^^ | + = note: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this attribute macro through its public re-export | @@ -31,6 +32,7 @@ LL | #[empty_helper] LL | gen_helper_use!(); | ----------------- in this macro invocation | + = note: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this attribute macro through its public re-export | diff --git a/tests/ui/proc-macro/disappearing-resolution.stderr b/tests/ui/proc-macro/disappearing-resolution.stderr index 734e0cd2ab6df..6c0f1a52915f6 100644 --- a/tests/ui/proc-macro/disappearing-resolution.stderr +++ b/tests/ui/proc-macro/disappearing-resolution.stderr @@ -3,6 +3,12 @@ error: cannot find attribute `empty_helper` in this scope | LL | #[empty_helper] | ^^^^^^^^^^^^ + | +help: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute + | +LL + #[derive(Empty)] +LL | struct S; + | error[E0603]: derive macro import `Empty` is private --> $DIR/disappearing-resolution.rs:11:8 From ed06f361acb0d1267cf5d3457a70033e573e8b66 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 10 Jun 2025 16:50:17 -0700 Subject: [PATCH 27/28] Remove unneeded `FunctionCx` from some codegen methods No changes; just removing the `self` that wasn't needed. --- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 190 +++++++++---------- 1 file changed, 94 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 5c14fe5cd10b7..b62ac89661f26 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { { let from_backend_ty = bx.backend_type(operand.layout); let to_backend_ty = bx.backend_type(cast); - Some(OperandValue::Immediate(self.transmute_immediate( + Some(OperandValue::Immediate(transmute_immediate( bx, imm, from_scalar, @@ -303,8 +303,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false); let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false); Some(OperandValue::Pair( - self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty), - self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty), + transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty), + transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty), )) } else { None @@ -332,7 +332,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // valid ranges. For example, `char`s are passed as just `i32`, with no // way for LLVM to know that they're 0x10FFFF at most. Thus we assume // the range of the input value too, not just the output range. - self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); + assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { (Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed), @@ -365,98 +365,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(imm) } - /// Transmutes one of the immediates from an [`OperandValue::Immediate`] - /// or an [`OperandValue::Pair`] to an immediate of the target type. - /// - /// `to_backend_ty` must be the *non*-immediate backend type (so it will be - /// `i8`, not `i1`, for `bool`-like types.) - fn transmute_immediate( - &self, - bx: &mut Bx, - mut imm: Bx::Value, - from_scalar: abi::Scalar, - from_backend_ty: Bx::Type, - to_scalar: abi::Scalar, - to_backend_ty: Bx::Type, - ) -> Bx::Value { - assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx)); - - // While optimizations will remove no-op transmutes, they might still be - // there in debug or things that aren't no-op in MIR because they change - // the Rust type but not the underlying layout/niche. - if from_scalar == to_scalar && from_backend_ty == to_backend_ty { - return imm; - } - - use abi::Primitive::*; - imm = bx.from_immediate(imm); - - // If we have a scalar, we must already know its range. Either - // - // 1) It's a parameter with `range` parameter metadata, - // 2) It's something we `load`ed with `!range` metadata, or - // 3) After a transmute we `assume`d the range (see below). - // - // That said, last time we tried removing this, it didn't actually help - // the rustc-perf results, so might as well keep doing it - // - self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); - - imm = match (from_scalar.primitive(), to_scalar.primitive()) { - (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), - (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), - (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), - (Pointer(..), Int(..)) => { - // FIXME: this exposes the provenance, which shouldn't be necessary. - bx.ptrtoint(imm, to_backend_ty) - } - (Float(_), Pointer(..)) => { - let int_imm = bx.bitcast(imm, bx.cx().type_isize()); - bx.ptradd(bx.const_null(bx.type_ptr()), int_imm) - } - (Pointer(..), Float(_)) => { - // FIXME: this exposes the provenance, which shouldn't be necessary. - let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); - bx.bitcast(int_imm, to_backend_ty) - } - }; - - // This `assume` remains important for cases like (a conceptual) - // transmute::(x) == 0 - // since it's never passed to something with parameter metadata (especially - // after MIR inlining) so the only way to tell the backend about the - // constraint that the `transmute` introduced is to `assume` it. - self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty); - - imm = bx.to_immediate_scalar(imm, to_scalar); - imm - } - - fn assume_scalar_range( - &self, - bx: &mut Bx, - imm: Bx::Value, - scalar: abi::Scalar, - backend_ty: Bx::Type, - ) { - if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) { - return; - } - - match scalar.primitive() { - abi::Primitive::Int(..) => { - let range = scalar.valid_range(self.cx); - bx.assume_integer_range(imm, backend_ty, range); - } - abi::Primitive::Pointer(abi::AddressSpace::DATA) - if !scalar.valid_range(self.cx).contains(0) => - { - bx.assume_nonnull(imm); - } - abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {} - } - } - pub(crate) fn codegen_rvalue_unsized( &mut self, bx: &mut Bx, @@ -1231,3 +1139,93 @@ impl OperandValueKind { }) } } + +/// Transmutes one of the immediates from an [`OperandValue::Immediate`] +/// or an [`OperandValue::Pair`] to an immediate of the target type. +/// +/// `to_backend_ty` must be the *non*-immediate backend type (so it will be +/// `i8`, not `i1`, for `bool`-like types.) +fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &mut Bx, + mut imm: Bx::Value, + from_scalar: abi::Scalar, + from_backend_ty: Bx::Type, + to_scalar: abi::Scalar, + to_backend_ty: Bx::Type, +) -> Bx::Value { + assert_eq!(from_scalar.size(bx.cx()), to_scalar.size(bx.cx())); + + // While optimizations will remove no-op transmutes, they might still be + // there in debug or things that aren't no-op in MIR because they change + // the Rust type but not the underlying layout/niche. + if from_scalar == to_scalar && from_backend_ty == to_backend_ty { + return imm; + } + + use abi::Primitive::*; + imm = bx.from_immediate(imm); + + // If we have a scalar, we must already know its range. Either + // + // 1) It's a parameter with `range` parameter metadata, + // 2) It's something we `load`ed with `!range` metadata, or + // 3) After a transmute we `assume`d the range (see below). + // + // That said, last time we tried removing this, it didn't actually help + // the rustc-perf results, so might as well keep doing it + // + assume_scalar_range(bx, imm, from_scalar, from_backend_ty); + + imm = match (from_scalar.primitive(), to_scalar.primitive()) { + (Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty), + (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), + (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), + (Pointer(..), Int(..)) => { + // FIXME: this exposes the provenance, which shouldn't be necessary. + bx.ptrtoint(imm, to_backend_ty) + } + (Float(_), Pointer(..)) => { + let int_imm = bx.bitcast(imm, bx.cx().type_isize()); + bx.ptradd(bx.const_null(bx.type_ptr()), int_imm) + } + (Pointer(..), Float(_)) => { + // FIXME: this exposes the provenance, which shouldn't be necessary. + let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); + bx.bitcast(int_imm, to_backend_ty) + } + }; + + // This `assume` remains important for cases like (a conceptual) + // transmute::(x) == 0 + // since it's never passed to something with parameter metadata (especially + // after MIR inlining) so the only way to tell the backend about the + // constraint that the `transmute` introduced is to `assume` it. + assume_scalar_range(bx, imm, to_scalar, to_backend_ty); + + imm = bx.to_immediate_scalar(imm, to_scalar); + imm +} + +fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &mut Bx, + imm: Bx::Value, + scalar: abi::Scalar, + backend_ty: Bx::Type, +) { + if matches!(bx.cx().sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(bx.cx()) { + return; + } + + match scalar.primitive() { + abi::Primitive::Int(..) => { + let range = scalar.valid_range(bx.cx()); + bx.assume_integer_range(imm, backend_ty, range); + } + abi::Primitive::Pointer(abi::AddressSpace::DATA) + if !scalar.valid_range(bx.cx()).contains(0) => + { + bx.assume_nonnull(imm); + } + abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {} + } +} From 199b80887043acdc029558f3739c094bdfd72b6a Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sat, 7 Jun 2025 22:38:30 +0900 Subject: [PATCH 28/28] feat: Add `bit_width` for unsigned integer types --- library/core/src/num/uint_macros.rs | 24 ++++++++++++++++++++++ library/coretests/tests/lib.rs | 1 + library/coretests/tests/num/uint_macros.rs | 8 ++++++++ 3 files changed, 33 insertions(+) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 5f82e6af86b08..4ee0e7326b3a8 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -213,6 +213,30 @@ macro_rules! uint_impl { (!self).trailing_zeros() } + /// Returns the minimum number of bits required to represent `self`. + /// + /// This method returns zero if `self` is zero. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(uint_bit_width)] + /// + #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".bit_width(), 0);")] + #[doc = concat!("assert_eq!(0b111_", stringify!($SelfT), ".bit_width(), 3);")] + #[doc = concat!("assert_eq!(0b1110_", stringify!($SelfT), ".bit_width(), 4);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.bit_width(), ", stringify!($BITS), ");")] + /// ``` + #[unstable(feature = "uint_bit_width", issue = "142326")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn bit_width(self) -> u32 { + Self::BITS - self.leading_zeros() + } + /// Returns `self` with only the most significant bit set, or `0` if /// the input is `0`. /// diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 92b920dd775ed..5449132413b54 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -94,6 +94,7 @@ #![feature(try_blocks)] #![feature(try_find)] #![feature(try_trait_v2)] +#![feature(uint_bit_width)] #![feature(unsize)] #![feature(unwrap_infallible)] // tidy-alphabetical-end diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs index 6f3d160964f14..7e02027bdd6a1 100644 --- a/library/coretests/tests/num/uint_macros.rs +++ b/library/coretests/tests/num/uint_macros.rs @@ -72,6 +72,14 @@ macro_rules! uint_module { assert_eq_const_safe!(u32: X.trailing_ones(), 0); } + fn test_bit_width() { + assert_eq_const_safe!(u32: A.bit_width(), 6); + assert_eq_const_safe!(u32: B.bit_width(), 6); + assert_eq_const_safe!(u32: C.bit_width(), 7); + assert_eq_const_safe!(u32: _0.bit_width(), 0); + assert_eq_const_safe!(u32: _1.bit_width(), $T::BITS); + } + fn test_rotate() { assert_eq_const_safe!($T: A.rotate_left(6).rotate_right(2).rotate_right(4), A); assert_eq_const_safe!($T: B.rotate_left(3).rotate_left(2).rotate_right(5), B);