From 0f5c2215ad3a6e5475c87ddd6416b9a13437aaa8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 16 Feb 2026 17:13:47 +1100 Subject: [PATCH 1/2] Regression test for "unstable" traits in force-unstable builds --- tests/ui/traits/auxiliary/force_unstable.rs | 7 ++++ .../traits/nightly-only-unstable.force.stderr | 36 +++++++++++++++++++ .../nightly-only-unstable.normal.stderr | 36 +++++++++++++++++++ tests/ui/traits/nightly-only-unstable.rs | 36 +++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 tests/ui/traits/auxiliary/force_unstable.rs create mode 100644 tests/ui/traits/nightly-only-unstable.force.stderr create mode 100644 tests/ui/traits/nightly-only-unstable.normal.stderr create mode 100644 tests/ui/traits/nightly-only-unstable.rs diff --git a/tests/ui/traits/auxiliary/force_unstable.rs b/tests/ui/traits/auxiliary/force_unstable.rs new file mode 100644 index 000000000000..ce71e1241f9c --- /dev/null +++ b/tests/ui/traits/auxiliary/force_unstable.rs @@ -0,0 +1,7 @@ +//@ edition: 2024 +//@ compile-flags: -Zforce-unstable-if-unmarked + +// Auxiliary crate that uses `-Zforce-unstable-if-unmarked` to export an +// "unstable" trait. + +pub trait ForeignTrait {} diff --git a/tests/ui/traits/nightly-only-unstable.force.stderr b/tests/ui/traits/nightly-only-unstable.force.stderr new file mode 100644 index 000000000000..b24e2867a304 --- /dev/null +++ b/tests/ui/traits/nightly-only-unstable.force.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `(): LocalTrait` is not satisfied + --> $DIR/nightly-only-unstable.rs:25:21 + | +LL | use_local_trait(()); + | --------------- ^^ the nightly-only, unstable trait `LocalTrait` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/nightly-only-unstable.rs:14:1 + | +LL | trait LocalTrait {} + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `use_local_trait` + --> $DIR/nightly-only-unstable.rs:16:28 + | +LL | fn use_local_trait(_: impl LocalTrait) {} + | ^^^^^^^^^^ required by this bound in `use_local_trait` + +error[E0277]: the trait bound `(): ForeignTrait` is not satisfied + --> $DIR/nightly-only-unstable.rs:31:23 + | +LL | use_foreign_trait(()); + | ----------------- ^^ the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `use_foreign_trait` + --> $DIR/nightly-only-unstable.rs:20:30 + | +LL | fn use_foreign_trait(_: impl force_unstable::ForeignTrait) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `use_foreign_trait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/nightly-only-unstable.normal.stderr b/tests/ui/traits/nightly-only-unstable.normal.stderr new file mode 100644 index 000000000000..51b896cfefdf --- /dev/null +++ b/tests/ui/traits/nightly-only-unstable.normal.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `(): LocalTrait` is not satisfied + --> $DIR/nightly-only-unstable.rs:25:21 + | +LL | use_local_trait(()); + | --------------- ^^ the trait `LocalTrait` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/nightly-only-unstable.rs:14:1 + | +LL | trait LocalTrait {} + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `use_local_trait` + --> $DIR/nightly-only-unstable.rs:16:28 + | +LL | fn use_local_trait(_: impl LocalTrait) {} + | ^^^^^^^^^^ required by this bound in `use_local_trait` + +error[E0277]: the trait bound `(): ForeignTrait` is not satisfied + --> $DIR/nightly-only-unstable.rs:31:23 + | +LL | use_foreign_trait(()); + | ----------------- ^^ the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `use_foreign_trait` + --> $DIR/nightly-only-unstable.rs:20:30 + | +LL | fn use_foreign_trait(_: impl force_unstable::ForeignTrait) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `use_foreign_trait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/nightly-only-unstable.rs b/tests/ui/traits/nightly-only-unstable.rs new file mode 100644 index 000000000000..c3fa5df944b6 --- /dev/null +++ b/tests/ui/traits/nightly-only-unstable.rs @@ -0,0 +1,36 @@ +//@ revisions: normal force +//@ edition: 2024 +//@ aux-crate: force_unstable=force_unstable.rs +//@[force] compile-flags: -Zforce-unstable-if-unmarked + +#![feature(rustc_private)] + +// Regression test for . +// +// When building a crate with `-Zforce-unstable-if-unmarked` (e.g. the compiler or stdlib), +// it's unhelpful to mention that a not-implemented trait is unstable, because that will +// be true of every local and foreign trait that isn't explicitly marked stable. + +trait LocalTrait {} + +fn use_local_trait(_: impl LocalTrait) {} +//~^ NOTE required by a bound in `use_local_trait` +//~| NOTE required by this bound in `use_local_trait` + +fn use_foreign_trait(_: impl force_unstable::ForeignTrait) {} +//~^ NOTE required by a bound in `use_foreign_trait` +//~| NOTE required by this bound in `use_foreign_trait` + +fn main() { + use_local_trait(()); + //~^ ERROR the trait bound `(): LocalTrait` is not satisfied + //[normal]~| NOTE the trait `LocalTrait` is not implemented for `()` + //[force]~| NOTE the nightly-only, unstable trait `LocalTrait` is not implemented for `()` + //~| NOTE required by a bound introduced by this call + + use_foreign_trait(()); + //~^ ERROR the trait bound `(): ForeignTrait` is not satisfied + //[normal]~| NOTE the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` + //[force]~| NOTE the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` + //~| NOTE required by a bound introduced by this call +} From 125e69e862b79a2943a68c7dd03bea224073cdf1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 16 Feb 2026 17:05:13 +1100 Subject: [PATCH 2/2] Suppress unstable-trait notes under `-Zforce-unstable-if-unmarked` --- .../src/error_reporting/traits/suggestions.rs | 18 ++++++++++-------- .../traits/nightly-only-unstable.force.stderr | 4 ++-- tests/ui/traits/nightly-only-unstable.rs | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 63fd61cb257b..434c8caae7dc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5608,15 +5608,17 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>( None => String::new(), }; if let ty::PredicatePolarity::Positive = trait_predicate.polarity() { + // If the trait in question is unstable, mention that fact in the diagnostic. + // But if we're building with `-Zforce-unstable-if-unmarked` then _any_ trait + // not explicitly marked stable is considered unstable, so the extra text is + // unhelpful noise. See . + let mention_unstable = !tcx.sess.opts.unstable_opts.force_unstable_if_unmarked + && try { tcx.lookup_stability(trait_predicate.def_id())?.level.is_stable() } + == Some(false); + let unstable = if mention_unstable { "nightly-only, unstable " } else { "" }; + format!( - "{pre_message}the {}trait `{}` is not implemented for{desc} `{}`", - if tcx.lookup_stability(trait_predicate.def_id()).map(|s| s.level.is_stable()) - == Some(false) - { - "nightly-only, unstable " - } else { - "" - }, + "{pre_message}the {unstable}trait `{}` is not implemented for{desc} `{}`", trait_predicate.print_modifiers_and_trait_path(), tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path), ) diff --git a/tests/ui/traits/nightly-only-unstable.force.stderr b/tests/ui/traits/nightly-only-unstable.force.stderr index b24e2867a304..c1b5a45dc827 100644 --- a/tests/ui/traits/nightly-only-unstable.force.stderr +++ b/tests/ui/traits/nightly-only-unstable.force.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): LocalTrait` is not satisfied --> $DIR/nightly-only-unstable.rs:25:21 | LL | use_local_trait(()); - | --------------- ^^ the nightly-only, unstable trait `LocalTrait` is not implemented for `()` + | --------------- ^^ the trait `LocalTrait` is not implemented for `()` | | | required by a bound introduced by this call | @@ -21,7 +21,7 @@ error[E0277]: the trait bound `(): ForeignTrait` is not satisfied --> $DIR/nightly-only-unstable.rs:31:23 | LL | use_foreign_trait(()); - | ----------------- ^^ the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` + | ----------------- ^^ the trait `ForeignTrait` is not implemented for `()` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/nightly-only-unstable.rs b/tests/ui/traits/nightly-only-unstable.rs index c3fa5df944b6..94f300074390 100644 --- a/tests/ui/traits/nightly-only-unstable.rs +++ b/tests/ui/traits/nightly-only-unstable.rs @@ -25,12 +25,12 @@ fn main() { use_local_trait(()); //~^ ERROR the trait bound `(): LocalTrait` is not satisfied //[normal]~| NOTE the trait `LocalTrait` is not implemented for `()` - //[force]~| NOTE the nightly-only, unstable trait `LocalTrait` is not implemented for `()` + //[force]~| NOTE the trait `LocalTrait` is not implemented for `()` //~| NOTE required by a bound introduced by this call use_foreign_trait(()); //~^ ERROR the trait bound `(): ForeignTrait` is not satisfied //[normal]~| NOTE the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` - //[force]~| NOTE the nightly-only, unstable trait `ForeignTrait` is not implemented for `()` + //[force]~| NOTE the trait `ForeignTrait` is not implemented for `()` //~| NOTE required by a bound introduced by this call }