Skip to content

Actually use the #[do_not_recommend] attribute if present #124708

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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
Expand Down Expand Up @@ -1003,6 +1004,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
--> $DIR/as_expression.rs:57:15
|
LL | SelectInt.check("bar");
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
= help: the trait `AsExpression<Text>` 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`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the new solver does not resolve associated types here yet?

--> $DIR/as_expression.rs:57:21
|
LL | SelectInt.check("bar");
| ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
| |
| required by a bound introduced by this call
|
= help: the trait `AsExpression<Text>` is implemented for `&str`
note: required by a bound in `Foo::check`
--> $DIR/as_expression.rs:48:12
|
LL | fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
| ----- required by a bound in this associated function
LL | where
LL | T: AsExpression<Self::SqlType>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
60 changes: 60 additions & 0 deletions tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
Original file line number Diff line number Diff line change
@@ -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<ST> {
type Expression: Expression<SqlType = ST>;
}

pub struct Text;
pub struct Integer;

pub struct Bound<T>(T);
pub struct SelectInt;

impl Expression for SelectInt {
type SqlType = Integer;
}

impl<T> Expression for Bound<T> {
type SqlType = T;
}

#[do_not_recommend]
impl<T, ST> AsExpression<ST> for T
where
T: Expression<SqlType = ST>,
{
type Expression = T;
}

impl AsExpression<Integer> for i32 {
type Expression = Bound<Integer>;
}

impl AsExpression<Text> for &'_ str {
type Expression = Bound<Text>;
}

trait Foo: Expression + Sized {
fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
where
T: AsExpression<Self::SqlType>,
{
todo!()
}
}

impl<T> Foo for T where T: Expression {}

fn main() {
SelectInt.check("bar");
//[next]~^ ERROR the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
//[current]~^^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
}
Original file line number Diff line number Diff line change
@@ -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<T> 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<T: Foo>() {}
| ^^^ required by this bound in `needs_foo`
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T: Foo>() {}
| ^^^ required by this bound in `needs_foo`
Expand Down
5 changes: 1 addition & 4 deletions tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ trait Foo {}

#[do_not_recommend]
impl<T> Foo for T where T: Send {}
//[current]~^ NOTE required for `*mut ()` to implement `Foo`
//[current]~| NOTE unsatisfied trait bound introduced here

fn needs_foo<T: Foo>() {}
//~^ NOTE required by a bound in `needs_foo`
Expand All @@ -18,6 +16,5 @@ fn needs_foo<T: 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 ()`
}
Original file line number Diff line number Diff line change
@@ -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<T: 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`.
15 changes: 15 additions & 0 deletions tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr
Original file line number Diff line number Diff line change
@@ -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<T: 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`.
21 changes: 21 additions & 0 deletions tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs
Original file line number Diff line number Diff line change
@@ -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<T> Root for T where T: DontRecommend {}

impl<T> DontRecommend for T where T: Other {}

fn needs_root<T: Root>() {}

fn main() {
needs_root::<()>();
//~^ ERROR the trait bound `(): Root` is not satisfied
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Foo> Bar for T {
| --- ^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `stuff`
--> $DIR/feature-gate-do_not_recommend.rs:16:13
|
Expand Down
Loading