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 d693bac90dc..20dfb5e6642 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 @@ -422,6 +422,7 @@ fn report_selection_error( ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); + let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation); // Let's use the root obligation as the main message, when we care about the // most general case ("X doesn't implement Pattern<'_>") over the case that @@ -1003,6 +1004,31 @@ fn report_selection_error( err.emit() } + fn apply_do_not_recommend( + &self, + mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + obligation: &'_ mut PredicateObligation<'tcx>, + ) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> { + let mut base_cause = obligation.cause.code().clone(); + loop { + if let ObligationCauseCode::ImplDerived(ref c) = base_cause { + if self.tcx.has_attr(c.impl_or_alias_def_id, sym::do_not_recommend) { + let code = (*c.derived.parent_code).clone(); + obligation.cause.map_code(|_| code); + obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); + trait_predicate = c.derived.parent_trait_pred.clone(); + } + } + if let Some((parent_cause, _parent_pred)) = base_cause.parent() { + base_cause = parent_cause.clone(); + } else { + break; + } + } + + trait_predicate + } + fn emit_specialized_closure_kind_error( &self, obligation: &PredicateObligation<'tcx>, diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr new file mode 100644 index 00000000000..41f222e46a7 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&str: AsExpression` is not satisfied + --> $DIR/as_expression.rs:57:15 + | +LL | SelectInt.check("bar"); + | ^^^^^ the trait `AsExpression` is not implemented for `&str` + | + = help: the trait `AsExpression` is implemented for `&str` + = help: for that trait implementation, expected `Text`, found `Integer` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr new file mode 100644 index 00000000000..47acf5b968b --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&str: AsExpression<::SqlType>` is not satisfied + --> $DIR/as_expression.rs:57:21 + | +LL | SelectInt.check("bar"); + | ----- ^^^^^ the trait `AsExpression<::SqlType>` is not implemented for `&str` + | | + | required by a bound introduced by this call + | + = help: the trait `AsExpression` is implemented for `&str` +note: required by a bound in `Foo::check` + --> $DIR/as_expression.rs:48:12 + | +LL | fn check(&self, _: T) -> ::SqlType>>::Expression + | ----- required by a bound in this associated function +LL | where +LL | T: AsExpression, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs new file mode 100644 index 00000000000..9cdc193d386 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -0,0 +1,60 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +pub trait Expression { + type SqlType; +} + +pub trait AsExpression { + type Expression: Expression; +} + +pub struct Text; +pub struct Integer; + +pub struct Bound(T); +pub struct SelectInt; + +impl Expression for SelectInt { + type SqlType = Integer; +} + +impl Expression for Bound { + type SqlType = T; +} + +#[do_not_recommend] +impl AsExpression for T +where + T: Expression, +{ + type Expression = T; +} + +impl AsExpression for i32 { + type Expression = Bound; +} + +impl AsExpression for &'_ str { + type Expression = Bound; +} + +trait Foo: Expression + Sized { + fn check(&self, _: T) -> ::SqlType>>::Expression + where + T: AsExpression, + { + todo!() + } +} + +impl Foo for T where T: Expression {} + +fn main() { + SelectInt.check("bar"); + //[next]~^ ERROR the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //[current]~^^ ERROR the trait bound `&str: AsExpression` is not satisfied +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr index a4d4b7b359e..729cb5694e2 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr @@ -1,16 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:19:17 + --> $DIR/simple.rs:17:17 | LL | needs_foo::<*mut ()>(); - | ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo` + | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | -note: required for `*mut ()` to implement `Foo` - --> $DIR/simple.rs:10:9 - | -LL | impl Foo for T where T: Send {} - | ^^^ ^ ---- unsatisfied trait bound introduced here note: required by a bound in `needs_foo` - --> $DIR/simple.rs:14:17 + --> $DIR/simple.rs:12:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr index 1341ca8175a..729cb5694e2 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `*mut (): Foo` is not satisfied - --> $DIR/simple.rs:19:17 + --> $DIR/simple.rs:17:17 | LL | needs_foo::<*mut ()>(); | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | note: required by a bound in `needs_foo` - --> $DIR/simple.rs:14:17 + --> $DIR/simple.rs:12:17 | LL | fn needs_foo() {} | ^^^ required by this bound in `needs_foo` diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs index 15ff80ae4d9..6fb15b90138 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs @@ -8,8 +8,6 @@ trait Foo {} #[do_not_recommend] impl Foo for T where T: Send {} -//[current]~^ NOTE required for `*mut ()` to implement `Foo` -//[current]~| NOTE unsatisfied trait bound introduced here fn needs_foo() {} //~^ NOTE required by a bound in `needs_foo` @@ -18,6 +16,5 @@ fn needs_foo() {} fn main() { needs_foo::<*mut ()>(); //~^ ERROR the trait bound `*mut (): Foo` is not satisfied - //[current]~| NOTE the trait `Send` is not implemented for `*mut ()` - //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()` + //~| NOTE the trait `Foo` is not implemented for `*mut ()` } diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr new file mode 100644 index 00000000000..41a10a61e1d --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): Root` is not satisfied + --> $DIR/stacked.rs:19:18 + | +LL | needs_root::<()>(); + | ^^ the trait `Root` is not implemented for `()` + | +note: required by a bound in `needs_root` + --> $DIR/stacked.rs:16:18 + | +LL | fn needs_root() {} + | ^^^^ required by this bound in `needs_root` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr new file mode 100644 index 00000000000..41a10a61e1d --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): Root` is not satisfied + --> $DIR/stacked.rs:19:18 + | +LL | needs_root::<()>(); + | ^^ the trait `Root` is not implemented for `()` + | +note: required by a bound in `needs_root` + --> $DIR/stacked.rs:16:18 + | +LL | fn needs_root() {} + | ^^^^ required by this bound in `needs_root` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs new file mode 100644 index 00000000000..695660d3596 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs @@ -0,0 +1,21 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +trait Root {} +trait DontRecommend {} +trait Other {} + +#[do_not_recommend] +impl Root for T where T: DontRecommend {} + +impl DontRecommend for T where T: Other {} + +fn needs_root() {} + +fn main() { + needs_root::<()>(); + //~^ ERROR the trait bound `(): Root` is not satisfied +} diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index 284dacf7000..e6f199445bf 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -2,18 +2,8 @@ error[E0277]: the trait bound `u8: Bar` is not satisfied --> $DIR/feature-gate-do_not_recommend.rs:19:11 | LL | stuff(1u8); - | ----- ^^^ the trait `Foo` is not implemented for `u8`, which is required by `u8: Bar` - | | - | required by a bound introduced by this call + | ^^^ the trait `Bar` is not implemented for `u8` | - = help: the trait `Foo` is implemented for `i32` -note: required for `u8` to implement `Bar` - --> $DIR/feature-gate-do_not_recommend.rs:13:14 - | -LL | impl Bar for T { - | --- ^^^ ^ - | | - | unsatisfied trait bound introduced here note: required by a bound in `stuff` --> $DIR/feature-gate-do_not_recommend.rs:16:13 |