From a3d8cffde39bfb0d50b87a8ded5e0534adec4cd5 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 2 Feb 2020 17:11:54 +0100 Subject: Use variables in predicates as well --- crates/ra_hir_ty/src/db.rs | 4 +- crates/ra_hir_ty/src/infer/expr.rs | 4 +- crates/ra_hir_ty/src/lib.rs | 28 ++------------ crates/ra_hir_ty/src/lower.rs | 73 ++++++++++++++++++++---------------- crates/ra_hir_ty/src/traits/chalk.rs | 6 +-- 5 files changed, 52 insertions(+), 63 deletions(-) (limited to 'crates/ra_hir_ty') diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 7684ade06..21ab22fa9 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -50,10 +50,10 @@ pub trait HirDatabase: DefDatabase { fn generic_predicates_for_param( &self, param_id: TypeParamId, - ) -> Arc<[GenericPredicate]>; + ) -> Arc<[Binders]>; #[salsa::invoke(crate::lower::generic_predicates_query)] - fn generic_predicates(&self, def: GenericDefId) -> Arc<[GenericPredicate]>; + fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders]>; #[salsa::invoke(crate::lower::generic_defaults_query)] fn generic_defaults(&self, def: GenericDefId) -> Substs; diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index b32df8e90..b69785e55 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -20,7 +20,7 @@ use crate::{ traits::InEnvironment, utils::{generics, variant_data, Generics}, ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty, - TypeCtor, TypeWalk, Uncertain, Binders, + TypeCtor, Uncertain, Binders, }; use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; @@ -686,7 +686,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { if let TypeCtor::FnDef(def) = a_ty.ctor { let generic_predicates = self.db.generic_predicates(def.into()); for predicate in generic_predicates.iter() { - let predicate = predicate.clone().subst_type_params(self.db, def.into(), &a_ty.parameters); + let predicate = predicate.clone().subst(&a_ty.parameters); if let Some(obligation) = Obligation::from_predicate(predicate) { self.obligations.push(obligation); } diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 1da4bcc19..a685e70c2 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -749,28 +749,7 @@ pub trait TypeWalk { self } - /// Replaces type parameters in this type using the given `Substs`. (So e.g. - /// if `self` is `&[T]`, where type parameter T has index 0, and the - /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) - // TODO: this should mostly not be used anymore - fn subst_type_params(self, db: &impl HirDatabase, def: GenericDefId, substs: &Substs) -> Self - where - Self: Sized, - { - let generics = generics(db, def); - self.fold(&mut |ty| match ty { - Ty::Param(id) => { - if let Some(idx) = generics.param_idx(id) { - substs.get(idx as usize).cloned().unwrap_or(Ty::Param(id)) - } else { - ty - } - } - ty => ty, - }) - } - - /// Substitutes `Ty::Bound` vars (as opposed to type parameters). + /// Substitutes `Ty::Bound` vars with the given substitution. fn subst_bound_vars(mut self, substs: &Substs) -> Self where Self: Sized, @@ -1045,9 +1024,10 @@ impl HirDisplay for Ty { write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? } TypeParamProvenance::ArgumentImplTrait => { - let bounds = f.db.generic_predicates_for_param(*id); write!(f, "impl ")?; - write_bounds_like_dyn_trait(&bounds, f)?; + let bounds = f.db.generic_predicates_for_param(*id); + let substs = Substs::type_params(&generics); + write_bounds_like_dyn_trait(&bounds.iter().map(|b| b.clone().subst(&substs)).collect::>(), f)?; } } } diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 76e2fbabf..847111748 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -10,13 +10,13 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, - generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance}, + generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget}, path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, - LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, - TypeParamId + LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, + VariantId, }; use ra_arena::map::ArenaMap; use ra_db::CrateId; @@ -148,7 +148,9 @@ impl Ty { let generics = generics(ctx.db, def); let param = generics .iter() - .filter(|(_, data)| data.provenance == TypeParamProvenance::ArgumentImplTrait) + .filter(|(_, data)| { + data.provenance == TypeParamProvenance::ArgumentImplTrait + }) .nth(idx as usize) .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); param @@ -338,19 +340,12 @@ impl Ty { return Ty::Unknown; }; param_id - }, + } _ => return Ty::Unknown, // Error: Ambiguous associated type }; let predicates = ctx.db.generic_predicates_for_param(param_id); - let traits_from_env = predicates.iter().filter_map(|pred| match pred { - GenericPredicate::Implemented(tr) => { - if let Ty::Param(id) = tr.self_ty() { - if *id == param_id { - return Some(tr.trait_); - } - } - None - } + let traits_from_env = predicates.iter().filter_map(|pred| match &pred.value { + GenericPredicate::Implemented(tr) => Some(tr.trait_), _ => None, }); let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); @@ -620,8 +615,8 @@ pub(crate) fn field_types_query( }; let generics = generics(db, def); let mut res = ArenaMap::default(); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); for (field_id, field_data) in var_data.fields().iter() { res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) } @@ -639,10 +634,11 @@ pub(crate) fn field_types_query( pub(crate) fn generic_predicates_for_param_query( db: &impl HirDatabase, param_id: TypeParamId, -) -> Arc<[GenericPredicate]> { +) -> Arc<[Binders]> { let resolver = param_id.parent.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver); - // let generics = generics(db, def); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); + let generics = generics(db, param_id.parent); resolver .where_predicates_in_scope() // we have to filter out all other predicates *first*, before attempting to lower them @@ -650,11 +646,12 @@ pub(crate) fn generic_predicates_for_param_query( WherePredicateTarget::TypeRef(type_ref) => { Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) } - WherePredicateTarget::TypeParam(local_id) => { - *local_id == param_id.local_id - } + WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.local_id, + }) + .flat_map(|pred| { + GenericPredicate::from_where_predicate(&ctx, pred) + .map(|p| Binders::new(generics.len(), p)) }) - .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .collect() } @@ -662,13 +659,14 @@ pub(crate) fn generic_predicates_for_param_recover( _db: &impl HirDatabase, _cycle: &[String], _param_id: &TypeParamId, -) -> Arc<[GenericPredicate]> { +) -> Arc<[Binders]> { Arc::new([]) } impl TraitEnvironment { pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc { - let ctx = TyLoweringContext::new(db, &resolver); + let ctx = TyLoweringContext::new(db, &resolver) + .with_type_param_mode(TypeParamLoweringMode::Placeholder); let predicates = resolver .where_predicates_in_scope() .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) @@ -682,12 +680,17 @@ impl TraitEnvironment { pub(crate) fn generic_predicates_query( db: &impl HirDatabase, def: GenericDefId, -) -> Arc<[GenericPredicate]> { +) -> Arc<[Binders]> { let resolver = def.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); + let generics = generics(db, def); resolver .where_predicates_in_scope() - .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) + .flat_map(|pred| { + GenericPredicate::from_where_predicate(&ctx, pred) + .map(|p| Binders::new(generics.len(), p)) + }) .collect() } @@ -915,12 +918,18 @@ pub(crate) fn impl_self_ty_recover( Binders::new(generics.len(), Ty::Unknown) } -pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option> { +pub(crate) fn impl_trait_query( + db: &impl HirDatabase, + impl_id: ImplId, +) -> Option> { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let ctx = TyLoweringContext::new(db, &resolver) - .with_type_param_mode(TypeParamLoweringMode::Variable); + let ctx = + TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); let self_ty = db.impl_self_ty(impl_id); let target_trait = impl_data.target_trait.as_ref()?; - Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?)) + Some(Binders::new( + self_ty.num_binders, + TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?, + )) } diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 6e97f7dd2..8260bd157 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -14,7 +14,7 @@ use ra_db::{ use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, - ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, + ProjectionTy, Substs, TraitRef, Ty, TypeCtor, }; #[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] @@ -522,11 +522,11 @@ fn convert_where_clauses( let generic_predicates = db.generic_predicates(def); let mut result = Vec::with_capacity(generic_predicates.len()); for pred in generic_predicates.iter() { - if pred.is_error() { + if pred.value.is_error() { // skip errored predicates completely continue; } - result.push(pred.clone().subst_type_params(db, def, substs).to_chalk(db)); + result.push(pred.clone().subst(substs).to_chalk(db)); } result } -- cgit v1.2.3