From 90d6fe2cba2b621b4fc331a1f6dd67c63a7c1033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 27 Dec 2023 15:29:52 +0100 Subject: [PATCH 01/21] Imply outlives-bounds on lazy type aliases --- .../src/outlives/implicit_infer.rs | 179 +++++++++++------- .../rustc_hir_analysis/src/outlives/mod.rs | 8 +- .../associated-type-bounds/duplicate.stderr | 48 ++--- .../implied-outlives-bounds.neg.stderr | 34 ++++ .../implied-outlives-bounds.rs | 39 ++++ 5 files changed, 211 insertions(+), 97 deletions(-) create mode 100644 tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr create mode 100644 tests/ui/lazy-type-alias/implied-outlives-bounds.rs diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index c17925471d983..0cb38094ceca5 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -59,6 +59,17 @@ pub(super) fn infer_predicates( } } + DefKind::TyAlias if tcx.type_alias_is_lazy(item_did) => { + insert_required_predicates_to_be_wf( + tcx, + tcx.type_of(item_did).instantiate_identity(), + tcx.def_span(item_did), + &global_inferred_outlives, + &mut item_required_predicates, + &mut explicit_map, + ); + } + _ => {} }; @@ -88,14 +99,14 @@ pub(super) fn infer_predicates( fn insert_required_predicates_to_be_wf<'tcx>( tcx: TyCtxt<'tcx>, - field_ty: Ty<'tcx>, - field_span: Span, + ty: Ty<'tcx>, + span: Span, global_inferred_outlives: &FxHashMap>>, required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, ) { - for arg in field_ty.walk() { - let ty = match arg.unpack() { + for arg in ty.walk() { + let leaf_ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, // No predicates from lifetimes or constants, except potentially @@ -103,63 +114,26 @@ fn insert_required_predicates_to_be_wf<'tcx>( GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue, }; - match *ty.kind() { - // The field is of type &'a T which means that we will have - // a predicate requirement of T: 'a (T outlives 'a). - // - // We also want to calculate potential predicates for the T + match *leaf_ty.kind() { ty::Ref(region, rty, _) => { + // The type is `&'a T` which means that we will have + // a predicate requirement of `T: 'a` (`T` outlives `'a`). + // + // We also want to calculate potential predicates for the `T`. debug!("Ref"); - insert_outlives_predicate(tcx, rty.into(), region, field_span, required_predicates); + insert_outlives_predicate(tcx, rty.into(), region, span, required_predicates); } - // For each Adt (struct/enum/union) type `Foo<'a, T>`, we - // can load the current set of inferred and explicit - // predicates from `global_inferred_outlives` and filter the - // ones that are TypeOutlives. ty::Adt(def, args) => { - // First check the inferred predicates - // - // Example 1: - // - // struct Foo<'a, T> { - // field1: Bar<'a, T> - // } - // - // struct Bar<'b, U> { - // field2: &'b U - // } - // - // Here, when processing the type of `field1`, we would - // request the set of implicit predicates computed for `Bar` - // thus far. This will initially come back empty, but in next - // round we will get `U: 'b`. We then apply the substitution - // `['b => 'a, U => T]` and thus get the requirement that `T: - // 'a` holds for `Foo`. + // For ADTs (structs/enums/unions), we check inferred and explicit predicates. debug!("Adt"); - if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) { - for (unsubstituted_predicate, &span) in - unsubstituted_predicates.as_ref().skip_binder() - { - // `unsubstituted_predicate` is `U: 'b` in the - // example above. So apply the substitution to - // get `T: 'a` (or `predicate`): - let predicate = unsubstituted_predicates - .rebind(*unsubstituted_predicate) - .instantiate(tcx, args); - insert_outlives_predicate( - tcx, - predicate.0, - predicate.1, - span, - required_predicates, - ); - } - } - - // Check if the type has any explicit predicates that need - // to be added to `required_predicates` - // let _: () = args.region_at(0); + check_inferred_predicates( + tcx, + def.did(), + args, + global_inferred_outlives, + required_predicates, + ); check_explicit_predicates( tcx, def.did(), @@ -170,13 +144,31 @@ fn insert_required_predicates_to_be_wf<'tcx>( ); } + ty::Alias(ty::Weak, alias) => { + // This corresponds to a type like `Type<'a, T>`. + // We check inferred and explicit predicates. + debug!("Weak"); + check_inferred_predicates( + tcx, + alias.def_id, + alias.args, + global_inferred_outlives, + required_predicates, + ); + check_explicit_predicates( + tcx, + alias.def_id, + alias.args, + required_predicates, + explicit_map, + None, + ); + } + ty::Dynamic(obj, ..) => { // This corresponds to `dyn Trait<..>`. In this case, we should // use the explicit predicates as well. - debug!("Dynamic"); - debug!("field_ty = {}", &field_ty); - debug!("ty in field = {}", &ty); if let Some(ex_trait_ref) = obj.principal() { // Here, we are passing the type `usize` as a // placeholder value with the function @@ -198,21 +190,22 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } - ty::Alias(ty::Projection, obj) => { - // This corresponds to `>::Bar`. In this case, we should use the - // explicit predicates as well. + ty::Alias(ty::Projection, alias) => { + // This corresponds to a type like `<() as Trait<'a, T>>::Type`. + // We only use the explicit predicates of the trait but + // not the ones of the associated type itself. debug!("Projection"); check_explicit_predicates( tcx, - tcx.parent(obj.def_id), - obj.args, + tcx.parent(alias.def_id), + alias.args, required_predicates, explicit_map, None, ); } - // FIXME(inherent_associated_types): Handle this case properly. + // FIXME(inherent_associated_types): Use the explicit predicates from the parent impl. ty::Alias(ty::Inherent, _) => {} _ => {} @@ -220,19 +213,21 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } -/// We also have to check the explicit predicates -/// declared on the type. +/// Check the explicit predicates declared on the type. +/// +/// ### Example +/// /// ```ignore (illustrative) -/// struct Foo<'a, T> { -/// field1: Bar +/// struct Outer<'a, T> { +/// field: Inner, /// } /// -/// struct Bar where U: 'static, U: Foo { -/// ... +/// struct Inner where U: 'static, U: Outer { +/// // ... /// } /// ``` /// Here, we should fetch the explicit predicates, which -/// will give us `U: 'static` and `U: Foo`. The latter we +/// will give us `U: 'static` and `U: Outer`. The latter we /// can ignore, but we will want to process `U: 'static`, /// applying the substitution as above. fn check_explicit_predicates<'tcx>( @@ -303,3 +298,45 @@ fn check_explicit_predicates<'tcx>( insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates); } } + +/// Check the inferred predicates declared on the type. +/// +/// ### Example +/// +/// ```ignore (illustrative) +/// struct Outer<'a, T> { +/// outer: Inner<'a, T>, +/// } +/// +/// struct Inner<'b, U> { +/// inner: &'b U, +/// } +/// ``` +/// +/// Here, when processing the type of field `outer`, we would request the +/// set of implicit predicates computed for `Inner` thus far. This will +/// initially come back empty, but in next round we will get `U: 'b`. +/// We then apply the substitution `['b => 'a, U => T]` and thus get the +/// requirement that `T: 'a` holds for `Outer`. +fn check_inferred_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, + global_inferred_outlives: &FxHashMap>>, + required_predicates: &mut RequiredPredicates<'tcx>, +) { + // Load the current set of inferred and explicit predicates from `global_inferred_outlives` + // and filter the ones that are `TypeOutlives`. + + let Some(predicates) = global_inferred_outlives.get(&def_id) else { + return; + }; + + for (&predicate, &span) in predicates.as_ref().skip_binder() { + // `predicate` is `U: 'b` in the example above. + // So apply the substitution to get `T: 'a`. + let ty::OutlivesPredicate(arg, region) = + predicates.rebind(predicate).instantiate(tcx, args); + insert_outlives_predicate(tcx, arg, region, span, required_predicates); + } +} diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 72511bfa01f14..a87112dcc1230 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -21,6 +21,10 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau let crate_map = tcx.inferred_outlives_crate(()); crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]) } + DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => { + let crate_map = tcx.inferred_outlives_crate(()); + crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]) + } DefKind::AnonConst if tcx.features().generic_const_exprs => { let id = tcx.local_def_id_to_hir_id(item_def_id); if tcx.hir().opt_const_param_default_param_def_id(id).is_some() { @@ -47,8 +51,8 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau } fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { - // Compute a map from each struct/enum/union S to the **explicit** - // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote. + // Compute a map from each ADT (struct/enum/union) and lazy type alias to + // the **explicit** outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote. // Typically there won't be many of these, except in older code where // they were mandatory. Nonetheless, we have to ensure that every such // predicate is satisfied, so they form a kind of base set of requirements diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index 3888e62230f14..38b812dfdd442 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -6,6 +6,30 @@ LL | struct SI1> { | | | `Item` bound here first +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:255:40 + | +LL | type TADyn1 = dyn Iterator; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:257:44 + | +LL | type TADyn2 = Box>; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified + --> $DIR/duplicate.rs:259:43 + | +LL | type TADyn3 = dyn Iterator; + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:11:36 | @@ -490,30 +514,6 @@ LL | Self: Iterator, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:255:40 - | -LL | type TADyn1 = dyn Iterator; - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:257:44 - | -LL | type TADyn2 = Box>; - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:259:43 - | -LL | type TADyn3 = dyn Iterator; - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:243:34 | diff --git a/tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr b/tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr new file mode 100644 index 0000000000000..a2dbb58ecd03d --- /dev/null +++ b/tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr @@ -0,0 +1,34 @@ +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:21:12 + | +LL | fn env0<'any>() { + | ---- lifetime `'any` defined here +LL | let _: TypeOutlives<'static, &'any ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:26:12 + | +LL | fn env1<'any>() { + | ---- lifetime `'any` defined here +LL | let _: RegionOutlives<'static, 'any>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:31:12 + | +LL | fn env2<'any>() { + | ---- lifetime `'any` defined here +LL | let _: Outer0<'static, &'any ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:36:12 + | +LL | fn env3<'any>() { + | ---- lifetime `'any` defined here +LL | let _: Outer1<'static, &'any ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lazy-type-alias/implied-outlives-bounds.rs b/tests/ui/lazy-type-alias/implied-outlives-bounds.rs new file mode 100644 index 0000000000000..c08e45975de10 --- /dev/null +++ b/tests/ui/lazy-type-alias/implied-outlives-bounds.rs @@ -0,0 +1,39 @@ +// Check that we imply outlives-bounds on lazy type aliases. + +// revisions: pos neg +//[pos] check-pass + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type TypeOutlives<'a, T> = &'a T; +type RegionOutlives<'a, 'b> = &'a &'b (); + +// Ensure that we imply bounds from the explicit bounds of weak aliases. +struct Outer0<'a, T>(ExplicitTypeOutlives<'a, T>); +type ExplicitTypeOutlives<'a, T: 'a> = (&'a (), T); + +// Ensure that we imply bounds from the implied bounds of weak aliases. +type Outer1<'b, U> = TypeOutlives<'b, U>; + +#[cfg(neg)] +fn env0<'any>() { + let _: TypeOutlives<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env1<'any>() { + let _: RegionOutlives<'static, 'any>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env2<'any>() { + let _: Outer0<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env3<'any>() { + let _: Outer1<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough +} + +fn main() {} From 3ab43e522eeaee2333828e8e0e8b0df96c4f0fe2 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Thu, 21 Dec 2023 14:02:58 +0100 Subject: [PATCH 02/21] Allow emitting diagnostics from the `#[diagnostic]` namespace without a nightly feature (Using this attribute still requires a nightly feature, this just enables that this feature does not need to be enabled on the child crate as well) --- .../src/traits/error_reporting/on_unimplemented.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 52f91d282f0b6..c9e8b30c4c48c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -521,7 +521,7 @@ impl<'tcx> OnUnimplementedDirective { pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result, ErrorGuaranteed> { if let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) { return Self::parse_attribute(attr, false, tcx, item_def_id); - } else if tcx.features().diagnostic_namespace { + } else { tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, sym::on_unimplemented]) .filter_map(|attr| Self::parse_attribute(attr, true, tcx, item_def_id).transpose()) .try_fold(None, |aggr: Option, directive| { @@ -592,8 +592,6 @@ impl<'tcx> OnUnimplementedDirective { Ok(Some(directive)) } }) - } else { - Ok(None) } } From cd9425b8d1fe7c0c84e9743efc0223640ff4fe08 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 22 Dec 2023 14:30:12 +0100 Subject: [PATCH 03/21] Replace some usage of `#[rustc_on_unimplemented]` with `#[diagnostic::on_unimplemented]` This commit replaces those `#[rustc_on_unimplemented]` attributes with their equivalent `#[diagnostic::on_unimplemented]` where this is supported (So no filter or any extended option) --- library/core/src/future/future.rs | 2 +- library/core/src/lib.rs | 1 + library/core/src/marker.rs | 16 +++++++-------- library/core/src/ops/arith.rs | 16 +++++++-------- library/core/src/ops/bit.rs | 20 +++++++++---------- library/core/src/ops/index.rs | 2 +- library/core/src/panic/unwind_safe.rs | 4 ++-- tests/ui/proc-macro/meta-macro-hygiene.stdout | 3 +++ .../nonterminal-token-hygiene.stdout | 3 +++ 9 files changed, 37 insertions(+), 30 deletions(-) diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 71b9464efd288..af2e422e8a00c 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -28,7 +28,7 @@ use crate::task::{Context, Poll}; #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( label = "`{Self}` is not a future", message = "`{Self}` is not a future", note = "{Self} must be a future or must implement `IntoFuture` to be awaited" diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 07720f235989b..9f8ae7a09f094 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -218,6 +218,7 @@ #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] +#![feature(diagnostic_namespace)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 99762bccd18f2..69d54f0640780 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -75,7 +75,7 @@ macro marker_impls { /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Send")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" )] @@ -134,7 +134,7 @@ unsafe impl Send for &T {} #[doc(alias = "?", alias = "?Sized")] #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sized"] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "the size for values of type `{Self}` cannot be known at compilation time", label = "doesn't have a size known at compile-time" )] @@ -205,7 +205,7 @@ pub trait Unsize { /// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md /// [issue 63438]: https://github.com/rust-lang/rust/issues/63438 #[unstable(feature = "structural_match", issue = "31434")] -#[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] +#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")] #[lang = "structural_peq"] pub trait StructuralPartialEq { // Empty. @@ -273,7 +273,7 @@ marker_impls! { /// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check /// that both of them are present as part of structural-match checking. #[unstable(feature = "structural_match", issue = "31434")] -#[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] +#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] #[lang = "structural_teq"] pub trait StructuralEq { // Empty. @@ -941,7 +941,7 @@ marker_impls! { /// [Pin]: crate::pin::Pin /// [`pin` module]: crate::pin #[stable(feature = "pin", since = "1.33.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( note = "consider using the `pin!` macro\nconsider using `Box::pin` if you need to access the pinned value outside of the current scope", message = "`{Self}` cannot be unpinned" )] @@ -989,7 +989,7 @@ pub trait Destruct {} /// for any user type. #[unstable(feature = "tuple_trait", issue = "none")] #[lang = "tuple_trait"] -#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")] +#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")] #[rustc_deny_explicit_impl(implement_via_object = false)] pub trait Tuple {} @@ -999,7 +999,7 @@ pub trait Tuple {} /// `*const ()` automatically implement this trait. #[unstable(feature = "pointer_like_trait", issue = "none")] #[lang = "pointer_like"] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "`{Self}` needs to have the same ABI as a pointer", label = "`{Self}` needs to be a pointer-like type" )] @@ -1013,7 +1013,7 @@ pub trait PointerLike {} /// are `StructuralPartialEq`. #[lang = "const_param_ty"] #[unstable(feature = "adt_const_params", issue = "95174")] -#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] +#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] #[allow(multiple_supertrait_upcastable)] pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {} diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 1773fdbf37cc7..bb3cdde66d173 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -307,7 +307,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "mul"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot multiply `{Self}` by `{Rhs}`", label = "no implementation for `{Self} * {Rhs}`" )] @@ -441,7 +441,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "div"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot divide `{Self}` by `{Rhs}`", label = "no implementation for `{Self} / {Rhs}`" )] @@ -543,7 +543,7 @@ div_impl_float! { f32 f64 } /// ``` #[lang = "rem"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot calculate the remainder of `{Self}` divided by `{Rhs}`", label = "no implementation for `{Self} % {Rhs}`" )] @@ -729,7 +729,7 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "add_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot add-assign `{Rhs}` to `{Self}`", label = "no implementation for `{Self} += {Rhs}`" )] @@ -796,7 +796,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "sub_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot subtract-assign `{Rhs}` from `{Self}`", label = "no implementation for `{Self} -= {Rhs}`" )] @@ -854,7 +854,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "mul_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot multiply-assign `{Self}` by `{Rhs}`", label = "no implementation for `{Self} *= {Rhs}`" )] @@ -912,7 +912,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "div_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot divide-assign `{Self}` by `{Rhs}`", label = "no implementation for `{Self} /= {Rhs}`" )] @@ -973,7 +973,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } /// ``` #[lang = "rem_assign"] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`", label = "no implementation for `{Self} %= {Rhs}`" )] diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs index c70f4a3da2ed8..6984100e498e8 100644 --- a/library/core/src/ops/bit.rs +++ b/library/core/src/ops/bit.rs @@ -137,7 +137,7 @@ impl Not for ! { #[lang = "bitand"] #[doc(alias = "&")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} & {Rhs}`", label = "no implementation for `{Self} & {Rhs}`" )] @@ -237,7 +237,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitor"] #[doc(alias = "|")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} | {Rhs}`", label = "no implementation for `{Self} | {Rhs}`" )] @@ -337,7 +337,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitxor"] #[doc(alias = "^")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} ^ {Rhs}`", label = "no implementation for `{Self} ^ {Rhs}`" )] @@ -436,7 +436,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "shl"] #[doc(alias = "<<")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} << {Rhs}`", label = "no implementation for `{Self} << {Rhs}`" )] @@ -554,7 +554,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } #[lang = "shr"] #[doc(alias = ">>")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} >> {Rhs}`", label = "no implementation for `{Self} >> {Rhs}`" )] @@ -681,7 +681,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "bitand_assign"] #[doc(alias = "&=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} &= {Rhs}`", label = "no implementation for `{Self} &= {Rhs}`" )] @@ -752,7 +752,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitor_assign"] #[doc(alias = "|=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} |= {Rhs}`", label = "no implementation for `{Self} |= {Rhs}`" )] @@ -823,7 +823,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "bitxor_assign"] #[doc(alias = "^=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} ^= {Rhs}`", label = "no implementation for `{Self} ^= {Rhs}`" )] @@ -892,7 +892,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } #[lang = "shl_assign"] #[doc(alias = "<<=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} <<= {Rhs}`", label = "no implementation for `{Self} <<= {Rhs}`" )] @@ -974,7 +974,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } #[lang = "shr_assign"] #[doc(alias = ">>=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "no implementation for `{Self} >>= {Rhs}`", label = "no implementation for `{Self} >>= {Rhs}`" )] diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs index 6ceee46372980..37d9a28fb99c0 100644 --- a/library/core/src/ops/index.rs +++ b/library/core/src/ops/index.rs @@ -47,7 +47,7 @@ /// assert_eq!(nucleotide_count[Nucleotide::T], 12); /// ``` #[lang = "index"] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "the type `{Self}` cannot be indexed by `{Idx}`", label = "`{Self}` cannot be indexed by `{Idx}`" )] diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 6a53909a8f128..37859212c0ee3 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -83,7 +83,7 @@ use crate::task::{Context, Poll}; /// implemented for any closed over variables passed to `catch_unwind`. #[stable(feature = "catch_unwind", since = "1.9.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "the type `{Self}` may not be safely transferred across an unwind boundary", label = "`{Self}` may not be safely transferred across an unwind boundary" )] @@ -99,7 +99,7 @@ pub auto trait UnwindSafe {} /// [`UnwindSafe`] trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")] -#[rustc_on_unimplemented( +#[diagnostic::on_unimplemented( message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ transferrable across a catch_unwind boundary", label = "`{Self}` may contain interior mutability and a reference may not be safely \ diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index 6d10cc604c27f..3672a3590fd7a 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -50,6 +50,9 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 5c70e780f7489..d3c2c46ac75cf 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -73,6 +73,9 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #3, def_site_ctxt: #3, kind: Macro(Bang, "inner") crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "diagnostic::on_unimplemented") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") From eabf4df7719baa100ab20e427ce18f17c26d32ed Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Sat, 23 Dec 2023 14:02:01 +0100 Subject: [PATCH 04/21] Add a test that emitting diagnostics does not require the crate to use the corresponding feature. --- .../on_unimplemented/auxiliary/other.rs | 8 ++++++++ .../error_is_shown_in_downstream_crates.rs | 12 ++++++++++++ ...error_is_shown_in_downstream_crates.stderr | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs create mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs create mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs new file mode 100644 index 0000000000000..884bab2800a5b --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs @@ -0,0 +1,8 @@ +#![feature(diagnostic_namespace)] + +#[diagnostic::on_unimplemented( + message = "Message", + note = "Note", + label = "label" +)] +pub trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs new file mode 100644 index 0000000000000..b39375a09f369 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.rs @@ -0,0 +1,12 @@ +// aux-build:other.rs + +extern crate other; + +use other::Foo; + +fn take_foo(_: impl Foo) {} + +fn main() { + take_foo(()); + //~^ERROR Message +} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr new file mode 100644 index 0000000000000..a9968538d0d38 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unimplemented/error_is_shown_in_downstream_crates.stderr @@ -0,0 +1,19 @@ +error[E0277]: Message + --> $DIR/error_is_shown_in_downstream_crates.rs:10:14 + | +LL | take_foo(()); + | -------- ^^ label + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is not implemented for `()` + = note: Note +note: required by a bound in `take_foo` + --> $DIR/error_is_shown_in_downstream_crates.rs:7:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ required by this bound in `take_foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From cc31adc3452e5787ad8d91fe8214b8d974a9b46d Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 29 Dec 2023 15:09:10 +0100 Subject: [PATCH 05/21] Fix a rustdoc test --- tests/rustdoc/synthetic_auto/no-redundancy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rustdoc/synthetic_auto/no-redundancy.rs b/tests/rustdoc/synthetic_auto/no-redundancy.rs index ea57d7388b85f..64dab429647ae 100644 --- a/tests/rustdoc/synthetic_auto/no-redundancy.rs +++ b/tests/rustdoc/synthetic_auto/no-redundancy.rs @@ -10,7 +10,7 @@ where // @has no_redundancy/struct.Outer.html // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \ -// "impl Send for Outerwhere T: Send + Copy" +// "impl Send for Outerwhere T: Copy + Send" pub struct Outer { inner_field: Inner, } From fdd991f95b3effca449cb5b9f2770837bfc161d2 Mon Sep 17 00:00:00 2001 From: David Koloski Date: Wed, 6 Dec 2023 18:25:13 +0000 Subject: [PATCH 06/21] Add support for shell argfiles --- Cargo.lock | 1 + compiler/rustc_driver_impl/Cargo.toml | 1 + compiler/rustc_driver_impl/src/args.rs | 107 +++++++++++++++--- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 + .../src/compiler-flags/shell-argfiles.md | 11 ++ src/tools/tidy/src/deps.rs | 1 + src/tools/tidy/src/ui_tests.rs | 6 +- .../shell-argfiles-badquotes.args | 1 + .../shell-argfiles-badquotes.rs | 6 + .../shell-argfiles-badquotes.stderr | 2 + .../shell-argfiles-via-argfile-shell.args | 1 + .../shell-argfiles-via-argfile.args | 1 + .../shell-argfiles-via-argfile.rs | 10 ++ tests/ui/shell-argfiles/shell-argfiles.args | 3 + tests/ui/shell-argfiles/shell-argfiles.rs | 19 ++++ 16 files changed, 156 insertions(+), 17 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/shell-argfiles.md create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes.rs create mode 100644 tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr create mode 100644 tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles-via-argfile.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs create mode 100644 tests/ui/shell-argfiles/shell-argfiles.args create mode 100644 tests/ui/shell-argfiles/shell-argfiles.rs diff --git a/Cargo.lock b/Cargo.lock index b8192e333fe91..c7fa0b5675286 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3738,6 +3738,7 @@ dependencies = [ "rustc_trait_selection", "rustc_ty_utils", "serde_json", + "shlex", "time", "tracing", "windows", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 490429845538d..97a7dfef3b395 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -50,6 +50,7 @@ rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" +shlex = "1.0" time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index b7407f5a508e4..5dfd37a6da4de 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -5,18 +5,92 @@ use std::io; use rustc_session::EarlyDiagCtxt; -fn arg_expand(arg: String) -> Result, Error> { - if let Some(path) = arg.strip_prefix('@') { - let file = match fs::read_to_string(path) { - Ok(file) => file, - Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { - return Err(Error::Utf8Error(Some(path.to_string()))); +/// Expands argfiles in command line arguments. +#[derive(Default)] +struct Expander { + shell_argfiles: bool, + next_is_unstable_option: bool, + expanded: Vec, +} + +impl Expander { + /// Handles the next argument. If the argument is an argfile, it is expanded + /// inline. + fn arg(&mut self, arg: &str) -> Result<(), Error> { + if let Some(argfile) = arg.strip_prefix('@') { + match argfile.split_once(':') { + Some(("shell", path)) if self.shell_argfiles => { + shlex::split(&Self::read_file(path)?) + .ok_or_else(|| Error::ShellParseError(path.to_string()))? + .into_iter() + .for_each(|arg| self.push(arg)); + } + _ => { + let contents = Self::read_file(argfile)?; + contents.lines().for_each(|arg| self.push(arg.to_string())); + } + } + } else { + self.push(arg.to_string()); + } + + Ok(()) + } + + /// Adds a command line argument verbatim with no argfile expansion. + fn push(&mut self, arg: String) { + // Unfortunately, we have to do some eager argparsing to handle unstable + // options which change the behavior of argfile arguments. + // + // Normally, all of the argfile arguments (e.g. `@args.txt`) are + // expanded into our arguments list *and then* the whole list of + // arguments are passed on to be parsed. However, argfile parsing + // options like `-Zshell_argfiles` need to change the behavior of that + // argument expansion. So we have to do a little parsing on our own here + // instead of leaning on the existing logic. + // + // All we care about are unstable options, so we parse those out and + // look for any that affect how we expand argfiles. This argument + // inspection is very conservative; we only change behavior when we see + // exactly the options we're looking for and everything gets passed + // through. + + if self.next_is_unstable_option { + self.inspect_unstable_option(&arg); + self.next_is_unstable_option = false; + } else if let Some(unstable_option) = arg.strip_prefix("-Z") { + if unstable_option.is_empty() { + self.next_is_unstable_option = true; + } else { + self.inspect_unstable_option(unstable_option); + } + } + + self.expanded.push(arg); + } + + /// Consumes the `Expander`, returning the expanded arguments. + fn finish(self) -> Vec { + self.expanded + } + + /// Parses any relevant unstable flags specified on the command line. + fn inspect_unstable_option(&mut self, option: &str) { + match option { + "shell-argfiles" => self.shell_argfiles = true, + _ => (), + } + } + + /// Reads the contents of a file as UTF-8. + fn read_file(path: &str) -> Result { + fs::read_to_string(path).map_err(|e| { + if e.kind() == io::ErrorKind::InvalidData { + Error::Utf8Error(Some(path.to_string())) + } else { + Error::IOError(path.to_string(), e) } - Err(err) => return Err(Error::IOError(path.to_string(), err)), - }; - Ok(file.lines().map(ToString::to_string).collect()) - } else { - Ok(vec![arg]) + }) } } @@ -24,20 +98,20 @@ fn arg_expand(arg: String) -> Result, Error> { /// If this function is intended to be used with command line arguments, /// `argv[0]` must be removed prior to calling it manually. pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec { - let mut args = Vec::new(); + let mut expander = Expander::default(); for arg in at_args { - match arg_expand(arg.clone()) { - Ok(arg) => args.extend(arg), - Err(err) => early_dcx.early_fatal(format!("Failed to load argument file: {err}")), + if let Err(err) = expander.arg(arg) { + early_dcx.early_fatal(format!("Failed to load argument file: {err}")); } } - args + expander.finish() } #[derive(Debug)] pub enum Error { Utf8Error(Option), IOError(String, io::Error), + ShellParseError(String), } impl fmt::Display for Error { @@ -46,6 +120,7 @@ impl fmt::Display for Error { Error::Utf8Error(None) => write!(fmt, "Utf8 error"), Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"), Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"), + Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"), } } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index c4a1f3a0e510b..ee0518edc5825 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -700,6 +700,7 @@ fn test_unstable_options_tracking_hash() { untracked!(query_dep_graph, true); untracked!(self_profile, SwitchWithOptPath::Enabled(None)); untracked!(self_profile_events, Some(vec![String::new()])); + untracked!(shell_argfiles, true); untracked!(span_debug, true); untracked!(span_free_formats, true); untracked!(temps_dir, Some(String::from("abc"))); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 8274fd05bc057..8083954377898 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1875,6 +1875,8 @@ written to standard error output)"), query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes"), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), + shell_argfiles: bool = (false, parse_bool, [UNTRACKED], + "allow argument files to be specified with POSIX \"shell-style\" argument quoting"), show_span: Option = (None, parse_opt_string, [TRACKED], "show spans for compiler debugging (expr|pat|ty)"), simulate_remapped_rust_src_base: Option = (None, parse_opt_pathbuf, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/shell-argfiles.md b/src/doc/unstable-book/src/compiler-flags/shell-argfiles.md new file mode 100644 index 0000000000000..4f3c780972de5 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/shell-argfiles.md @@ -0,0 +1,11 @@ +# `shell-argfiles` + +-------------------- + +The `-Zshell-argfiles` compiler flag allows argfiles to be parsed using POSIX +"shell-style" quoting. When enabled, the compiler will use `shlex` to parse the +arguments from argfiles specified with `@shell:`. + +Because this feature controls the parsing of input arguments, the +`-Zshell-argfiles` flag must be present before the argument specifying the +shell-style arguemnt file. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3c00027b9fdc9..62d48315d434e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -325,6 +325,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "sha1", "sha2", "sharded-slab", + "shlex", "smallvec", "snap", "stable_deref_trait", diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index dfa386b49de7c..76fa06b0b42be 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1852; -const ROOT_ENTRY_LIMIT: usize = 867; +const ROOT_ENTRY_LIMIT: usize = 868; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files @@ -36,6 +36,10 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/unused-crate-deps/test.mk", // why would you use make "tests/ui/proc-macro/auxiliary/included-file.txt", // more include "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer + "tests/ui/shell-argfiles/shell-argfiles.args", // passing args via a file + "tests/ui/shell-argfiles/shell-argfiles-badquotes.args", // passing args via a file + "tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args", // passing args via a file + "tests/ui/shell-argfiles/shell-argfiles-via-argfile.args", // passing args via a file ]; fn check_entries(tests_path: &Path, bad: &mut bool) { diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.args b/tests/ui/shell-argfiles/shell-argfiles-badquotes.args new file mode 100644 index 0000000000000..c0d531adf3ffb --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.args @@ -0,0 +1 @@ +"--cfg" "unquoted_set diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.rs b/tests/ui/shell-argfiles/shell-argfiles-badquotes.rs new file mode 100644 index 0000000000000..c05e9b3c8bfbd --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.rs @@ -0,0 +1,6 @@ +// Check to see if we can get parameters from an @argsfile file +// +// compile-flags: --cfg cmdline_set -Z shell-argfiles @shell:{{src-base}}/shell-argfiles/shell-argfiles-badquotes.args + +fn main() { +} diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr new file mode 100644 index 0000000000000..14adb1f740abb --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args + diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args b/tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args new file mode 100644 index 0000000000000..4e66d5a039529 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile-shell.args @@ -0,0 +1 @@ +"--cfg" "shell_args_set" \ No newline at end of file diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile.args b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.args new file mode 100644 index 0000000000000..d0af54e24e33c --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.args @@ -0,0 +1 @@ +-Zshell-argfiles \ No newline at end of file diff --git a/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs new file mode 100644 index 0000000000000..d71e3218f53b8 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles-via-argfile.rs @@ -0,0 +1,10 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: @{{src-base}}/shell-argfiles/shell-argfiles-via-argfile.args @shell:{{src-base}}/shell-argfiles/shell-argfiles-via-argfile-shell.args + +#[cfg(not(shell_args_set))] +compile_error!("shell_args_set not set"); + +fn main() { +} diff --git a/tests/ui/shell-argfiles/shell-argfiles.args b/tests/ui/shell-argfiles/shell-argfiles.args new file mode 100644 index 0000000000000..e5bb4b807ec4d --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles.args @@ -0,0 +1,3 @@ +--cfg unquoted_set +'--cfg' 'single_quoted_set' +"--cfg" "double_quoted_set" diff --git a/tests/ui/shell-argfiles/shell-argfiles.rs b/tests/ui/shell-argfiles/shell-argfiles.rs new file mode 100644 index 0000000000000..9bc252ea628a9 --- /dev/null +++ b/tests/ui/shell-argfiles/shell-argfiles.rs @@ -0,0 +1,19 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: --cfg cmdline_set -Z shell-argfiles @shell:{{src-base}}/shell-argfiles/shell-argfiles.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unquoted_set))] +compile_error!("unquoted_set not set"); + +#[cfg(not(single_quoted_set))] +compile_error!("single_quoted_set not set"); + +#[cfg(not(double_quoted_set))] +compile_error!("double_quoted_set not set"); + +fn main() { +} From 505c1371d070ba6c9e15db7d331f2d6a2b167b68 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 24 Dec 2023 09:08:41 +1100 Subject: [PATCH 07/21] Rename some `Diagnostic` setters. `Diagnostic` has 40 methods that return `&mut Self` and could be considered setters. Four of them have a `set_` prefix. This doesn't seem necessary for a type that implements the builder pattern. This commit removes the `set_` prefixes on those four methods. --- compiler/rustc_ast_passes/src/errors.rs | 4 +- .../rustc_attr/src/session_diagnostics.rs | 8 +- compiler/rustc_builtin_macros/src/errors.rs | 6 +- compiler/rustc_builtin_macros/src/test.rs | 2 +- compiler/rustc_codegen_gcc/src/errors.rs | 4 +- compiler/rustc_codegen_llvm/src/errors.rs | 10 +-- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 54 ++++++------ compiler/rustc_const_eval/src/errors.rs | 86 +++++++++---------- compiler/rustc_errors/src/diagnostic.rs | 13 +-- .../rustc_errors/src/diagnostic_builder.rs | 10 +-- compiler/rustc_errors/src/diagnostic_impls.rs | 32 +++---- compiler/rustc_errors/src/lib.rs | 12 +-- compiler/rustc_expand/src/expand.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 2 +- .../src/astconv/generics.rs | 2 +- compiler/rustc_hir_analysis/src/errors.rs | 6 +- compiler/rustc_hir_typeck/src/errors.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_infer/src/errors/mod.rs | 34 +++----- .../src/errors/note_and_explain.rs | 8 +- compiler/rustc_lint/src/errors.rs | 2 +- compiler/rustc_lint/src/levels.rs | 2 +- compiler/rustc_lint/src/lints.rs | 24 +++--- compiler/rustc_lint/src/non_fmt_panic.rs | 6 +- .../src/diagnostics/diagnostic_builder.rs | 18 ++-- .../src/diagnostics/subdiagnostic.rs | 14 +-- .../rustc_macros/src/diagnostics/utils.rs | 6 +- compiler/rustc_metadata/src/errors.rs | 22 ++--- compiler/rustc_middle/src/lint.rs | 6 +- compiler/rustc_mir_build/src/errors.rs | 8 +- compiler/rustc_mir_transform/src/errors.rs | 24 +++--- compiler/rustc_monomorphize/src/errors.rs | 2 +- compiler/rustc_parse/src/errors.rs | 8 +- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_parse/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 4 +- compiler/rustc_parse/src/parser/mod.rs | 7 +- compiler/rustc_passes/src/check_attr.rs | 6 +- compiler/rustc_passes/src/errors.rs | 38 ++++---- compiler/rustc_pattern_analysis/src/lints.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 6 +- compiler/rustc_session/src/errors.rs | 2 +- compiler/rustc_symbol_mangling/src/errors.rs | 2 +- compiler/rustc_trait_selection/src/errors.rs | 17 ++-- .../src/traits/error_reporting/suggestions.rs | 6 +- .../error_reporting/type_err_ctxt_ext.rs | 4 +- .../passes/collect_intra_doc_links.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- ...diagnostic-derive-doc-comment-field.stderr | 4 +- .../session-diagnostic/diagnostic-derive.rs | 2 +- .../diagnostic-derive.stderr | 2 +- 53 files changed, 274 insertions(+), 281 deletions(-) diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 0cec4374be2ee..b177378c8e7ca 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -707,8 +707,8 @@ impl AddToDiagnostic for StableFeature { rustc_errors::SubdiagnosticMessage, ) -> rustc_errors::SubdiagnosticMessage, { - diag.set_arg("name", self.name); - diag.set_arg("since", self.since); + diag.arg("name", self.name); + diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); } } diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index fd2b08668673c..fdb5d66bf62b5 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -55,10 +55,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::>(); let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0541)); - diag.set_arg("item", self.item); - diag.set_arg("expected", expected.join(", ")); + diag.arg("item", self.item); + diag.arg("expected", expected.join(", ")); diag.span_label(self.span, fluent::attr_label); diag } @@ -215,7 +215,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { } }, ); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0565)); if self.is_bytestr { diag.span_suggestion( diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index e07eb2e490b71..f9ddffcc155d5 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -454,7 +454,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMe reason = "cannot translate user-provided messages" )] let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string()); - diag.set_span(self.span); + diag.span(self.span); diag } } @@ -618,7 +618,7 @@ impl AddToDiagnostic for FormatUnusedArg { rustc_errors::SubdiagnosticMessage, ) -> rustc_errors::SubdiagnosticMessage, { - diag.set_arg("named", self.named); + diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diag.span_label(self.span, msg); } @@ -808,7 +808,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg { level, crate::fluent_generated::builtin_macros_asm_clobber_no_reg, ); - diag.set_span(self.spans.clone()); + diag.span(self.spans.clone()); // eager translation as `span_labels` takes `AsRef` let lbl1 = dcx.eagerly_translate_to_string( crate::fluent_generated::builtin_macros_asm_clobber_abi, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 2af46f175d7d8..82fe043820ccd 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -398,7 +398,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) _ => Level::Error { lint: false }, }; let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg); - err.set_span(attr_sp); + err.span(attr_sp); if let Some(item) = item { err.span_label( item.span, diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 1b1ed0b411c71..e9283b1989453 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -119,12 +119,12 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl fluent::codegen_gcc_target_feature_disable_or_enable ); if let Some(span) = self.span { - diag.set_span(span); + diag.span(span); }; if let Some(missing_features) = self.missing_features { diag.subdiagnostic(missing_features); } - diag.set_arg("features", self.features.join(", ")); + diag.arg("features", self.features.join(", ")); diag } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 8db97d577ca76..422e8edff5f64 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -107,7 +107,7 @@ impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_ let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config); - diag.set_arg("error", message); + diag.arg("error", message); diag } } @@ -130,12 +130,12 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl fluent::codegen_llvm_target_feature_disable_or_enable, ); if let Some(span) = self.span { - diag.set_span(span); + diag.span(span); }; if let Some(missing_features) = self.missing_features { diag.subdiagnostic(missing_features); } - diag.set_arg("features", self.features.join(", ")); + diag.arg("features", self.features.join(", ")); diag } } @@ -205,8 +205,8 @@ impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, }; let mut diag = self.0.into_diagnostic(dcx, level); - diag.set_primary_message(msg_with_llvm_err); - diag.set_arg("llvm_err", self.1); + diag.primary_message(msg_with_llvm_err); + diag.arg("llvm_err", self.1); diag } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 5a8db7bbf2d67..cb12470478500 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1860,7 +1860,7 @@ impl SharedEmitterMain { if cookie != 0 { let pos = BytePos::from_u32(cookie); let span = Span::with_root_ctxt(pos, pos); - err.set_span(span); + err.span(span); }; // Point to the generated assembly if it is available. diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 2b628d2aa69b7..c1086bebb8d48 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -244,30 +244,30 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::NamelessSection(_, offset) => { diag = build(fluent::codegen_ssa_thorin_section_without_name); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); - diag.set_arg("section", section); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("section", section); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MultipleRelocations(section, offset) => { diag = build(fluent::codegen_ssa_thorin_multiple_relocations); - diag.set_arg("section", section); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("section", section); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::UnsupportedRelocation(section, offset) => { diag = build(fluent::codegen_ssa_thorin_unsupported_relocation); - diag.set_arg("section", section); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("section", section); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MissingDwoName(id) => { diag = build(fluent::codegen_ssa_thorin_missing_dwo_name); - diag.set_arg("id", format!("0x{id:08x}")); + diag.arg("id", format!("0x{id:08x}")); diag } thorin::Error::NoCompilationUnits => { @@ -284,7 +284,7 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::MissingRequiredSection(section) => { diag = build(fluent::codegen_ssa_thorin_missing_required_section); - diag.set_arg("section", section); + diag.arg("section", section); diag } thorin::Error::ParseUnitAbbreviations(_) => { @@ -305,34 +305,34 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::IncompatibleIndexVersion(section, format, actual) => { diag = build(fluent::codegen_ssa_thorin_incompatible_index_version); - diag.set_arg("section", section); - diag.set_arg("actual", actual); - diag.set_arg("format", format); + diag.arg("section", section); + diag.arg("actual", actual); + diag.arg("format", format); diag } thorin::Error::OffsetAtIndex(_, index) => { diag = build(fluent::codegen_ssa_thorin_offset_at_index); - diag.set_arg("index", index); + diag.arg("index", index); diag } thorin::Error::StrAtOffset(_, offset) => { diag = build(fluent::codegen_ssa_thorin_str_at_offset); - diag.set_arg("offset", format!("0x{offset:08x}")); + diag.arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::ParseIndex(_, section) => { diag = build(fluent::codegen_ssa_thorin_parse_index); - diag.set_arg("section", section); + diag.arg("section", section); diag } thorin::Error::UnitNotInIndex(unit) => { diag = build(fluent::codegen_ssa_thorin_unit_not_in_index); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::RowNotInIndex(_, row) => { diag = build(fluent::codegen_ssa_thorin_row_not_in_index); - diag.set_arg("row", row); + diag.arg("row", row); diag } thorin::Error::SectionNotInRow => { @@ -341,7 +341,7 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::EmptyUnit(unit) => { diag = build(fluent::codegen_ssa_thorin_empty_unit); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MultipleDebugInfoSection => { @@ -358,12 +358,12 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::DuplicateUnit(unit) => { diag = build(fluent::codegen_ssa_thorin_duplicate_unit); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MissingReferencedUnit(unit) => { diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit); - diag.set_arg("unit", format!("0x{unit:08x}")); + diag.arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::NoOutputObjectCreated => { @@ -376,27 +376,27 @@ impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { } thorin::Error::Io(e) => { diag = build(fluent::codegen_ssa_thorin_io); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::ObjectRead(e) => { diag = build(fluent::codegen_ssa_thorin_object_read); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::ObjectWrite(e) => { diag = build(fluent::codegen_ssa_thorin_object_write); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::GimliRead(e) => { diag = build(fluent::codegen_ssa_thorin_gimli_read); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } thorin::Error::GimliWrite(e) => { diag = build(fluent::codegen_ssa_thorin_gimli_write); - diag.set_arg("error", format!("{e}")); + diag.arg("error", format!("{e}")); diag } _ => unimplemented!("Untranslated thorin error"), @@ -414,8 +414,8 @@ pub struct LinkingFailed<'a> { impl IntoDiagnostic<'_, G> for LinkingFailed<'_> { fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_ssa_linking_failed); - diag.set_arg("linker_path", format!("{}", self.linker_path.display())); - diag.set_arg("exit_status", format!("{}", self.exit_status)); + diag.arg("linker_path", format!("{}", self.linker_path.display())); + diag.arg("exit_status", format!("{}", self.exit_status)); let contains_undefined_ref = self.escaped_output.contains("undefined reference to"); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 110ff87e27ef3..171cc89d6adb8 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -518,7 +518,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { Ub(_) => {} Custom(custom) => { (custom.add_args)(&mut |name, value| { - builder.set_arg(name, value); + builder.arg(name, value); }); } ValidationError(e) => e.add_args(dcx, builder), @@ -536,65 +536,65 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | UninhabitedEnumVariantWritten(_) | UninhabitedEnumVariantRead(_) => {} BoundsCheckFailed { len, index } => { - builder.set_arg("len", len); - builder.set_arg("index", index); + builder.arg("len", len); + builder.arg("index", index); } UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => { - builder.set_arg("pointer", ptr); + builder.arg("pointer", ptr); } PointerUseAfterFree(alloc_id, msg) => { builder - .set_arg("alloc_id", alloc_id) - .set_arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + .arg("alloc_id", alloc_id) + .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => { builder - .set_arg("alloc_id", alloc_id) - .set_arg("alloc_size", alloc_size.bytes()) - .set_arg("ptr_offset", ptr_offset) - .set_arg("ptr_size", ptr_size.bytes()) - .set_arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + .arg("alloc_id", alloc_id) + .arg("alloc_size", alloc_size.bytes()) + .arg("ptr_offset", ptr_offset) + .arg("ptr_size", ptr_size.bytes()) + .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } DanglingIntPointer(ptr, msg) => { if ptr != 0 { - builder.set_arg("pointer", format!("{ptr:#x}[noalloc]")); + builder.arg("pointer", format!("{ptr:#x}[noalloc]")); } - builder.set_arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + builder.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } AlignmentCheckFailed(Misalignment { required, has }, msg) => { - builder.set_arg("required", required.bytes()); - builder.set_arg("has", has.bytes()); - builder.set_arg("msg", format!("{msg:?}")); + builder.arg("required", required.bytes()); + builder.arg("has", has.bytes()); + builder.arg("msg", format!("{msg:?}")); } WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => { - builder.set_arg("allocation", alloc); + builder.arg("allocation", alloc); } InvalidBool(b) => { - builder.set_arg("value", format!("{b:02x}")); + builder.arg("value", format!("{b:02x}")); } InvalidChar(c) => { - builder.set_arg("value", format!("{c:08x}")); + builder.arg("value", format!("{c:08x}")); } InvalidTag(tag) => { - builder.set_arg("tag", format!("{tag:x}")); + builder.arg("tag", format!("{tag:x}")); } InvalidStr(err) => { - builder.set_arg("err", format!("{err}")); + builder.arg("err", format!("{err}")); } InvalidUninitBytes(Some((alloc, info))) => { - builder.set_arg("alloc", alloc); - builder.set_arg("access", info.access); - builder.set_arg("uninit", info.bad); + builder.arg("alloc", alloc); + builder.arg("access", info.access); + builder.arg("uninit", info.bad); } ScalarSizeMismatch(info) => { - builder.set_arg("target_size", info.target_size); - builder.set_arg("data_size", info.data_size); + builder.arg("target_size", info.target_size); + builder.arg("data_size", info.data_size); } AbiMismatchArgument { caller_ty, callee_ty } | AbiMismatchReturn { caller_ty, callee_ty } => { - builder.set_arg("caller_ty", caller_ty.to_string()); - builder.set_arg("callee_ty", callee_ty.to_string()); + builder.arg("caller_ty", caller_ty.to_string()); + builder.arg("callee_ty", callee_ty.to_string()); } } } @@ -695,7 +695,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ) }; - err.set_arg("front_matter", message); + err.arg("front_matter", message); fn add_range_arg( r: WrappingRange, @@ -725,12 +725,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ]; let args = args.iter().map(|(a, b)| (a, b)); let message = dcx.eagerly_translate_to_string(msg, args); - err.set_arg("in_range", message); + err.arg("in_range", message); } match self.kind { PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => { - err.set_arg("ty", ty); + err.arg("ty", ty); } PointerAsInt { expected } | Uninit { expected } => { let msg = match expected { @@ -747,28 +747,28 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ExpectedKind::Str => fluent::const_eval_validation_expected_str, }; let msg = dcx.eagerly_translate_to_string(msg, [].into_iter()); - err.set_arg("expected", msg); + err.arg("expected", msg); } InvalidEnumTag { value } | InvalidVTablePtr { value } | InvalidBool { value } | InvalidChar { value } | InvalidFnPtr { value } => { - err.set_arg("value", value); + err.arg("value", value); } NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => { add_range_arg(range, max_value, dcx, err) } OutOfRange { range, max_value, value } => { - err.set_arg("value", value); + err.arg("value", value); add_range_arg(range, max_value, dcx, err); } UnalignedPtr { required_bytes, found_bytes, .. } => { - err.set_arg("required_bytes", required_bytes); - err.set_arg("found_bytes", found_bytes); + err.arg("required_bytes", required_bytes); + err.arg("found_bytes", found_bytes); } DanglingPtrNoProvenance { pointer, .. } => { - err.set_arg("pointer", pointer); + err.arg("pointer", pointer); } NullPtr { .. } | PtrToStatic { .. } @@ -814,10 +814,10 @@ impl ReportErrorExt for UnsupportedOpInfo { // print. So it's not worth the effort of having diagnostics that can print the `info`. UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {} OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { - builder.set_arg("ptr", ptr); + builder.arg("ptr", ptr); } ThreadLocalStatic(did) | ReadExternStatic(did) => { - builder.set_arg("did", format!("{did:?}")); + builder.arg("did", format!("{did:?}")); } } } @@ -844,7 +844,7 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> { InterpError::InvalidProgram(e) => e.add_args(dcx, builder), InterpError::ResourceExhaustion(e) => e.add_args(dcx, builder), InterpError::MachineStop(e) => e.add_args(&mut |name, value| { - builder.set_arg(name, value); + builder.arg(name, value); }), } } @@ -880,15 +880,15 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(dcx, dummy_level); for (name, val) in diag.args() { - builder.set_arg(name.clone(), val.clone()); + builder.arg(name.clone(), val.clone()); } diag.cancel(); } InvalidProgramInfo::FnAbiAdjustForForeignAbi( AdjustForForeignAbiError::Unsupported { arch, abi }, ) => { - builder.set_arg("arch", arch); - builder.set_arg("abi", abi.name()); + builder.arg("arch", arch); + builder.arg("abi", abi.name()); } } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 49431fb7b3f18..f2d54eb427db3 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -212,6 +212,9 @@ impl StringPart { } } +// Note: most of these methods are setters that return `&mut Self`. The small +// number of simple getter functions all have `get_` prefixes to distinguish +// them from the setters. impl Diagnostic { #[track_caller] pub fn new>(level: Level, message: M) -> Self { @@ -344,7 +347,7 @@ impl Diagnostic { pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); - self.set_span(after); + self.span(after); for span_label in before.span_labels() { if let Some(label) = span_label.label { if span_label.is_primary && keep_label { @@ -876,7 +879,7 @@ impl Diagnostic { self } - pub fn set_span>(&mut self, sp: S) -> &mut Self { + pub fn span>(&mut self, sp: S) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { self.sort_span = span; @@ -884,7 +887,7 @@ impl Diagnostic { self } - pub fn set_is_lint(&mut self) -> &mut Self { + pub fn is_lint(&mut self) -> &mut Self { self.is_lint = true; self } @@ -903,7 +906,7 @@ impl Diagnostic { self.code.clone() } - pub fn set_primary_message(&mut self, msg: impl Into) -> &mut Self { + pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self } @@ -915,7 +918,7 @@ impl Diagnostic { self.args.iter() } - pub fn set_arg( + pub fn arg( &mut self, name: impl Into>, arg: impl IntoDiagnosticArg, diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index ae54d343dad96..d8838bbdbab1d 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -31,7 +31,7 @@ where { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = self.node.into_diagnostic(dcx, level); - diag.set_span(self.span); + diag.span(self.span); diag } } @@ -428,7 +428,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { sp: impl Into, msg: impl Into, ) -> &mut Self); - forward!(pub fn set_is_lint(&mut self,) -> &mut Self); + forward!(pub fn is_lint(&mut self,) -> &mut Self); forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); @@ -499,10 +499,10 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { applicability: Applicability, ) -> &mut Self); - forward!(pub fn set_primary_message(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn set_span(&mut self, sp: impl Into) -> &mut Self); + forward!(pub fn primary_message(&mut self, msg: impl Into) -> &mut Self); + forward!(pub fn span(&mut self, sp: impl Into) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); - forward!(pub fn set_arg( + forward!(pub fn arg( &mut self, name: impl Into>, arg: impl IntoDiagnosticArg, diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 29cb304e8b5b0..de27c6e910b2b 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -254,29 +254,29 @@ impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space); - diag.set_arg("addr_space", addr_space); - diag.set_arg("cause", cause); - diag.set_arg("err", err); + diag.arg("addr_space", addr_space); + diag.arg("cause", cause); + diag.arg("err", err); diag } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits); - diag.set_arg("kind", kind); - diag.set_arg("bit", bit); - diag.set_arg("cause", cause); - diag.set_arg("err", err); + diag.arg("kind", kind); + diag.arg("bit", bit); + diag.arg("cause", cause); + diag.arg("err", err); diag } TargetDataLayoutErrors::MissingAlignment { cause } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment); - diag.set_arg("cause", cause); + diag.arg("cause", cause); diag } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment); - diag.set_arg("cause", cause); - diag.set_arg("err_kind", err.diag_ident()); - diag.set_arg("align", err.align()); + diag.arg("cause", cause); + diag.arg("err_kind", err.diag_ident()); + diag.arg("align", err.align()); diag } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { @@ -285,8 +285,8 @@ impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> level, fluent::errors_target_inconsistent_architecture, ); - diag.set_arg("dl", dl); - diag.set_arg("target", target); + diag.arg("dl", dl); + diag.arg("target", target); diag } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { @@ -295,13 +295,13 @@ impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> level, fluent::errors_target_inconsistent_pointer_width, ); - diag.set_arg("pointer_size", pointer_size); - diag.set_arg("target", target); + diag.arg("pointer_size", pointer_size); + diag.arg("target", target); diag } TargetDataLayoutErrors::InvalidBitsSize { err } => { diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size); - diag.set_arg("err", err); + diag.arg("err", err); diag } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e9507dcfed7e4..6dc3a8cd08ece 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -732,7 +732,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, ()> { let mut result = self.struct_warn(msg); - result.set_span(span); + result.span(span); result } @@ -789,7 +789,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); - result.set_span(span); + result.span(span); result } @@ -850,7 +850,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); - result.set_span(span); + result.span(span); result } @@ -917,7 +917,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, BugAbort> { let mut result = self.struct_bug(msg); - result.set_span(span); + result.span(span); result } @@ -1008,7 +1008,7 @@ impl DiagCtxt { self.span_bug(sp, msg); } let mut diagnostic = Diagnostic::new(DelayedBug, msg); - diagnostic.set_span(sp); + diagnostic.span(sp); self.emit_diagnostic(diagnostic).unwrap() } @@ -1039,7 +1039,7 @@ impl DiagCtxt { msg: impl Into, ) -> DiagnosticBuilder<'_, ()> { let mut db = DiagnosticBuilder::new(self, Note, msg); - db.set_span(span); + db.span(span); db } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 676f9f17976cf..5a616e0ffbff3 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -855,7 +855,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(mut err) => { if err.span.is_dummy() { - err.set_span(span); + err.span(span); } annotate_err_with_kind(&mut err, kind, span); err.emit(); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 5eb6aed72534d..2c08891b1096a 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -497,7 +497,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { let mut diag = rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message); - diag.set_span(MultiSpan::from_spans(diagnostic.spans)); + diag.span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 7d840ba7e8153..3f0ad6584b65f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -70,7 +70,7 @@ fn generic_arg_mismatch_err( Res::Err => { add_braces_suggestion(arg, &mut err); return err - .set_primary_message("unresolved item provided when a constant was expected") + .primary_message("unresolved item provided when a constant was expected") .emit(); } Res::Def(DefKind::TyParam, src_def_id) => { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 75e7a5524a744..9124d50211056 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -319,10 +319,10 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params); - err.set_span(self.span); + err.span(self.span); err.code(error_code!(E0393)); - err.set_arg("parameterCount", self.missing_type_params.len()); - err.set_arg( + err.arg("parameterCount", self.missing_type_params.len()); + err.arg( "parameters", self.missing_type_params .iter() diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index ff03cf16a27f3..4f92906888796 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -215,7 +215,7 @@ impl AddToDiagnostic for TypeMismatchFruTypo { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("expr", self.expr.as_deref().unwrap_or("NONE")); + diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up if self.expr_span.between(self.fru_span).is_empty() { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 47fdd64796e9d..bba40b1fa3d9f 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -961,7 +961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { but its trait bounds were not satisfied" ) }); - err.set_primary_message(primary_message); + err.primary_message(primary_message); if let Some(label) = label { custom_span_label = true; err.span_label(span, label); diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index a0768fc711546..aee99063e0396 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -247,8 +247,8 @@ impl AddToDiagnostic for RegionOriginNote<'_> { } RegionOriginNote::WithName { span, msg, name, continues } => { label_or_note(span, msg); - diag.set_arg("name", name); - diag.set_arg("continues", continues); + diag.arg("name", name); + diag.arg("continues", continues); } RegionOriginNote::WithRequirement { span, @@ -256,7 +256,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> { expected_found: Some((expected, found)), } => { label_or_note(span, fluent::infer_subtype); - diag.set_arg("requirement", requirement); + diag.arg("requirement", requirement); diag.note_expected_found(&"", expected, &"", found); } @@ -265,7 +265,7 @@ impl AddToDiagnostic for RegionOriginNote<'_> { // handling of region checking when type errors are present is // *terrible*. label_or_note(span, fluent::infer_subtype_2); - diag.set_arg("requirement", requirement); + diag.arg("requirement", requirement); } }; } @@ -298,8 +298,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels { diag.span_label(param_span, fluent::infer_declared_different); diag.span_label(ret_span, fluent::infer_nothing); diag.span_label(span, fluent::infer_data_returned); - diag.set_arg("label_var1_exists", label_var1.is_some()); - diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); + diag.arg("label_var1_exists", label_var1.is_some()); + diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); } LifetimeMismatchLabels::Normal { hir_equal, @@ -317,16 +317,10 @@ impl AddToDiagnostic for LifetimeMismatchLabels { diag.span_label(ty_sup, fluent::infer_types_declared_different); diag.span_label(ty_sub, fluent::infer_nothing); diag.span_label(span, fluent::infer_data_flows); - diag.set_arg("label_var1_exists", label_var1.is_some()); - diag.set_arg( - "label_var1", - label_var1.map(|x| x.to_string()).unwrap_or_default(), - ); - diag.set_arg("label_var2_exists", label_var2.is_some()); - diag.set_arg( - "label_var2", - label_var2.map(|x| x.to_string()).unwrap_or_default(), - ); + diag.arg("label_var1_exists", label_var1.is_some()); + diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); + diag.arg("label_var2_exists", label_var2.is_some()); + diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default()); } } } @@ -417,7 +411,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { suggestions, Applicability::MaybeIncorrect, ); - diag.set_arg("is_impl", is_impl); + diag.arg("is_impl", is_impl); true }; if mk_suggestion() && self.add_note { @@ -878,8 +872,8 @@ impl AddToDiagnostic for MoreTargeted { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.code(rustc_errors::error_code!(E0772)); - diag.set_primary_message(fluent::infer_more_targeted); - diag.set_arg("ident", self.ident); + diag.primary_message(fluent::infer_more_targeted); + diag.arg("ident", self.ident); } } @@ -1299,7 +1293,7 @@ impl AddToDiagnostic for SuggestTuplePatternMany { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("path", self.path); + diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diag.multipart_suggestions( message, diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 68bf36a1615dd..8e45cc6d80e92 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -164,10 +164,10 @@ impl AddToDiagnostic for RegionExplanation<'_> { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("pref_kind", self.prefix); - diag.set_arg("suff_kind", self.suffix); - diag.set_arg("desc_kind", self.desc.kind); - diag.set_arg("desc_arg", self.desc.arg); + diag.arg("pref_kind", self.prefix); + diag.arg("suff_kind", self.suffix); + diag.arg("desc_kind", self.desc.kind); + diag.arg("desc_arg", self.desc.arg); let msg = f(diag, fluent::infer_region_explanation.into()); if let Some(span) = self.desc.span { diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index eccea35c702e0..841d282a09942 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -31,7 +31,7 @@ impl AddToDiagnostic for OverruledAttributeSub { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); - diag.set_arg("id", id); + diag.arg("id", id); } OverruledAttributeSub::NodeSource { span, reason } => { diag.span_label(span, fluent::lint_node_source); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5950bc76adeb7..49821437b7657 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1069,7 +1069,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { Some(span.into()), fluent::lint_unknown_gated_lint, |lint| { - lint.set_arg("name", lint_id.lint.name_lower()); + lint.arg("name", lint_id.lint.name_lower()); lint.note(fluent::lint_note); rustc_session::parse::add_feature_diagnostics_for_issue( lint, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ca6408bdf3ddb..1b81402e0031d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -135,7 +135,7 @@ pub struct BuiltinMissingDebugImpl<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("debug", self.tcx.def_path_str(self.def_id)); + diag.arg("debug", self.tcx.def_path_str(self.def_id)); } fn msg(&self) -> DiagnosticMessage { @@ -426,7 +426,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> { impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("ty", self.ty); + diag.arg("ty", self.ty); diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. @@ -830,7 +830,7 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { // FIXME: in other suggestions we've reversed the inner spans of doc comments. We // should do the same here to provide the same good suggestions as we do for // literals above. - diag.set_arg( + diag.arg( "escaped", spans .into_iter() @@ -1148,7 +1148,7 @@ pub struct NonFmtPanicUnused { // Used because of two suggestions based on one Option impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("count", self.count); + diag.arg("count", self.count); diag.note(fluent::lint_note); if let Some(span) = self.suggestion { diag.span_suggestion( @@ -1343,8 +1343,8 @@ pub struct DropTraitConstraintsDiag<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("predicate", self.predicate); - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + diag.arg("predicate", self.predicate); + diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } fn msg(&self) -> rustc_errors::DiagnosticMessage { @@ -1360,7 +1360,7 @@ pub struct DropGlue<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id)); + diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } fn msg(&self) -> rustc_errors::DiagnosticMessage { @@ -1634,8 +1634,8 @@ pub struct ImproperCTypes<'a> { // Used because of the complexity of Option, DiagnosticMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("ty", self.ty); - diag.set_arg("desc", self.desc); + diag.arg("ty", self.ty); + diag.arg("desc", self.desc); diag.span_label(self.label, fluent::lint_label); if let Some(help) = self.help { diag.help(help); @@ -1777,9 +1777,9 @@ pub enum UnusedDefSuggestion { // Needed because of def_path_str impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { - diag.set_arg("pre", self.pre); - diag.set_arg("post", self.post); - diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id)); + diag.arg("pre", self.pre); + diag.arg("post", self.post); + diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); // check for #[must_use = "..."] if let Some(note) = self.note { diag.note(note.to_string()); diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 9fcd70ba0b569..f0bbc03d74777 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -121,7 +121,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc #[allow(rustc::diagnostic_outside_of_impl)] cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| { - lint.set_arg("name", symbol); + lint.arg("name", symbol); lint.note(fluent::lint_note); lint.note(fluent::lint_more_info_note); if !is_arg_inside_call(arg_span, span) { @@ -180,7 +180,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc fmt_applicability, ); } else if suggest_debug { - lint.set_arg("ty", ty); + lint.arg("ty", ty); lint.span_suggestion_verbose( arg_span.shrink_to_lo(), fluent::lint_debug_suggestion, @@ -191,7 +191,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if suggest_panic_any { if let Some((open, close, del)) = find_delimiters(cx, span) { - lint.set_arg("already_suggested", suggest_display || suggest_debug); + lint.arg("already_suggested", suggest_display || suggest_debug); lint.multipart_suggestion( fluent::lint_panic_suggestion, if del == '(' { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index f3e98d68b6040..fb908fe2db155 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -5,8 +5,8 @@ use crate::diagnostics::error::{ }; use crate::diagnostics::utils::{ build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, - should_generate_set_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo, - FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, + should_generate_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, + FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; @@ -125,15 +125,15 @@ impl DiagnosticDeriveVariantBuilder { } /// Generates calls to `span_label` and similar functions based on the attributes on fields or - /// calls to `set_arg` when no attributes are present. + /// calls to `arg` when no attributes are present. pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; - // Generate `set_arg` calls first.. - for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) { + // Generate `arg` calls first.. + for binding in variant.bindings().iter().filter(|bi| should_generate_arg(bi.ast())) { body.extend(self.generate_field_code(binding)); } // ..and then subdiagnostic additions. - for binding in variant.bindings().iter().filter(|bi| !should_generate_set_arg(bi.ast())) { + for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) { body.extend(self.generate_field_attrs_code(binding)); } body @@ -253,7 +253,7 @@ impl DiagnosticDeriveVariantBuilder { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - diag.set_arg( + diag.arg( stringify!(#ident), #field_binding ); @@ -312,7 +312,7 @@ impl DiagnosticDeriveVariantBuilder { let name = ident.to_string(); match (&attr.meta, name.as_str()) { // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. + // `arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { match self.kind { @@ -320,7 +320,7 @@ impl DiagnosticDeriveVariantBuilder { report_error_if_not_applied_to_span(attr, &info)?; return Ok(quote! { - diag.set_span(#binding); + diag.span(#binding); }); } DiagnosticDeriveKind::LintDiagnostic => { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 663abecb67c6e..c029b931e7dde 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -6,8 +6,8 @@ use crate::diagnostics::error::{ use crate::diagnostics::utils::{ build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident, report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, - should_generate_set_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, - HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, + should_generate_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, + SetOnce, SpannedOption, SubdiagnosticKind, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -214,7 +214,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } /// Generates the code for a field with no attributes. - fn generate_field_set_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { + fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { let diag = &self.parent.diag; let field = binding_info.ast(); @@ -225,7 +225,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - #diag.set_arg( + #diag.arg( stringify!(#ident), #field_binding ); @@ -505,7 +505,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .variant .bindings() .iter() - .filter(|binding| !should_generate_set_arg(binding.ast())) + .filter(|binding| !should_generate_arg(binding.ast())) .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); @@ -593,8 +593,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .variant .bindings() .iter() - .filter(|binding| should_generate_set_arg(binding.ast())) - .map(|binding| self.generate_field_set_arg(binding)) + .filter(|binding| should_generate_arg(binding.ast())) + .map(|binding| self.generate_field_arg(binding)) .collect(); let formatting_init = &self.formatting_init; diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 2700f02e33a66..4684306e23592 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -584,7 +584,7 @@ pub(super) enum SubdiagnosticKind { suggestion_kind: SuggestionKind, applicability: SpannedOption, /// Identifier for variable used for formatted code, e.g. `___code_0`. Enables separation - /// of formatting and diagnostic emission so that `set_arg` calls can happen in-between.. + /// of formatting and diagnostic emission so that `arg` calls can happen in-between.. code_field: syn::Ident, /// Initialization logic for `code_field`'s variable, e.g. /// `let __formatted_code = /* whatever */;` @@ -863,9 +863,9 @@ impl quote::IdentFragment for SubdiagnosticKind { } } -/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic +/// Returns `true` if `field` should generate a `arg` call rather than any other diagnostic /// call (like `span_label`). -pub(super) fn should_generate_set_arg(field: &Field) -> bool { +pub(super) fn should_generate_arg(field: &Field) -> bool { // Perhaps this should be an exhaustive list... field.attrs.iter().all(|attr| is_doc_comment(attr)) } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index e13068cb6f9e4..27c26d3178144 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -500,10 +500,10 @@ pub(crate) struct MultipleCandidates { impl IntoDiagnostic<'_, G> for MultipleCandidates { fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates); - diag.set_arg("crate_name", self.crate_name); - diag.set_arg("flavor", self.flavor); + diag.arg("crate_name", self.crate_name); + diag.arg("flavor", self.flavor); diag.code(error_code!(E0464)); - diag.set_span(self.span); + diag.span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { diag.note(format!("candidate #{}: {}", i + 1, candidate.display())); } @@ -596,10 +596,10 @@ impl IntoDiagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files); - diag.set_arg("crate_name", self.crate_name); - diag.set_arg("add_info", self.add_info); + diag.arg("crate_name", self.crate_name); + diag.arg("add_info", self.add_info); diag.code(error_code!(E0786)); - diag.set_span(self.span); + diag.span(self.span); for crate_rejection in self.crate_rejections { diag.note(crate_rejection); } @@ -623,12 +623,12 @@ impl IntoDiagnostic<'_, G> for CannotFindCrate { #[track_caller] fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_cannot_find_crate); - diag.set_arg("crate_name", self.crate_name); - diag.set_arg("current_crate", self.current_crate); - diag.set_arg("add_info", self.add_info); - diag.set_arg("locator_triple", self.locator_triple.triple()); + diag.arg("crate_name", self.crate_name); + diag.arg("current_crate", self.current_crate); + diag.arg("add_info", self.add_info); + diag.arg("locator_triple", self.locator_triple.triple()); diag.code(error_code!(E0463)); - diag.set_span(self.span); + diag.span(self.span); if (self.crate_name == sym::std || self.crate_name == sym::core) && self.locator_triple != TargetTriple::from_triple(config::host_triple()) { diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index ae432a0406567..ea1439c959d50 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -318,10 +318,10 @@ pub fn struct_lint_level( }; let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, ""); if let Some(span) = span { - err.set_span(span); + err.span(span); } - err.set_is_lint(); + err.is_lint(); // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate @@ -348,7 +348,7 @@ pub fn struct_lint_level( // Delay evaluating and setting the primary message until after we've // suppressed the lint due to macros. - err.set_primary_message(msg); + err.primary_message(msg); // Lint diagnostics that are covered by the expect level will not be emitted outside // the compiler. It is therefore not necessary to add any information for the user. diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 8677cba6a7c3d..61ad99acf38a5 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -467,11 +467,11 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { level, fluent::mir_build_non_exhaustive_patterns_type_not_empty, ); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0004)); let peeled_ty = self.ty.peel_refs(); - diag.set_arg("ty", self.ty); - diag.set_arg("peeled_ty", peeled_ty); + diag.arg("ty", self.ty); + diag.arg("peeled_ty", peeled_ty); if let ty::Adt(def, _) = peeled_ty.kind() { let def_span = self @@ -855,7 +855,7 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { - diag.set_arg("ty", self.ty); + diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); for Variant { span } in self.variants { diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 17916e16daf46..bde442049b1d3 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -67,11 +67,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); - diag.set_span(self.span); + diag.span(self.span); diag.span_label(self.span, self.details.label()); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); - diag.set_arg("details", desc); - diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); + diag.arg("details", desc); + diag.arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); self.details.add_subdiagnostics(&mut diag); if let Some(sp) = self.enclosing { diag.span_label(sp, fluent::mir_transform_not_inherited); @@ -122,16 +122,16 @@ impl RequiresUnsafeDetail { } CallToFunctionWith { ref missing, ref build_enabled } => { diag.help(fluent::mir_transform_target_feature_call_help); - diag.set_arg( + diag.arg( "missing_target_features", DiagnosticArgValue::StrListSepByAnd( missing.iter().map(|feature| Cow::from(feature.as_str())).collect(), ), ); - diag.set_arg("missing_target_features_count", missing.len()); + diag.arg("missing_target_features_count", missing.len()); if !build_enabled.is_empty() { diag.note(fluent::mir_transform_target_feature_call_note); - diag.set_arg( + diag.arg( "build_target_features", DiagnosticArgValue::StrListSepByAnd( build_enabled @@ -140,7 +140,7 @@ impl RequiresUnsafeDetail { .collect(), ), ); - diag.set_arg("build_target_features_count", build_enabled.len()); + diag.arg("build_target_features_count", build_enabled.len()); } } } @@ -183,7 +183,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { let dcx = diag.dcx().expect("lint should not yet be emitted"); let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); - diag.set_arg("details", desc); + diag.arg("details", desc); diag.span_label(self.details.span, self.details.label()); self.details.add_subdiagnostics(diag); @@ -213,7 +213,7 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint

{ let assert_kind = self.panic(); let message = assert_kind.diagnostic_message(); assert_kind.add_args(&mut |name, value| { - diag.set_arg(name, value); + diag.arg(name, value); }); diag.span_label(span, message); } @@ -280,9 +280,9 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { diag.subdiagnostic(reason); } diag.span_help(self.src_sp, fluent::_subdiag::help); - diag.set_arg("pre", self.pre); - diag.set_arg("def_path", self.tcx.def_path_str(self.def_id)); - diag.set_arg("post", self.post); + diag.arg("pre", self.pre); + diag.arg("def_path", self.tcx.def_path_str(self.def_id)); + diag.arg("post", self.post); } fn msg(&self) -> rustc_errors::DiagnosticMessage { diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 592e71251b8ba..2ca14673a58a3 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -51,7 +51,7 @@ impl IntoDiagnostic<'_, G> for UnusedGenericParamsHint { fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::monomorphize_unused_generic_params); - diag.set_span(self.span); + diag.span(self.span); for (span, name) in self.param_spans.into_iter().zip(self.param_names) { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, // or a label with a dynamic value in a hard-coded string, but I haven't figured out diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e276b34ca37af..3f6582bda0262 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1065,8 +1065,8 @@ impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { None => fluent::parse_expected_identifier_found_str, }, ); - diag.set_span(self.span); - diag.set_arg("token", self.token); + diag.span(self.span); + diag.arg("token", self.token); if let Some(sugg) = self.suggest_raw { sugg.add_to_diagnostic(&mut diag); @@ -1123,8 +1123,8 @@ impl<'a> IntoDiagnostic<'a> for ExpectedSemi { None => fluent::parse_expected_semi_found_str, }, ); - diag.set_span(self.span); - diag.set_arg("token", self.token); + diag.span(self.span); + diag.arg("token", self.token); if let Some(unexpected_token_label) = self.unexpected_token_label { diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token); diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 083d1984e0031..fdbb19103c6e9 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -252,7 +252,7 @@ impl<'a> StringReader<'a> { if starts_with_number { let span = self.mk_sp(start, self.pos); let mut diag = self.dcx().struct_err("lifetimes cannot start with a number"); - diag.set_span(span); + diag.span(span); diag.stash(span, StashKey::LifetimeIsChar); } let ident = Symbol::intern(lifetime_name); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f06aeed8628b8..579c3cffcfbf5 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -154,7 +154,7 @@ fn try_file_to_source_file( let msg = format!("couldn't read {}: {}", path.display(), e); let mut diag = Diagnostic::new(Level::Fatal, msg); if let Some(sp) = spanopt { - diag.set_span(sp); + diag.span(sp); } diag }) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index fb8ad05f25df7..c8629069968aa 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -174,7 +174,7 @@ impl<'a> Parser<'a> { ) { Ok(Some(item)) => { // FIXME(#100717) - err.set_arg("item", item.kind.descr()); + err.arg("item", item.kind.descr()); err.span_label(item.span, fluent::parse_label_does_not_annotate_this); err.span_suggestion_verbose( replacement_span, diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 77bca2f138a9d..aed5e11133bc4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -846,7 +846,7 @@ impl<'a> Parser<'a> { ) => { let n_hashes: u8 = *n_hashes; - err.set_primary_message("too many `#` when terminating raw string"); + err.primary_message("too many `#` when terminating raw string"); let str_span = self.prev_token.span; let mut span = self.token.span; let mut count = 0; @@ -857,7 +857,7 @@ impl<'a> Parser<'a> { self.bump(); count += 1; } - err.set_span(span); + err.span(span); err.span_suggestion( span, format!("remove the extra `#`{}", pluralize!(count)), diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3932d32a6e1a4..b201d36455e64 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -925,9 +925,8 @@ impl<'a> Parser<'a> { }); } - expect_err.set_primary_message( - "closure bodies that contain statements must be surrounded by braces", - ); + expect_err + .primary_message("closure bodies that contain statements must be surrounded by braces"); let preceding_pipe_span = closure_spans.closing_pipe; let following_token_span = self.token.span; @@ -951,7 +950,7 @@ impl<'a> Parser<'a> { ); expect_err.span_note(second_note, "the closure body may be incorrectly delimited"); - expect_err.set_span(vec![preceding_pipe_span, following_token_span]); + expect_err.span(vec![preceding_pipe_span, following_token_span]); let opening_suggestion_str = " {".to_string(); let closing_suggestion_str = "}".to_string(); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index edce99db7050c..e4bbc9eeaf7d8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2341,17 +2341,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match terr { TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => { if let Some(ty) = hir_sig.decl.inputs.get(idx) { - diag.set_span(ty.span); + diag.span(ty.span); cause.span = ty.span; } else if idx == hir_sig.decl.inputs.len() { let span = hir_sig.decl.output.span(); - diag.set_span(span); + diag.span(span); cause.span = span; } } TypeError::ArgCount => { if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) { - diag.set_span(ty.span); + diag.span(ty.span); cause.span = ty.span; } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 856256a064149..9bd9dd41cf691 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -868,8 +868,8 @@ impl IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_invalid_attr_at_crate_level); - diag.set_span(self.span); - diag.set_arg("name", self.name); + diag.span(self.span); + diag.arg("name", self.name); // Only emit an error with a suggestion if we can create a string out // of the attribute span if let Some(span) = self.sugg_span { @@ -881,7 +881,7 @@ impl IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { ); } if let Some(item) = self.item { - diag.set_arg("kind", item.kind); + diag.arg("kind", item.kind); diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item); } diag @@ -1018,9 +1018,9 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0571)); - diag.set_arg("kind", self.kind); + diag.arg("kind", self.kind); diag.span_label(self.span, fluent::passes_label); if let Some(head) = self.head { diag.span_label(head, fluent::passes_label2); @@ -1162,7 +1162,7 @@ impl IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0787)); for span in self.multiple_asms.iter() { diag.span_label(*span, fluent::passes_label_multiple_asm); @@ -1273,11 +1273,11 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function); - diag.set_span(DUMMY_SP); + diag.span(DUMMY_SP); diag.code(error_code!(E0601)); - diag.set_arg("crate_name", self.crate_name); - diag.set_arg("filename", self.filename); - diag.set_arg("has_filename", self.has_filename); + diag.arg("crate_name", self.crate_name); + diag.arg("filename", self.filename); + diag.arg("has_filename", self.has_filename); let note = if !self.non_main_fns.is_empty() { for &span in &self.non_main_fns { diag.span_note(span, fluent::passes_here_is_main); @@ -1294,7 +1294,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { if self.file_empty { diag.note(note); } else { - diag.set_span(self.sp.shrink_to_hi()); + diag.span(self.sp.shrink_to_hi()); diag.span_label(self.sp.shrink_to_hi(), note); } @@ -1340,15 +1340,15 @@ impl IntoDiagnostic<'_, G> for DuplicateLangItem { }, ); diag.code(error_code!(E0152)); - diag.set_arg("lang_item_name", self.lang_item_name); - diag.set_arg("crate_name", self.crate_name); - diag.set_arg("dependency_of", self.dependency_of); - diag.set_arg("path", self.path); - diag.set_arg("orig_crate_name", self.orig_crate_name); - diag.set_arg("orig_dependency_of", self.orig_dependency_of); - diag.set_arg("orig_path", self.orig_path); + diag.arg("lang_item_name", self.lang_item_name); + diag.arg("crate_name", self.crate_name); + diag.arg("dependency_of", self.dependency_of); + diag.arg("path", self.path); + diag.arg("orig_crate_name", self.orig_crate_name); + diag.arg("orig_dependency_of", self.orig_dependency_of); + diag.arg("orig_path", self.orig_path); if let Some(span) = self.local_span { - diag.set_span(span); + diag.span(span); } if let Some(span) = self.first_defined_span { diag.span_note(span, fluent::passes_first_defined_span); diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index cb712fe640c5e..1a4f3edd8102e 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -204,7 +204,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( use rustc_errors::DecorateLint; let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().unwrap().span, ""); - err.set_primary_message(decorator.msg()); + err.primary_message(decorator.msg()); decorator.decorate_lint(&mut err); err.emit(); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9bd58dfe82be5..6c38ed6227038 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1383,7 +1383,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { | PathSource::TupleStruct(span, _) => { // We want the main underline to cover the suggested code as well for // cleaner output. - err.set_span(*span); + err.span(*span); *span } _ => span, @@ -1615,7 +1615,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let field_spans = match source { // e.g. `if let Enum::TupleVariant(field1, field2) = _` PathSource::TupleStruct(_, pattern_spans) => { - err.set_primary_message( + err.primary_message( "cannot match against a tuple struct which contains private fields", ); @@ -1628,7 +1628,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { span: call_span, .. })) => { - err.set_primary_message( + err.primary_message( "cannot initialize a tuple struct which contains private fields", ); self.suggest_alternative_construction_methods( diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 0f86773b73fc9..758c31224045c 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -19,7 +19,7 @@ impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { let mut diag = DiagnosticBuilder::new(dcx, level, self.explain); - diag.set_span(self.span); + diag.span(self.span); diag.code(error_code!(E0658)); diag } diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index 06a2b3ca9c4f3..0fa59d2ddfba1 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -19,7 +19,7 @@ impl IntoDiagnostic<'_, G> for TestOutput { #[allow(rustc::untranslatable_diagnostic)] let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")); - diag.set_span(span); + diag.span(span); diag } } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index bea6fbd6ac5cd..5eff52afbca2b 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -66,12 +66,9 @@ impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_ ) -> rustc_errors::DiagnosticBuilder<'_, G> { let mut diag = DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict); - diag.set_arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); - diag.set_arg( - "self_desc", - self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()), - ); - diag.set_span(self.impl_span); + diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); + diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); + diag.span(self.impl_span); diag.code(rustc_errors::error_code!(E0751)); match self.negative_impl_span { Ok(span) => { @@ -79,7 +76,7 @@ impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_ } Err(cname) => { diag.note(fluent::trait_selection_negative_implementation_in_crate); - diag.set_arg("negative_impl_cname", cname.to_string()); + diag.arg("negative_impl_cname", cname.to_string()); } } match self.positive_impl_span { @@ -88,7 +85,7 @@ impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_ } Err(cname) => { diag.note(fluent::trait_selection_positive_implementation_in_crate); - diag.set_arg("positive_impl_cname", cname.to_string()); + diag.arg("positive_impl_cname", cname.to_string()); } } diag @@ -115,7 +112,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow { { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { - diag.set_arg("len", to_borrow.len()); + diag.arg("len", to_borrow.len()); diag.multipart_suggestion_verbose( fluent::trait_selection_adjust_signature_borrow, to_borrow, @@ -123,7 +120,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow { ); } AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { - diag.set_arg("len", remove_borrow.len()); + diag.arg("len", remove_borrow.len()); diag.multipart_suggestion_verbose( fluent::trait_selection_adjust_signature_remove_borrow, remove_borrow, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index f63314081d615..787d2cac0b25c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2008,7 +2008,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; err.code(error_code!(E0746)); - err.set_primary_message("return type cannot have an unboxed trait object"); + err.primary_message("return type cannot have an unboxed trait object"); err.children.clear(); let span = obligation.cause.span; @@ -2713,7 +2713,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; err.clear_code(); - err.set_primary_message(format!( + err.primary_message(format!( "{future_or_coroutine} cannot be {trait_verb} between threads safely" )); @@ -2801,7 +2801,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}")); span.push_span_label(original_span, message); - err.set_span(span); + err.span(span); format!("is not {trait_name}") } else { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index d2598b0defe7f..0b2c946deeb2b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -3163,14 +3163,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) { match obligation_cause_code { ObligationCauseCode::RustCall => { - err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); + err.primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument"); } ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ItemObligation(def_id) if self.tcx.is_fn_trait(*def_id) => { err.code(rustc_errors::error_code!(E0059)); - err.set_primary_message(format!( + err.primary_message(format!( "type parameter to bare `{}` trait must be a tuple", self.tcx.def_path_str(*def_id) )); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index ee185ab98922d..506eb56fdc8ff 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1733,7 +1733,7 @@ fn report_diagnostic( }; if let Some(sp) = span { - lint.set_span(sp); + lint.span(sp); } else { // blah blah blah\nblah\nblah [blah] blah blah\nblah blah // ^ ~~~~ diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 4375fa67b807b..d9b4eb2f0ad1b 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -459,7 +459,7 @@ pub fn report_msg<'tcx>( DiagLevel::Note => Level::Note, }; let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, title); - err.set_span(span); + err.span(span); // Show main message. if span != DUMMY_SP { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index bdcf54bd19042..f07b69326b0cf 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -8,7 +8,7 @@ LL | arg: NotIntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg` | = help: normalized in stderr -note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` +note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -22,7 +22,7 @@ LL | arg: NotIntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg` | = help: normalized in stderr -note: required by a bound in `Diagnostic::set_arg` +note: required by a bound in `Diagnostic::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC error: aborting due to 2 previous errors diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 63fb78ee91995..f553aa96505ec 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -741,7 +741,7 @@ struct SubdiagnosticEagerCorrect { } // Check that formatting of `correct` in suggestion doesn't move the binding for that field, making -// the `set_arg` call a compile error; and that isn't worked around by moving the `set_arg` call +// the `arg` call a compile error; and that isn't worked around by moving the `arg` call // after the `span_suggestion` call - which breaks eager translation. #[derive(Subdiagnostic)] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index d8ba65d297e42..f376c034587fa 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -654,7 +654,7 @@ LL | other: Hello, | ^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` | = help: normalized in stderr -note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` +note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) From 5fe5d5da4e10eccdaf3d46aee5fc21701c32f206 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 2 Jan 2024 14:39:57 +1100 Subject: [PATCH 08/21] Remove lots of `rustc_errors::` qualifiers in `lints.rs`. --- compiler/rustc_lint/src/lints.rs | 99 ++++++++++++-------------------- 1 file changed, 36 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1b81402e0031d..614c3ecbcae2b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,8 +5,8 @@ use std::num::NonZeroU32; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, DiagnosticStyledString, - SuggestionStyle, + AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage, + DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -239,7 +239,7 @@ pub struct BuiltinUngatedAsyncFnTrackCaller<'a> { } impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.span_label(self.label, fluent::lint_label); rustc_session::parse::add_feature_diagnostics( diag, @@ -268,12 +268,9 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -281,7 +278,7 @@ impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { // We use a HIR visitor to walk the type. use rustc_hir::intravisit::{self, Visitor}; struct WalkAssocTypes<'a> { - err: &'a mut rustc_errors::Diagnostic, + err: &'a mut Diagnostic, } impl Visitor<'_> for WalkAssocTypes<'_> { fn visit_qpath( @@ -326,12 +323,9 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.multipart_suggestion( fluent::lint_suggestion, @@ -425,7 +419,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> { } impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("ty", self.ty); diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { @@ -438,7 +432,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> { self.sub.add_to_diagnostic(diag); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { self.msg.clone() } } @@ -449,12 +443,9 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { let mut err = self.err; loop { @@ -506,12 +497,9 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); @@ -779,12 +767,9 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); @@ -799,12 +784,9 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { @@ -953,12 +935,9 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.span_suggestion_verbose( self.suggestion, @@ -1147,7 +1126,7 @@ pub struct NonFmtPanicUnused { // Used because of two suggestions based on one Option impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("count", self.count); diag.note(fluent::lint_note); if let Some(span) = self.suggestion { @@ -1166,7 +1145,7 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused { } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_non_fmt_panic_unused } } @@ -1224,12 +1203,9 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { match self { NonSnakeCaseDiagSub::Label { span } => { @@ -1342,12 +1318,12 @@ pub struct DropTraitConstraintsDiag<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("predicate", self.predicate); diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_drop_trait_constraints } } @@ -1359,11 +1335,11 @@ pub struct DropGlue<'a> { // Needed for def_path_str impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_drop_glue } } @@ -1423,12 +1399,9 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { match self { OverflowingBinHexSign::Positive => { @@ -1633,7 +1606,7 @@ pub struct ImproperCTypes<'a> { // Used because of the complexity of Option, DiagnosticMessage, and Option impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("ty", self.ty); diag.arg("desc", self.desc); diag.span_label(self.label, fluent::lint_label); @@ -1646,7 +1619,7 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> { } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_improper_ctypes } } @@ -1776,7 +1749,7 @@ pub enum UnusedDefSuggestion { // Needed because of def_path_str impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.arg("pre", self.pre); diag.arg("post", self.post); diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); @@ -1789,7 +1762,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_unused_def } } @@ -1859,14 +1832,14 @@ pub struct AsyncFnInTraitDiag { } impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag { - fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { + fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { diag.note(fluent::lint_note); if let Some(sugg) = self.sugg { diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect); } } - fn msg(&self) -> rustc_errors::DiagnosticMessage { + fn msg(&self) -> DiagnosticMessage { fluent::lint_async_fn_in_trait } } From 096b844a2b38436d2e7a4eb4419a6be3eff7da67 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 14:27:35 +1100 Subject: [PATCH 09/21] Remove forward for `downgrade_to_delayed_bug`. It's not used, and doesn't quite fit the general pattern. Also, `Diagnostic::downgrade_to_delayed_bug` doesn't need to return `&mut Self` for the same reason. --- compiler/rustc_errors/src/diagnostic.rs | 4 +--- compiler/rustc_errors/src/diagnostic_builder.rs | 5 ----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f2d54eb427db3..e0689297b21de 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -311,15 +311,13 @@ impl Diagnostic { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn downgrade_to_delayed_bug(&mut self) -> &mut Self { + pub fn downgrade_to_delayed_bug(&mut self) { assert!( self.is_error(), "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); self.level = Level::DelayedBug; - - self } /// Adds a span/label to be included in the resulting snippet. diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index d8838bbdbab1d..d3b11552aa119 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -356,11 +356,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.emit() } - forward!( - #[track_caller] - pub fn downgrade_to_delayed_bug(&mut self,) -> &mut Self - ); - forward!( /// Appends a labeled span to the diagnostic. /// From caefa553476c2b9bda30ab89f5882f7a35649572 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 14:32:17 +1100 Subject: [PATCH 10/21] Fix up `forward!` decls. - Move comments onto corresponding `Diagnostic` methods. - Make formatting more consistent. --- compiler/rustc_errors/src/diagnostic.rs | 16 ++++++---- .../rustc_errors/src/diagnostic_builder.rs | 32 ++++--------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e0689297b21de..863bfee4f183f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -320,14 +320,18 @@ impl Diagnostic { self.level = Level::DelayedBug; } - /// Adds a span/label to be included in the resulting snippet. + /// Appends a labeled span to the diagnostic. /// - /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic - /// was first built. That means it will be shown together with the original - /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods. + /// Labels are used to convey additional context for the diagnostic's primary span. They will + /// be shown together with the original diagnostic's span, *not* with spans added by + /// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because + /// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed + /// either. /// - /// This span is *not* considered a ["primary span"][`MultiSpan`]; only - /// the `Span` supplied when creating the diagnostic is primary. + /// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when + /// the diagnostic was constructed. However, the label span is *not* considered a + /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is + /// primary. #[rustc_lint_diagnostics] pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label)); diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index d3b11552aa119..24efc87100126 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -356,30 +356,16 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.emit() } - forward!( - /// Appends a labeled span to the diagnostic. - /// - /// Labels are used to convey additional context for the diagnostic's primary span. They will - /// be shown together with the original diagnostic's span, *not* with spans added by - /// `span_note`, `span_help`, etc. Therefore, if the primary span is not displayable (because - /// the span is `DUMMY_SP` or the source code isn't found), labels will not be displayed - /// either. - /// - /// Implementation-wise, the label span is pushed onto the [`MultiSpan`] that was created when - /// the diagnostic was constructed. However, the label span is *not* considered a - /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is - /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self); - - forward!( - /// Labels all the given spans with the provided label. - /// See [`Diagnostic::span_label()`] for more information. - pub fn span_labels( + forward!(pub fn span_label( + &mut self, + span: Span, + label: impl Into + ) -> &mut Self); + forward!(pub fn span_labels( &mut self, spans: impl IntoIterator, label: &str, ) -> &mut Self); - forward!(pub fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, @@ -387,7 +373,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { found_label: &dyn fmt::Display, found: DiagnosticStyledString, ) -> &mut Self); - forward!(pub fn note_expected_found_extra( &mut self, expected_label: &dyn fmt::Display, @@ -397,7 +382,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { expected_extra: &dyn fmt::Display, found_extra: &dyn fmt::Display, ) -> &mut Self); - forward!(pub fn note(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn note_once(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn span_note( @@ -424,9 +408,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { msg: impl Into, ) -> &mut Self); forward!(pub fn is_lint(&mut self,) -> &mut Self); - forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); - forward!(pub fn multipart_suggestion( &mut self, msg: impl Into, @@ -493,7 +475,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { suggestion: impl ToString, applicability: Applicability, ) -> &mut Self); - forward!(pub fn primary_message(&mut self, msg: impl Into) -> &mut Self); forward!(pub fn span(&mut self, sp: impl Into) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); @@ -502,7 +483,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { name: impl Into>, arg: impl IntoDiagnosticArg, ) -> &mut Self); - forward!(pub fn subdiagnostic( &mut self, subdiagnostic: impl crate::AddToDiagnostic From b4a62399840d61c56081e7378220d65e183a00fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 14:38:20 +1100 Subject: [PATCH 11/21] Fix `forward!` so it doesn't require trailing commas in some cases. --- compiler/rustc_errors/src/diagnostic_builder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 24efc87100126..e018c14a4a5cd 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -207,11 +207,11 @@ macro_rules! forward { // Forward pattern for &mut self -> &mut Self ( $(#[$attrs:meta])* - pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)?) -> &mut Self + pub fn $n:ident(&mut self $(, $name:ident: $ty:ty)* $(,)?) -> &mut Self ) => { $(#[$attrs])* #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] - pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { + pub fn $n(&mut self $(, $name: $ty)*) -> &mut Self { self.diagnostic.$n($($name),*); self } @@ -407,8 +407,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { sp: impl Into, msg: impl Into, ) -> &mut Self); - forward!(pub fn is_lint(&mut self,) -> &mut Self); - forward!(pub fn disable_suggestions(&mut self,) -> &mut Self); + forward!(pub fn is_lint(&mut self) -> &mut Self); + forward!(pub fn disable_suggestions(&mut self) -> &mut Self); forward!(pub fn multipart_suggestion( &mut self, msg: impl Into, From 1e922239256348270dd58fc72a24ad0972ddafe4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 07:55:59 +1100 Subject: [PATCH 12/21] Remove unused `DiagnosticBuilder::struct_almost_fatal`. `create_almost_fatal` and `emit_almost_fatal` are always used instead. --- compiler/rustc_errors/src/lib.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6dc3a8cd08ece..a4b31748e85bd 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -878,16 +878,6 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Fatal, msg) } - /// Construct a builder at the `Fatal` level with the `msg`, that doesn't abort. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_almost_fatal( - &self, - msg: impl Into, - ) -> DiagnosticBuilder<'_, FatalError> { - DiagnosticBuilder::new(self, Fatal, msg) - } - /// Construct a builder at the `Help` level with the `msg`. #[rustc_lint_diagnostics] pub fn struct_help(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { From 9560c58c2ae77569e9855136537834669f5bbc3b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:43:19 +1100 Subject: [PATCH 13/21] Avoid some `rustc_errors::` qualifiers. These are misleading, because the mixture of `Level` and `rustc_errors::Level` makes it look like there are two different types involved. --- compiler/rustc_codegen_ssa/src/back/write.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index cb12470478500..a465c83326491 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1848,9 +1848,9 @@ impl SharedEmitterMain { } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let err_level = match level { - Level::Error { lint: false } => rustc_errors::Level::Error { lint: false }, - Level::Warning(_) => rustc_errors::Level::Warning(None), - Level::Note => rustc_errors::Level::Note, + Level::Error { lint: false } => Level::Error { lint: false }, + Level::Warning(_) => Level::Warning(None), + Level::Note => Level::Note, _ => bug!("Invalid inline asm diagnostic level"), }; let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); From 4d35981703ad64ae8b5957386550539ed1ed1435 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:44:03 +1100 Subject: [PATCH 14/21] Remove unused `struct_error` function. --- compiler/rustc_middle/src/mir/interpret/error.rs | 10 +--------- compiler/rustc_middle/src/mir/interpret/mod.rs | 11 +++++------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e6536074f35fc..1b4e9c286351a 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -2,14 +2,10 @@ use super::{AllocId, AllocRange, Pointer, Scalar}; use crate::error; use crate::mir::{ConstAlloc, ConstValue}; -use crate::query::TyCtxtAt; use crate::ty::{layout, tls, Ty, TyCtxt, ValTree}; use rustc_data_structures::sync::Lock; -use rustc_errors::{ - struct_span_err, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, - IntoDiagnosticArg, -}; +use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; @@ -90,10 +86,6 @@ pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; /// This is needed in `thir::pattern::lower_inline_const`. pub type EvalToValTreeResult<'tcx> = Result>, ErrorHandled>; -pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> { - struct_span_err!(tcx.dcx(), tcx.span, E0080, "{}", msg) -} - #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(InterpErrorInfo<'_>, 8); diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 2db5600855343..0da3524e05564 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -142,12 +142,11 @@ use crate::ty::GenericArgKind; use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ - struct_error, BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, - EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, - InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo, - MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo, - ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo, - ValidationErrorKind, + BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, + EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, + InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, Misalignment, PointerKind, + ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, + UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind, }; pub use self::value::Scalar; From 8e6bca63f943a061264aec986446fac67c59c262 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:44:16 +1100 Subject: [PATCH 15/21] Inline and remove `StringReader::struct_fatal_span_char`. It has a single call site. --- compiler/rustc_parse/src/lexer/mod.rs | 33 +++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index fdbb19103c6e9..4819ed6021d0d 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,9 +7,7 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{ - error_code, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalAbort, StashKey, -}; +use rustc_errors::{error_code, Applicability, DiagCtxt, Diagnostic, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -344,18 +342,6 @@ impl<'a> StringReader<'a> { token::Ident(sym, false) } - fn struct_fatal_span_char( - &self, - from_pos: BytePos, - to_pos: BytePos, - m: &str, - c: char, - ) -> DiagnosticBuilder<'a, FatalAbort> { - self.sess - .dcx - .struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c))) - } - /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly /// complain about it. fn lint_unicode_text_flow(&self, start: BytePos) { @@ -568,13 +554,16 @@ impl<'a> StringReader<'a> { } fn report_non_started_raw_string(&self, start: BytePos, bad_char: char) -> ! { - self.struct_fatal_span_char( - start, - self.pos, - "found invalid character; only `#` is allowed in raw string delimitation", - bad_char, - ) - .emit() + self.sess + .dcx + .struct_span_fatal( + self.mk_sp(start, self.pos), + format!( + "found invalid character; only `#` is allowed in raw string delimitation: {}", + escaped_char(bad_char) + ), + ) + .emit() } fn report_unterminated_raw_string( From 1d48f69d65af74201314304623f37f5bcefa9a24 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 4 Jan 2024 01:46:43 +0000 Subject: [PATCH 16/21] Check yield terminator's resume type in borrowck --- .../src/type_check/input_output.rs | 33 +++++++---------- .../src/type_check/liveness/mod.rs | 1 + compiler/rustc_borrowck/src/type_check/mod.rs | 26 ++++++++++++-- .../rustc_borrowck/src/universal_regions.rs | 12 +++++-- compiler/rustc_middle/src/mir/mod.rs | 9 +++++ compiler/rustc_middle/src/mir/visit.rs | 8 +++++ compiler/rustc_mir_build/src/build/mod.rs | 27 ++++++++------ compiler/rustc_mir_transform/src/coroutine.rs | 1 + .../coroutine/check-resume-ty-lifetimes-2.rs | 35 ++++++++++++++++++ .../check-resume-ty-lifetimes-2.stderr | 36 +++++++++++++++++++ .../ui/coroutine/check-resume-ty-lifetimes.rs | 27 ++++++++++++++ .../check-resume-ty-lifetimes.stderr | 11 ++++++ 12 files changed, 190 insertions(+), 36 deletions(-) create mode 100644 tests/ui/coroutine/check-resume-ty-lifetimes-2.rs create mode 100644 tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr create mode 100644 tests/ui/coroutine/check-resume-ty-lifetimes.rs create mode 100644 tests/ui/coroutine/check-resume-ty-lifetimes.stderr diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 5bd7cc9514ca2..61b6bef3b87b9 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -94,31 +94,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } - debug!( - "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}", - body.yield_ty(), - universal_regions.yield_ty - ); - - // We will not have a universal_regions.yield_ty if we yield (by accident) - // outside of a coroutine and return an `impl Trait`, so emit a span_delayed_bug - // because we don't want to panic in an assert here if we've already got errors. - if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() { - self.tcx().dcx().span_delayed_bug( - body.span, - format!( - "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})", - body.yield_ty(), - universal_regions.yield_ty, - ), + if let Some(mir_yield_ty) = body.yield_ty() { + let yield_span = body.local_decls[RETURN_PLACE].source_info.span; + self.equate_normalized_input_or_output( + universal_regions.yield_ty.unwrap(), + mir_yield_ty, + yield_span, ); } - if let (Some(mir_yield_ty), Some(ur_yield_ty)) = - (body.yield_ty(), universal_regions.yield_ty) - { + if let Some(mir_resume_ty) = body.resume_ty() { let yield_span = body.local_decls[RETURN_PLACE].source_info.span; - self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span); + self.equate_normalized_input_or_output( + universal_regions.resume_ty.unwrap(), + mir_resume_ty, + yield_span, + ); } // Return types are a bit more complex. They may contain opaque `impl Trait` types. diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index dc4695fd2b058..e137bc1be0aeb 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -183,6 +183,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> { match ty_context { TyContext::ReturnTy(SourceInfo { span, .. }) | TyContext::YieldTy(SourceInfo { span, .. }) + | TyContext::ResumeTy(SourceInfo { span, .. }) | TyContext::UserTy(span) | TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => { span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 80575e30a8d23..9c0f53ddb86fa 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1450,13 +1450,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } } - TerminatorKind::Yield { value, .. } => { + TerminatorKind::Yield { value, resume_arg, .. } => { self.check_operand(value, term_location); - let value_ty = value.ty(body, tcx); match body.yield_ty() { None => span_mirbug!(self, term, "yield in non-coroutine"), Some(ty) => { + let value_ty = value.ty(body, tcx); if let Err(terr) = self.sub_types( value_ty, ty, @@ -1474,6 +1474,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } } + + match body.resume_ty() { + None => span_mirbug!(self, term, "yield in non-coroutine"), + Some(ty) => { + let resume_ty = resume_arg.ty(body, tcx); + if let Err(terr) = self.sub_types( + ty, + resume_ty.ty, + term_location.to_locations(), + ConstraintCategory::Yield, + ) { + span_mirbug!( + self, + term, + "type of resume place is {:?}, but the resume type is {:?}: {:?}", + resume_ty, + ty, + terr + ); + } + } + } } } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index a02304a2f8b30..addb41ff5fc8f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -76,6 +76,8 @@ pub struct UniversalRegions<'tcx> { pub unnormalized_input_tys: &'tcx [Ty<'tcx>], pub yield_ty: Option>, + + pub resume_ty: Option>, } /// The "defining type" for this MIR. The key feature of the "defining @@ -525,9 +527,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { debug!("build: extern regions = {}..{}", first_extern_index, first_local_index); debug!("build: local regions = {}..{}", first_local_index, num_universals); - let yield_ty = match defining_ty { - DefiningTy::Coroutine(_, args) => Some(args.as_coroutine().yield_ty()), - _ => None, + let (resume_ty, yield_ty) = match defining_ty { + DefiningTy::Coroutine(_, args) => { + let tys = args.as_coroutine(); + (Some(tys.resume_ty()), Some(tys.yield_ty())) + } + _ => (None, None), }; UniversalRegions { @@ -541,6 +546,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { unnormalized_output_ty: *unnormalized_output_ty, unnormalized_input_tys, yield_ty, + resume_ty, } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5c425fef27ebc..01ad3aefffa3b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -250,6 +250,9 @@ pub struct CoroutineInfo<'tcx> { /// The yield type of the function, if it is a coroutine. pub yield_ty: Option>, + /// The resume type of the function, if it is a coroutine. + pub resume_ty: Option>, + /// Coroutine drop glue. pub coroutine_drop: Option>, @@ -385,6 +388,7 @@ impl<'tcx> Body<'tcx> { coroutine: coroutine_kind.map(|coroutine_kind| { Box::new(CoroutineInfo { yield_ty: None, + resume_ty: None, coroutine_drop: None, coroutine_layout: None, coroutine_kind, @@ -551,6 +555,11 @@ impl<'tcx> Body<'tcx> { self.coroutine.as_ref().and_then(|coroutine| coroutine.yield_ty) } + #[inline] + pub fn resume_ty(&self) -> Option> { + self.coroutine.as_ref().and_then(|coroutine| coroutine.resume_ty) + } + #[inline] pub fn coroutine_layout(&self) -> Option<&CoroutineLayout<'tcx>> { self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_layout.as_ref()) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 132ecf91af187..2ccf5a9f6f7ad 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -996,6 +996,12 @@ macro_rules! super_body { TyContext::YieldTy(SourceInfo::outermost(span)) ); } + if let Some(resume_ty) = $(& $mutability)? gen.resume_ty { + $self.visit_ty( + resume_ty, + TyContext::ResumeTy(SourceInfo::outermost(span)) + ); + } } for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) { @@ -1244,6 +1250,8 @@ pub enum TyContext { YieldTy(SourceInfo), + ResumeTy(SourceInfo), + /// A type found at some location. Location(Location), } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index e0199fb876717..c4cade839478c 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -488,7 +488,7 @@ fn construct_fn<'tcx>( let arguments = &thir.params; - let (yield_ty, return_ty) = if coroutine_kind.is_some() { + let (resume_ty, yield_ty, return_ty) = if coroutine_kind.is_some() { let coroutine_ty = arguments[thir::UPVAR_ENV_PARAM].ty; let coroutine_sig = match coroutine_ty.kind() { ty::Coroutine(_, gen_args, ..) => gen_args.as_coroutine().sig(), @@ -496,9 +496,9 @@ fn construct_fn<'tcx>( span_bug!(span, "coroutine w/o coroutine type: {:?}", coroutine_ty) } }; - (Some(coroutine_sig.yield_ty), coroutine_sig.return_ty) + (Some(coroutine_sig.resume_ty), Some(coroutine_sig.yield_ty), coroutine_sig.return_ty) } else { - (None, fn_sig.output()) + (None, None, fn_sig.output()) }; if let Some(custom_mir_attr) = @@ -562,9 +562,12 @@ fn construct_fn<'tcx>( } else { None }; - if yield_ty.is_some() { + + if coroutine_kind.is_some() { body.coroutine.as_mut().unwrap().yield_ty = yield_ty; + body.coroutine.as_mut().unwrap().resume_ty = resume_ty; } + body } @@ -631,18 +634,18 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - let hir_id = tcx.local_def_id_to_hir_id(def_id); let coroutine_kind = tcx.coroutine_kind(def_id); - let (inputs, output, yield_ty) = match tcx.def_kind(def_id) { + let (inputs, output, resume_ty, yield_ty) = match tcx.def_kind(def_id) { DefKind::Const | DefKind::AssocConst | DefKind::AnonConst | DefKind::InlineConst - | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None), + | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None, None), DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { let sig = tcx.liberate_late_bound_regions( def_id.to_def_id(), tcx.fn_sig(def_id).instantiate_identity(), ); - (sig.inputs().to_vec(), sig.output(), None) + (sig.inputs().to_vec(), sig.output(), None, None) } DefKind::Closure if coroutine_kind.is_some() => { let coroutine_ty = tcx.type_of(def_id).instantiate_identity(); @@ -650,9 +653,10 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - bug!("expected type of coroutine-like closure to be a coroutine") }; let args = args.as_coroutine(); + let resume_ty = args.resume_ty(); let yield_ty = args.yield_ty(); let return_ty = args.return_ty(); - (vec![coroutine_ty, args.resume_ty()], return_ty, Some(yield_ty)) + (vec![coroutine_ty, args.resume_ty()], return_ty, Some(resume_ty), Some(yield_ty)) } DefKind::Closure => { let closure_ty = tcx.type_of(def_id).instantiate_identity(); @@ -666,7 +670,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ty::ClosureKind::FnMut => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty), ty::ClosureKind::FnOnce => closure_ty, }; - ([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None) + ([self_ty].into_iter().chain(sig.inputs().to_vec()).collect(), sig.output(), None, None) } dk => bug!("{:?} is not a body: {:?}", def_id, dk), }; @@ -705,7 +709,10 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - Some(guar), ); - body.coroutine.as_mut().map(|gen| gen.yield_ty = yield_ty); + body.coroutine.as_mut().map(|gen| { + gen.yield_ty = yield_ty; + gen.resume_ty = resume_ty; + }); body } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index ce1a36cf67021..33e305497b505 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1733,6 +1733,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { } body.coroutine.as_mut().unwrap().yield_ty = None; + body.coroutine.as_mut().unwrap().resume_ty = None; body.coroutine.as_mut().unwrap().coroutine_layout = Some(layout); // Insert `drop(coroutine_struct)` which is used to drop upvars for coroutines in diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs b/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs new file mode 100644 index 0000000000000..a316c50e86732 --- /dev/null +++ b/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs @@ -0,0 +1,35 @@ +#![feature(coroutine_trait)] +#![feature(coroutines)] + +use std::ops::Coroutine; + +struct Contravariant<'a>(fn(&'a ())); +struct Covariant<'a>(fn() -> &'a ()); + +fn bad1<'short, 'long: 'short>() -> impl Coroutine> { + |_: Covariant<'short>| { + let a: Covariant<'long> = yield (); + //~^ ERROR lifetime may not live long enough + } +} + +fn bad2<'short, 'long: 'short>() -> impl Coroutine> { + |_: Contravariant<'long>| { + let a: Contravariant<'short> = yield (); + //~^ ERROR lifetime may not live long enough + } +} + +fn good1<'short, 'long: 'short>() -> impl Coroutine> { + |_: Covariant<'long>| { + let a: Covariant<'short> = yield (); + } +} + +fn good2<'short, 'long: 'short>() -> impl Coroutine> { + |_: Contravariant<'short>| { + let a: Contravariant<'long> = yield (); + } +} + +fn main() {} diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr b/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr new file mode 100644 index 0000000000000..e0cbca2dd5267 --- /dev/null +++ b/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr @@ -0,0 +1,36 @@ +error: lifetime may not live long enough + --> $DIR/check-resume-ty-lifetimes-2.rs:11:16 + | +LL | fn bad1<'short, 'long: 'short>() -> impl Coroutine> { + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +LL | |_: Covariant<'short>| { +LL | let a: Covariant<'long> = yield (); + | ^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` +help: consider adding 'move' keyword before the nested closure + | +LL | move |_: Covariant<'short>| { + | ++++ + +error: lifetime may not live long enough + --> $DIR/check-resume-ty-lifetimes-2.rs:18:40 + | +LL | fn bad2<'short, 'long: 'short>() -> impl Coroutine> { + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +LL | |_: Contravariant<'long>| { +LL | let a: Contravariant<'short> = yield (); + | ^^^^^^^^ yielding this value requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` +help: consider adding 'move' keyword before the nested closure + | +LL | move |_: Contravariant<'long>| { + | ++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes.rs b/tests/ui/coroutine/check-resume-ty-lifetimes.rs new file mode 100644 index 0000000000000..add0b5080a8a8 --- /dev/null +++ b/tests/ui/coroutine/check-resume-ty-lifetimes.rs @@ -0,0 +1,27 @@ +#![feature(coroutine_trait)] +#![feature(coroutines)] +#![allow(unused)] + +use std::ops::Coroutine; +use std::ops::CoroutineState; +use std::pin::pin; + +fn mk_static(s: &str) -> &'static str { + let mut storage: Option<&'static str> = None; + + let mut coroutine = pin!(|_: &str| { + let x: &'static str = yield (); + //~^ ERROR lifetime may not live long enough + storage = Some(x); + }); + + coroutine.as_mut().resume(s); + coroutine.as_mut().resume(s); + + storage.unwrap() +} + +fn main() { + let s = mk_static(&String::from("hello, world")); + println!("{s}"); +} diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes.stderr b/tests/ui/coroutine/check-resume-ty-lifetimes.stderr new file mode 100644 index 0000000000000..f373aa778a82c --- /dev/null +++ b/tests/ui/coroutine/check-resume-ty-lifetimes.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/check-resume-ty-lifetimes.rs:13:16 + | +LL | fn mk_static(s: &str) -> &'static str { + | - let's call the lifetime of this reference `'1` +... +LL | let x: &'static str = yield (); + | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` + +error: aborting due to 1 previous error + From 8388112970288c79ddb217949070cfb04c2798a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:44:37 +1100 Subject: [PATCH 17/21] Remove `is_lint` field from `Level::Error`. Because it's redundant w.r.t. `Diagnostic::is_lint`, which is present for every diagnostic level. `struct_lint_level_impl` was the only place that set the `Error` field to `true`, and it's also the only place that calls `Diagnostic::is_lint()` to set the `is_lint` field. --- compiler/rustc_builtin_macros/src/test.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- .../src/annotate_snippet_emitter_writer.rs | 4 +--- compiler/rustc_errors/src/diagnostic.rs | 8 +++---- compiler/rustc_errors/src/lib.rs | 24 ++++++++----------- .../rustc_expand/src/proc_macro_server.rs | 2 +- compiler/rustc_middle/src/lint.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- 9 files changed, 20 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 82fe043820ccd..568f8247b2807 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -395,7 +395,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) // These were a warning before #92959 and need to continue being that to avoid breaking // stable user code (#94508). Some(ast::ItemKind::MacCall(_)) => Level::Warning(None), - _ => Level::Error { lint: false }, + _ => Level::Error, }; let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg); err.span(attr_sp); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c607533a08ed0..45be85934b46b 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -416,7 +416,7 @@ fn report_inline_asm( cookie = 0; } let level = match level { - llvm::DiagnosticLevel::Error => Level::Error { lint: false }, + llvm::DiagnosticLevel::Error => Level::Error, llvm::DiagnosticLevel::Warning => Level::Warning(None), llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index a465c83326491..d2c6b6e0c7bf6 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1848,7 +1848,7 @@ impl SharedEmitterMain { } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { let err_level = match level { - Level::Error { lint: false } => Level::Error { lint: false }, + Level::Error => Level::Error, Level::Warning(_) => Level::Warning(None), Level::Note => Level::Note, _ => bug!("Invalid inline asm diagnostic level"), diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 48e48f59a9992..0390829b33b45 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -86,9 +86,7 @@ fn source_string(file: Lrc, line: &Line) -> String { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error { .. } => { - AnnotationType::Error - } + Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error, Level::Warning(_) => AnnotationType::Warning, Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help | Level::OnceHelp => AnnotationType::Help, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 863bfee4f183f..701c1c02ab0ef 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -244,11 +244,9 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug - | Level::DelayedBug - | Level::Fatal - | Level::Error { .. } - | Level::FailureNote => true, + Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => { + true + } Level::Warning(_) | Level::Note diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a4b31748e85bd..1cedc6081ef31 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -673,7 +673,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if matches!(diag.level, Error { lint: true }) { + if diag.level == Error && diag.is_lint { inner.lint_err_count += 1; } else { inner.err_count += 1; @@ -697,7 +697,7 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if matches!(diag.level, Error { lint: true }) { + if diag.level == Error && diag.is_lint { inner.lint_err_count -= 1; } else { inner.err_count -= 1; @@ -812,7 +812,7 @@ impl DiagCtxt { #[rustc_lint_diagnostics] #[track_caller] pub fn struct_err(&self, msg: impl Into) -> DiagnosticBuilder<'_> { - DiagnosticBuilder::new(self, Error { lint: false }, msg) + DiagnosticBuilder::new(self, Error, msg) } /// Construct a builder at the `Error` level with the `msg` and the `code`. @@ -1212,7 +1212,7 @@ impl DiagCtxt { #[track_caller] pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> DiagnosticBuilder<'a> { - err.into_diagnostic(self, Error { lint: false }) + err.into_diagnostic(self, Error) } #[track_caller] @@ -1367,7 +1367,7 @@ impl DiagCtxtInner { for diag in diags { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if matches!(diag.level, Error { lint: true }) { + if diag.level == Error && diag.is_lint { self.lint_err_count -= 1; } else { self.err_count -= 1; @@ -1398,7 +1398,7 @@ impl DiagCtxtInner { &mut self, diagnostic: &mut Diagnostic, ) -> Option { - if matches!(diagnostic.level, Error { .. } | Fatal) && self.treat_err_as_bug() { + if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { diagnostic.level = Bug; } @@ -1499,7 +1499,7 @@ impl DiagCtxtInner { } } if diagnostic.is_error() { - if matches!(diagnostic.level, Error { lint: true }) { + if diagnostic.level == Error && diagnostic.is_lint { self.bump_lint_err_count(); } else { self.bump_err_count(); @@ -1695,11 +1695,7 @@ pub enum Level { /// most common case. /// /// Its `EmissionGuarantee` is `ErrorGuaranteed`. - Error { - /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is - /// called. - lint: bool, - }, + Error, /// A warning about the code being compiled. Does not prevent compilation from finishing. /// @@ -1758,7 +1754,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | DelayedBug | Fatal | Error { .. } => { + Bug | DelayedBug | Fatal | Error => { spec.set_fg(Some(Color::Red)).set_intense(true); } Warning(_) => { @@ -1779,7 +1775,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { Bug | DelayedBug => "error: internal compiler error", - Fatal | Error { .. } => "error", + Fatal | Error => "error", Warning(_) => "warning", Note | OnceNote => "note", Help | OnceHelp => "help", diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 2c08891b1096a..66695e020f1d1 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -379,7 +379,7 @@ impl ToInternal> impl ToInternal for Level { fn to_internal(self) -> rustc_errors::Level { match self { - Level::Error => rustc_errors::Level::Error { lint: false }, + Level::Error => rustc_errors::Level::Error, Level::Warning => rustc_errors::Level::Warning(None), Level::Note => rustc_errors::Level::Note, Level::Help => rustc_errors::Level::Help, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index ea1439c959d50..d45ec8e464690 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -314,7 +314,7 @@ pub fn struct_lint_level( } Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::Warning(Some(expect_id)), Level::Warn | Level::ForceWarn(None) => rustc_errors::Level::Warning(None), - Level::Deny | Level::Forbid => rustc_errors::Level::Error { lint: true }, + Level::Deny | Level::Forbid => rustc_errors::Level::Error, }; let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, ""); if let Some(span) = span { diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index d9b4eb2f0ad1b..d3d4490f30202 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -454,7 +454,7 @@ pub fn report_msg<'tcx>( let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span); let sess = machine.tcx.sess; let level = match diag_level { - DiagLevel::Error => Level::Error { lint: false }, + DiagLevel::Error => Level::Error, DiagLevel::Warning => Level::Warning(None), DiagLevel::Note => Level::Note, }; From 4bc3552cd871afe32cb45f7c9685492af430ed77 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 4 Jan 2024 21:09:13 +0300 Subject: [PATCH 18/21] cstore: Remove unnecessary locking from `CrateMetadata` --- compiler/rustc_metadata/src/creader.rs | 41 ++++++++++--------- compiler/rustc_metadata/src/rmeta/decoder.rs | 39 +++++++++--------- .../src/rmeta/decoder/cstore_impl.rs | 36 ++++++++-------- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index a3da8c14f63a7..bb02a8a1e4743 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -196,6 +196,10 @@ impl CStore { CrateMetadataRef { cdata, cstore: self } } + pub(crate) fn get_crate_data_mut(&mut self, cnum: CrateNum) -> &mut CrateMetadata { + self.metas[cnum].as_mut().unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}")) + } + fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) { assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry"); self.metas[cnum] = Some(Box::new(data)); @@ -207,6 +211,12 @@ impl CStore { .filter_map(|(cnum, data)| data.as_deref().map(|data| (cnum, data))) } + fn iter_crate_data_mut(&mut self) -> impl Iterator { + self.metas + .iter_enumerated_mut() + .filter_map(|(cnum, data)| data.as_deref_mut().map(|data| (cnum, data))) + } + fn push_dependencies_in_postorder(&self, deps: &mut Vec, cnum: CrateNum) { if !deps.contains(&cnum) { let data = self.get_crate_data(cnum); @@ -586,11 +596,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match result { (LoadResult::Previous(cnum), None) => { - let data = self.cstore.get_crate_data(cnum); + let data = self.cstore.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; } - data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind)); + data.set_dep_kind(cmp::max(data.dep_kind(), dep_kind)); if let Some(private_dep) = private_dep { data.update_and_private_dep(private_dep); } @@ -637,17 +647,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { })) } - fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) { - let cmeta = self.cstore.get_crate_data(cnum); - if cmeta.update_extern_crate(extern_crate) { - // Propagate the extern crate info to dependencies if it was updated. - let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - for dep_cnum in cmeta.dependencies() { - self.update_extern_crate(dep_cnum, extern_crate); - } - } - } - // Go through the crate metadata and load any crates that it references fn resolve_crate_deps( &mut self, @@ -726,17 +725,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let mut runtime_found = false; let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime); + let mut panic_runtimes = Vec::new(); for (cnum, data) in self.cstore.iter_crate_data() { needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); if data.is_panic_runtime() { // Inject a dependency from all #![needs_panic_runtime] to this // #![panic_runtime] crate. - self.inject_dependency_if(cnum, "a panic runtime", &|data| { - data.needs_panic_runtime() - }); + panic_runtimes.push(cnum); runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit; } } + for cnum in panic_runtimes { + self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime()); + } // If an explicitly linked and matching panic runtime was found, or if // we just don't need one at all, then we're done here and there's @@ -917,7 +918,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } fn inject_dependency_if( - &self, + &mut self, krate: CrateNum, what: &str, needs_dep: &dyn Fn(&CrateMetadata) -> bool, @@ -947,7 +948,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // crate provided for this compile, but in order for this compilation to // be successfully linked we need to inject a dependency (to order the // crates on the command line correctly). - for (cnum, data) in self.cstore.iter_crate_data() { + for (cnum, data) in self.cstore.iter_crate_data_mut() { if needs_dep(data) { info!("injecting a dep from {} to {}", cnum, krate); data.add_dependency(krate); @@ -1031,7 +1032,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let cnum = self.resolve_crate(name, item.span, dep_kind)?; let path_len = definitions.def_path(def_id).data.len(); - self.update_extern_crate( + self.cstore.update_extern_crate( cnum, ExternCrate { src: ExternCrateSource::Extern(def_id.to_def_id()), @@ -1049,7 +1050,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; - self.update_extern_crate( + self.cstore.update_extern_crate( cnum, ExternCrate { src: ExternCrateSource::Path, diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2de29db9e5c84..d13a1664adea4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -8,7 +8,7 @@ use rustc_ast as ast; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::owned_slice::OwnedSlice; -use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceLock}; +use rustc_data_structures::sync::{Lock, Lrc, OnceLock}; use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; @@ -31,7 +31,6 @@ use rustc_span::{BytePos, Pos, SpanData, SyntaxContext, DUMMY_SP}; use proc_macro::bridge::client::ProcMacro; use std::iter::TrustedLen; use std::path::Path; -use std::sync::atomic::Ordering; use std::{io, iter, mem}; pub(super) use cstore_impl::provide; @@ -96,15 +95,15 @@ pub(crate) struct CrateMetadata { /// IDs as they are seen from the current compilation session. cnum_map: CrateNumMap, /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. - dependencies: AppendOnlyVec, + dependencies: Vec, /// How to link (or not link) this crate to the currently compiled crate. - dep_kind: Lock, + dep_kind: CrateDepKind, /// Filesystem location of this crate. source: Lrc, /// Whether or not this crate should be consider a private dependency. /// Used by the 'exported_private_dependencies' lint, and for determining /// whether to emit suggestions that reference this crate. - private_dep: AtomicBool, + private_dep: bool, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option, @@ -118,7 +117,7 @@ pub(crate) struct CrateMetadata { // --- Data used only for improving diagnostics --- /// Information about the `extern crate` item or path that caused this crate to be loaded. /// If this is `None`, then the crate was injected (e.g., by the allocator). - extern_crate: Lock>, + extern_crate: Option, } /// Holds information about a rustc_span::SourceFile imported from another crate. @@ -1818,11 +1817,11 @@ impl CrateMetadata { cnum, cnum_map, dependencies, - dep_kind: Lock::new(dep_kind), + dep_kind, source: Lrc::new(source), - private_dep: AtomicBool::new(private_dep), + private_dep, host_hash, - extern_crate: Lock::new(None), + extern_crate: None, hygiene_context: Default::default(), def_key_cache: Default::default(), }; @@ -1839,18 +1838,18 @@ impl CrateMetadata { } pub(crate) fn dependencies(&self) -> impl Iterator + '_ { - self.dependencies.iter() + self.dependencies.iter().copied() } - pub(crate) fn add_dependency(&self, cnum: CrateNum) { + pub(crate) fn add_dependency(&mut self, cnum: CrateNum) { self.dependencies.push(cnum); } - pub(crate) fn update_extern_crate(&self, new_extern_crate: ExternCrate) -> bool { - let mut extern_crate = self.extern_crate.borrow_mut(); - let update = Some(new_extern_crate.rank()) > extern_crate.as_ref().map(ExternCrate::rank); + pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool { + let update = + Some(new_extern_crate.rank()) > self.extern_crate.as_ref().map(ExternCrate::rank); if update { - *extern_crate = Some(new_extern_crate); + self.extern_crate = Some(new_extern_crate); } update } @@ -1860,15 +1859,15 @@ impl CrateMetadata { } pub(crate) fn dep_kind(&self) -> CrateDepKind { - *self.dep_kind.lock() + self.dep_kind } - pub(crate) fn update_dep_kind(&self, f: impl FnOnce(CrateDepKind) -> CrateDepKind) { - self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) + pub(crate) fn set_dep_kind(&mut self, dep_kind: CrateDepKind) { + self.dep_kind = dep_kind; } - pub(crate) fn update_and_private_dep(&self, private_dep: bool) { - self.private_dep.fetch_and(private_dep, Ordering::SeqCst); + pub(crate) fn update_and_private_dep(&mut self, private_dep: bool) { + self.private_dep &= private_dep; } pub(crate) fn required_panic_strategy(&self) -> Option { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index bb8f4af8e97ae..912c2f36eb3c8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -19,7 +19,7 @@ use rustc_middle::query::LocalCrate; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; -use rustc_session::cstore::CrateStore; +use rustc_session::cstore::{CrateStore, ExternCrate}; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::symbol::{kw, Symbol}; @@ -290,13 +290,7 @@ provide! { tcx, def_id, other, cdata, cross_crate_inlinable => { cdata.cross_crate_inlinable(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } - is_private_dep => { - // Parallel compiler needs to synchronize type checking and linting (which use this flag) - // so that they happen strictly crate loading. Otherwise, the full list of available - // impls aren't loaded yet. - use std::sync::atomic::Ordering; - cdata.private_dep.load(Ordering::Acquire) - } + is_private_dep => { cdata.private_dep } is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } @@ -305,10 +299,7 @@ provide! { tcx, def_id, other, cdata, is_profiler_runtime => { cdata.root.profiler_runtime } required_panic_strategy => { cdata.root.required_panic_strategy } panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy } - extern_crate => { - let r = *cdata.extern_crate.lock(); - r.map(|c| &*tcx.arena.alloc(c)) - } + extern_crate => { cdata.extern_crate.map(|c| &*tcx.arena.alloc(c)) } is_no_builtins => { cdata.root.no_builtins } symbol_mangling_version => { cdata.root.symbol_mangling_version } reachable_non_generics => { @@ -339,10 +330,7 @@ provide! { tcx, def_id, other, cdata, implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) } - dep_kind => { - let r = *cdata.dep_kind.lock(); - r - } + dep_kind => { cdata.dep_kind } module_children => { tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess)) } @@ -357,8 +345,7 @@ provide! { tcx, def_id, other, cdata, missing_lang_items => { cdata.get_missing_lang_items(tcx) } missing_extern_crate_item => { - let r = matches!(*cdata.extern_crate.borrow(), Some(extern_crate) if !extern_crate.is_direct()); - r + matches!(cdata.extern_crate, Some(extern_crate) if !extern_crate.is_direct()) } used_crate_source => { Lrc::clone(&cdata.source) } @@ -581,6 +568,19 @@ impl CStore { ) -> Span { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } + + pub(crate) fn update_extern_crate(&mut self, cnum: CrateNum, extern_crate: ExternCrate) { + let cmeta = self.get_crate_data_mut(cnum); + if cmeta.update_extern_crate(extern_crate) { + // Propagate the extern crate info to dependencies if it was updated. + let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; + let dependencies = std::mem::take(&mut cmeta.dependencies); + for &dep_cnum in &dependencies { + self.update_extern_crate(dep_cnum, extern_crate); + } + self.get_crate_data_mut(cnum).dependencies = dependencies; + } + } } impl CrateStore for CStore { From 12b92c8a87c041416dfec8cdd61c7f14c1cd9d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 30 Dec 2023 00:00:00 +0000 Subject: [PATCH 19/21] Visit only reachable blocks in MIR lint No functional changes - all checks have been emitted conditionally on block being rechable already. --- compiler/rustc_mir_transform/src/lint.rs | 27 +++++++++++------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index 3940d0ddbf344..e5d607e39b239 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -11,7 +11,6 @@ use rustc_mir_dataflow::{Analysis, ResultsCursor}; use std::borrow::Cow; pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { - let reachable_blocks = traversal::reachable_as_bitset(body); let always_live_locals = &always_storage_live_locals(body); let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) @@ -24,17 +23,18 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { .iterate_to_fixpoint() .into_results_cursor(body); - Lint { + let mut lint = Lint { tcx, when, body, is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(), always_live_locals, - reachable_blocks, maybe_storage_live, maybe_storage_dead, + }; + for (bb, data) in traversal::reachable(body) { + lint.visit_basic_block_data(bb, data); } - .visit_body(body); } struct Lint<'a, 'tcx> { @@ -43,7 +43,6 @@ struct Lint<'a, 'tcx> { body: &'a Body<'tcx>, is_fn_like: bool, always_live_locals: &'a BitSet, - reachable_blocks: BitSet, maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, } @@ -67,7 +66,7 @@ impl<'a, 'tcx> Lint<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { - if self.reachable_blocks.contains(location.block) && context.is_use() { + if context.is_use() { self.maybe_storage_dead.seek_after_primary_effect(location); if self.maybe_storage_dead.get().contains(local) { self.fail(location, format!("use of local {local:?}, which has no storage here")); @@ -78,14 +77,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::StorageLive(local) => { - if self.reachable_blocks.contains(location.block) { - self.maybe_storage_live.seek_before_primary_effect(location); - if self.maybe_storage_live.get().contains(local) { - self.fail( - location, - format!("StorageLive({local:?}) which already has storage here"), - ); - } + self.maybe_storage_live.seek_before_primary_effect(location); + if self.maybe_storage_live.get().contains(local) { + self.fail( + location, + format!("StorageLive({local:?}) which already has storage here"), + ); } } _ => {} @@ -97,7 +94,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { match terminator.kind { TerminatorKind::Return => { - if self.is_fn_like && self.reachable_blocks.contains(location.block) { + if self.is_fn_like { self.maybe_storage_live.seek_after_primary_effect(location); for local in self.maybe_storage_live.get().iter() { if !self.always_live_locals.contains(local) { From a084e063e690697a6ad46545a107228247024393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 1 Jan 2024 00:00:00 +0000 Subject: [PATCH 20/21] Fix validation and linting of injected MIR Reevaluate `body.should_skip()` after updating the MIR phase to ensure that injected MIR is processed correctly. Update a few custom MIR tests that were ill-formed for the injected phase. --- compiler/rustc_mir_transform/src/pass_manager.rs | 12 +++++++++--- .../custom_move_arg.f.CopyProp.panic-unwind.diff | 8 ++++---- tests/mir-opt/copy-prop/custom_move_arg.rs | 6 +++--- .../move_projection.f.CopyProp.panic-unwind.diff | 6 +++--- tests/mir-opt/copy-prop/move_projection.rs | 6 +++--- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 82074f1960d25..f4c572aec128a 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -109,14 +109,15 @@ fn run_passes_inner<'tcx>( phase_change: Option, validate_each: bool, ) { - let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); - let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip(); let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id())); if !body.should_skip() { + let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir; + let lint = tcx.sess.opts.unstable_opts.lint_mir; + for pass in passes { let name = pass.name(); @@ -162,7 +163,12 @@ fn run_passes_inner<'tcx>( body.pass_count = 0; dump_mir_for_phase_change(tcx, body); - if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) { + + let validate = + (validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip()) + || new_phase == MirPhase::Runtime(RuntimePhase::Optimized); + let lint = tcx.sess.opts.unstable_opts.lint_mir & !body.should_skip(); + if validate { validate_body(tcx, body, format!("after phase change to {}", new_phase.name())); } if lint { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff index eb40183c1c954..7ba8530105179 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.panic-unwind.diff @@ -8,14 +8,14 @@ bb0: { - _2 = _1; -- _0 = opaque::(move _1) -> [return: bb1, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb1, unwind continue]; +- _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; ++ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; } bb1: { - _3 = move _2; -- _0 = opaque::(_3) -> [return: bb2, unwind continue]; -+ _0 = opaque::(_1) -> [return: bb2, unwind continue]; +- _0 = opaque::(_3) -> [return: bb2, unwind unreachable]; ++ _0 = opaque::(_1) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index 45913626a8fe5..1ee294fcfd917 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -10,15 +10,15 @@ use core::intrinsics::mir::*; struct NotCopy(bool); // EMIT_MIR custom_move_arg.f.CopyProp.diff -#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +#[custom_mir(dialect = "runtime")] fn f(_1: NotCopy) { mir!({ let _2 = _1; - Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindContinue()) + Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { let _3 = Move(_2); - Call(RET = opaque(_3), ReturnTo(bb2), UnwindContinue()) + Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable()) } bb2 = { Return() diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff index ad3889639e0cf..b2b89968d70b0 100644 --- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.panic-unwind.diff @@ -9,13 +9,13 @@ bb0: { - _2 = _1; - _3 = move (_2.0: u8); -- _0 = opaque::(move _1) -> [return: bb1, unwind continue]; +- _0 = opaque::(move _1) -> [return: bb1, unwind unreachable]; + _3 = (_1.0: u8); -+ _0 = opaque::(_1) -> [return: bb1, unwind continue]; ++ _0 = opaque::(_1) -> [return: bb1, unwind unreachable]; } bb1: { - _0 = opaque::(move _3) -> [return: bb2, unwind continue]; + _0 = opaque::(move _3) -> [return: bb2, unwind unreachable]; } bb2: { diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index f02867814ac0a..f31e82c1f0302 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -11,17 +11,17 @@ fn opaque(_: impl Sized) -> bool { true } struct Foo(u8); -#[custom_mir(dialect = "analysis", phase = "post-cleanup")] +#[custom_mir(dialect = "runtime")] fn f(a: Foo) -> bool { mir!( { let b = a; // This is a move out of a copy, so must become a copy of `a.0`. let c = Move(b.0); - Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindContinue()) + Call(RET = opaque(Move(a)), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { - Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindContinue()) + Call(RET = opaque(Move(c)), ReturnTo(ret), UnwindUnreachable()) } ret = { Return() From df116ec246a795c0940993454643c62e0d849b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 4 Jan 2024 14:24:41 +0100 Subject: [PATCH 21/21] Migrate memory overlap check from validator to lint The check attempts to identify potential undefined behaviour, rather than whether MIR is well-formed. It belongs in the lint not validator. --- .../src/transform/validate.rs | 46 +---------- compiler/rustc_mir_transform/src/dest_prop.rs | 7 -- compiler/rustc_mir_transform/src/lint.rs | 43 +++++++++- ....f.DestinationPropagation.panic-abort.diff | 82 ------------------- ...f.DestinationPropagation.panic-unwind.diff | 82 ------------------- tests/mir-opt/dest-prop/unreachable.rs | 20 ----- tests/ui/mir/lint/assignment-overlap.rs | 19 +++++ tests/ui/mir/lint/call-overlap.rs | 23 ++++++ 8 files changed, 85 insertions(+), 237 deletions(-) delete mode 100644 tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff delete mode 100644 tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff delete mode 100644 tests/mir-opt/dest-prop/unreachable.rs create mode 100644 tests/ui/mir/lint/assignment-overlap.rs create mode 100644 tests/ui/mir/lint/call-overlap.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b249ffb84b3a8..0b73691204d53 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -74,7 +74,6 @@ impl<'tcx> MirPass<'tcx> for Validator { mir_phase, unwind_edge_count: 0, reachable_blocks: traversal::reachable_as_bitset(body), - place_cache: FxHashSet::default(), value_cache: FxHashSet::default(), can_unwind, }; @@ -106,7 +105,6 @@ struct CfgChecker<'a, 'tcx> { mir_phase: MirPhase, unwind_edge_count: usize, reachable_blocks: BitSet, - place_cache: FxHashSet>, value_cache: FxHashSet, // If `false`, then the MIR must not contain `UnwindAction::Continue` or // `TerminatorKind::Resume`. @@ -294,19 +292,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match &statement.kind { - StatementKind::Assign(box (dest, rvalue)) => { - // FIXME(JakobDegen): Check this for all rvalues, not just this one. - if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue { - // The sides of an assignment must not alias. Currently this just checks whether - // the places are identical. - if dest == src { - self.fail( - location, - "encountered `Assign` statement with overlapping memory", - ); - } - } - } StatementKind::AscribeUserType(..) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( @@ -341,7 +326,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, format!("explicit `{kind:?}` is forbidden")); } } - StatementKind::StorageLive(_) + StatementKind::Assign(..) + | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Intrinsic(_) | StatementKind::Coverage(_) @@ -404,10 +390,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } // The call destination place and Operand::Move place used as an argument might be - // passed by a reference to the callee. Consequently they must be non-overlapping - // and cannot be packed. Currently this simply checks for duplicate places. - self.place_cache.clear(); - self.place_cache.insert(destination.as_ref()); + // passed by a reference to the callee. Consequently they cannot be packed. if is_within_packed(self.tcx, &self.body.local_decls, *destination).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( @@ -418,10 +401,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ), ); } - let mut has_duplicates = false; for arg in args { if let Operand::Move(place) = arg { - has_duplicates |= !self.place_cache.insert(place.as_ref()); if is_within_packed(self.tcx, &self.body.local_decls, *place).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( @@ -434,16 +415,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } } - - if has_duplicates { - self.fail( - location, - format!( - "encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}", - terminator.kind, - ), - ); - } } TerminatorKind::Assert { target, unwind, .. } => { self.check_edge(location, *target, EdgeKind::Normal); @@ -1112,17 +1083,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ) } } - // FIXME(JakobDegen): Check this for all rvalues, not just this one. - if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue { - // The sides of an assignment must not alias. Currently this just checks whether - // the places are identical. - if dest == src { - self.fail( - location, - "encountered `Assign` statement with overlapping memory", - ); - } - } } StatementKind::AscribeUserType(..) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 15502adfb5aad..cd80f423466bc 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -133,7 +133,6 @@ use std::collections::hash_map::{Entry, OccupiedEntry}; -use crate::simplify::remove_dead_blocks; use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; @@ -241,12 +240,6 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { apply_merges(body, tcx, &merges, &merged_locals); } - if round_count != 0 { - // Merging can introduce overlap between moved arguments and/or call destination in an - // unreachable code, which validator considers to be ill-formed. - remove_dead_blocks(body); - } - trace!(round_count); } } diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index e5d607e39b239..c0c0a3f5ee649 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -1,6 +1,7 @@ //! This pass statically detects code which has undefined behaviour or is likely to be erroneous. //! It can be used to locate problems in MIR building or optimizations. It assumes that all code //! can be executed, so it has false positives. +use rustc_data_structures::fx::FxHashSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -31,6 +32,7 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { always_live_locals, maybe_storage_live, maybe_storage_dead, + places: Default::default(), }; for (bb, data) in traversal::reachable(body) { lint.visit_basic_block_data(bb, data); @@ -45,6 +47,7 @@ struct Lint<'a, 'tcx> { always_live_locals: &'a BitSet, maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, + places: FxHashSet>, } impl<'a, 'tcx> Lint<'a, 'tcx> { @@ -75,10 +78,22 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { } fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - match statement.kind { + match &statement.kind { + StatementKind::Assign(box (dest, rvalue)) => { + if let Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) = rvalue { + // The sides of an assignment must not alias. Currently this just checks whether + // the places are identical. + if dest == src { + self.fail( + location, + "encountered `Assign` statement with overlapping memory", + ); + } + } + } StatementKind::StorageLive(local) => { self.maybe_storage_live.seek_before_primary_effect(location); - if self.maybe_storage_live.get().contains(local) { + if self.maybe_storage_live.get().contains(*local) { self.fail( location, format!("StorageLive({local:?}) which already has storage here"), @@ -92,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { } fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - match terminator.kind { + match &terminator.kind { TerminatorKind::Return => { if self.is_fn_like { self.maybe_storage_live.seek_after_primary_effect(location); @@ -108,6 +123,28 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { } } } + TerminatorKind::Call { args, destination, .. } => { + // The call destination place and Operand::Move place used as an argument might be + // passed by a reference to the callee. Consequently they must be non-overlapping. + // Currently this simply checks for duplicate places. + self.places.clear(); + self.places.insert(destination.as_ref()); + let mut has_duplicates = false; + for arg in args { + if let Operand::Move(place) = arg { + has_duplicates |= !self.places.insert(place.as_ref()); + } + } + if has_duplicates { + self.fail( + location, + format!( + "encountered overlapping memory in `Move` arguments to `Call` terminator: {:?}", + terminator.kind, + ), + ); + } + } _ => {} } diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff deleted file mode 100644 index 80b5681ad062c..0000000000000 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-abort.diff +++ /dev/null @@ -1,82 +0,0 @@ -- // MIR for `f` before DestinationPropagation -+ // MIR for `f` after DestinationPropagation - - fn f(_1: T) -> () { - debug a => _1; - let mut _0: (); - let _2: T; - let mut _3: bool; - let _4: (); - let mut _5: T; - let mut _6: T; - let _7: (); - let mut _8: T; - let mut _9: T; - scope 1 { -- debug b => _2; -+ debug b => _1; - } - - bb0: { -- StorageLive(_2); -- _2 = _1; -+ nop; -+ nop; - StorageLive(_3); - _3 = const false; -- goto -> bb3; -+ goto -> bb1; - } - - bb1: { -- StorageLive(_4); -- StorageLive(_5); -- _5 = _1; -- StorageLive(_6); -- _6 = _1; -- _4 = g::(_1, _1) -> [return: bb2, unwind unreachable]; -- } -- -- bb2: { -- StorageDead(_6); -- StorageDead(_5); -- StorageDead(_4); -- _0 = const (); -- goto -> bb5; -- } -- -- bb3: { - StorageLive(_7); -- StorageLive(_8); -- _8 = _1; -- StorageLive(_9); -- _9 = _1; -- _7 = g::(_1, _1) -> [return: bb4, unwind unreachable]; -+ nop; -+ nop; -+ nop; -+ nop; -+ _7 = g::(_1, _1) -> [return: bb2, unwind unreachable]; - } - -- bb4: { -- StorageDead(_9); -- StorageDead(_8); -+ bb2: { -+ nop; -+ nop; - StorageDead(_7); - _0 = const (); -- goto -> bb5; -+ goto -> bb3; - } - -- bb5: { -+ bb3: { - StorageDead(_3); -- StorageDead(_2); -+ nop; - return; - } - } - diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff deleted file mode 100644 index eae7dd17b4882..0000000000000 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.panic-unwind.diff +++ /dev/null @@ -1,82 +0,0 @@ -- // MIR for `f` before DestinationPropagation -+ // MIR for `f` after DestinationPropagation - - fn f(_1: T) -> () { - debug a => _1; - let mut _0: (); - let _2: T; - let mut _3: bool; - let _4: (); - let mut _5: T; - let mut _6: T; - let _7: (); - let mut _8: T; - let mut _9: T; - scope 1 { -- debug b => _2; -+ debug b => _1; - } - - bb0: { -- StorageLive(_2); -- _2 = _1; -+ nop; -+ nop; - StorageLive(_3); - _3 = const false; -- goto -> bb3; -+ goto -> bb1; - } - - bb1: { -- StorageLive(_4); -- StorageLive(_5); -- _5 = _1; -- StorageLive(_6); -- _6 = _1; -- _4 = g::(_1, _1) -> [return: bb2, unwind continue]; -- } -- -- bb2: { -- StorageDead(_6); -- StorageDead(_5); -- StorageDead(_4); -- _0 = const (); -- goto -> bb5; -- } -- -- bb3: { - StorageLive(_7); -- StorageLive(_8); -- _8 = _1; -- StorageLive(_9); -- _9 = _1; -- _7 = g::(_1, _1) -> [return: bb4, unwind continue]; -+ nop; -+ nop; -+ nop; -+ nop; -+ _7 = g::(_1, _1) -> [return: bb2, unwind continue]; - } - -- bb4: { -- StorageDead(_9); -- StorageDead(_8); -+ bb2: { -+ nop; -+ nop; - StorageDead(_7); - _0 = const (); -- goto -> bb5; -+ goto -> bb3; - } - -- bb5: { -+ bb3: { - StorageDead(_3); -- StorageDead(_2); -+ nop; - return; - } - } - diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs deleted file mode 100644 index 0bde157ff6185..0000000000000 --- a/tests/mir-opt/dest-prop/unreachable.rs +++ /dev/null @@ -1,20 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// Check that unreachable code is removed after the destination propagation. -// Regression test for issue #105428. -// -// compile-flags: --crate-type=lib -Zmir-opt-level=0 -// compile-flags: -Zmir-enable-passes=+GVN,+SimplifyConstCondition-after-const-prop,+DestinationPropagation - -// EMIT_MIR unreachable.f.DestinationPropagation.diff -pub fn f(a: T) { - let b = a; - if false { - g(a, b); - } else { - g(b, b); - } -} - -#[inline(never)] -pub fn g(_: T, _: T) {} diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs new file mode 100644 index 0000000000000..0e4a11467dc8a --- /dev/null +++ b/tests/ui/mir/lint/assignment-overlap.rs @@ -0,0 +1,19 @@ +// compile-flags: --crate-type=lib -Zlint-mir -Ztreat-err-as-bug +// build-fail +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: encountered `Assign` statement with overlapping memory +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn main() { + mir!( + let a: [u8; 1024]; + { + a = a; + Return() + } + ) +} diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs new file mode 100644 index 0000000000000..df38e901e7328 --- /dev/null +++ b/tests/ui/mir/lint/call-overlap.rs @@ -0,0 +1,23 @@ +// compile-flags: -Zlint-mir -Ztreat-err-as-bug +// build-fail +// failure-status: 101 +// dont-check-compiler-stderr +// error-pattern: encountered overlapping memory in `Move` arguments to `Call` +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +pub fn main() { + mir!( + let a: [u8; 1024]; + { + Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + Return() + } + ) +} + +pub fn f(a: T) -> T { a }