Allow ambiguous autoderef with defininte guidance.

This enables autoderefing types with inference variables inside.
This commit is contained in:
Dawer 2021-08-09 14:30:05 +05:00
parent 14898729f4
commit e89ad9f345
2 changed files with 28 additions and 10 deletions

View File

@ -14,8 +14,8 @@ use log::{info, warn};
use crate::{
db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
DebruijnIndex, Environment, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution,
Ty, TyBuilder, TyKind,
ConstrainedSubst, DebruijnIndex, Environment, Guidance, InEnvironment, Interner,
ProjectionTyExt, Solution, Substitution, Ty, TyBuilder, TyKind,
};
const AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
@ -187,7 +187,8 @@ fn deref_by_trait(
let solution = db.trait_solve(krate, canonical)?;
match &solution {
Solution::Unique(vars) => {
Solution::Unique(Canonical { value: ConstrainedSubst { subst, .. }, binders })
| Solution::Ambig(Guidance::Definite(Canonical { value: subst, binders })) => {
// FIXME: vars may contain solutions for any inference variables
// that happened to be inside ty. To correctly handle these, we
// would have to pass the solution up to the inference context, but
@ -203,8 +204,8 @@ fn deref_by_trait(
// assumptions will be broken. We would need to properly introduce
// new variables in that case
for i in 1..vars.binders.len(&Interner) {
if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
for i in 1..binders.len(&Interner) {
if subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
!= &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
{
warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@ -214,13 +215,11 @@ fn deref_by_trait(
// FIXME: we remove lifetime variables here since they can confuse
// the method resolution code later
Some(fixup_lifetime_variables(Canonical {
value: vars
.value
.subst
.at(&Interner, vars.value.subst.len(&Interner) - 1)
value: subst
.at(&Interner, subst.len(&Interner) - 1)
.assert_ty_ref(&Interner)
.clone(),
binders: vars.binders.clone(),
binders: binders.clone(),
}))
}
Solution::Ambig(_) => {

View File

@ -648,6 +648,25 @@ fn test(s: Arc<S>) {
);
}
#[test]
fn deref_trait_with_implicit_sized_requirement_on_inference_var() {
check_types(
r#"
//- minicore: deref
struct Foo<T>;
impl<T> core::ops::Deref for Foo<T> {
type Target = ();
}
fn test() {
let foo = Foo;
*foo;
//^^^^ ()
let _: Foo<u8> = foo;
}
"#,
)
}
#[test]
fn obligation_from_function_clause() {
check_types(