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 std::sync::Arc;
use hir_def::{ 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_arena::map::ArenaMap;
use ra_db::{salsa, CrateId}; use ra_db::{impl_intern_key, salsa, CrateId};
use ra_prof::profile; use ra_prof::profile;
use crate::{ use crate::{
@ -37,10 +37,10 @@ pub trait HirDatabase: DefDatabase {
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>; fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
#[salsa::invoke(crate::lower::impl_trait_query)] #[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)] #[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)] #[salsa::invoke(crate::callable_item_sig)]
fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; 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)] #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
fn generic_predicates_for_param( fn generic_predicates_for_param(
&self, &self,
def: GenericDefId, param_id: TypeParamId,
param_idx: u32,
) -> Arc<[GenericPredicate]>; ) -> Arc<[GenericPredicate]>;
#[salsa::invoke(crate::lower::generic_predicates_query)] #[salsa::invoke(crate::lower::generic_predicates_query)]
@ -77,6 +76,8 @@ pub trait HirDatabase: DefDatabase {
#[salsa::interned] #[salsa::interned]
fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
#[salsa::interned] #[salsa::interned]
fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
#[salsa::interned]
fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
#[salsa::interned] #[salsa::interned]
fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; 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 hir_database_is_object_safe() {
fn _assert_object_safe(_: &dyn HirDatabase) {} 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)?; let trait_ref = db.impl_trait(impl_id)?;
// `CoerseUnsized` has one generic parameter for the target type. // `CoerseUnsized` has one generic parameter for the target type.
let cur_from_ty = trait_ref.substs.0.get(0)?; let cur_from_ty = trait_ref.value.substs.0.get(0)?;
let cur_to_ty = trait_ref.substs.0.get(1)?; let cur_to_ty = trait_ref.value.substs.0.get(1)?;
match (&cur_from_ty, cur_to_ty) { match (&cur_from_ty, cur_to_ty) {
(ty_app!(ctor1, st1), ty_app!(ctor2, st2)) => { (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. // This works for smart-pointer-like coercion, which covers all impls from std.
st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| { st1.iter().zip(st2.iter()).enumerate().find_map(|(i, (ty1, ty2))| {
match (ty1, ty2) { match (ty1, ty2) {
(Ty::Param { idx: p1, .. }, Ty::Param { idx: p2, .. }) (Ty::Bound(idx1), Ty::Bound(idx2))
if p1 != p2 => if idx1 != idx2 =>
{ {
Some(((*ctor1, *ctor2), i)) Some(((*ctor1, *ctor2), i))
} }
@ -256,8 +256,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let unsize_generic_index = { let unsize_generic_index = {
let mut index = None; let mut index = None;
let mut multiple_param = false; let mut multiple_param = false;
field_tys[last_field_id].walk(&mut |ty| match ty { field_tys[last_field_id].value.walk(&mut |ty| match ty {
&Ty::Param { idx, .. } => { &Ty::Bound(idx) => {
if index.is_none() { if index.is_none() {
index = Some(idx); index = Some(idx);
} else if Some(idx) != index { } else if Some(idx) != index {
@ -276,8 +276,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
// Check other fields do not involve it. // Check other fields do not involve it.
let mut multiple_used = false; let mut multiple_used = false;
fields.for_each(|(field_id, _data)| { fields.for_each(|(field_id, _data)| {
field_tys[field_id].walk(&mut |ty| match ty { field_tys[field_id].value.walk(&mut |ty| match ty {
&Ty::Param { idx, .. } if idx == unsize_generic_index => { &Ty::Bound(idx) if idx == unsize_generic_index => {
multiple_used = true 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); self.result.record_field_resolutions.insert(field.expr, field_def);
} }
let field_ty = field_def let field_ty = field_def
.map_or(Ty::Unknown, |it| field_types[it.local_id].clone()) .map_or(Ty::Unknown, |it| field_types[it.local_id].clone().subst(&substs));
.subst(&substs);
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
} }
if let Some(expr) = spread { if let Some(expr) = spread {
@ -686,7 +685,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(&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) { if let Some(obligation) = Obligation::from_predicate(predicate) {
self.obligations.push(obligation); self.obligations.push(obligation);
} }

View file

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

View file

@ -45,10 +45,10 @@ use std::{fmt, iter, mem};
use hir_def::{ use hir_def::{
expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, 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 ra_db::{impl_intern_key, salsa, CrateId};
use hir_expand::name::Name;
use crate::{ use crate::{
db::HirDatabase, db::HirDatabase,
@ -288,14 +288,7 @@ pub enum Ty {
Projection(ProjectionTy), Projection(ProjectionTy),
/// A type parameter; for example, `T` in `fn f<T>(x: T) {} /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
Param { Param(TypeParamId),
/// 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,
},
/// A bound type variable. Used during trait resolution to represent Chalk /// A bound type variable. Used during trait resolution to represent Chalk
/// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type. /// 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`). /// 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( 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. /// Return Substs that replace each parameter by a bound variable.
pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { 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 { 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)) 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 { pub fn fill_with_unknown(self) -> Self {
self.fill(iter::repeat(Ty::Unknown)) 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. /// 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 /// if `self` is `&[T]`, where type parameter T has index 0, and the
/// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) /// `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 where
Self: Sized, Self: Sized,
{ {
let generics = generics(db, def);
self.fold(&mut |ty| match ty { self.fold(&mut |ty| match ty {
Ty::Param { idx, name } => { Ty::Param(id) => {
substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name }) if let Some(idx) = generics.param_idx(id) {
substs.get(idx as usize).cloned().unwrap_or(Ty::Param(id))
} else {
ty
}
} }
ty => ty, ty => ty,
}) })
@ -1042,7 +1036,18 @@ impl HirDisplay for Ty {
match self { match self {
Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
Ty::Projection(p_ty) => p_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::Bound(idx) => write!(f, "?{}", idx)?,
Ty::Dyn(predicates) | Ty::Opaque(predicates) => { Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
match self { match self {

View file

@ -30,7 +30,7 @@ use crate::{
Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs,
TraitEnvironment, TraitRef, Ty, TypeCtor, TraitEnvironment, TraitRef, Ty, TypeCtor,
}; };
use hir_expand::name::Name; use hir_def::TypeParamId;
#[derive(Debug)] #[derive(Debug)]
pub struct TyLoweringContext<'a, DB: HirDatabase> { pub struct TyLoweringContext<'a, DB: HirDatabase> {
@ -145,7 +145,16 @@ impl Ty {
ImplTraitLoweringMode::Param => { ImplTraitLoweringMode::Param => {
let idx = ctx.impl_trait_counter.get(); let idx = ctx.impl_trait_counter.get();
ctx.impl_trait_counter.set(idx + 1); 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 => { ImplTraitLoweringMode::Variable => {
let idx = ctx.impl_trait_counter.get(); let idx = ctx.impl_trait_counter.get();
@ -176,7 +185,7 @@ impl Ty {
fn from_hir_only_param( fn from_hir_only_param(
ctx: &TyLoweringContext<'_, impl HirDatabase>, ctx: &TyLoweringContext<'_, impl HirDatabase>,
type_ref: &TypeRef, type_ref: &TypeRef,
) -> Option<u32> { ) -> Option<TypeParamId> {
let path = match type_ref { let path = match type_ref {
TypeRef::Path(path) => path, TypeRef::Path(path) => path,
_ => return None, _ => return None,
@ -192,9 +201,7 @@ impl Ty {
_ => return None, _ => return None,
}; };
if let TypeNs::GenericParam(param_id) = resolution { if let TypeNs::GenericParam(param_id) = resolution {
let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); Some(param_id)
let idx = generics.param_idx(param_id);
Some(idx)
} else { } else {
None None
} }
@ -256,20 +263,18 @@ impl Ty {
TypeNs::GenericParam(param_id) => { TypeNs::GenericParam(param_id) => {
let generics = let generics =
generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope"));
let idx = generics.param_idx(param_id);
match ctx.type_param_mode { match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => { TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
// FIXME: maybe return name in resolution? TypeParamLoweringMode::Variable => {
let name = generics.param_name(param_id); let idx = generics.param_idx(param_id).expect("matching generics");
Ty::Param { idx, name } Ty::Bound(idx)
} }
TypeParamLoweringMode::Variable => Ty::Bound(idx),
} }
} }
TypeNs::SelfType(impl_id) => { TypeNs::SelfType(impl_id) => {
let generics = generics(ctx.db, impl_id.into()); let generics = generics(ctx.db, impl_id.into());
let substs = match ctx.type_param_mode { let substs = match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Substs::identity(&generics), TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
}; };
ctx.db.impl_self_ty(impl_id).subst(&substs) ctx.db.impl_self_ty(impl_id).subst(&substs)
@ -277,7 +282,7 @@ impl Ty {
TypeNs::AdtSelfType(adt) => { TypeNs::AdtSelfType(adt) => {
let generics = generics(ctx.db, adt.into()); let generics = generics(ctx.db, adt.into());
let substs = match ctx.type_param_mode { let substs = match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => Substs::identity(&generics), TypeParamLoweringMode::Placeholder => Substs::type_params(&generics),
TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), TypeParamLoweringMode::Variable => Substs::bound_vars(&generics),
}; };
ctx.db.ty(adt.into()).subst(&substs) ctx.db.ty(adt.into()).subst(&substs)
@ -319,20 +324,28 @@ impl Ty {
self_ty: Ty, self_ty: Ty,
segment: PathSegment<'_>, segment: PathSegment<'_>,
) -> Ty { ) -> 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() { let def = match ctx.resolver.generic_def() {
Some(def) => def, Some(def) => def,
None => return Ty::Unknown, // this can't actually happen 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 { let traits_from_env = predicates.iter().filter_map(|pred| match pred {
GenericPredicate::Implemented(tr) => { GenericPredicate::Implemented(tr) => {
if let Ty::Param { idx, .. } = tr.self_ty() { if let Ty::Param(id) = tr.self_ty() {
if *idx == param_idx { if *id == param_id {
return Some(tr.trait_); return Some(tr.trait_);
} }
} }
@ -530,13 +543,12 @@ impl GenericPredicate {
let generic_def = ctx.resolver.generic_def().expect("generics in scope"); let generic_def = ctx.resolver.generic_def().expect("generics in scope");
let generics = generics(ctx.db, generic_def); let generics = generics(ctx.db, generic_def);
let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; 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 { match ctx.type_param_mode {
TypeParamLoweringMode::Placeholder => { TypeParamLoweringMode::Placeholder => Ty::Param(param_id),
let name = generics.param_name(param_id); TypeParamLoweringMode::Variable => {
Ty::Param { idx, name } 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( pub(crate) fn field_types_query(
db: &impl HirDatabase, db: &impl HirDatabase,
variant_id: VariantId, variant_id: VariantId,
) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { ) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> {
let var_data = variant_data(db, variant_id); let var_data = variant_data(db, variant_id);
let resolver = match variant_id { let (resolver, def): (_, GenericDefId) = match variant_id {
VariantId::StructId(it) => it.resolver(db), VariantId::StructId(it) => (it.resolver(db), it.into()),
VariantId::UnionId(it) => it.resolver(db), VariantId::UnionId(it) => (it.resolver(db), it.into()),
VariantId::EnumVariantId(it) => it.parent.resolver(db), VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()),
}; };
let generics = generics(db, def);
let mut res = ArenaMap::default(); 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() { 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) Arc::new(res)
} }
@ -624,23 +638,20 @@ pub(crate) fn field_types_query(
/// these are fine: `T: Foo<U::Item>, U: Foo<()>`. /// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
pub(crate) fn generic_predicates_for_param_query( pub(crate) fn generic_predicates_for_param_query(
db: &impl HirDatabase, db: &impl HirDatabase,
def: GenericDefId, param_id: TypeParamId,
param_idx: u32,
) -> Arc<[GenericPredicate]> { ) -> Arc<[GenericPredicate]> {
let resolver = def.resolver(db); let resolver = param_id.parent.resolver(db);
let ctx = TyLoweringContext::new(db, &resolver); let ctx = TyLoweringContext::new(db, &resolver);
let generics = generics(db, def); // let generics = generics(db, def);
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
.filter(|pred| match &pred.target { .filter(|pred| match &pred.target {
WherePredicateTarget::TypeRef(type_ref) => { 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) => { WherePredicateTarget::TypeParam(local_id) => {
let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; *local_id == param_id.local_id
let idx = generics.param_idx(param_id);
idx == param_idx
} }
}) })
.flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) .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( pub(crate) fn generic_predicates_for_param_recover(
_db: &impl HirDatabase, _db: &impl HirDatabase,
_cycle: &[String], _cycle: &[String],
_def: &GenericDefId, _param_id: &TypeParamId,
_param_idx: &u32,
) -> Arc<[GenericPredicate]> { ) -> Arc<[GenericPredicate]> {
Arc::new([]) Arc::new([])
} }
@ -905,12 +915,12 @@ 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<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 generics = generics(db, impl_id.into()); let ctx = TyLoweringContext::new(db, &resolver)
let ctx = TyLoweringContext::new(db, &resolver); .with_type_param_mode(TypeParamLoweringMode::Variable);
let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics)); 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()?;
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() { for impl_id in module_data.scope.impls() {
match db.impl_trait(impl_id) { match db.impl_trait(impl_id) {
Some(tr) => { 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 => { None => {
let self_ty = db.impl_self_ty(impl_id); 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 [71; 72) 't': T
[77; 96) '{ ...d(); }': () [77; 96) '{ ...d(); }': ()
[83; 84) 't': T [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]. // 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<T>");
assert_eq!(t, "ApplyL::Out<[missing name]>");
} }
#[test] #[test]

View file

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

View file

@ -99,23 +99,19 @@ pub(crate) struct Generics {
} }
impl 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 self.parent_generics
.as_ref() .as_ref()
.into_iter() .into_iter()
.flat_map(|it| it.params.types.iter()) .flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
.chain(self.params.types.iter()) .chain(self.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: self.def, local_id }, p)))
.enumerate()
.map(|(i, (_local_id, p))| (i as u32, 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 self.parent_generics
.as_ref() .as_ref()
.into_iter() .into_iter()
.flat_map(|it| it.params.types.iter()) .flat_map(|it| it.params.types.iter().map(move |(local_id, p)| (TypeParamId { parent: it.def, local_id }, p)))
.enumerate()
.map(|(i, (_local_id, p))| (i as u32, p))
} }
pub(crate) fn len(&self) -> usize { pub(crate) fn len(&self) -> usize {
@ -137,16 +133,11 @@ impl Generics {
(self_params, list_params, impl_trait_params) (self_params, list_params, impl_trait_params)
} }
pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { pub(crate) fn param_idx(&self, param: TypeParamId) -> Option<u32> {
self.find_param(param).0 Some(self.find_param(param)?.0)
} }
pub(crate) fn param_name(&self, param: TypeParamId) -> Name { fn find_param(&self, param: TypeParamId) -> Option<(u32, &TypeParamData)> {
// 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) {
if param.parent == self.def { if param.parent == self.def {
let (idx, (_local_id, data)) = self let (idx, (_local_id, data)) = self
.params .params
@ -156,9 +147,10 @@ impl Generics {
.find(|(_, (idx, _))| *idx == param.local_id) .find(|(_, (idx, _))| *idx == param.local_id)
.unwrap(); .unwrap();
let (_total, parent_len, _child) = self.len_split(); 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)
} }
} }