From e89ad9f345a30029e56138362832babbf43f9067 Mon Sep 17 00:00:00 2001 From: Dawer <7803845+iDawer@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:30:05 +0500 Subject: [PATCH] Allow ambiguous autoderef with defininte guidance. This enables autoderefing types with inference variables inside. --- crates/hir_ty/src/autoderef.rs | 19 +++++++++---------- crates/hir_ty/src/tests/traits.rs | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 267d08d69a..0be337fc2d 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs @@ -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(_) => { diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 35854e42c1..de1b0e9f29 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -648,6 +648,25 @@ fn test(s: Arc) { ); } +#[test] +fn deref_trait_with_implicit_sized_requirement_on_inference_var() { + check_types( + r#" +//- minicore: deref +struct Foo; +impl core::ops::Deref for Foo { + type Target = (); +} +fn test() { + let foo = Foo; + *foo; + //^^^^ () + let _: Foo = foo; +} +"#, + ) +} + #[test] fn obligation_from_function_clause() { check_types(