From c82d1823a1624f4990b1ebaba5b6173f15631381 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 13 Mar 2021 20:38:11 +0100 Subject: Create TraitEnvironment through a query --- crates/hir_ty/src/db.rs | 3 ++ crates/hir_ty/src/infer.rs | 4 ++- crates/hir_ty/src/lower.rs | 88 ++++++++++++++++++++++----------------------- crates/hir_ty/src/traits.rs | 9 +++++ 4 files changed, 59 insertions(+), 45 deletions(-) (limited to 'crates/hir_ty/src') diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 8a3cc0283..74a048672 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs @@ -65,6 +65,9 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::lower::generic_predicates_query)] fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders]>; + #[salsa::invoke(crate::lower::trait_environment_query)] + fn trait_environment(&self, def: GenericDefId) -> Arc; + #[salsa::invoke(crate::lower::generic_defaults_query)] fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders]>; diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 4f7463422..bc52f447d 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -228,7 +228,9 @@ impl<'a> InferenceContext<'a> { table: unify::InferenceTable::new(), obligations: Vec::default(), return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature - trait_env: TraitEnvironment::lower(db, &resolver), + trait_env: owner + .as_generic_def_id() + .map_or_else(Default::default, |d| db.trait_environment(d)), db, owner, body: db.body(owner), diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index e57d5970f..3b0706530 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -935,55 +935,55 @@ pub(crate) fn generic_predicates_for_param_recover( Arc::new([]) } -impl TraitEnvironment { - pub fn lower(db: &dyn HirDatabase, resolver: &Resolver) -> Arc { - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Placeholder); - let mut traits_in_scope = Vec::new(); - let mut clauses = Vec::new(); - for pred in resolver.where_predicates_in_scope() { - for pred in GenericPredicate::from_where_predicate(&ctx, pred) { - if pred.is_error() { - continue; - } - if let GenericPredicate::Implemented(tr) = &pred { - traits_in_scope.push((tr.self_ty().clone(), tr.trait_)); - } - let program_clause: chalk_ir::ProgramClause = - pred.clone().to_chalk(db).cast(&Interner); - clauses.push(program_clause.into_from_env_clause(&Interner)); +pub(crate) fn trait_environment_query( + db: &dyn HirDatabase, + def: GenericDefId, +) -> Arc { + let resolver = def.resolver(db.upcast()); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Placeholder); + let mut traits_in_scope = Vec::new(); + let mut clauses = Vec::new(); + for pred in resolver.where_predicates_in_scope() { + for pred in GenericPredicate::from_where_predicate(&ctx, pred) { + if pred.is_error() { + continue; } - } - - if let Some(def) = resolver.generic_def() { - let container: Option = match def { - // FIXME: is there a function for this? - GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container), - GenericDefId::AdtId(_) => None, - GenericDefId::TraitId(_) => None, - GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container), - GenericDefId::ImplId(_) => None, - GenericDefId::EnumVariantId(_) => None, - GenericDefId::ConstId(c) => Some(c.lookup(db.upcast()).container), - }; - if let Some(AssocContainerId::TraitId(trait_id)) = container { - // add `Self: Trait` to the environment in trait - // function default implementations (and hypothetical code - // inside consts or type aliases) - cov_mark::hit!(trait_self_implements_self); - let substs = Substs::type_params(db, trait_id); - let trait_ref = TraitRef { trait_: trait_id, substs }; - let pred = GenericPredicate::Implemented(trait_ref); - let program_clause: chalk_ir::ProgramClause = - pred.clone().to_chalk(db).cast(&Interner); - clauses.push(program_clause.into_from_env_clause(&Interner)); + if let GenericPredicate::Implemented(tr) = &pred { + traits_in_scope.push((tr.self_ty().clone(), tr.trait_)); } + let program_clause: chalk_ir::ProgramClause = + pred.clone().to_chalk(db).cast(&Interner); + clauses.push(program_clause.into_from_env_clause(&Interner)); } + } - let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses); - - Arc::new(TraitEnvironment { traits_from_clauses: traits_in_scope, env }) + let container: Option = match def { + // FIXME: is there a function for this? + GenericDefId::FunctionId(f) => Some(f.lookup(db.upcast()).container), + GenericDefId::AdtId(_) => None, + GenericDefId::TraitId(_) => None, + GenericDefId::TypeAliasId(t) => Some(t.lookup(db.upcast()).container), + GenericDefId::ImplId(_) => None, + GenericDefId::EnumVariantId(_) => None, + GenericDefId::ConstId(c) => Some(c.lookup(db.upcast()).container), + }; + if let Some(AssocContainerId::TraitId(trait_id)) = container { + // add `Self: Trait` to the environment in trait + // function default implementations (and hypothetical code + // inside consts or type aliases) + cov_mark::hit!(trait_self_implements_self); + let substs = Substs::type_params(db, trait_id); + let trait_ref = TraitRef { trait_: trait_id, substs }; + let pred = GenericPredicate::Implemented(trait_ref); + let program_clause: chalk_ir::ProgramClause = + pred.clone().to_chalk(db).cast(&Interner); + clauses.push(program_clause.into_from_env_clause(&Interner)); } + + let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses); + + Arc::new(TraitEnvironment { traits_from_clauses: traits_in_scope, env }) } /// Resolve the where clause(s) of an item with generics. diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 500d1781c..edfafdff8 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs @@ -63,6 +63,15 @@ impl TraitEnvironment { } } +impl Default for TraitEnvironment { + fn default() -> Self { + TraitEnvironment { + traits_from_clauses: Vec::new(), + env: chalk_ir::Environment::new(&Interner), + } + } +} + /// Something (usually a goal), along with an environment. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct InEnvironment { -- cgit v1.2.3