Use variables in predicates as well

This commit is contained in:
Florian Diebold 2020-02-02 17:11:54 +01:00 committed by Florian Diebold
parent 86348f5994
commit a3d8cffde3
5 changed files with 52 additions and 63 deletions

View File

@ -50,10 +50,10 @@ pub trait HirDatabase: DefDatabase {
fn generic_predicates_for_param(
&self,
param_id: TypeParamId,
) -> Arc<[GenericPredicate]>;
) -> Arc<[Binders<GenericPredicate>]>;
#[salsa::invoke(crate::lower::generic_predicates_query)]
fn generic_predicates(&self, def: GenericDefId) -> Arc<[GenericPredicate]>;
fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>;
#[salsa::invoke(crate::lower::generic_defaults_query)]
fn generic_defaults(&self, def: GenericDefId) -> Substs;

View File

@ -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);
}

View File

@ -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::<Vec<_>>(), f)?;
}
}
}

View File

@ -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<GenericPredicate>]> {
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<GenericPredicate>]> {
Arc::new([])
}
impl TraitEnvironment {
pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
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<GenericPredicate>]> {
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<Binders<TraitRef>> {
pub(crate) fn impl_trait_query(
db: &impl HirDatabase,
impl_id: ImplId,
) -> Option<Binders<TraitRef>> {
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()))?,
))
}

View File

@ -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
}