From 15862fc04183c7f9b3f3af666336a594a6a52cd9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 7 Jul 2019 18:14:56 +0200 Subject: Use environment for associated type normalization as well --- crates/ra_hir/src/ty/autoderef.rs | 6 +++++- crates/ra_hir/src/ty/infer.rs | 3 ++- crates/ra_hir/src/ty/infer/unify.rs | 12 ++++++++---- crates/ra_hir/src/ty/tests.rs | 19 +++++++++++++++++++ crates/ra_hir/src/ty/traits.rs | 15 ++------------- crates/ra_hir/src/ty/traits/chalk.rs | 15 +++++++++++++++ 6 files changed, 51 insertions(+), 19 deletions(-) (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 90c1ae630..214aa7d03 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs @@ -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)?; diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index f8839ebd2..f6cf61ad2 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -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()); diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index ad2eefcaf..2ed326cd5 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs @@ -129,10 +129,14 @@ where pub fn canonicalize_projection( mut self, - projection: ProjectionPredicate, - ) -> Canonicalized { - let result = self.do_canonicalize_projection_predicate(projection); - self.into_canonicalized(result) + projection: InEnvironment, + ) -> Canonicalized> { + let result = self.do_canonicalize_projection_predicate(projection.value); + // FIXME canonicalize env + self.into_canonicalized(InEnvironment { + value: result, + environment: projection.environment, + }) } } diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 594e82af2..7340bb9bd 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -3010,6 +3010,25 @@ fn test(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 Deref for T where T: Trait { + type Target = i128; +} +fn test(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::(file.syntax(), pos.offset).unwrap(); diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index e0c93550a..01f350bc1 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs @@ -134,20 +134,9 @@ pub(crate) fn implements_query( pub(crate) fn normalize_query( db: &impl HirDatabase, krate: Crate, - projection: Canonical, + projection: Canonical>, ) -> Option { - 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 }; diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index f36ff2fc6..32a45731d 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -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 ToChalk for Canonical where T: ToChalk, -- cgit v1.2.3