Implement do_not_recommend in the new solver
This commit is contained in:
parent
d7ea27808d
commit
b33599485b
5 changed files with 68 additions and 1 deletions
|
@ -518,7 +518,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
// RFC 2397
|
// RFC 2397
|
||||||
gated!(
|
gated!(
|
||||||
do_not_recommend, Normal, template!(Word), WarnFollowing,
|
do_not_recommend, Normal, template!(Word), WarnFollowing,
|
||||||
EncodeCrossCrate::No, experimental!(do_not_recommend)
|
EncodeCrossCrate::Yes, experimental!(do_not_recommend)
|
||||||
),
|
),
|
||||||
|
|
||||||
// `#[cfi_encoding = ""]`
|
// `#[cfi_encoding = ""]`
|
||||||
|
|
|
@ -11,6 +11,7 @@ use rustc_infer::traits::{
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use super::eval_ctxt::GenerateProofTree;
|
use super::eval_ctxt::GenerateProofTree;
|
||||||
use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
|
use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||||
|
@ -320,6 +321,14 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
||||||
return ControlFlow::Break(self.obligation.clone());
|
return ControlFlow::Break(self.obligation.clone());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Don't walk into impls that have `do_not_recommend`.
|
||||||
|
if let ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } =
|
||||||
|
candidate.kind()
|
||||||
|
&& goal.infcx().tcx.has_attr(impl_def_id, sym::do_not_recommend)
|
||||||
|
{
|
||||||
|
return ControlFlow::Break(self.obligation.clone());
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Could we extract a trait ref from a projection here too?
|
// FIXME: Could we extract a trait ref from a projection here too?
|
||||||
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
|
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
|
||||||
// for normalizes-to.
|
// for normalizes-to.
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0277]: the trait bound `*mut (): Foo` is not satisfied
|
||||||
|
--> $DIR/simple.rs:19:17
|
||||||
|
|
|
||||||
|
LL | needs_foo::<*mut ()>();
|
||||||
|
| ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo`
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
LL | fn needs_foo<T: Foo>() {}
|
||||||
|
| ^^^ required by this bound in `needs_foo`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0277]: the trait bound `*mut (): Foo` is not satisfied
|
||||||
|
--> $DIR/simple.rs:19: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
|
||||||
|
|
|
||||||
|
LL | fn needs_foo<T: Foo>() {}
|
||||||
|
| ^^^ required by this bound in `needs_foo`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
23
tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
Normal file
23
tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
#![feature(do_not_recommend)]
|
||||||
|
|
||||||
|
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`
|
||||||
|
//~| NOTE required by this bound in `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 ()`
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue