Apply nested goals certainty to InspectGoals for normalizes-to
This commit is contained in:
@@ -120,15 +120,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
|
||||
fn visit_goal(&mut self, inspect_goal: &InspectGoal<'_, 'tcx>) {
|
||||
// No need to walk into goal subtrees that certainly hold, since they
|
||||
// wouldn't then be stalled on an infer var.
|
||||
// FIXME: We also walk into normalizes-to goals since their certainty
|
||||
// is forced to `Certainty::Yes` since they pass down ambiguous subgoals
|
||||
// to their parent.
|
||||
if inspect_goal.result() == Ok(Certainty::Yes)
|
||||
&& !matches!(
|
||||
inspect_goal.goal().predicate.kind().skip_binder(),
|
||||
ty::PredicateKind::NormalizesTo(_)
|
||||
)
|
||||
{
|
||||
if inspect_goal.result() == Ok(Certainty::Yes) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
|
||||
@@ -20,7 +21,7 @@ use rustc_middle::{bug, ty};
|
||||
use rustc_next_trait_solver::resolve::eager_resolve_vars;
|
||||
use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state};
|
||||
use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::Span;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::solve::delegate::SolverDelegate;
|
||||
@@ -60,19 +61,21 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
|
||||
/// Relate the `term` with the new `unconstrained_term` created
|
||||
/// when computing the proof tree for this `NormalizesTo` goals.
|
||||
/// This handles nested obligations.
|
||||
fn constrain(
|
||||
self,
|
||||
fn constrain_and(
|
||||
&self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
f: impl FnOnce(&ObligationCtxt<'_, 'tcx>),
|
||||
) -> Result<Certainty, NoSolution> {
|
||||
infcx
|
||||
.at(&ObligationCause::dummy_with_span(span), param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, self.term, self.unconstrained_term)
|
||||
.map_err(|_| NoSolution)
|
||||
.and_then(|InferOk { value: (), obligations }| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligations(obligations);
|
||||
ocx.eq(
|
||||
&ObligationCause::dummy_with_span(span),
|
||||
param_env,
|
||||
self.term,
|
||||
self.unconstrained_term,
|
||||
)?;
|
||||
f(&ocx);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if errors.is_empty() {
|
||||
Ok(Certainty::Yes)
|
||||
@@ -81,7 +84,6 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,11 +162,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
||||
let () =
|
||||
instantiate_canonical_state(infcx, span, param_env, &mut orig_values, self.final_state);
|
||||
|
||||
if let Some(term_hack) = self.goal.normalizes_to_term_hack {
|
||||
if let Some(term_hack) = &self.goal.normalizes_to_term_hack {
|
||||
// FIXME: We ignore the expected term of `NormalizesTo` goals
|
||||
// when computing the result of its candidates. This is
|
||||
// scuffed.
|
||||
let _ = term_hack.constrain(infcx, span, param_env);
|
||||
let _ = term_hack.constrain_and(infcx, span, param_env, |_| {});
|
||||
}
|
||||
|
||||
instantiated_goals
|
||||
@@ -240,13 +242,39 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
||||
// building their proof tree, the expected term was unconstrained, but when
|
||||
// instantiating the candidate it is already constrained to the result of another
|
||||
// candidate.
|
||||
let proof_tree = infcx
|
||||
.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None).1);
|
||||
let normalizes_to_term_hack = NormalizesToTermHack { term, unconstrained_term };
|
||||
let (proof_tree, nested_goals_result) = infcx.probe(|_| {
|
||||
// Here, if we have any nested goals, then we make sure to apply them
|
||||
// considering the constrained RHS, and pass the resulting certainty to
|
||||
// `InspectGoal::new` so that the goal has the right result (and maintains
|
||||
// the impression that we don't do this normalizes-to infer hack at all).
|
||||
let (nested, proof_tree) =
|
||||
infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None);
|
||||
let proof_tree = proof_tree.unwrap();
|
||||
let nested_goals_result = nested.and_then(|(nested, _)| {
|
||||
normalizes_to_term_hack.constrain_and(
|
||||
infcx,
|
||||
span,
|
||||
proof_tree.uncanonicalized_goal.param_env,
|
||||
|ocx| {
|
||||
ocx.register_obligations(nested.0.into_iter().map(|(_, goal)| {
|
||||
Obligation::new(
|
||||
infcx.tcx,
|
||||
ObligationCause::dummy_with_span(span),
|
||||
goal.param_env,
|
||||
goal.predicate,
|
||||
)
|
||||
}));
|
||||
},
|
||||
)
|
||||
});
|
||||
(proof_tree, nested_goals_result)
|
||||
});
|
||||
InspectGoal::new(
|
||||
infcx,
|
||||
self.goal.depth + 1,
|
||||
proof_tree.unwrap(),
|
||||
Some(NormalizesToTermHack { term, unconstrained_term }),
|
||||
proof_tree,
|
||||
Some((normalizes_to_term_hack, nested_goals_result)),
|
||||
source,
|
||||
)
|
||||
}
|
||||
@@ -393,20 +421,21 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
depth: usize,
|
||||
root: inspect::GoalEvaluation<TyCtxt<'tcx>>,
|
||||
normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
|
||||
term_hack_and_nested_certainty: Option<(
|
||||
NormalizesToTermHack<'tcx>,
|
||||
Result<Certainty, NoSolution>,
|
||||
)>,
|
||||
source: GoalSource,
|
||||
) -> Self {
|
||||
let infcx = <&SolverDelegate<'tcx>>::from(infcx);
|
||||
|
||||
let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root;
|
||||
// If there's a normalizes-to goal, AND the evaluation result with the result of
|
||||
// constraining the normalizes-to RHS and computing the nested goals.
|
||||
let result = evaluation.result.and_then(|ok| {
|
||||
if let Some(term_hack) = normalizes_to_term_hack {
|
||||
infcx
|
||||
.probe(|_| term_hack.constrain(infcx, DUMMY_SP, uncanonicalized_goal.param_env))
|
||||
.map(|certainty| ok.value.certainty.and(certainty))
|
||||
} else {
|
||||
Ok(ok.value.certainty)
|
||||
}
|
||||
let nested_goals_certainty =
|
||||
term_hack_and_nested_certainty.map_or(Ok(Certainty::Yes), |(_, c)| c)?;
|
||||
Ok(ok.value.certainty.and(nested_goals_certainty))
|
||||
});
|
||||
|
||||
InspectGoal {
|
||||
@@ -416,7 +445,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
|
||||
goal: eager_resolve_vars(infcx, uncanonicalized_goal),
|
||||
result,
|
||||
evaluation_kind: evaluation.kind,
|
||||
normalizes_to_term_hack,
|
||||
normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n),
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
|
||||
--> $DIR/auto-trait-selection-freeze.rs:19:5
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/auto-trait-selection-freeze.rs:19:16
|
||||
|
|
||||
LL | if false { is_trait(foo()) } else { Default::default() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
|
||||
| ^^^^^^^^ ----- type must be known at this point
|
||||
| |
|
||||
| cannot infer type of the type parameter `T` declared on the function `is_trait`
|
||||
|
|
||||
= note: cannot satisfy `_: Trait<_>`
|
||||
note: required by a bound in `is_trait`
|
||||
--> $DIR/auto-trait-selection-freeze.rs:11:16
|
||||
|
|
||||
LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
|
||||
| ^^^^^^^^ required by this bound in `is_trait`
|
||||
help: consider specifying the generic arguments
|
||||
|
|
||||
LL | if false { is_trait::<T, U>(foo()) } else { Default::default() }
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
|
||||
--> $DIR/auto-trait-selection.rs:15:5
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/auto-trait-selection.rs:15:16
|
||||
|
|
||||
LL | if false { is_trait(foo()) } else { Default::default() }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _`
|
||||
| ^^^^^^^^ ----- type must be known at this point
|
||||
| |
|
||||
| cannot infer type of the type parameter `T` declared on the function `is_trait`
|
||||
|
|
||||
= note: cannot satisfy `_: Trait<_>`
|
||||
note: required by a bound in `is_trait`
|
||||
--> $DIR/auto-trait-selection.rs:7:16
|
||||
|
|
||||
LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
|
||||
| ^^^^^^^^ required by this bound in `is_trait`
|
||||
help: consider specifying the generic arguments
|
||||
|
|
||||
LL | if false { is_trait::<T, U>(foo()) } else { Default::default() }
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
|
||||
@@ -25,7 +25,7 @@ LL | type LineStream<'c, 'd> = impl Stream;
|
||||
|
|
||||
= note: `LineStream` must be used in combination with a concrete type within the same impl
|
||||
|
||||
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
|
||||
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to ()`
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:43
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
|
||||
@@ -29,7 +29,7 @@ impl X for Y {
|
||||
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
//~^ ERROR method `line_stream` is not a member of trait `X`
|
||||
//[current]~^^ ERROR `()` is not a future
|
||||
//[next]~^^^ ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
|
||||
//[next]~^^^ ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to ()`
|
||||
//[next]~| ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
|
||||
//[next]~| ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `impl Sized == _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:19:17
|
||||
error[E0284]: type annotations needed: cannot normalize `build<_>::{opaque#0}`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:20:5
|
||||
|
|
||||
LL | let (x,) = (build(x),);
|
||||
| ^^^^^^^^ cannot satisfy `impl Sized == _`
|
||||
LL | build(x)
|
||||
| ^^^^^^^^ cannot normalize `build<_>::{opaque#0}`
|
||||
|
||||
error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:30:6
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
fn build<T>(x: T) -> impl Sized {
|
||||
//[current]~^ ERROR cannot resolve opaque type
|
||||
let (x,) = (build(x),);
|
||||
//[next]~^ ERROR type annotations needed
|
||||
build(x)
|
||||
//[next]~^ ERROR type annotations needed: cannot normalize `build<_>::{opaque#0}`
|
||||
}
|
||||
|
||||
// Opaque<T> = (Opaque<T>,)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `_ == A`
|
||||
--> $DIR/two_tait_defining_each_other2.rs:12:8
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/two_tait_defining_each_other2.rs:12:11
|
||||
|
|
||||
LL | fn muh(x: A) -> B {
|
||||
| ^ cannot satisfy `_ == A`
|
||||
| ^ cannot infer type
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
||||
@@ -10,7 +10,7 @@ trait Foo {}
|
||||
|
||||
#[define_opaque(A, B)]
|
||||
fn muh(x: A) -> B {
|
||||
//[next]~^ ERROR: cannot satisfy `_ == A`
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
x // B's hidden type is A (opaquely)
|
||||
//[current]~^ ERROR opaque type's hidden type cannot be another opaque type
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ fn main() {
|
||||
}
|
||||
|
||||
fn weird0() -> impl Sized + !Sized {}
|
||||
//~^ ERROR type mismatch resolving
|
||||
//~^ ERROR the trait bound `(): !Sized` is not satisfied
|
||||
fn weird1() -> impl !Sized + Sized {}
|
||||
//~^ ERROR type mismatch resolving
|
||||
//~^ ERROR the trait bound `(): !Sized` is not satisfied
|
||||
fn weird2() -> impl !Sized {}
|
||||
//~^ ERROR type mismatch resolving
|
||||
//~^ ERROR the trait bound `(): !Sized` is not satisfied
|
||||
//~| ERROR the size for values of type
|
||||
|
||||
@@ -7,23 +7,23 @@ LL | fn weird2() -> impl !Sized {}
|
||||
= help: the trait `Sized` is not implemented for `impl !Sized`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0271]: type mismatch resolving `impl !Sized + Sized == ()`
|
||||
error[E0277]: the trait bound `(): !Sized` is not satisfied
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:15:16
|
||||
|
|
||||
LL | fn weird0() -> impl Sized + !Sized {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ types differ
|
||||
| ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
|
||||
|
||||
error[E0271]: type mismatch resolving `impl !Sized + Sized == ()`
|
||||
error[E0277]: the trait bound `(): !Sized` is not satisfied
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:17:16
|
||||
|
|
||||
LL | fn weird1() -> impl !Sized + Sized {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ types differ
|
||||
| ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
|
||||
|
||||
error[E0271]: type mismatch resolving `impl !Sized == ()`
|
||||
error[E0277]: the trait bound `(): !Sized` is not satisfied
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:19:16
|
||||
|
|
||||
LL | fn weird2() -> impl !Sized {}
|
||||
| ^^^^^^^^^^^ types differ
|
||||
| ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
|
||||
|
||||
error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
|
||||
--> $DIR/opaque-type-unsatisfied-bound.rs:12:13
|
||||
@@ -41,5 +41,4 @@ LL | fn consume(_: impl Trait) {}
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
#![feature(negative_bounds, unboxed_closures)]
|
||||
|
||||
fn produce() -> impl !Fn<(u32,)> {}
|
||||
//~^ ERROR type mismatch resolving
|
||||
//~^ ERROR the trait bound `(): !Fn(u32)` is not satisfied
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
error[E0271]: type mismatch resolving `impl !Fn<(u32,)> == ()`
|
||||
error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied
|
||||
--> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17
|
||||
|
|
||||
LL | fn produce() -> impl !Fn<(u32,)> {}
|
||||
| ^^^^^^^^^^^^^^^^ types differ
|
||||
| ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
|
||||
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
|
||||
--> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
|
||||
|
|
||||
LL | needs_send::<Foo>();
|
||||
| ^^^ cannot satisfy `Foo == _`
|
||||
| ^^^
|
||||
|
|
||||
= note: cannot satisfy `Foo: Send`
|
||||
note: required by a bound in `needs_send`
|
||||
--> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
|
||||
|
|
||||
LL | fn needs_send<T: Send>() {}
|
||||
| ^^^^ required by this bound in `needs_send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `Foo == _`
|
||||
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
|
||||
--> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
|
||||
|
|
||||
LL | needs_send::<Foo>();
|
||||
| ^^^ cannot satisfy `Foo == _`
|
||||
| ^^^
|
||||
|
|
||||
= note: cannot satisfy `Foo: Send`
|
||||
note: required by a bound in `needs_send`
|
||||
--> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
|
||||
|
|
||||
LL | fn needs_send<T: Send>() {}
|
||||
| ^^^^ required by this bound in `needs_send`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
|
||||
@@ -14,7 +14,7 @@ fn needs_send<T: Send>() {}
|
||||
#[define_opaque(Foo)]
|
||||
fn test(_: Foo) {
|
||||
needs_send::<Foo>();
|
||||
//~^ ERROR type annotations needed: cannot satisfy `Foo == _`
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
|
||||
#[define_opaque(Foo)]
|
||||
|
||||
@@ -7,7 +7,7 @@ LL | impl<In, Out> Trait<Bar, In> for Out {
|
||||
LL | impl<In, Out> Trait<(), In> for Out {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `Bar == _`
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-84660-unsoundness.rs:24:37
|
||||
|
|
||||
LL | fn convert(_i: In) -> Self::Out {
|
||||
@@ -16,9 +16,9 @@ LL | |
|
||||
LL | |
|
||||
LL | | unreachable!();
|
||||
LL | | }
|
||||
| |_____^ cannot satisfy `Bar == _`
|
||||
| |_____^ cannot infer type
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0119, E0284.
|
||||
Some errors have detailed explanations: E0119, E0282.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
||||
|
||||
@@ -22,7 +22,7 @@ impl<In, Out> Trait<Bar, In> for Out {
|
||||
type Out = Out;
|
||||
#[define_opaque(Bar)]
|
||||
fn convert(_i: In) -> Self::Out {
|
||||
//[next]~^ ERROR: type annotations needed: cannot satisfy `Bar == _`
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
//[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/nested-tait-inference2.rs:20:5
|
||||
|
|
||||
LL | ()
|
||||
| ^^ cannot satisfy `impl Foo<FooX> == ()`
|
||||
| ^^ cannot infer type
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
|
||||
@@ -18,7 +18,7 @@ impl Foo<u32> for () {}
|
||||
fn foo() -> impl Foo<FooX> {
|
||||
//[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
()
|
||||
//[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
Reference in New Issue
Block a user