Rollup merge of #135866 - BoxyUwU:dont_pick_fnptr_nested_goals, r=lcnr
Don't pick `T: FnPtr` nested goals as the leaf goal in diagnostics for new solver r? `@lcnr` See `tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.rs` for a minimized example of what code this affects the diagnostics off. The output of running nightly `-Znext-solver` on that test is the following: ``` error[E0277]: the trait bound `Foo: Trait` is not satisfied --> src/lib.rs:14:20 | 14 | requires_trait(Foo); | -------------- ^^^ the trait `FnPtr` is not implemented for `Foo` | | | required by a bound introduced by this call | note: required for `Foo` to implement `Trait` --> src/lib.rs:7:16 | 7 | impl<T: FnPtr> Trait for T {} | ----- ^^^^^ ^ | | | unsatisfied trait bound introduced here note: required by a bound in `requires_trait` --> src/lib.rs:11:22 | 11 | fn requires_trait<T: Trait>(_: T) {} | ^^^^^ required by this bound in `requires_trait` ``` Part of rust-lang/trait-system-refactor-initiative#148
This commit is contained in:
commit
318466aec0
26 changed files with 389 additions and 69 deletions
|
@ -513,8 +513,27 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
|||
_ => ChildMode::PassThrough,
|
||||
};
|
||||
|
||||
let nested_goals = candidate.instantiate_nested_goals(self.span());
|
||||
|
||||
// If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as
|
||||
// an actual candidate, instead we should treat them as if the impl was never considered to
|
||||
// have potentially applied. As if `impl<A, R> Trait for for<..> fn(..A) -> R` was written
|
||||
// instead of `impl<T: FnPtr> Trait for T`.
|
||||
//
|
||||
// We do this as a separate loop so that we do not choose to tell the user about some nested
|
||||
// goal before we encounter a `T: FnPtr` nested goal.
|
||||
for nested_goal in &nested_goals {
|
||||
if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait()
|
||||
&& let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause()
|
||||
&& poly_trait_pred.def_id() == fn_ptr_trait
|
||||
&& let Err(NoSolution) = nested_goal.result()
|
||||
{
|
||||
return ControlFlow::Break(self.obligation.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let mut impl_where_bound_count = 0;
|
||||
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
|
||||
for nested_goal in nested_goals {
|
||||
trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
|
||||
|
||||
let make_obligation = |cause| Obligation {
|
||||
|
@ -605,7 +624,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum ChildMode<'tcx> {
|
||||
// Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
|
||||
// and skip all `GoalSource::Misc`, which represent useless obligations
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
error[E0277]: the trait bound `Foo: Trait` is not satisfied
|
||||
--> $DIR/dont-pick-fnptr-bound-as-leaf.rs:24:20
|
||||
|
|
||||
LL | requires_trait(Foo);
|
||||
| -------------- ^^^ the trait `Trait` is not implemented for `Foo`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `requires_trait`
|
||||
--> $DIR/dont-pick-fnptr-bound-as-leaf.rs:19:22
|
||||
|
|
||||
LL | fn requires_trait<T: Trait>(_: T) {}
|
||||
| ^^^^^ required by this bound in `requires_trait`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,17 @@
|
|||
error[E0277]: the trait bound `Foo: Trait` is not satisfied
|
||||
--> $DIR/dont-pick-fnptr-bound-as-leaf.rs:24:20
|
||||
|
|
||||
LL | requires_trait(Foo);
|
||||
| -------------- ^^^ the trait `Trait` is not implemented for `Foo`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `requires_trait`
|
||||
--> $DIR/dont-pick-fnptr-bound-as-leaf.rs:19:22
|
||||
|
|
||||
LL | fn requires_trait<T: Trait>(_: T) {}
|
||||
| ^^^^^ required by this bound in `requires_trait`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,28 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
// When emitting an error for `Foo: Trait` not holding we attempt to find a nested goal
|
||||
// to give as the reason why the bound does not hold. This test checks that we do not
|
||||
// try to tell the user that `Foo: FnPtr` is unimplemented as that would be confusing.
|
||||
|
||||
#![feature(fn_ptr_trait)]
|
||||
|
||||
use std::marker::FnPtr;
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl<T: FnPtr> Trait for T {}
|
||||
|
||||
struct Foo;
|
||||
|
||||
fn requires_trait<T: Trait>(_: T) {}
|
||||
//~^ NOTE: required by a bound in `requires_trait`
|
||||
//~| NOTE: required by this bound in `requires_trait`
|
||||
|
||||
fn main() {
|
||||
requires_trait(Foo);
|
||||
//~^ ERROR: the trait bound `Foo: Trait` is not satisfied
|
||||
//~| NOTE: the trait `Trait` is not implemented for `Foo`
|
||||
//~| NOTE: required by a bound introduced by this call
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
error[E0277]: the trait bound `K: Hash` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:5
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^ the trait `Hash` is not implemented for `K`
|
||||
|
|
||||
note: required for `HashMap<K, V>` to implement `Index<&K>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:7:12
|
||||
--> $DIR/bad-index-due-to-nested.rs:11:12
|
||||
|
|
||||
LL | impl<K, V> Index<&K> for HashMap<K, V>
|
||||
| ^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
|
@ -18,13 +18,13 @@ LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V
|
|||
| +++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `V: Copy` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:5
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^ the trait `Copy` is not implemented for `V`
|
||||
|
|
||||
note: required for `HashMap<K, V>` to implement `Index<&K>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:7:12
|
||||
--> $DIR/bad-index-due-to-nested.rs:11:12
|
||||
|
|
||||
LL | impl<K, V> Index<&K> for HashMap<K, V>
|
||||
| ^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
|
@ -37,7 +37,7 @@ LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a
|
|||
| +++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:9
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:9
|
||||
|
|
||||
LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| - found this type parameter
|
||||
|
@ -52,7 +52,7 @@ LL | map[&k]
|
|||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-index-due-to-nested.rs:20:5
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:5
|
||||
|
|
||||
LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| - found this type parameter ----- expected `&'a V` because of return type
|
76
tests/ui/typeck/bad-index-due-to-nested.next.stderr
Normal file
76
tests/ui/typeck/bad-index-due-to-nested.next.stderr
Normal file
|
@ -0,0 +1,76 @@
|
|||
error[E0277]: the trait bound `K: Hash` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^ the trait `Hash` is not implemented for `K`
|
||||
|
|
||||
note: required for `HashMap<K, V>` to implement `Index<&K>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:11:12
|
||||
|
|
||||
LL | impl<K, V> Index<&K> for HashMap<K, V>
|
||||
| ^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
LL | where
|
||||
LL | K: Hash,
|
||||
| ---- unsatisfied trait bound introduced here
|
||||
help: consider restricting type parameter `K` with trait `Hash`
|
||||
|
|
||||
LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| +++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `V: Copy` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^ the trait `Copy` is not implemented for `V`
|
||||
|
|
||||
note: required for `HashMap<K, V>` to implement `Index<&K>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:11:12
|
||||
|
|
||||
LL | impl<K, V> Index<&K> for HashMap<K, V>
|
||||
| ^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
...
|
||||
LL | V: Copy,
|
||||
| ---- unsatisfied trait bound introduced here
|
||||
help: consider restricting type parameter `V` with trait `Copy`
|
||||
|
|
||||
LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| +++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:9
|
||||
|
|
||||
LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| - found this type parameter
|
||||
LL | map[k]
|
||||
| ^ expected `&K`, found type parameter `K`
|
||||
|
|
||||
= note: expected reference `&_`
|
||||
found type parameter `_`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | map[&k]
|
||||
| +
|
||||
|
||||
error[E0277]: the trait bound `K: Hash` is not satisfied
|
||||
--> $DIR/bad-index-due-to-nested.rs:24:5
|
||||
|
|
||||
LL | map[k]
|
||||
| ^^^^^^ the trait `Hash` is not implemented for `K`
|
||||
|
|
||||
note: required for `HashMap<K, V>` to implement `Index<&K>`
|
||||
--> $DIR/bad-index-due-to-nested.rs:11:12
|
||||
|
|
||||
LL | impl<K, V> Index<&K> for HashMap<K, V>
|
||||
| ^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
LL | where
|
||||
LL | K: Hash,
|
||||
| ---- unsatisfied trait bound introduced here
|
||||
help: consider restricting type parameter `K` with trait `Hash`
|
||||
|
|
||||
LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
|
@ -1,3 +1,7 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Index;
|
||||
|
@ -21,7 +25,8 @@ fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
|
|||
//~^ ERROR the trait bound `K: Hash` is not satisfied
|
||||
//~| ERROR the trait bound `V: Copy` is not satisfied
|
||||
//~| ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
//[current]~| ERROR mismatched types
|
||||
//[next]~^^^^^ ERROR the trait bound `K: Hash` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
|
||||
--> $DIR/union-derive-eq.rs:13:5
|
||||
--> $DIR/union-derive-eq.rs:21:5
|
||||
|
|
||||
LL | #[derive(Eq)]
|
||||
| -- in this derive macro expansion
|
19
tests/ui/union/union-derive-eq.next.stderr
Normal file
19
tests/ui/union/union-derive-eq.next.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied
|
||||
--> $DIR/union-derive-eq.rs:21:5
|
||||
|
|
||||
LL | #[derive(Eq)]
|
||||
| -- in this derive macro expansion
|
||||
LL | union U2 {
|
||||
LL | a: PartialEqNotEq,
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq`
|
||||
|
|
||||
= note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]`
|
||||
|
|
||||
LL + #[derive(Eq)]
|
||||
LL | struct PartialEqNotEq;
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,9 +1,17 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
#[derive(Eq)] // OK
|
||||
union U1 {
|
||||
a: u8,
|
||||
}
|
||||
|
||||
impl PartialEq for U1 { fn eq(&self, rhs: &Self) -> bool { true } }
|
||||
impl PartialEq for U1 {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
struct PartialEqNotEq;
|
||||
|
@ -13,6 +21,10 @@ union U2 {
|
|||
a: PartialEqNotEq, //~ ERROR the trait bound `PartialEqNotEq: Eq` is not satisfied
|
||||
}
|
||||
|
||||
impl PartialEq for U2 { fn eq(&self, rhs: &Self) -> bool { true } }
|
||||
impl PartialEq for U2 {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-arg.rs:10:23
|
||||
--> $DIR/wf-trait-fn-arg.rs:16:23
|
||||
|
|
||||
LL | fn bar(&self, x: &Bar<Self>);
|
||||
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/wf-trait-fn-arg.rs:7:14
|
||||
--> $DIR/wf-trait-fn-arg.rs:11:15
|
||||
|
|
||||
LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
LL | struct Bar<T: Eq + ?Sized> {
|
||||
| ^^ required by this bound in `Bar`
|
||||
help: consider further restricting `Self`
|
||||
|
|
14
tests/ui/wf/wf-trait-fn-arg.next.stderr
Normal file
14
tests/ui/wf/wf-trait-fn-arg.next.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-arg.rs:16:23
|
||||
|
|
||||
LL | fn bar(&self, x: &Bar<Self>);
|
||||
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
help: consider further restricting `Self`
|
||||
|
|
||||
LL | fn bar(&self, x: &Bar<Self>) where Self: Eq;
|
||||
| ++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,10 +1,16 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
// Check that we test WF conditions for fn arguments in a trait definition.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
struct Bar<T: Eq + ?Sized> {
|
||||
value: Box<T>,
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self, x: &Bar<Self>);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-ret.rs:10:23
|
||||
--> $DIR/wf-trait-fn-ret.rs:15:23
|
||||
|
|
||||
LL | fn bar(&self) -> &Bar<Self>;
|
||||
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/wf-trait-fn-ret.rs:7:14
|
||||
--> $DIR/wf-trait-fn-ret.rs:10:15
|
||||
|
|
||||
LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
LL | struct Bar<T: Eq + ?Sized> {
|
||||
| ^^ required by this bound in `Bar`
|
||||
help: consider further restricting `Self`
|
||||
|
|
14
tests/ui/wf/wf-trait-fn-ret.next.stderr
Normal file
14
tests/ui/wf/wf-trait-fn-ret.next.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-ret.rs:15:23
|
||||
|
|
||||
LL | fn bar(&self) -> &Bar<Self>;
|
||||
| ^^^^^^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
help: consider further restricting `Self`
|
||||
|
|
||||
LL | fn bar(&self) -> &Bar<Self> where Self: Eq;
|
||||
| ++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,10 +1,15 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
// Check that we test WF conditions for fn return types in a trait definition.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
struct Bar<T: Eq + ?Sized> {
|
||||
value: Box<T>,
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) -> &Bar<Self>;
|
||||
|
|
19
tests/ui/wf/wf-trait-fn-where-clause.current.stderr
Normal file
19
tests/ui/wf/wf-trait-fn-where-clause.current.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-where-clause.rs:18:20
|
||||
|
|
||||
LL | Bar<Self>: Copy;
|
||||
| ^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/wf-trait-fn-where-clause.rs:10:15
|
||||
|
|
||||
LL | struct Bar<T: Eq + ?Sized> {
|
||||
| ^^ required by this bound in `Bar`
|
||||
help: consider further restricting `Self`
|
||||
|
|
||||
LL | Bar<Self>: Copy, Self: Eq;
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
14
tests/ui/wf/wf-trait-fn-where-clause.next.stderr
Normal file
14
tests/ui/wf/wf-trait-fn-where-clause.next.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-where-clause.rs:18:20
|
||||
|
|
||||
LL | Bar<Self>: Copy;
|
||||
| ^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
help: consider further restricting `Self`
|
||||
|
|
||||
LL | Bar<Self>: Copy, Self: Eq;
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,17 +1,24 @@
|
|||
// Check that we test WF conditions for fn where clauses in a trait definition.
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
// Check that we test WF conditions for fn where clauses in a trait definition.
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
struct Bar<T: Eq + ?Sized> {
|
||||
value: Box<T>,
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fn bar(&self) where Self: Sized, Bar<Self>: Copy;
|
||||
fn bar(&self)
|
||||
where
|
||||
Self: Sized,
|
||||
Bar<Self>: Copy;
|
||||
//~^ ERROR E0277
|
||||
//
|
||||
// Here, Eq ought to be implemented.
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
error[E0277]: the trait bound `Self: Eq` is not satisfied
|
||||
--> $DIR/wf-trait-fn-where-clause.rs:10:49
|
||||
|
|
||||
LL | fn bar(&self) where Self: Sized, Bar<Self>: Copy;
|
||||
| ^^^^ the trait `Eq` is not implemented for `Self`
|
||||
|
|
||||
note: required by a bound in `Bar`
|
||||
--> $DIR/wf-trait-fn-where-clause.rs:7:14
|
||||
|
|
||||
LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
|
||||
| ^^ required by this bound in `Bar`
|
||||
help: consider further restricting `Self`
|
||||
|
|
||||
LL | fn bar(&self) where Self: Sized, Bar<Self>: Copy, Self: Eq;
|
||||
| ++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,13 +1,16 @@
|
|||
error[E0277]: the trait bound `Bar: Eq` is not satisfied
|
||||
--> $DIR/where-clauses-method-unsatisfied.rs:18:7
|
||||
--> $DIR/where-clauses-method-unsatisfied.rs:24:7
|
||||
|
|
||||
LL | x.equals(&x);
|
||||
| ^^^^^^ the trait `Eq` is not implemented for `Bar`
|
||||
|
|
||||
note: required by a bound in `Foo::<T>::equals`
|
||||
--> $DIR/where-clauses-method-unsatisfied.rs:11:52
|
||||
--> $DIR/where-clauses-method-unsatisfied.rs:16:12
|
||||
|
|
||||
LL | fn equals(&self, u: &Foo<T>) -> bool where T : Eq {
|
||||
LL | fn equals(&self, u: &Foo<T>) -> bool
|
||||
| ------ required by a bound in this associated function
|
||||
LL | where
|
||||
LL | T: Eq,
|
||||
| ^^ required by this bound in `Foo::<T>::equals`
|
||||
help: consider annotating `Bar` with `#[derive(Eq)]`
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
error[E0277]: the trait bound `Bar: Eq` is not satisfied
|
||||
--> $DIR/where-clauses-method-unsatisfied.rs:24:7
|
||||
|
|
||||
LL | x.equals(&x);
|
||||
| ^^^^^^ the trait `Eq` is not implemented for `Bar`
|
||||
|
|
||||
note: required by a bound in `Foo::<T>::equals`
|
||||
--> $DIR/where-clauses-method-unsatisfied.rs:16:12
|
||||
|
|
||||
LL | fn equals(&self, u: &Foo<T>) -> bool
|
||||
| ------ required by a bound in this associated function
|
||||
LL | where
|
||||
LL | T: Eq,
|
||||
| ^^ required by this bound in `Foo::<T>::equals`
|
||||
help: consider annotating `Bar` with `#[derive(Eq)]`
|
||||
|
|
||||
LL + #[derive(Eq)]
|
||||
LL | struct Bar; // does not implement Eq
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,14 +1,20 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
// Test that a where clause attached to a method allows us to add
|
||||
// additional constraints to a parameter out of scope.
|
||||
|
||||
struct Foo<T> {
|
||||
value: T
|
||||
value: T,
|
||||
}
|
||||
|
||||
struct Bar; // does not implement Eq
|
||||
|
||||
impl<T> Foo<T> {
|
||||
fn equals(&self, u: &Foo<T>) -> bool where T : Eq {
|
||||
fn equals(&self, u: &Foo<T>) -> bool
|
||||
where
|
||||
T: Eq,
|
||||
{
|
||||
self.value == u.value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
error[E0277]: the trait bound `Struct: Eq` is not satisfied
|
||||
--> $DIR/where-clauses-unsatisfied.rs:6:10
|
||||
--> $DIR/where-clauses-unsatisfied.rs:15:10
|
||||
|
|
||||
LL | drop(equal(&Struct, &Struct))
|
||||
| ^^^^^ the trait `Eq` is not implemented for `Struct`
|
||||
|
|
||||
note: required by a bound in `equal`
|
||||
--> $DIR/where-clauses-unsatisfied.rs:1:45
|
||||
--> $DIR/where-clauses-unsatisfied.rs:7:8
|
||||
|
|
||||
LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b }
|
||||
LL | fn equal<T>(a: &T, b: &T) -> bool
|
||||
| ----- required by a bound in this function
|
||||
LL | where
|
||||
LL | T: Eq,
|
||||
| ^^ required by this bound in `equal`
|
||||
help: consider annotating `Struct` with `#[derive(Eq)]`
|
||||
|
|
23
tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr
Normal file
23
tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr
Normal file
|
@ -0,0 +1,23 @@
|
|||
error[E0277]: the trait bound `Struct: Eq` is not satisfied
|
||||
--> $DIR/where-clauses-unsatisfied.rs:15:10
|
||||
|
|
||||
LL | drop(equal(&Struct, &Struct))
|
||||
| ^^^^^ the trait `Eq` is not implemented for `Struct`
|
||||
|
|
||||
note: required by a bound in `equal`
|
||||
--> $DIR/where-clauses-unsatisfied.rs:7:8
|
||||
|
|
||||
LL | fn equal<T>(a: &T, b: &T) -> bool
|
||||
| ----- required by a bound in this function
|
||||
LL | where
|
||||
LL | T: Eq,
|
||||
| ^^ required by this bound in `equal`
|
||||
help: consider annotating `Struct` with `#[derive(Eq)]`
|
||||
|
|
||||
LL + #[derive(Eq)]
|
||||
LL | struct Struct;
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,4 +1,13 @@
|
|||
fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b }
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
fn equal<T>(a: &T, b: &T) -> bool
|
||||
where
|
||||
T: Eq,
|
||||
{
|
||||
a == b
|
||||
}
|
||||
|
||||
struct Struct;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue