Auto merge of #113336 - compiler-errors:new-solver-iat, r=lcnr
Add support for inherent projections in new solver Not hard to support these, and it cuts out a really big chunk of failing UI tests with `--compare-mode=next-solver` r? `@lcnr` (feel free to reassign, anyone can review this)
This commit is contained in:
commit
4c7af429f3
@ -1313,7 +1313,7 @@ impl<'tcx> AliasTy<'tcx> {
|
|||||||
/// I_i impl subst
|
/// I_i impl subst
|
||||||
/// P_j GAT subst
|
/// P_j GAT subst
|
||||||
/// ```
|
/// ```
|
||||||
pub fn rebase_args_onto_impl(
|
pub fn rebase_inherent_args_onto_impl(
|
||||||
self,
|
self,
|
||||||
impl_args: ty::GenericArgsRef<'tcx>,
|
impl_args: ty::GenericArgsRef<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||||
|
use rustc_middle::ty;
|
||||||
|
|
||||||
|
use super::EvalCtxt;
|
||||||
|
|
||||||
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
|
pub(super) fn normalize_inherent_associated_type(
|
||||||
|
&mut self,
|
||||||
|
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
||||||
|
) -> QueryResult<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
let inherent = goal.predicate.projection_ty;
|
||||||
|
let expected = goal.predicate.term.ty().expect("inherent consts are treated separately");
|
||||||
|
|
||||||
|
let impl_def_id = tcx.parent(inherent.def_id);
|
||||||
|
let impl_substs = self.fresh_args_for_item(impl_def_id);
|
||||||
|
|
||||||
|
// Equate impl header and add impl where clauses
|
||||||
|
self.eq(
|
||||||
|
goal.param_env,
|
||||||
|
inherent.self_ty(),
|
||||||
|
tcx.type_of(impl_def_id).instantiate(tcx, impl_substs),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Equate IAT with the RHS of the project goal
|
||||||
|
let inherent_substs = inherent.rebase_inherent_args_onto_impl(impl_substs, tcx);
|
||||||
|
self.eq(
|
||||||
|
goal.param_env,
|
||||||
|
expected,
|
||||||
|
tcx.type_of(inherent.def_id).instantiate(tcx, inherent_substs),
|
||||||
|
)
|
||||||
|
.expect("expected goal term to be fully unconstrained");
|
||||||
|
|
||||||
|
// Check both where clauses on the impl and IAT
|
||||||
|
self.add_goals(
|
||||||
|
tcx.predicates_of(inherent.def_id)
|
||||||
|
.instantiate(tcx, inherent_substs)
|
||||||
|
.into_iter()
|
||||||
|
.map(|(pred, _)| goal.with(tcx, pred)),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ mod assembly;
|
|||||||
mod canonicalize;
|
mod canonicalize;
|
||||||
mod eval_ctxt;
|
mod eval_ctxt;
|
||||||
mod fulfill;
|
mod fulfill;
|
||||||
|
mod inherent_projection;
|
||||||
pub mod inspect;
|
pub mod inspect;
|
||||||
mod normalize;
|
mod normalize;
|
||||||
mod opaques;
|
mod opaques;
|
||||||
|
@ -48,7 +48,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
self.merge_candidates(candidates)
|
self.merge_candidates(candidates)
|
||||||
}
|
}
|
||||||
ty::AssocItemContainer::ImplContainer => {
|
ty::AssocItemContainer::ImplContainer => {
|
||||||
bug!("IATs not supported here yet")
|
self.normalize_inherent_associated_type(goal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -112,6 +112,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
if let Some(projection_pred) = assumption.as_projection_clause() {
|
if let Some(projection_pred) = assumption.as_projection_clause() {
|
||||||
if projection_pred.projection_def_id() == goal.predicate.def_id() {
|
if projection_pred.projection_def_id() == goal.predicate.def_id() {
|
||||||
|
let tcx = ecx.tcx();
|
||||||
ecx.probe_candidate("assumption").enter(|ecx| {
|
ecx.probe_candidate("assumption").enter(|ecx| {
|
||||||
let assumption_projection_pred =
|
let assumption_projection_pred =
|
||||||
ecx.instantiate_binder_with_infer(projection_pred);
|
ecx.instantiate_binder_with_infer(projection_pred);
|
||||||
@ -122,6 +123,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||||||
)?;
|
)?;
|
||||||
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
|
ecx.eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
|
||||||
.expect("expected goal term to be fully unconstrained");
|
.expect("expected goal term to be fully unconstrained");
|
||||||
|
|
||||||
|
// Add GAT where clauses from the trait's definition
|
||||||
|
ecx.add_goals(
|
||||||
|
tcx.predicates_of(goal.predicate.def_id())
|
||||||
|
.instantiate_own(tcx, goal.predicate.projection_ty.args)
|
||||||
|
.map(|(pred, _)| goal.with(tcx, pred)),
|
||||||
|
);
|
||||||
|
|
||||||
then(ecx)
|
then(ecx)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -160,6 +169,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||||||
.map(|pred| goal.with(tcx, pred));
|
.map(|pred| goal.with(tcx, pred));
|
||||||
ecx.add_goals(where_clause_bounds);
|
ecx.add_goals(where_clause_bounds);
|
||||||
|
|
||||||
|
// Add GAT where clauses from the trait's definition
|
||||||
|
ecx.add_goals(
|
||||||
|
tcx.predicates_of(goal.predicate.def_id())
|
||||||
|
.instantiate_own(tcx, goal.predicate.projection_ty.args)
|
||||||
|
.map(|(pred, _)| goal.with(tcx, pred)),
|
||||||
|
);
|
||||||
|
|
||||||
// In case the associated item is hidden due to specialization, we have to
|
// In case the associated item is hidden due to specialization, we have to
|
||||||
// return ambiguity this would otherwise be incomplete, resulting in
|
// return ambiguity this would otherwise be incomplete, resulting in
|
||||||
// unsoundness during coherence (#105782).
|
// unsoundness during coherence (#105782).
|
||||||
|
@ -14,6 +14,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
|
|
||||||
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
|
let actual = tcx.type_of(weak_ty.def_id).instantiate(tcx, weak_ty.args);
|
||||||
self.eq(goal.param_env, expected, actual)?;
|
self.eq(goal.param_env, expected, actual)?;
|
||||||
|
|
||||||
|
// Check where clauses
|
||||||
|
self.add_goals(
|
||||||
|
tcx.predicates_of(weak_ty.def_id)
|
||||||
|
.instantiate(tcx, weak_ty.args)
|
||||||
|
.predicates
|
||||||
|
.into_iter()
|
||||||
|
.map(|pred| goal.with(tcx, pred)),
|
||||||
|
);
|
||||||
|
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1402,9 +1402,17 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
|
|||||||
let impl_def_id = tcx.parent(alias_ty.def_id);
|
let impl_def_id = tcx.parent(alias_ty.def_id);
|
||||||
let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);
|
let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);
|
||||||
|
|
||||||
let impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
|
let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
|
||||||
let impl_ty =
|
if !selcx.infcx.next_trait_solver() {
|
||||||
normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
|
impl_ty = normalize_with_depth_to(
|
||||||
|
selcx,
|
||||||
|
param_env,
|
||||||
|
cause.clone(),
|
||||||
|
depth + 1,
|
||||||
|
impl_ty,
|
||||||
|
obligations,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Infer the generic parameters of the impl by unifying the
|
// Infer the generic parameters of the impl by unifying the
|
||||||
// impl type with the self type of the projection.
|
// impl type with the self type of the projection.
|
||||||
@ -1421,7 +1429,7 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alias_ty.rebase_args_onto_impl(impl_args, tcx)
|
alias_ty.rebase_inherent_args_onto_impl(impl_args, tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Projected<'tcx> {
|
enum Projected<'tcx> {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// Testing inference capabilities.
|
// Testing inference capabilities.
|
||||||
// check-pass
|
// check-pass
|
||||||
|
// revisions: current next
|
||||||
|
//[next] compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
#![feature(inherent_associated_types)]
|
#![feature(inherent_associated_types)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
@ -16,12 +16,17 @@ 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`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = String::from("hello, world");
|
let x = String::from("hello, world");
|
||||||
drop(<() as Foo>::copy_me(&x));
|
drop(<() as Foo>::copy_me(&x));
|
||||||
//~^ ERROR the type `&<() as Foo>::Item` is not well-formed
|
//~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
|
||||||
//~| ERROR `<() as Foo>::Item` is not well-formed
|
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||||
|
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||||
|
//~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||||
|
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
||||||
|
//~| ERROR type annotations needed
|
||||||
println!("{x}");
|
println!("{x}");
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,69 @@
|
|||||||
error: the type `&<() as Foo>::Item` is not well-formed
|
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Copy`
|
||||||
--> $DIR/alias-bound-unsound.rs:23:31
|
--> $DIR/alias-bound-unsound.rs:18:17
|
||||||
|
|
|
||||||
|
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`)
|
||||||
|
note: required by a bound in `Foo::Item`
|
||||||
|
--> $DIR/alias-bound-unsound.rs:8:16
|
||||||
|
|
|
||||||
|
LL | type Item: Copy
|
||||||
|
| ^^^^ required by this bound in `Foo::Item`
|
||||||
|
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/alias-bound-unsound.rs:24:5
|
||||||
|
|
|
||||||
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
|
| ^^^^ cannot infer type of the type parameter `T` declared on the function `drop`
|
||||||
|
|
|
||||||
|
help: consider specifying the generic argument
|
||||||
|
|
|
||||||
|
LL | drop::<T>(<() as Foo>::copy_me(&x));
|
||||||
|
| +++++
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed`
|
||||||
|
--> $DIR/alias-bound-unsound.rs:24:31
|
||||||
|
|
|
|
||||||
LL | drop(<() as Foo>::copy_me(&x));
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
|
|
||||||
error: the type `<() as Foo>::Item` is not well-formed
|
error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item`
|
||||||
--> $DIR/alias-bound-unsound.rs:23:10
|
--> $DIR/alias-bound-unsound.rs:24:31
|
||||||
|
|
|
||||||
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed`
|
||||||
|
--> $DIR/alias-bound-unsound.rs:24:10
|
||||||
|
|
|
|
||||||
LL | drop(<() as Foo>::copy_me(&x));
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
|
||||||
|
--> $DIR/alias-bound-unsound.rs:24:10
|
||||||
|
|
|
||||||
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
|
|
||||||
|
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized`
|
||||||
|
--> $DIR/alias-bound-unsound.rs:24:10
|
||||||
|
|
|
||||||
|
LL | drop(<() as Foo>::copy_me(&x));
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
|
||||||
|
= note: the return type of a function must have a statically known size
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0275, E0282.
|
||||||
|
For more information about an error, try `rustc --explain E0275`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user