Use variables in predicates as well
This commit is contained in:
parent
86348f5994
commit
a3d8cffde3
@ -50,10 +50,10 @@ pub trait HirDatabase: DefDatabase {
|
|||||||
fn generic_predicates_for_param(
|
fn generic_predicates_for_param(
|
||||||
&self,
|
&self,
|
||||||
param_id: TypeParamId,
|
param_id: TypeParamId,
|
||||||
) -> Arc<[GenericPredicate]>;
|
) -> Arc<[Binders<GenericPredicate>]>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::lower::generic_predicates_query)]
|
#[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)]
|
#[salsa::invoke(crate::lower::generic_defaults_query)]
|
||||||
fn generic_defaults(&self, def: GenericDefId) -> Substs;
|
fn generic_defaults(&self, def: GenericDefId) -> Substs;
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
traits::InEnvironment,
|
traits::InEnvironment,
|
||||||
utils::{generics, variant_data, Generics},
|
utils::{generics, variant_data, Generics},
|
||||||
ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
|
ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
|
||||||
TypeCtor, TypeWalk, Uncertain, Binders,
|
TypeCtor, Uncertain, Binders,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
|
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 {
|
if let TypeCtor::FnDef(def) = a_ty.ctor {
|
||||||
let generic_predicates = self.db.generic_predicates(def.into());
|
let generic_predicates = self.db.generic_predicates(def.into());
|
||||||
for predicate in generic_predicates.iter() {
|
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) {
|
if let Some(obligation) = Obligation::from_predicate(predicate) {
|
||||||
self.obligations.push(obligation);
|
self.obligations.push(obligation);
|
||||||
}
|
}
|
||||||
|
@ -749,28 +749,7 @@ pub trait TypeWalk {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces type parameters in this type using the given `Substs`. (So e.g.
|
/// Substitutes `Ty::Bound` vars with the given substitution.
|
||||||
/// 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).
|
|
||||||
fn subst_bound_vars(mut self, substs: &Substs) -> Self
|
fn subst_bound_vars(mut self, substs: &Substs) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
@ -1045,9 +1024,10 @@ impl HirDisplay for Ty {
|
|||||||
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
|
||||||
}
|
}
|
||||||
TypeParamProvenance::ArgumentImplTrait => {
|
TypeParamProvenance::ArgumentImplTrait => {
|
||||||
let bounds = f.db.generic_predicates_for_param(*id);
|
|
||||||
write!(f, "impl ")?;
|
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)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
builtin_type::BuiltinType,
|
builtin_type::BuiltinType,
|
||||||
generics::{WherePredicate, WherePredicateTarget, TypeParamProvenance},
|
generics::{TypeParamProvenance, WherePredicate, WherePredicateTarget},
|
||||||
path::{GenericArg, Path, PathSegment, PathSegments},
|
path::{GenericArg, Path, PathSegment, PathSegments},
|
||||||
resolver::{HasResolver, Resolver, TypeNs},
|
resolver::{HasResolver, Resolver, TypeNs},
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef},
|
||||||
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
|
AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
|
||||||
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
|
LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
|
||||||
TypeParamId
|
VariantId,
|
||||||
};
|
};
|
||||||
use ra_arena::map::ArenaMap;
|
use ra_arena::map::ArenaMap;
|
||||||
use ra_db::CrateId;
|
use ra_db::CrateId;
|
||||||
@ -148,7 +148,9 @@ impl Ty {
|
|||||||
let generics = generics(ctx.db, def);
|
let generics = generics(ctx.db, def);
|
||||||
let param = generics
|
let param = generics
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, data)| data.provenance == TypeParamProvenance::ArgumentImplTrait)
|
.filter(|(_, data)| {
|
||||||
|
data.provenance == TypeParamProvenance::ArgumentImplTrait
|
||||||
|
})
|
||||||
.nth(idx as usize)
|
.nth(idx as usize)
|
||||||
.map_or(Ty::Unknown, |(id, _)| Ty::Param(id));
|
.map_or(Ty::Unknown, |(id, _)| Ty::Param(id));
|
||||||
param
|
param
|
||||||
@ -338,19 +340,12 @@ impl Ty {
|
|||||||
return Ty::Unknown;
|
return Ty::Unknown;
|
||||||
};
|
};
|
||||||
param_id
|
param_id
|
||||||
},
|
}
|
||||||
_ => return Ty::Unknown, // Error: Ambiguous associated type
|
_ => return Ty::Unknown, // Error: Ambiguous associated type
|
||||||
};
|
};
|
||||||
let predicates = ctx.db.generic_predicates_for_param(param_id);
|
let predicates = ctx.db.generic_predicates_for_param(param_id);
|
||||||
let traits_from_env = predicates.iter().filter_map(|pred| match pred {
|
let traits_from_env = predicates.iter().filter_map(|pred| match &pred.value {
|
||||||
GenericPredicate::Implemented(tr) => {
|
GenericPredicate::Implemented(tr) => Some(tr.trait_),
|
||||||
if let Ty::Param(id) = tr.self_ty() {
|
|
||||||
if *id == param_id {
|
|
||||||
return Some(tr.trait_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t));
|
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 generics = generics(db, def);
|
||||||
let mut res = ArenaMap::default();
|
let mut res = ArenaMap::default();
|
||||||
let ctx = TyLoweringContext::new(db, &resolver)
|
let ctx =
|
||||||
.with_type_param_mode(TypeParamLoweringMode::Variable);
|
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
|
||||||
for (field_id, field_data) in var_data.fields().iter() {
|
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)))
|
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(
|
pub(crate) fn generic_predicates_for_param_query(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
param_id: TypeParamId,
|
param_id: TypeParamId,
|
||||||
) -> Arc<[GenericPredicate]> {
|
) -> Arc<[Binders<GenericPredicate>]> {
|
||||||
let resolver = param_id.parent.resolver(db);
|
let resolver = param_id.parent.resolver(db);
|
||||||
let ctx = TyLoweringContext::new(db, &resolver);
|
let ctx =
|
||||||
// let generics = generics(db, def);
|
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
|
||||||
|
let generics = generics(db, param_id.parent);
|
||||||
resolver
|
resolver
|
||||||
.where_predicates_in_scope()
|
.where_predicates_in_scope()
|
||||||
// we have to filter out all other predicates *first*, before attempting to lower them
|
// 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) => {
|
WherePredicateTarget::TypeRef(type_ref) => {
|
||||||
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
|
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
|
||||||
}
|
}
|
||||||
WherePredicateTarget::TypeParam(local_id) => {
|
WherePredicateTarget::TypeParam(local_id) => *local_id == param_id.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()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,13 +659,14 @@ pub(crate) fn generic_predicates_for_param_recover(
|
|||||||
_db: &impl HirDatabase,
|
_db: &impl HirDatabase,
|
||||||
_cycle: &[String],
|
_cycle: &[String],
|
||||||
_param_id: &TypeParamId,
|
_param_id: &TypeParamId,
|
||||||
) -> Arc<[GenericPredicate]> {
|
) -> Arc<[Binders<GenericPredicate>]> {
|
||||||
Arc::new([])
|
Arc::new([])
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraitEnvironment {
|
impl TraitEnvironment {
|
||||||
pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<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
|
let predicates = resolver
|
||||||
.where_predicates_in_scope()
|
.where_predicates_in_scope()
|
||||||
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
|
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
|
||||||
@ -682,12 +680,17 @@ impl TraitEnvironment {
|
|||||||
pub(crate) fn generic_predicates_query(
|
pub(crate) fn generic_predicates_query(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
) -> Arc<[GenericPredicate]> {
|
) -> Arc<[Binders<GenericPredicate>]> {
|
||||||
let resolver = def.resolver(db);
|
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
|
resolver
|
||||||
.where_predicates_in_scope()
|
.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()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -915,12 +918,18 @@ pub(crate) fn impl_self_ty_recover(
|
|||||||
Binders::new(generics.len(), Ty::Unknown)
|
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 impl_data = db.impl_data(impl_id);
|
||||||
let resolver = impl_id.resolver(db);
|
let resolver = impl_id.resolver(db);
|
||||||
let ctx = TyLoweringContext::new(db, &resolver)
|
let ctx =
|
||||||
.with_type_param_mode(TypeParamLoweringMode::Variable);
|
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
|
||||||
let self_ty = db.impl_self_ty(impl_id);
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
let target_trait = impl_data.target_trait.as_ref()?;
|
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()))?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use ra_db::{
|
|||||||
use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
|
use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate,
|
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)]
|
#[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 generic_predicates = db.generic_predicates(def);
|
||||||
let mut result = Vec::with_capacity(generic_predicates.len());
|
let mut result = Vec::with_capacity(generic_predicates.len());
|
||||||
for pred in generic_predicates.iter() {
|
for pred in generic_predicates.iter() {
|
||||||
if pred.is_error() {
|
if pred.value.is_error() {
|
||||||
// skip errored predicates completely
|
// skip errored predicates completely
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.push(pred.clone().subst_type_params(db, def, substs).to_chalk(db));
|
result.push(pred.clone().subst(substs).to_chalk(db));
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user