Use environment for associated type normalization as well

This commit is contained in:
Florian Diebold 2019-07-07 18:14:56 +02:00
parent b1b12072ed
commit 15862fc041
7 changed files with 52 additions and 20 deletions

View File

@ -224,7 +224,7 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
fn normalize(
&self,
krate: Crate,
goal: crate::ty::Canonical<crate::ty::ProjectionPredicate>,
goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::ProjectionPredicate>>,
) -> Option<crate::ty::traits::Solution>;
}

View File

@ -52,6 +52,8 @@ fn deref_by_trait(
// FIXME make the Canonical handling nicer
let env = super::lower::trait_env(db, resolver);
let projection = super::traits::ProjectionPredicate {
ty: Ty::Bound(0),
projection_ty: super::ProjectionTy {
@ -60,7 +62,9 @@ fn deref_by_trait(
},
};
let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: projection };
let in_env = super::traits::InEnvironment { value: projection, environment: env };
let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env };
let solution = db.normalize(krate, canonical)?;

View File

@ -356,7 +356,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
};
}
Obligation::Projection(pr) => {
let canonicalized = self.canonicalizer().canonicalize_projection(pr.clone());
let in_env = InEnvironment::new(self.trait_env.clone(), pr.clone());
let canonicalized = self.canonicalizer().canonicalize_projection(in_env);
let solution = self
.db
.normalize(self.resolver.krate().unwrap(), canonicalized.value.clone());

View File

@ -129,10 +129,14 @@ where
pub fn canonicalize_projection(
mut self,
projection: ProjectionPredicate,
) -> Canonicalized<ProjectionPredicate> {
let result = self.do_canonicalize_projection_predicate(projection);
self.into_canonicalized(result)
projection: InEnvironment<ProjectionPredicate>,
) -> Canonicalized<InEnvironment<ProjectionPredicate>> {
let result = self.do_canonicalize_projection_predicate(projection.value);
// FIXME canonicalize env
self.into_canonicalized(InEnvironment {
value: result,
environment: projection.environment,
})
}
}

View File

@ -3010,6 +3010,25 @@ fn test<T>(t: T) { t.foo()<|>; }
assert_eq!(t, "{unknown}");
}
#[test]
fn generic_param_env_deref() {
let t = type_at(
r#"
//- /main.rs
#[lang = "deref"]
trait Deref {
type Target;
}
trait Trait {}
impl<T> Deref for T where T: Trait {
type Target = i128;
}
fn test<T: Trait>(t: T) { (*t)<|>; }
"#,
);
assert_eq!(t, "i128");
}
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
let file = db.parse(pos.file_id).ok().unwrap();
let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();

View File

@ -134,20 +134,9 @@ pub(crate) fn implements_query(
pub(crate) fn normalize_query(
db: &impl HirDatabase,
krate: Crate,
projection: Canonical<ProjectionPredicate>,
projection: Canonical<InEnvironment<ProjectionPredicate>>,
) -> Option<Solution> {
let goal: chalk_ir::Goal = chalk_ir::Normalize {
projection: projection.value.projection_ty.to_chalk(db),
ty: projection.value.ty.to_chalk(db),
}
.cast();
debug!("goal: {:?}", goal);
// FIXME unify with `implements`
let env = chalk_ir::Environment::new();
let in_env = chalk_ir::InEnvironment::new(&env, goal);
let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT);
let canonical =
chalk_ir::Canonical { value: in_env, binders: vec![parameter; projection.num_vars] };
let canonical = projection.to_chalk(db).cast();
// We currently don't deal with universes (I think / hope they're not yet
// relevant for our use cases?)
let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };

View File

@ -218,6 +218,21 @@ impl ToChalk for ProjectionTy {
}
}
impl ToChalk for super::ProjectionPredicate {
type Chalk = chalk_ir::Normalize;
fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize {
chalk_ir::Normalize {
projection: self.projection_ty.to_chalk(db),
ty: self.ty.to_chalk(db),
}
}
fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self {
unimplemented!()
}
}
impl<T> ToChalk for Canonical<T>
where
T: ToChalk,