Use a proof tree visitor to refine the Obligation for error reporting

This commit is contained in:
Michael Goulet 2024-05-01 16:03:26 -04:00
parent 382d0f73ad
commit 3e03b1b190
32 changed files with 406 additions and 69 deletions

View File

@ -454,7 +454,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
} else { } else {
self.infcx.enter_forall(kind, |kind| { self.infcx.enter_forall(kind, |kind| {
let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
self.add_goal(GoalSource::Misc, goal); self.add_goal(GoalSource::ImplWhereBound, goal);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}) })
} }

View File

@ -1,15 +1,19 @@
use std::mem; use std::mem;
use std::ops::ControlFlow;
use rustc_infer::infer::InferCtxt; use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::solve::MaybeCause; use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::solve::inspect::ProbeKind;
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
use rustc_infer::traits::{ use rustc_infer::traits::{
query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
PredicateObligation, SelectionError, TraitEngine, PredicateObligation, SelectionError, TraitEngine,
}; };
use rustc_middle::ty; use rustc_middle::ty;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use super::eval_ctxt::GenerateProofTree; use super::eval_ctxt::GenerateProofTree;
use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
use super::{Certainty, InferCtxtEvalExt}; use super::{Certainty, InferCtxtEvalExt};
/// A trait engine using the new trait solver. /// A trait engine using the new trait solver.
@ -133,9 +137,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
.collect(); .collect();
errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError { errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
root_obligation: obligation.clone(), obligation: find_best_leaf_obligation(infcx, &obligation),
code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
obligation, root_obligation: obligation,
})); }));
errors errors
@ -192,8 +196,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
fn fulfillment_error_for_no_solution<'tcx>( fn fulfillment_error_for_no_solution<'tcx>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
obligation: PredicateObligation<'tcx>, root_obligation: PredicateObligation<'tcx>,
) -> FulfillmentError<'tcx> { ) -> FulfillmentError<'tcx> {
let obligation = find_best_leaf_obligation(infcx, &root_obligation);
let code = match obligation.predicate.kind().skip_binder() { let code = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
FulfillmentErrorCode::ProjectionError( FulfillmentErrorCode::ProjectionError(
@ -213,14 +219,14 @@ fn fulfillment_error_for_no_solution<'tcx>(
} }
ty::PredicateKind::Subtype(pred) => { ty::PredicateKind::Subtype(pred) => {
let (a, b) = infcx.enter_forall_and_leak_universe( let (a, b) = infcx.enter_forall_and_leak_universe(
obligation.predicate.kind().rebind((pred.a, pred.b)), root_obligation.predicate.kind().rebind((pred.a, pred.b)),
); );
let expected_found = ExpectedFound::new(true, a, b); let expected_found = ExpectedFound::new(true, a, b);
FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found)) FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found))
} }
ty::PredicateKind::Coerce(pred) => { ty::PredicateKind::Coerce(pred) => {
let (a, b) = infcx.enter_forall_and_leak_universe( let (a, b) = infcx.enter_forall_and_leak_universe(
obligation.predicate.kind().rebind((pred.a, pred.b)), root_obligation.predicate.kind().rebind((pred.a, pred.b)),
); );
let expected_found = ExpectedFound::new(false, a, b); let expected_found = ExpectedFound::new(false, a, b);
FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found)) FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found))
@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>(
bug!("unexpected goal: {obligation:?}") bug!("unexpected goal: {obligation:?}")
} }
}; };
FulfillmentError { root_obligation: obligation.clone(), code, obligation }
FulfillmentError { obligation, code, root_obligation }
} }
fn fulfillment_error_for_stalled<'tcx>( fn fulfillment_error_for_stalled<'tcx>(
@ -258,5 +265,135 @@ fn fulfillment_error_for_stalled<'tcx>(
} }
}); });
FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation } FulfillmentError {
obligation: find_best_leaf_obligation(infcx, &obligation),
code,
root_obligation: obligation,
}
}
struct BestObligation<'tcx> {
obligation: PredicateObligation<'tcx>,
}
impl<'tcx> BestObligation<'tcx> {
fn with_derived_obligation(
&mut self,
derive_obligation: impl FnOnce(&mut Self) -> PredicateObligation<'tcx>,
and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
) -> <Self as ProofTreeVisitor<'tcx>>::Result {
let derived_obligation = derive_obligation(self);
let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
let res = and_then(self);
self.obligation = old_obligation;
res
}
}
impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
type Result = ControlFlow<PredicateObligation<'tcx>>;
fn span(&self) -> rustc_span::Span {
self.obligation.cause.span
}
fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
let candidates = goal.candidates();
// FIXME: Throw out candidates that have no failing WC and >1 failing misc goal.
// HACK:
if self.obligation.recursion_depth > 3 {
return ControlFlow::Break(self.obligation.clone());
}
let [candidate] = candidates.as_slice() else {
return ControlFlow::Break(self.obligation.clone());
};
// 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
// for normalizes-to.
let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
return ControlFlow::Break(self.obligation.clone());
};
let tcx = goal.infcx().tcx;
let mut impl_where_bound_count = 0;
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
if matches!(nested_goal.source(), GoalSource::ImplWhereBound) {
impl_where_bound_count += 1;
} else {
continue;
}
// Skip nested goals that hold.
if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
continue;
}
self.with_derived_obligation(
|self_| {
let mut cause = self_.obligation.cause.clone();
cause = match candidate.kind() {
ProbeKind::TraitCandidate {
source: CandidateSource::Impl(impl_def_id),
result: _,
} => {
let idx = impl_where_bound_count - 1;
if let Some((_, span)) = tcx
.predicates_of(impl_def_id)
.instantiate_identity(tcx)
.iter()
.nth(idx)
{
cause.derived_cause(parent_trait_pred, |derived| {
traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause {
derived,
impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: Some(idx),
span,
},
))
})
} else {
cause
}
}
ProbeKind::TraitCandidate {
source: CandidateSource::BuiltinImpl(..),
result: _,
} => {
cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation)
}
_ => cause,
};
Obligation {
cause,
param_env: nested_goal.goal().param_env,
predicate: nested_goal.goal().predicate,
recursion_depth: self_.obligation.recursion_depth + 1,
}
},
|self_| self_.visit_goal(&nested_goal),
)?;
}
ControlFlow::Break(self.obligation.clone())
}
}
fn find_best_leaf_obligation<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> PredicateObligation<'tcx> {
let obligation = infcx.resolve_vars_if_possible(obligation.clone());
infcx
.visit_proof_tree(
obligation.clone().into(),
&mut BestObligation { obligation: obligation.clone() },
)
.break_value()
.unwrap_or(obligation)
} }

View File

@ -11,7 +11,7 @@ error[E0282]: type annotations needed
--> $DIR/opaques.rs:13:20 --> $DIR/opaques.rs:13:20
| |
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> { LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
| ^ cannot infer type for struct `Container<T, T>` | ^ cannot infer type for associated type `<T as Trait<T>>::Assoc`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -2,9 +2,14 @@ error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/issue-20605.rs:6:17 --> $DIR/issue-20605.rs:6:17
| |
LL | for item in *things { *item = 0 } LL | for item in *things { *item = 0 }
| ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
| |
= help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>` = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
= note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
help: consider mutably borrowing here
|
LL | for item in &mut *things { *item = 0 }
| ++++
error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:6:17 --> $DIR/issue-20605.rs:6:17

View File

@ -23,7 +23,20 @@ error[E0283]: type annotations needed
LL | impls_indirect_leak::<Box<_>>(); LL | impls_indirect_leak::<Box<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak`
| |
= note: cannot satisfy `for<'a> Box<_>: IndirectLeak<'a>` note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found
--> $DIR/leak-check-in-selection-3.rs:9:1
|
LL | impl Leak<'_> for Box<u32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl Leak<'static> for Box<u16> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required for `Box<_>` to implement `for<'a> IndirectLeak<'a>`
--> $DIR/leak-check-in-selection-3.rs:23:23
|
LL | impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
| -------- ^^^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `impls_indirect_leak` note: required by a bound in `impls_indirect_leak`
--> $DIR/leak-check-in-selection-3.rs:25:27 --> $DIR/leak-check-in-selection-3.rs:25:27
| |

View File

@ -1,18 +1,26 @@
error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely error: future cannot be sent between threads safely
--> $DIR/auto-with-drop_tracking_mir.rs:25:13 --> $DIR/auto-with-drop_tracking_mir.rs:25:13
| |
LL | is_send(foo()); LL | is_send(foo());
| ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely | ^^^^^ future returned by `foo` is not `Send`
| |
| required by a bound introduced by this call
| |
= help: the trait `Send` is not implemented for `impl Future<Output = ()>` = help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send`
note: future is not `Send` as this value is used across an await
--> $DIR/auto-with-drop_tracking_mir.rs:16:11
|
LL | let x = &NotSync;
| - has type `&NotSync` which is not `Send`
LL | bar().await;
| ^^^^^ await occurs here, with `x` maybe used later
note: required by a bound in `is_send` note: required by a bound in `is_send`
--> $DIR/auto-with-drop_tracking_mir.rs:24:24 --> $DIR/auto-with-drop_tracking_mir.rs:24:24
| |
LL | fn is_send(_: impl Send) {} LL | fn is_send(_: impl Send) {}
| ^^^^ required by this bound in `is_send` | ^^^^ required by this bound in `is_send`
help: consider dereferencing here
|
LL | is_send(*foo());
| +
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -23,5 +23,5 @@ async fn bar() {}
fn main() { fn main() {
fn is_send(_: impl Send) {} fn is_send(_: impl Send) {}
is_send(foo()); is_send(foo());
//[fail]~^ ERROR `impl Future<Output = ()>` cannot be sent between threads safely //[fail]~^ ERROR future cannot be sent between threads safely
} }

View File

@ -13,5 +13,5 @@ fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
fn main() { fn main() {
foo::<fn() -> str, _>(None, ()); foo::<fn() -> str, _>(None, ());
//~^ expected a `Fn<_>` closure, found `fn() -> str` //~^ the size for values of type `str` cannot be known at compilation time
} }

View File

@ -1,10 +1,11 @@
error[E0277]: expected a `Fn<_>` closure, found `fn() -> str` error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/builtin-fn-must-return-sized.rs:15:11 --> $DIR/builtin-fn-must-return-sized.rs:15:11
| |
LL | foo::<fn() -> str, _>(None, ()); LL | foo::<fn() -> str, _>(None, ());
| ^^^^^^^^^^^ expected an `Fn<_>` closure, found `fn() -> str` | ^^^^^^^^^^^ doesn't have a size known at compile-time
| |
= help: the trait `Fn<_>` is not implemented for `fn() -> str` = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>`
= note: required because it appears within the type `fn() -> str`
note: required by a bound in `foo` note: required by a bound in `foo`
--> $DIR/builtin-fn-must-return-sized.rs:10:11 --> $DIR/builtin-fn-must-return-sized.rs:10:11
| |

View File

@ -1,12 +1,12 @@
error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>` error[E0119]: conflicting implementations of trait `Trait` for type `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/coherence-fulfill-overflow.rs:12:1 --> $DIR/coherence-fulfill-overflow.rs:12:1
| |
LL | impl<T: ?Sized + TwoW> Trait for W<T> {} LL | impl<T: ?Sized + TwoW> Trait for W<T> {}
| ------------------------------------- first implementation here | ------------------------------------- first implementation here
LL | impl<T: ?Sized + TwoW> Trait for T {} LL | impl<T: ?Sized + TwoW> Trait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>>`
| |
= note: overflow evaluating the requirement `W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>>>>>>>>: TwoW` = note: overflow evaluating the requirement `W<W<W<W<W<W<W<W<W<W<W<W<W<W<_>>>>>>>>>>>>>>: TwoW`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`) = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`)
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -1,9 +1,16 @@
error[E0275]: overflow evaluating the requirement `W<_>: Trait` error[E0275]: overflow evaluating the requirement `_: Sized`
--> $DIR/fixpoint-exponential-growth.rs:33:13 --> $DIR/fixpoint-exponential-growth.rs:33:13
| |
LL | impls::<W<_>>(); LL | impls::<W<_>>();
| ^^^^ | ^^^^
| |
note: required for `W<(W<_>, W<_>)>` to implement `Trait`
--> $DIR/fixpoint-exponential-growth.rs:23:12
|
LL | impl<T, U> Trait for W<(W<T>, W<U>)>
| - ^^^^^ ^^^^^^^^^^^^^^^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `impls` note: required by a bound in `impls`
--> $DIR/fixpoint-exponential-growth.rs:30:13 --> $DIR/fixpoint-exponential-growth.rs:30:13
| |

View File

@ -61,7 +61,7 @@ where
// entering the cycle from `A` fails, but would work if we were to use the cache // entering the cycle from `A` fails, but would work if we were to use the cache
// result of `B<X>`. // result of `B<X>`.
impls_trait::<A<X>, _, _, _>(); impls_trait::<A<X>, _, _, _>();
//~^ ERROR the trait bound `A<X>: Trait<_, _, _>` is not satisfied //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
} }
fn main() { fn main() {

View File

@ -1,10 +1,21 @@
error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied
--> $DIR/incompleteness-unstable-result.rs:63:19 --> $DIR/incompleteness-unstable-result.rs:63:19
| |
LL | impls_trait::<A<X>, _, _, _>(); LL | impls_trait::<A<X>, _, _, _>();
| ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>` | ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A<X>: Trait<_, _, _>`
| |
= help: the trait `Trait<U, V, D>` is implemented for `A<T>` = help: the following other types implement trait `IncompleteGuidance<T, V>`:
<T as IncompleteGuidance<U, i16>>
<T as IncompleteGuidance<U, i8>>
<T as IncompleteGuidance<U, u8>>
note: required for `A<X>` to implement `Trait<_, _, u8>`
--> $DIR/incompleteness-unstable-result.rs:32:50
|
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
| ^^^^^^^^^^^^^^ ^^^^
LL | where
LL | T: IncompleteGuidance<U, V>,
| ------------------------ unsatisfied trait bound introduced here
note: required by a bound in `impls_trait` note: required by a bound in `impls_trait`
--> $DIR/incompleteness-unstable-result.rs:51:28 --> $DIR/incompleteness-unstable-result.rs:51:28
| |

View File

@ -4,6 +4,22 @@ error[E0275]: overflow evaluating the requirement `(): Trait`
LL | impls_trait::<()>(); LL | impls_trait::<()>();
| ^^ | ^^
| |
note: required for `()` to implement `Inductive`
--> $DIR/double-cycle-inductive-coinductive.rs:12:16
|
LL | impl<T: Trait> Inductive for T {}
| ----- ^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `Trait`
--> $DIR/double-cycle-inductive-coinductive.rs:9:34
|
LL | impl<T: Inductive + Coinductive> Trait for T {}
| --------- ^^^^^ ^
| |
| unsatisfied trait bound introduced here
= note: 2 redundant requirements hidden
= note: required for `()` to implement `Trait`
note: required by a bound in `impls_trait` note: required by a bound in `impls_trait`
--> $DIR/double-cycle-inductive-coinductive.rs:17:19 --> $DIR/double-cycle-inductive-coinductive.rs:17:19
| |
@ -16,6 +32,22 @@ error[E0275]: overflow evaluating the requirement `(): TraitRev`
LL | impls_trait_rev::<()>(); LL | impls_trait_rev::<()>();
| ^^ | ^^
| |
note: required for `()` to implement `CoinductiveRev`
--> $DIR/double-cycle-inductive-coinductive.rs:27:19
|
LL | impl<T: TraitRev> CoinductiveRev for T {}
| -------- ^^^^^^^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `TraitRev`
--> $DIR/double-cycle-inductive-coinductive.rs:21:40
|
LL | impl<T: CoinductiveRev + InductiveRev> TraitRev for T {}
| -------------- ^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
= note: 2 redundant requirements hidden
= note: required for `()` to implement `TraitRev`
note: required by a bound in `impls_trait_rev` note: required by a bound in `impls_trait_rev`
--> $DIR/double-cycle-inductive-coinductive.rs:29:23 --> $DIR/double-cycle-inductive-coinductive.rs:29:23
| |

View File

@ -4,6 +4,16 @@ error[E0275]: overflow evaluating the requirement `W<_>: Trait`
LL | impls_trait::<W<_>>(); LL | impls_trait::<W<_>>();
| ^^^^ | ^^^^
| |
note: required for `W<W<_>>` to implement `Trait`
--> $DIR/inductive-fixpoint-hang.rs:22:17
|
LL | impl<T: ?Sized> Trait for W<W<T>>
| ^^^^^ ^^^^^^^
LL | where
LL | W<T>: Trait,
| ----- unsatisfied trait bound introduced here
= note: 3 redundant requirements hidden
= note: required for `W<W<W<W<W<_>>>>>` to implement `Trait`
note: required by a bound in `impls_trait` note: required by a bound in `impls_trait`
--> $DIR/inductive-fixpoint-hang.rs:28:19 --> $DIR/inductive-fixpoint-hang.rs:28:19
| |

View File

@ -42,5 +42,5 @@ fn main() {
//~^ ERROR overflow evaluating the requirement `(): A` //~^ ERROR overflow evaluating the requirement `(): A`
impls_ar::<()>(); impls_ar::<()>();
//~^ ERROR overflow evaluating the requirement `(): AR` //~^ ERROR overflow evaluating the requirement `(): CR`
} }

View File

@ -4,18 +4,57 @@ error[E0275]: overflow evaluating the requirement `(): A`
LL | impls_a::<()>(); LL | impls_a::<()>();
| ^^ | ^^
| |
note: required for `()` to implement `B`
--> $DIR/inductive-not-on-stack.rs:22:12
|
LL | impl<T: A> B for T {}
| - ^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `A`
--> $DIR/inductive-not-on-stack.rs:21:16
|
LL | impl<T: B + C> A for T {}
| - ^ ^
| |
| unsatisfied trait bound introduced here
= note: 2 redundant requirements hidden
= note: required for `()` to implement `A`
note: required by a bound in `impls_a` note: required by a bound in `impls_a`
--> $DIR/inductive-not-on-stack.rs:25:15 --> $DIR/inductive-not-on-stack.rs:25:15
| |
LL | fn impls_a<T: A>() {} LL | fn impls_a<T: A>() {}
| ^ required by this bound in `impls_a` | ^ required by this bound in `impls_a`
error[E0275]: overflow evaluating the requirement `(): AR` error[E0275]: overflow evaluating the requirement `(): CR`
--> $DIR/inductive-not-on-stack.rs:44:16 --> $DIR/inductive-not-on-stack.rs:44:16
| |
LL | impls_ar::<()>(); LL | impls_ar::<()>();
| ^^ | ^^
| |
note: required for `()` to implement `AR`
--> $DIR/inductive-not-on-stack.rs:34:18
|
LL | impl<T: CR + BR> AR for T {}
| -- ^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `BR`
--> $DIR/inductive-not-on-stack.rs:35:13
|
LL | impl<T: AR> BR for T {}
| -- ^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `CR`
--> $DIR/inductive-not-on-stack.rs:36:13
|
LL | impl<T: BR> CR for T {}
| -- ^^ ^
| |
| unsatisfied trait bound introduced here
= note: 1 redundant requirement hidden
= note: required for `()` to implement `AR`
note: required by a bound in `impls_ar` note: required by a bound in `impls_ar`
--> $DIR/inductive-not-on-stack.rs:38:16 --> $DIR/inductive-not-on-stack.rs:38:16
| |

View File

@ -35,5 +35,5 @@ fn impls_a<T: A>() {}
fn main() { fn main() {
impls_a::<()>(); impls_a::<()>();
//~^ ERROR overflow evaluating the requirement `(): A` //~^ ERROR overflow evaluating the requirement `(): C`
} }

View File

@ -1,9 +1,37 @@
error[E0275]: overflow evaluating the requirement `(): A` error[E0275]: overflow evaluating the requirement `(): C`
--> $DIR/mixed-cycles-1.rs:37:15 --> $DIR/mixed-cycles-1.rs:37:15
| |
LL | impls_a::<()>(); LL | impls_a::<()>();
| ^^ | ^^
| |
note: required for `()` to implement `CInd`
--> $DIR/mixed-cycles-1.rs:28:21
|
LL | impl<T: ?Sized + C> CInd for T {}
| - ^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `B`
--> $DIR/mixed-cycles-1.rs:31:28
|
LL | impl<T: ?Sized + CInd + C> B for T {}
| ---- ^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `BInd`
--> $DIR/mixed-cycles-1.rs:23:21
|
LL | impl<T: ?Sized + B> BInd for T {}
| - ^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `A`
--> $DIR/mixed-cycles-1.rs:30:28
|
LL | impl<T: ?Sized + BInd + C> A for T {}
| ---- ^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `impls_a` note: required by a bound in `impls_a`
--> $DIR/mixed-cycles-1.rs:34:15 --> $DIR/mixed-cycles-1.rs:34:15
| |

View File

@ -28,5 +28,5 @@ fn impls_a<T: A>() {}
fn main() { fn main() {
impls_a::<()>(); impls_a::<()>();
//~^ ERROR overflow evaluating the requirement `(): A` //~^ ERROR overflow evaluating the requirement `(): B`
} }

View File

@ -1,9 +1,32 @@
error[E0275]: overflow evaluating the requirement `(): A` error[E0275]: overflow evaluating the requirement `(): B`
--> $DIR/mixed-cycles-2.rs:30:15 --> $DIR/mixed-cycles-2.rs:30:15
| |
LL | impls_a::<()>(); LL | impls_a::<()>();
| ^^ | ^^
| |
note: required for `()` to implement `BInd`
--> $DIR/mixed-cycles-2.rs:22:21
|
LL | impl<T: ?Sized + B> BInd for T {}
| - ^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required for `()` to implement `B`
--> $DIR/mixed-cycles-2.rs:25:24
|
LL | impl<T: ?Sized + BInd> B for T {}
| ---- ^ ^
| |
| unsatisfied trait bound introduced here
= note: 1 redundant requirement hidden
= note: required for `()` to implement `BInd`
note: required for `()` to implement `A`
--> $DIR/mixed-cycles-2.rs:24:28
|
LL | impl<T: ?Sized + BInd + B> A for T {}
| ---- ^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `impls_a` note: required by a bound in `impls_a`
--> $DIR/mixed-cycles-2.rs:27:15 --> $DIR/mixed-cycles-2.rs:27:15
| |

View File

@ -25,7 +25,7 @@ fn foo<T: Foo>() {
// //
// https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 // https://github.com/rust-lang/trait-system-refactor-initiative/issues/76
require_bar::<T>(); require_bar::<T>();
//~^ ERROR the trait bound `T: Bar` is not satisfied //~^ ERROR type mismatch resolving `<T as Foo>::Assoc == i32`
} }
fn main() {} fn main() {}

View File

@ -1,19 +1,25 @@
error[E0277]: the trait bound `T: Bar` is not satisfied error[E0271]: type mismatch resolving `<T as Foo>::Assoc == i32`
--> $DIR/param-candidate-shadows-project.rs:27:19 --> $DIR/param-candidate-shadows-project.rs:27:19
| |
LL | require_bar::<T>(); LL | require_bar::<T>();
| ^ the trait `Bar` is not implemented for `T` | ^ type mismatch resolving `<T as Foo>::Assoc == i32`
| |
note: types differ
--> $DIR/param-candidate-shadows-project.rs:10:18
|
LL | type Assoc = i32;
| ^^^
note: required for `T` to implement `Bar`
--> $DIR/param-candidate-shadows-project.rs:13:9
|
LL | impl<T> Bar for T where T: Foo<Assoc = i32> {}
| ^^^ ^ ----------- unsatisfied trait bound introduced here
note: required by a bound in `require_bar` note: required by a bound in `require_bar`
--> $DIR/param-candidate-shadows-project.rs:15:19 --> $DIR/param-candidate-shadows-project.rs:15:19
| |
LL | fn require_bar<T: Bar>() {} LL | fn require_bar<T: Bar>() {}
| ^^^ required by this bound in `require_bar` | ^^^ required by this bound in `require_bar`
help: consider further restricting this bound
|
LL | fn foo<T: Foo + Bar>() {
| +++++
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0271`.

View File

@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
fn transmute<A, B>(x: A) -> B { fn transmute<A, B>(x: A) -> B {
foo::<A, B, dyn Trait<A = A, B = B>>(x) foo::<A, B, dyn Trait<A = A, B = B>>(x)
//~^ ERROR the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
} }
fn foo<A, B, T: ?Sized>(x: T::A) -> B fn foo<A, B, T: ?Sized>(x: T::A) -> B

View File

@ -1,9 +1,10 @@
error[E0277]: the trait bound `dyn Trait<A = A, B = B>: Trait` is not satisfied error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
--> $DIR/more-object-bound.rs:12:5 --> $DIR/more-object-bound.rs:12:5
| |
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x) LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait<A = A, B = B>` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
| |
= note: required because it appears within the type `dyn Trait<A = A, B = B>`
note: required by a bound in `foo` note: required by a bound in `foo`
--> $DIR/more-object-bound.rs:18:8 --> $DIR/more-object-bound.rs:18:8
| |
@ -12,11 +13,7 @@ LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
LL | where LL | where
LL | T: Trait<B = B>, LL | T: Trait<B = B>,
| ^^^^^^^^^^^^ required by this bound in `foo` | ^^^^^^^^^^^^ required by this bound in `foo`
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | fn transmute<A, B>(x: A) -> B where dyn Trait<A = A, B = B>: Trait {
| ++++++++++++++++++++++++++++++++++++
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0271`.

View File

@ -24,7 +24,7 @@ fn needs_bar<T: Bar>() {}
fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() { fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
needs_bar::<T>(); needs_bar::<T>();
//~^ ERROR type annotations needed: cannot satisfy `T: Bar` //~^ ERROR type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
} }
fn main() {} fn main() {}

View File

@ -1,11 +1,14 @@
error[E0283]: type annotations needed: cannot satisfy `T: Bar` error[E0284]: type annotations needed: cannot satisfy `<T as Foo>::Assoc == i32`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17
| |
LL | needs_bar::<T>(); LL | needs_bar::<T>();
| ^ | ^ cannot satisfy `<T as Foo>::Assoc == i32`
| |
= note: cannot satisfy `T: Bar` note: required for `T` to implement `Bar`
= help: the trait `Bar` is implemented for `T` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9
|
LL | impl<T> Bar for T where T: Foo<Assoc = i32> {}
| ^^^ ^ ----------- unsatisfied trait bound introduced here
note: required by a bound in `needs_bar` note: required by a bound in `needs_bar`
--> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17 --> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17
| |
@ -14,4 +17,4 @@ LL | fn needs_bar<T: Bar>() {}
error: aborting due to 1 previous error error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`. For more information about this error, try `rustc --explain E0284`.

View File

@ -11,9 +11,9 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
pub fn copy_any<T>(t: &T) -> T { pub fn copy_any<T>(t: &T) -> T {
copy::<dyn Setup<From=T>>(t) copy::<dyn Setup<From=T>>(t)
//~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed //~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
//~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
//~| ERROR mismatched types //~| ERROR mismatched types
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed //~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
//~| ERROR the trait bound `T: Copy` is not satisfied
// FIXME(-Znext-solver): These error messages are horrible and some of them // FIXME(-Znext-solver): These error messages are horrible and some of them
// are even simple fallout from previous error. // are even simple fallout from previous error.

View File

@ -1,18 +1,19 @@
error[E0277]: the trait bound `dyn Setup<From = T>: Setup` is not satisfied error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
--> $DIR/object-unsafety.rs:12:12 --> $DIR/object-unsafety.rs:12:12
| |
LL | copy::<dyn Setup<From=T>>(t) LL | copy::<dyn Setup<From=T>>(t)
| ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup<From = T>` | ^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup<From = T>: Setup`
| |
= note: required because it appears within the type `dyn Setup<From = T>`
note: required by a bound in `copy` note: required by a bound in `copy`
--> $DIR/object-unsafety.rs:7:12 --> $DIR/object-unsafety.rs:7:12
| |
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
| ^^^^^ required by this bound in `copy` | ^^^^^ required by this bound in `copy`
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement help: consider restricting type parameter `T`
| |
LL | pub fn copy_any<T>(t: &T) -> T where dyn Setup<From = T>: Setup { LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
| ++++++++++++++++++++++++++++++++ | +++++++++++++++++++
error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
--> $DIR/object-unsafety.rs:12:31 --> $DIR/object-unsafety.rs:12:31

View File

@ -15,5 +15,5 @@ fn impls<T: Trait>() {}
fn main() { fn main() {
impls::<W<_>>(); impls::<W<_>>();
//~^ ERROR overflow evaluating the requirement `W<_>: Trait` //~^ ERROR overflow evaluating the requirement `_: Sized`
} }

View File

@ -1,9 +1,16 @@
error[E0275]: overflow evaluating the requirement `W<_>: Trait` error[E0275]: overflow evaluating the requirement `_: Sized`
--> $DIR/exponential-trait-goals.rs:17:13 --> $DIR/exponential-trait-goals.rs:17:13
| |
LL | impls::<W<_>>(); LL | impls::<W<_>>();
| ^^^^ | ^^^^
| |
note: required for `W<(W<_>, W<_>)>` to implement `Trait`
--> $DIR/exponential-trait-goals.rs:7:12
|
LL | impl<T, U> Trait for W<(W<T>, W<U>)>
| - ^^^^^ ^^^^^^^^^^^^^^^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `impls` note: required by a bound in `impls`
--> $DIR/exponential-trait-goals.rs:14:13 --> $DIR/exponential-trait-goals.rs:14:13
| |

View File

@ -5,6 +5,15 @@ LL | impls_trait::<Four<Four<Four<Four<()>>>>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`) = help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`)
note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>>>` to implement `Trait`
--> $DIR/global-cache.rs:12:16
|
LL | impl<T: Trait> Trait for Inc<T> {}
| ----- ^^^^^ ^^^^^^
| |
| unsatisfied trait bound introduced here
= note: 3 redundant requirements hidden
= note: required for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<()>>>>>>>>>>>>>>>>` to implement `Trait`
note: required by a bound in `impls_trait` note: required by a bound in `impls_trait`
--> $DIR/global-cache.rs:15:19 --> $DIR/global-cache.rs:15:19
| |