Change Ty::Param to contain param ID

This commit is contained in:
Florian Diebold 2020-01-31 16:52:43 +01:00
parent f8b7b64bce
commit ed25cf70d5
11 changed files with 136 additions and 127 deletions

View file

@ -3,10 +3,10 @@
use std::sync::Arc;
use hir_def::{
db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId,
db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId, TypeParamId,
};
use ra_arena::map::ArenaMap;
use ra_db::{salsa, CrateId};
use ra_db::{impl_intern_key, salsa, CrateId};
use ra_prof::profile;
use crate::{
@ -37,10 +37,10 @@ pub trait HirDatabase: DefDatabase {
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
#[salsa::invoke(crate::lower::impl_trait_query)]
fn impl_trait(&self, def: ImplId) -> Option<TraitRef>;
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
#[salsa::invoke(crate::lower::field_types_query)]
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>>;
#[salsa::invoke(crate::callable_item_sig)]
fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig;
@ -49,8 +49,7 @@ pub trait HirDatabase: DefDatabase {
#[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
fn generic_predicates_for_param(
&self,
def: GenericDefId,
param_idx: u32,
param_id: TypeParamId,
) -> Arc<[GenericPredicate]>;
#[salsa::invoke(crate::lower::generic_predicates_query)]
@ -77,6 +76,8 @@ pub trait HirDatabase: DefDatabase {
#[salsa::interned]
fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
#[salsa::interned]
fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
#[salsa::interned]
fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
#[salsa::interned]
fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
@ -117,3 +118,7 @@ fn infer(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
fn hir_database_is_object_safe() {
fn _assert_object_safe(_: &dyn HirDatabase) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct GlobalTypeParamId(salsa::InternId);
impl_intern_key!(GlobalTypeParamId);

View file

@ -57,8 +57,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let trait_ref = db.impl_trait(impl_id)?;
// `CoerseUnsized` has one generic parameter for the target type.
let cur_from_ty = trait_ref.substs.0.get(0)?;
let cur_to_ty = trait_ref.substs.0.get(1)?;
let cur_from_ty = trait_ref.value.substs.0.get(0)?;
let cur_to_ty = trait_ref.value.substs.0.get(1)?;
match (&cur_from_ty, cur_to_ty) {
(ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => {
@ -66,8 +66,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
// This works for smart-pointer-like coercion, which covers all impls from std.
st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| {
match (ty1, ty2) {
(Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. })
if p1 != p2 =>
(Ty::Bound(idx1), Ty::Bound(idx2))
if idx1 != idx2 =>
{
Some(((*ctor1, *ctor2), i))
}
@ -256,8 +256,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let unsize_generic_index = {
let mut index = None;
let mut multiple_param = false;
field_tys[last_field_id].walk(&mut |ty| match ty {
&Ty::Param { idx, .. } => {
field_tys[last_field_id].value.walk(&mut |ty| match ty {
&Ty::Bound(idx) => {
if index.is_none() {
index = Some(idx);
} else if Some(idx) != index {
@ -276,8 +276,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
// Check other fields do not involve it.
let mut multiple_used = false;
fields.for_each(|(field_id, _data)| {
field_tys[field_id].walk(&mut |ty| match ty {
&Ty::Param { idx, .. } if idx == unsize_generic_index => {
field_tys[field_id].value.walk(&mut |ty| match ty {
&Ty::Bound(idx) if idx == unsize_generic_index => {
multiple_used = true
}
_ => {}

View file

@ -236,8 +236,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
self.result.record_field_resolutions.insert(field.expr, field_def);
}
let field_ty = field_def
.map_or(Ty::Unknown, |it| field_types[it.local_id].clone())
.subst(&substs);
.map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs));
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
}
if let Some(expr) = spread {
@ -686,7 +685,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(&a_ty.parameters);
let predicate = predicate.clone().subst_type_params(self.db, def.into(), &a_ty.parameters);
if let Some(obligation) = Obligation::from_predicate(predicate) {
self.obligations.push(obligation);
}

View file

@ -12,7 +12,7 @@ use hir_expand::name::Name;
use test_utils::tested_by;
use super::{BindingMode, InferenceContext};
use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk};
use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor};
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
fn infer_tuple_struct_pat(
@ -34,8 +34,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let expected_ty = var_data
.as_ref()
.and_then(|d| d.field(&Name::new_tuple_field(i)))
.map_or(Ty::Unknown, |field| field_tys[field].clone())
.subst(&substs);
.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
let expected_ty = self.normalize_associated_types_in(expected_ty);
self.infer_pat(subpat, &expected_ty, default_bm);
}
@ -65,7 +64,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
for subpat in subpats {
let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
let expected_ty =
matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs);
matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs));
let expected_ty = self.normalize_associated_types_in(expected_ty);
self.infer_pat(subpat.pat, &expected_ty, default_bm);
}

View file

@ -45,10 +45,10 @@ use std::{fmt, iter, mem};
use hir_def::{
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId,
HasModule, Lookup, TraitId, TypeAliasId,
HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, generics::TypeParamProvenance,
};
use hir_expand::name::Name;
use ra_db::{impl_intern_key, salsa, CrateId};
use hir_expand::name::Name;
use crate::{
db::HirDatabase,
@ -288,14 +288,7 @@ pub enum Ty {
Projection(ProjectionTy),
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
Param {
/// The index of the parameter (starting with parameters from the
/// surrounding impl, then the current function).
idx: u32,
/// The name of the parameter, for displaying.
// FIXME get rid of this
name: Name,
},
Param(TypeParamId),
/// A bound type variable. Used during trait resolution to represent Chalk
/// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
@ -366,15 +359,15 @@ impl Substs {
}
/// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
pub(crate) fn identity(generic_params: &Generics) -> Substs {
pub(crate) fn type_params(generic_params: &Generics) -> Substs {
Substs(
generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone().unwrap_or_else(Name::missing) }).collect(),
generic_params.iter().map(|(id, _)| Ty::Param(id)).collect(),
)
}
/// Return Substs that replace each parameter by a bound variable.
pub(crate) fn bound_vars(generic_params: &Generics) -> Substs {
Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect())
Substs(generic_params.iter().enumerate().map(|(idx, _)| Ty::Bound(idx as u32)).collect())
}
pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
@ -422,11 +415,6 @@ impl SubstsBuilder {
self.fill((starting_from..).map(Ty::Bound))
}
pub fn fill_with_params(self) -> Self {
let start = self.vec.len() as u32;
self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
}
pub fn fill_with_unknown(self) -> Self {
self.fill(iter::repeat(Ty::Unknown))
}
@ -762,13 +750,19 @@ pub trait TypeWalk {
/// 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.)
fn subst(self, substs: &Substs) -> Self
// 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 { idx, name } => {
substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
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,
})
@ -1042,7 +1036,18 @@ impl HirDisplay for Ty {
match self {
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
Ty::Param { name, .. } => write!(f, "{}", name)?,
Ty::Param(id) => {
let generic_params = f.db.generic_params(id.parent);
let param_data = &generic_params.types[id.local_id];
match param_data.provenance {
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
}
TypeParamProvenance::ArgumentImplTrait => {
write!(f, "impl TODO")?
}
}
},
Ty::Bound(idx) => write!(f, "?{}", idx)?,
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
match self {

View file

@ -30,7 +30,7 @@ use crate::{
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
TraitEnvironment, TraitRef, Ty, TypeCtor,
};
use hir_expand::name::Name;
use hir_def::TypeParamId;
#[derive(Debug)]
pub struct TyLoweringContext<'a, DB: HirDatabase> {
@ -145,7 +145,16 @@ impl Ty {
ImplTraitLoweringMode::Param => {
let idx = ctx.impl_trait_counter.get();
ctx.impl_trait_counter.set(idx + 1);
Ty::Param { idx: idx as u32, name: Name::missing() }
if let Some(def) = ctx.resolver.generic_def() {
let generics = generics(ctx.db, def);
let param = generics
.iter()
.nth(idx as usize)
.map_or(Ty::Unknown, |(id, _)| Ty::Param(id));
param
} else {
Ty::Unknown
}
}
ImplTraitLoweringMode::Variable => {
let idx = ctx.impl_trait_counter.get();
@ -176,7 +185,7 @@ impl Ty {
fn from_hir_only_param(
ctx: &TyLoweringContext<'_, impl HirDatabase>,
type_ref: &TypeRef,
) -> Option<u32> {
) -> Option<TypeParamId> {
let path = match type_ref {
TypeRef::Path(path) => path,
_ => return None,
@ -192,9 +201,7 @@ impl Ty {
_ => return None,
};
if let TypeNs::GenericParam(param_id) = resolution {
let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
let idx = generics.param_idx(param_id);
Some(idx)
Some(param_id)
} else {
None
}
@ -256,20 +263,18 @@ impl Ty {
TypeNs::GenericParam(param_id) => {
let generics =
generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
let idx = generics.param_idx(param_id);
match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => {
// FIXME: maybe return name in resolution?
let name = generics.param_name(param_id);
Ty::Param { idx, name }
TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
TypeParamLoweringMode::Variable => {
let idx = generics.param_idx(param_id).expect("matching generics");
Ty::Bound(idx)
}
TypeParamLoweringMode::Variable => Ty::Bound(idx),
}
}
TypeNs::SelfType(impl_id) => {
let generics = generics(ctx.db, impl_id.into());
let substs = match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Substs::identity(&generics),
TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
};
ctx.db.impl_self_ty(impl_id).subst(&substs)
@ -277,7 +282,7 @@ impl Ty {
TypeNs::AdtSelfType(adt) => {
let generics = generics(ctx.db, adt.into());
let substs = match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Substs::identity(&generics),
TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
};
ctx.db.ty(adt.into()).subst(&substs)
@ -319,20 +324,28 @@ impl Ty {
self_ty: Ty,
segment: PathSegment<'_>,
) -> Ty {
let param_idx = match self_ty {
Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx,
Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx,
_ => return Ty::Unknown, // Error: Ambiguous associated type
};
let def = match ctx.resolver.generic_def() {
Some(def) => def,
None => return Ty::Unknown, // this can't actually happen
};
let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx);
let param_id = match self_ty {
Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id,
Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => {
let generics = generics(ctx.db, def);
let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) {
id
} else {
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 { idx, .. } = tr.self_ty() {
if *idx == param_idx {
if let Ty::Param(id) = tr.self_ty() {
if *id == param_id {
return Some(tr.trait_);
}
}
@ -530,13 +543,12 @@ impl GenericPredicate {
let generic_def = ctx.resolver.generic_def().expect("generics in scope");
let generics = generics(ctx.db, generic_def);
let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id };
let idx = generics.param_idx(param_id);
match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => {
let name = generics.param_name(param_id);
Ty::Param { idx, name }
TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
TypeParamLoweringMode::Variable => {
let idx = generics.param_idx(param_id).expect("matching generics");
Ty::Bound(idx)
}
TypeParamLoweringMode::Variable => Ty::Bound(idx),
}
}
};
@ -599,17 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig {
pub(crate) fn field_types_query(
db: &impl HirDatabase,
variant_id: VariantId,
) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> {
let var_data = variant_data(db, variant_id);
let resolver = match variant_id {
VariantId::StructId(it) => it.resolver(db),
VariantId::UnionId(it) => it.resolver(db),
VariantId::EnumVariantId(it) => it.parent.resolver(db),
let (resolver, def): (_, GenericDefId) = match variant_id {
VariantId::StructId(it) => (it.resolver(db), it.into()),
VariantId::UnionId(it) => (it.resolver(db), it.into()),
VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()),
};
let generics = generics(db, def);
let mut res = ArenaMap::default();
let ctx = TyLoweringContext::new(db, &resolver);
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, Ty::from_hir(&ctx, &field_data.type_ref))
res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref)))
}
Arc::new(res)
}
@ -624,23 +638,20 @@ pub(crate) fn field_types_query(
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
pub(crate) fn generic_predicates_for_param_query(
db: &impl HirDatabase,
def: GenericDefId,
param_idx: u32,
param_id: TypeParamId,
) -> Arc<[GenericPredicate]> {
let resolver = def.resolver(db);
let resolver = param_id.parent.resolver(db);
let ctx = TyLoweringContext::new(db, &resolver);
let generics = generics(db, def);
// let generics = generics(db, def);
resolver
.where_predicates_in_scope()
// we have to filter out all other predicates *first*, before attempting to lower them
.filter(|pred| match &pred.target {
WherePredicateTarget::TypeRef(type_ref) => {
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx)
Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
}
WherePredicateTarget::TypeParam(local_id) => {
let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id };
let idx = generics.param_idx(param_id);
idx == param_idx
*local_id == param_id.local_id
}
})
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred))
@ -650,8 +661,7 @@ pub(crate) fn generic_predicates_for_param_query(
pub(crate) fn generic_predicates_for_param_recover(
_db: &impl HirDatabase,
_cycle: &[String],
_def: &GenericDefId,
_param_idx: &u32,
_param_id: &TypeParamId,
) -> Arc<[GenericPredicate]> {
Arc::new([])
}
@ -905,12 +915,12 @@ 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<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 generics = generics(db, impl_id.into());
let ctx = TyLoweringContext::new(db, &resolver);
let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics));
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()?;
TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone()))
Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?))
}

View file

@ -61,7 +61,7 @@ impl CrateImplBlocks {
for impl_id in module_data.scope.impls() {
match db.impl_trait(impl_id) {
Some(tr) => {
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
res.impls_by_trait.entry(tr.value.trait_).or_default().push(impl_id);
}
None => {
let self_ty = db.impl_self_ty(impl_id);

View file

@ -697,7 +697,7 @@ fn test<U, T: Trait<U>>(t: T) {
[71; 72) 't': T
[77; 96) '{ ...d(); }': ()
[83; 84) 't': T
[83; 93) 't.method()': [missing name]
[83; 93) 't.method()': U
"###
);
}

View file

@ -822,8 +822,7 @@ fn test<T: ApplyL>() {
"#,
);
// inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
// FIXME: fix type parameter names going missing when going through Chalk
assert_eq!(t, "ApplyL::Out<[missing name]>");
assert_eq!(t, "ApplyL::Out<T>");
}
#[test]

View file

@ -142,8 +142,9 @@ impl ToChalk for Ty {
let substitution = proj_ty.parameters.to_chalk(db);
chalk_ir::AliasTy { associated_ty_id, substitution }.cast().intern()
}
Ty::Param { idx, .. } => {
PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }
Ty::Param(id) => {
let interned_id = db.intern_type_param_id(id);
PlaceholderIndex { ui: UniverseIndex::ROOT, idx: interned_id.as_intern_id().as_usize() }
.to_ty::<TypeFamily>()
}
Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(),
@ -177,7 +178,8 @@ impl ToChalk for Ty {
},
chalk_ir::TyData::Placeholder(idx) => {
assert_eq!(idx.ui, UniverseIndex::ROOT);
Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() }
let interned_id = crate::db::GlobalTypeParamId::from_intern_id(crate::salsa::InternId::from(idx.idx));
Ty::Param(db.lookup_intern_type_param_id(interned_id))
}
chalk_ir::TyData::Alias(proj) => {
let associated_ty = from_chalk(db, proj.associated_ty_id);
@ -524,7 +526,7 @@ fn convert_where_clauses(
// skip errored predicates completely
continue;
}
result.push(pred.clone().subst(substs).to_chalk(db));
result.push(pred.clone().subst_type_params(db, def, substs).to_chalk(db));
}
result
}
@ -709,12 +711,12 @@ fn impl_block_datum(
let trait_ref = db
.impl_trait(impl_id)
// ImplIds for impls where the trait ref can't be resolved should never reach Chalk
.expect("invalid impl passed to Chalk");
.expect("invalid impl passed to Chalk")
.value;
let impl_data = db.impl_data(impl_id);
let generic_params = generics(db, impl_id.into());
let bound_vars = Substs::bound_vars(&generic_params);
let trait_ref = trait_ref.subst(&bound_vars);
let trait_ = trait_ref.trait_;
let impl_type = if impl_id.lookup(db).container.module(db).krate == krate {
chalk_rust_ir::ImplType::Local
@ -789,20 +791,18 @@ fn type_alias_associated_ty_value(
_ => panic!("assoc ty value should be in impl"),
};
let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved
let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved
let assoc_ty = db
.trait_data(trait_ref.trait_)
.associated_type_by_name(&type_alias_data.name)
.expect("assoc ty value should not exist"); // validated when building the impl data as well
let generic_params = generics(db, impl_id.into());
let bound_vars = Substs::bound_vars(&generic_params);
let ty = db.ty(type_alias.into()).subst(&bound_vars);
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
let ty = db.ty(type_alias.into());
let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
let value = chalk_rust_ir::AssociatedTyValue {
impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db),
associated_ty_id: assoc_ty.to_chalk(db),
value: make_binders(value_bound, bound_vars.len()),
value: make_binders(value_bound, ty.num_binders),
};
Arc::new(value)
}

View file

@ -99,23 +99,19 @@ pub(crate) struct Generics {
}
impl Generics {
pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a {
pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
self.parent_generics
.as_ref()
.into_iter()
.flat_map(|it| it.params.types.iter())
.chain(self.params.types.iter())
.enumerate()
.map(|(i, (_local_id, p))| (i as u32, p))
.flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
.chain(self.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)))
}
pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (u32, &'a TypeParamData)> + 'a {
pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator<Item = (TypeParamId, &'a TypeParamData)> + 'a {
self.parent_generics
.as_ref()
.into_iter()
.flat_map(|it| it.params.types.iter())
.enumerate()
.map(|(i, (_local_id, p))| (i as u32, p))
.flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
}
pub(crate) fn len(&self) -> usize {
@ -137,16 +133,11 @@ impl Generics {
(self_params, list_params, impl_trait_params)
}
pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 {
self.find_param(param).0
pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> {
Some(self.find_param(param)?.0)
}
pub(crate) fn param_name(&self, param: TypeParamId) -> Name {
// FIXME make this return Option
self.find_param(param).1.name.clone().unwrap_or_else(Name::missing)
}
fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) {
fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> {
if param.parent == self.def {
let (idx, (_local_id, data)) = self
.params
@ -156,9 +147,10 @@ impl Generics {
.find(|(_, (idx, _))| *idx == param.local_id)
.unwrap();
let (_total, parent_len, _child) = self.len_split();
return ((parent_len + idx) as u32, data);
Some(((parent_len + idx) as u32, data))
} else {
self.parent_generics.as_ref().and_then(|g| g.find_param(param))
}
self.parent_generics.as_ref().unwrap().find_param(param)
}
}