bye bye assemble_candidates_via_self_ty
This commit is contained in:
parent
fb4bca04fa
commit
0d71860368
@ -271,12 +271,40 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, G>,
|
goal: Goal<'tcx, G>,
|
||||||
) -> Vec<Candidate<'tcx>> {
|
) -> Vec<Candidate<'tcx>> {
|
||||||
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
|
let dummy_candidate = |this: &mut EvalCtxt<'_, 'tcx>, certainty| {
|
||||||
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
|
let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
|
||||||
return vec![ambig];
|
let result = this.evaluate_added_goals_and_make_canonical_response(certainty).unwrap();
|
||||||
|
let mut dummy_probe = this.inspect.new_probe();
|
||||||
|
dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) });
|
||||||
|
this.inspect.finish_probe(dummy_probe);
|
||||||
|
vec![Candidate { source, result }]
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(normalized_self_ty) =
|
||||||
|
self.try_normalize_ty(goal.param_env, goal.predicate.self_ty())
|
||||||
|
else {
|
||||||
|
debug!("overflow while evaluating self type");
|
||||||
|
return dummy_candidate(self, Certainty::OVERFLOW);
|
||||||
|
};
|
||||||
|
|
||||||
|
if normalized_self_ty.is_ty_var() {
|
||||||
|
debug!("self type has been normalized to infer");
|
||||||
|
return dummy_candidate(self, Certainty::AMBIGUOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut candidates = self.assemble_candidates_via_self_ty(goal, 0);
|
let goal =
|
||||||
|
goal.with(self.tcx(), goal.predicate.with_self_ty(self.tcx(), normalized_self_ty));
|
||||||
|
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
|
||||||
|
|
||||||
|
let mut candidates = vec![];
|
||||||
|
|
||||||
|
self.assemble_non_blanket_impl_candidates(goal, &mut candidates);
|
||||||
|
|
||||||
|
self.assemble_builtin_impl_candidates(goal, &mut candidates);
|
||||||
|
|
||||||
|
self.assemble_alias_bound_candidates(goal, &mut candidates);
|
||||||
|
|
||||||
|
self.assemble_object_bound_candidates(goal, &mut candidates);
|
||||||
|
|
||||||
self.assemble_unsize_to_dyn_candidate(goal, &mut candidates);
|
self.assemble_unsize_to_dyn_candidate(goal, &mut candidates);
|
||||||
|
|
||||||
@ -289,112 +317,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
candidates
|
candidates
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule,
|
|
||||||
/// object bound, alias bound, etc. We are unable to determine this until we can at
|
|
||||||
/// least structurally resolve the type one layer.
|
|
||||||
///
|
|
||||||
/// It would also require us to consider all impls of the trait, which is both pretty
|
|
||||||
/// bad for perf and would also constrain the self type if there is just a single impl.
|
|
||||||
fn assemble_self_ty_infer_ambiguity_response<G: GoalKind<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
goal: Goal<'tcx, G>,
|
|
||||||
) -> Option<Candidate<'tcx>> {
|
|
||||||
if goal.predicate.self_ty().is_ty_var() {
|
|
||||||
debug!("adding self_ty_infer_ambiguity_response");
|
|
||||||
let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
|
|
||||||
let result = self
|
|
||||||
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
|
||||||
.unwrap();
|
|
||||||
let mut dummy_probe = self.inspect.new_probe();
|
|
||||||
dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) });
|
|
||||||
self.inspect.finish_probe(dummy_probe);
|
|
||||||
Some(Candidate { source, result })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Assemble candidates which apply to the self type. This only looks at candidate which
|
|
||||||
/// apply to the specific self type and ignores all others.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the self type is still ambiguous.
|
|
||||||
fn assemble_candidates_via_self_ty<G: GoalKind<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
goal: Goal<'tcx, G>,
|
|
||||||
num_steps: usize,
|
|
||||||
) -> Vec<Candidate<'tcx>> {
|
|
||||||
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
|
|
||||||
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
|
|
||||||
return vec![ambig];
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut candidates = Vec::new();
|
|
||||||
|
|
||||||
self.assemble_non_blanket_impl_candidates(goal, &mut candidates);
|
|
||||||
|
|
||||||
self.assemble_builtin_impl_candidates(goal, &mut candidates);
|
|
||||||
|
|
||||||
self.assemble_alias_bound_candidates(goal, &mut candidates);
|
|
||||||
|
|
||||||
self.assemble_object_bound_candidates(goal, &mut candidates);
|
|
||||||
|
|
||||||
self.assemble_candidates_after_normalizing_self_ty(goal, &mut candidates, num_steps);
|
|
||||||
candidates
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If the self type of a goal is an alias we first try to normalize the self type
|
|
||||||
/// and compute the candidates for the normalized self type in case that succeeds.
|
|
||||||
///
|
|
||||||
/// These candidates are used in addition to the ones with the alias as a self type.
|
|
||||||
/// We do this to simplify both builtin candidates and for better performance.
|
|
||||||
///
|
|
||||||
/// We generate the builtin candidates on the fly by looking at the self type, e.g.
|
|
||||||
/// add `FnPtr` candidates if the self type is a function pointer. Handling builtin
|
|
||||||
/// candidates while the self type is still an alias seems difficult. This is similar
|
|
||||||
/// to `try_structurally_resolve_type` during hir typeck (FIXME once implemented).
|
|
||||||
///
|
|
||||||
/// Looking at all impls for some trait goal is prohibitively expensive. We therefore
|
|
||||||
/// only look at implementations with a matching self type. Because of this function,
|
|
||||||
/// we can avoid looking at all existing impls if the self type is an alias.
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
|
||||||
fn assemble_candidates_after_normalizing_self_ty<G: GoalKind<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
goal: Goal<'tcx, G>,
|
|
||||||
candidates: &mut Vec<Candidate<'tcx>>,
|
|
||||||
num_steps: usize,
|
|
||||||
) {
|
|
||||||
let tcx = self.tcx();
|
|
||||||
let &ty::Alias(_, alias) = goal.predicate.self_ty().kind() else { return };
|
|
||||||
|
|
||||||
candidates.extend(self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
|
|
||||||
if tcx.recursion_limit().value_within_limit(num_steps) {
|
|
||||||
let normalized_ty = ecx.next_ty_infer();
|
|
||||||
let normalizes_to_goal =
|
|
||||||
goal.with(tcx, ty::NormalizesTo { alias, term: normalized_ty.into() });
|
|
||||||
ecx.add_goal(GoalSource::Misc, normalizes_to_goal);
|
|
||||||
if let Err(NoSolution) = ecx.try_evaluate_added_goals() {
|
|
||||||
debug!("self type normalization failed");
|
|
||||||
return vec![];
|
|
||||||
}
|
|
||||||
let normalized_ty = ecx.resolve_vars_if_possible(normalized_ty);
|
|
||||||
debug!(?normalized_ty, "self type normalized");
|
|
||||||
// NOTE: Alternatively we could call `evaluate_goal` here and only
|
|
||||||
// have a `Normalized` candidate. This doesn't work as long as we
|
|
||||||
// use `CandidateSource` in winnowing.
|
|
||||||
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
|
|
||||||
ecx.assemble_candidates_via_self_ty(goal, num_steps + 1)
|
|
||||||
} else {
|
|
||||||
match ecx.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW) {
|
|
||||||
Ok(result) => vec![Candidate {
|
|
||||||
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
|
|
||||||
result,
|
|
||||||
}],
|
|
||||||
Err(NoSolution) => vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
#[instrument(level = "debug", skip_all)]
|
||||||
fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -288,11 +288,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
|
|
||||||
/// Normalize a type when it is structually matched on.
|
/// Normalize a type when it is structually matched on.
|
||||||
///
|
///
|
||||||
/// For self types this is generally already handled through
|
/// In nearly all cases this function must be used before matching on a type.
|
||||||
/// `assemble_candidates_after_normalizing_self_ty`, so anything happening
|
/// Not doing so is likely to be incomplete and therefore unsound during
|
||||||
/// in [`EvalCtxt::assemble_candidates_via_self_ty`] does not have to normalize
|
/// coherence.
|
||||||
/// the self type. It is required when structurally matching on any other
|
|
||||||
/// arguments of a trait goal, e.g. when assembling builtin unsize candidates.
|
|
||||||
#[instrument(level = "debug", skip(self), ret)]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
fn try_normalize_ty(
|
fn try_normalize_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -16,7 +16,7 @@ trait Foo {
|
|||||||
|
|
||||||
impl Foo for () {
|
impl Foo for () {
|
||||||
type Item = String where String: Copy;
|
type Item = String where String: Copy;
|
||||||
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Copy`
|
//~^ ERROR overflow evaluating the requirement `String: Copy`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Copy`
|
error[E0275]: overflow evaluating the requirement `String: Copy`
|
||||||
--> $DIR/alias-bound-unsound.rs:18:17
|
--> $DIR/alias-bound-unsound.rs:18:38
|
||||||
|
|
|
|
||||||
LL | type Item = String where String: Copy;
|
LL | type Item = String where String: Copy;
|
||||||
| ^^^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
note: required by a bound in `Foo::Item`
|
note: the requirement `String: Copy` appears on the `impl`'s associated type `Item` but not on the corresponding trait's associated type
|
||||||
--> $DIR/alias-bound-unsound.rs:8:16
|
--> $DIR/alias-bound-unsound.rs:8:10
|
||||||
|
|
|
|
||||||
|
LL | trait Foo {
|
||||||
|
| --- in this trait
|
||||||
LL | type Item: Copy
|
LL | type Item: Copy
|
||||||
| ^^^^ required by this bound in `Foo::Item`
|
| ^^^^ this trait's associated type doesn't have the requirement `String: Copy`
|
||||||
|
|
||||||
error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item`
|
error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||||
--> $DIR/alias-bound-unsound.rs:24:31
|
--> $DIR/alias-bound-unsound.rs:24:31
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
// check-pass
|
||||||
|
// compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
trait Reader: Default {
|
||||||
|
fn read_u8_array<A>(&self) -> Result<A, ()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_u8(&self) -> Result<u8, ()> {
|
||||||
|
let a: [u8; 1] = self.read_u8_array::<_>()?;
|
||||||
|
// This results in a nested `<Result<?0, ()> as Try>::Residual: Sized` goal.
|
||||||
|
// The self type normalizes to `?0`. We previously did not force that to be
|
||||||
|
// ambiguous but instead incompletely applied the `Self: Sized` candidate
|
||||||
|
// from the `ParamEnv`, resulting in a type error.
|
||||||
|
Ok(a[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,16 @@
|
|||||||
|
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
|
||||||
|
--> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
|
||||||
|
|
|
||||||
|
LL | needs_send::<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 E0283`.
|
@ -1,12 +1,12 @@
|
|||||||
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
|
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
|
||||||
--> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
|
--> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
|
||||||
|
|
|
|
||||||
LL | needs_send::<Foo>();
|
LL | needs_send::<Foo>();
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
= note: cannot satisfy `Foo: Send`
|
= note: cannot satisfy `Foo: Send`
|
||||||
note: required by a bound in `needs_send`
|
note: required by a bound in `needs_send`
|
||||||
--> $DIR/dont-type_of-tait-in-defining-scope.rs:13:18
|
--> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
|
||||||
|
|
|
|
||||||
LL | fn needs_send<T: Send>() {}
|
LL | fn needs_send<T: Send>() {}
|
||||||
| ^^^^ required by this bound in `needs_send`
|
| ^^^^ required by this bound in `needs_send`
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// revisions: is_send not_send
|
// revisions: is_send not_send
|
||||||
// compile-flags: -Znext-solver
|
// compile-flags: -Znext-solver
|
||||||
//[is_send] check-pass
|
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
@ -14,7 +13,7 @@ fn needs_send<T: Send>() {}
|
|||||||
|
|
||||||
fn test(_: Foo) {
|
fn test(_: Foo) {
|
||||||
needs_send::<Foo>();
|
needs_send::<Foo>();
|
||||||
//[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
|
//~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn defines(_: Foo) {
|
fn defines(_: Foo) {
|
||||||
|
@ -17,6 +17,7 @@ fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc
|
|||||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||||
|
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Sized`
|
||||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,23 @@ note: required by a bound in `needs_bar`
|
|||||||
LL | fn needs_bar<S: Bar>() {}
|
LL | fn needs_bar<S: Bar>() {}
|
||||||
| ^^^ required by this bound in `needs_bar`
|
| ^^^ required by this bound in `needs_bar`
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Sized`
|
||||||
|
--> $DIR/recursive-self-normalization-2.rs:15:17
|
||||||
|
|
|
||||||
|
LL | needs_bar::<T::Assoc1>();
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||||
|
note: required by a bound in `needs_bar`
|
||||||
|
--> $DIR/recursive-self-normalization-2.rs:12:14
|
||||||
|
|
|
||||||
|
LL | fn needs_bar<S: Bar>() {}
|
||||||
|
| ^ required by this bound in `needs_bar`
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | fn needs_bar<S: Bar + ?Sized>() {}
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||||
--> $DIR/recursive-self-normalization-2.rs:15:5
|
--> $DIR/recursive-self-normalization-2.rs:15:5
|
||||||
|
|
|
|
||||||
@ -45,6 +62,6 @@ LL | needs_bar::<T::Assoc1>();
|
|||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
For more information about this error, try `rustc --explain E0275`.
|
||||||
|
@ -13,6 +13,7 @@ fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
|
|||||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||||
|
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Sized`
|
||||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,23 @@ note: required by a bound in `needs_bar`
|
|||||||
LL | fn needs_bar<S: Bar>() {}
|
LL | fn needs_bar<S: Bar>() {}
|
||||||
| ^^^ required by this bound in `needs_bar`
|
| ^^^ required by this bound in `needs_bar`
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Sized`
|
||||||
|
--> $DIR/recursive-self-normalization.rs:11:17
|
||||||
|
|
|
||||||
|
LL | needs_bar::<T::Assoc>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||||
|
note: required by a bound in `needs_bar`
|
||||||
|
--> $DIR/recursive-self-normalization.rs:8:14
|
||||||
|
|
|
||||||
|
LL | fn needs_bar<S: Bar>() {}
|
||||||
|
| ^ required by this bound in `needs_bar`
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | fn needs_bar<S: Bar + ?Sized>() {}
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||||
--> $DIR/recursive-self-normalization.rs:11:5
|
--> $DIR/recursive-self-normalization.rs:11:5
|
||||||
|
|
|
|
||||||
@ -45,6 +62,6 @@ LL | needs_bar::<T::Assoc>();
|
|||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0275`.
|
For more information about this error, try `rustc --explain E0275`.
|
||||||
|
@ -4,20 +4,14 @@
|
|||||||
// revisions: current next
|
// revisions: current next
|
||||||
//[next] compile-flags: -Znext-solver
|
//[next] compile-flags: -Znext-solver
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
trait Dummy {}
|
|
||||||
impl Dummy for () {}
|
|
||||||
|
|
||||||
type F = impl Dummy;
|
|
||||||
fn f() -> F {}
|
|
||||||
|
|
||||||
trait Test {
|
trait Test {
|
||||||
fn test(self);
|
fn test(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Test for F {
|
|
||||||
|
impl Test for define::F {
|
||||||
fn test(self) {}
|
fn test(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +21,17 @@ impl Test for i32 {
|
|||||||
fn test(self) {}
|
fn test(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod define {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub trait Dummy {}
|
||||||
|
impl Dummy for () {}
|
||||||
|
|
||||||
|
pub type F = impl Dummy;
|
||||||
|
pub fn f() -> F {}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: F = f();
|
let x = define::f();
|
||||||
x.test();
|
x.test();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user