11660: Insert dummy values for const generics in subst r=flodiebold a=HKalbasi

fix #11659 

This is a band-aid until proper const generic support.

Co-authored-by: hkalbasi <hamidrezakalbasi@protonmail.com>
This commit is contained in:
bors[bot] 2022-03-09 17:18:03 +00:00 committed by GitHub
commit 4fcaefa62a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 176 additions and 62 deletions

View file

@ -293,7 +293,7 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
let params = f.db.generic_params(def); let params = f.db.generic_params(def);
if params.lifetimes.is_empty() if params.lifetimes.is_empty()
&& params && params
.types .tocs
.iter() .iter()
.filter_map(|x| x.1.type_param()) .filter_map(|x| x.1.type_param())
.all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList)) .all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
@ -315,7 +315,7 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
delim(f)?; delim(f)?;
write!(f, "{}", lifetime.name)?; write!(f, "{}", lifetime.name)?;
} }
for (_, ty) in params.types.iter() { for (_, ty) in params.tocs.iter() {
if let Some(name) = &ty.name() { if let Some(name) = &ty.name() {
match ty { match ty {
TypeOrConstParamData::TypeParamData(ty) => { TypeOrConstParamData::TypeParamData(ty) => {
@ -348,7 +348,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`. // unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target { let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
WherePredicateTypeTarget::TypeRef(_) => false, WherePredicateTypeTarget::TypeRef(_) => false,
WherePredicateTypeTarget::TypeOrConstParam(id) => params.types[*id].name().is_none(), WherePredicateTypeTarget::TypeOrConstParam(id) => params.tocs[*id].name().is_none(),
}; };
let has_displayable_predicate = params let has_displayable_predicate = params
@ -364,7 +364,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter) -> Result<(), Hir
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target { let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter| match target {
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f), WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
WherePredicateTypeTarget::TypeOrConstParam(id) => match &params.types[*id].name() { WherePredicateTypeTarget::TypeOrConstParam(id) => match &params.tocs[*id].name() {
Some(name) => write!(f, "{}", name), Some(name) => write!(f, "{}", name),
None => write!(f, "{{unnamed}}"), None => write!(f, "{{unnamed}}"),
}, },

View file

@ -2029,7 +2029,7 @@ impl_from!(
impl GenericDef { impl GenericDef {
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> { pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
let generics = db.generic_params(self.into()); let generics = db.generic_params(self.into());
let ty_params = generics.types.iter().map(|(local_id, _)| { let ty_params = generics.tocs.iter().map(|(local_id, _)| {
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } }; let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
match toc.split(db) { match toc.split(db) {
Either::Left(x) => GenericParam::ConstParam(x), Either::Left(x) => GenericParam::ConstParam(x),
@ -2049,7 +2049,7 @@ impl GenericDef {
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> { pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
let generics = db.generic_params(self.into()); let generics = db.generic_params(self.into());
generics generics
.types .tocs
.iter() .iter()
.map(|(local_id, _)| TypeOrConstParam { .map(|(local_id, _)| TypeOrConstParam {
id: TypeOrConstParamId { parent: self.into(), local_id }, id: TypeOrConstParamId { parent: self.into(), local_id },
@ -2371,7 +2371,7 @@ impl ConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name { pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent()); let params = db.generic_params(self.id.parent());
match params.types[self.id.local_id()].name() { match params.tocs[self.id.local_id()].name() {
Some(x) => x.clone(), Some(x) => x.clone(),
None => { None => {
never!(); never!();
@ -2403,7 +2403,7 @@ pub struct TypeOrConstParam {
impl TypeOrConstParam { impl TypeOrConstParam {
pub fn name(self, db: &dyn HirDatabase) -> Name { pub fn name(self, db: &dyn HirDatabase) -> Name {
let params = db.generic_params(self.id.parent); let params = db.generic_params(self.id.parent);
match params.types[self.id.local_id].name() { match params.tocs[self.id.local_id].name() {
Some(n) => n.clone(), Some(n) => n.clone(),
_ => Name::missing(), _ => Name::missing(),
} }
@ -2419,7 +2419,7 @@ impl TypeOrConstParam {
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> { pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
let params = db.generic_params(self.id.parent); let params = db.generic_params(self.id.parent);
match &params.types[self.id.local_id] { match &params.tocs[self.id.local_id] {
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => { hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
Either::Right(TypeParam { id: self.id.into() }) Either::Right(TypeParam { id: self.id.into() })
} }

View file

@ -77,6 +77,13 @@ impl TypeOrConstParamData {
} }
} }
pub fn const_param(&self) -> Option<&ConstParamData> {
match self {
TypeOrConstParamData::TypeParamData(_) => None,
TypeOrConstParamData::ConstParamData(x) => Some(x),
}
}
pub fn is_trait_self(&self) -> bool { pub fn is_trait_self(&self) -> bool {
match self { match self {
TypeOrConstParamData::TypeParamData(x) => { TypeOrConstParamData::TypeParamData(x) => {
@ -92,7 +99,7 @@ impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
/// Data about the generic parameters of a function, struct, impl, etc. /// Data about the generic parameters of a function, struct, impl, etc.
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
pub struct GenericParams { pub struct GenericParams {
pub types: Arena<TypeOrConstParamData>, pub tocs: Arena<TypeOrConstParamData>,
pub lifetimes: Arena<LifetimeParamData>, pub lifetimes: Arena<LifetimeParamData>,
pub where_predicates: Vec<WherePredicate>, pub where_predicates: Vec<WherePredicate>,
} }
@ -131,7 +138,13 @@ impl GenericParams {
pub fn type_iter<'a>( pub fn type_iter<'a>(
&'a self, &'a self,
) -> impl Iterator<Item = (Idx<TypeOrConstParamData>, &TypeParamData)> { ) -> impl Iterator<Item = (Idx<TypeOrConstParamData>, &TypeParamData)> {
self.types.iter().filter_map(|x| x.1.type_param().map(|y| (x.0, y))) self.tocs.iter().filter_map(|x| x.1.type_param().map(|y| (x.0, y)))
}
pub fn toc_iter<'a>(
&'a self,
) -> impl Iterator<Item = (Idx<TypeOrConstParamData>, &TypeOrConstParamData)> {
self.tocs.iter()
} }
pub(crate) fn generic_params_query( pub(crate) fn generic_params_query(
@ -238,7 +251,7 @@ impl GenericParams {
default, default,
provenance: TypeParamProvenance::TypeParamList, provenance: TypeParamProvenance::TypeParamList,
}; };
self.types.alloc(param.into()); self.tocs.alloc(param.into());
let type_ref = TypeRef::Path(name.into()); let type_ref = TypeRef::Path(name.into());
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
} }
@ -248,7 +261,7 @@ impl GenericParams {
.ty() .ty()
.map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); .map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
let param = ConstParamData { name, ty: Interned::new(ty) }; let param = ConstParamData { name, ty: Interned::new(ty) };
self.types.alloc(param.into()); self.tocs.alloc(param.into());
} }
} }
} }
@ -335,7 +348,7 @@ impl GenericParams {
default: None, default: None,
provenance: TypeParamProvenance::ArgumentImplTrait, provenance: TypeParamProvenance::ArgumentImplTrait,
}; };
let param_id = self.types.alloc(param.into()); let param_id = self.tocs.alloc(param.into());
for bound in bounds { for bound in bounds {
self.where_predicates.push(WherePredicate::TypeBound { self.where_predicates.push(WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeOrConstParam(param_id), target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
@ -359,27 +372,27 @@ impl GenericParams {
} }
pub(crate) fn shrink_to_fit(&mut self) { pub(crate) fn shrink_to_fit(&mut self) {
let Self { lifetimes, types, where_predicates } = self; let Self { lifetimes, tocs: types, where_predicates } = self;
lifetimes.shrink_to_fit(); lifetimes.shrink_to_fit();
types.shrink_to_fit(); types.shrink_to_fit();
where_predicates.shrink_to_fit(); where_predicates.shrink_to_fit();
} }
pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> { pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> {
self.types self.tocs
.iter() .iter()
.filter(|x| matches!(x.1, TypeOrConstParamData::TypeParamData(_))) .filter(|x| matches!(x.1, TypeOrConstParamData::TypeParamData(_)))
.find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None }) .find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None })
} }
pub fn find_type_or_const_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> { pub fn find_type_or_const_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> {
self.types self.tocs
.iter() .iter()
.find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None }) .find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None })
} }
pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> { pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
self.types.iter().find_map(|(id, p)| { self.tocs.iter().find_map(|(id, p)| {
if let TypeOrConstParamData::TypeParamData(p) = p { if let TypeOrConstParamData::TypeParamData(p) = p {
if p.provenance == TypeParamProvenance::TraitSelf { if p.provenance == TypeParamProvenance::TraitSelf {
Some(id) Some(id)
@ -438,7 +451,7 @@ impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
db: &dyn DefDatabase, db: &dyn DefDatabase,
) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> { ) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
let generic_params = db.generic_params(*self); let generic_params = db.generic_params(*self);
let mut idx_iter = generic_params.types.iter().map(|(idx, _)| idx); let mut idx_iter = generic_params.tocs.iter().map(|(idx, _)| idx);
let (file_id, generic_params_list) = file_id_and_params_of(*self, db); let (file_id, generic_params_list) = file_id_and_params_of(*self, db);
@ -492,7 +505,7 @@ impl ChildBySource for GenericDefId {
} }
let generic_params = db.generic_params(*self); let generic_params = db.generic_params(*self);
let mut toc_idx_iter = generic_params.types.iter().map(|(idx, _)| idx); let mut toc_idx_iter = generic_params.tocs.iter().map(|(idx, _)| idx);
let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx); let lts_idx_iter = generic_params.lifetimes.iter().map(|(idx, _)| idx);
// For traits the first type index is `Self`, skip it. // For traits the first type index is `Self`, skip it.

View file

@ -582,7 +582,7 @@ impl<'a> Ctx<'a> {
} }
GenericsOwner::Trait(trait_def) => { GenericsOwner::Trait(trait_def) => {
// traits get the Self type as an implicit first type parameter // traits get the Self type as an implicit first type parameter
generics.types.alloc( generics.tocs.alloc(
TypeParamData { TypeParamData {
name: Some(name![Self]), name: Some(name![Self]),
default: None, default: None,

View file

@ -626,7 +626,7 @@ impl<'a> Printer<'a> {
} }
fn print_generic_params(&mut self, params: &GenericParams) { fn print_generic_params(&mut self, params: &GenericParams) {
if params.types.is_empty() && params.lifetimes.is_empty() { if params.tocs.is_empty() && params.lifetimes.is_empty() {
return; return;
} }
@ -639,7 +639,7 @@ impl<'a> Printer<'a> {
first = false; first = false;
w!(self, "{}", lt.name); w!(self, "{}", lt.name);
} }
for (idx, x) in params.types.iter() { for (idx, x) in params.tocs.iter() {
if !first { if !first {
w!(self, ", "); w!(self, ", ");
} }
@ -701,7 +701,7 @@ impl<'a> Printer<'a> {
match target { match target {
WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty), WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
WherePredicateTypeTarget::TypeOrConstParam(id) => { WherePredicateTypeTarget::TypeOrConstParam(id) => {
match &params.types[*id].name() { match &params.tocs[*id].name() {
Some(name) => w!(this, "{}", name), Some(name) => w!(this, "{}", name),
None => w!(this, "_anon_{}", id.into_raw()), None => w!(this, "_anon_{}", id.into_raw()),
} }

View file

@ -518,10 +518,10 @@ impl Scope {
} }
Scope::GenericParams { params, def: parent } => { Scope::GenericParams { params, def: parent } => {
let parent = *parent; let parent = *parent;
for (local_id, param) in params.types.iter() { for (local_id, param) in params.tocs.iter() {
if let Some(name) = &param.name() { if let Some(name) = &param.name() {
let id = TypeOrConstParamId { parent, local_id }; let id = TypeOrConstParamId { parent, local_id };
let data = &db.generic_params(parent).types[local_id]; let data = &db.generic_params(parent).tocs[local_id];
acc.add( acc.add(
name, name,
ScopeDef::GenericParam(match data { ScopeDef::GenericParam(match data {

View file

@ -237,7 +237,7 @@ impl TyExt for Ty {
TyKind::Placeholder(idx) => { TyKind::Placeholder(idx) => {
let id = from_placeholder_idx(db, *idx); let id = from_placeholder_idx(db, *idx);
let generic_params = db.generic_params(id.parent); let generic_params = db.generic_params(id.parent);
let param_data = &generic_params.types[id.local_id]; let param_data = &generic_params.tocs[id.local_id];
match param_data { match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeOrConstParamData::TypeParamData(p) => match p.provenance {
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {

View file

@ -320,7 +320,7 @@ impl HirDisplay for Const {
ConstValue::Placeholder(idx) => { ConstValue::Placeholder(idx) => {
let id = from_placeholder_idx(f.db, idx); let id = from_placeholder_idx(f.db, idx);
let generics = generics(f.db.upcast(), id.parent); let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics.params.types[id.local_id]; let param_data = &generics.params.tocs[id.local_id];
write!(f, "{}", param_data.name().unwrap()) write!(f, "{}", param_data.name().unwrap())
} }
ConstValue::Concrete(c) => write!(f, "{}", c.interned), ConstValue::Concrete(c) => write!(f, "{}", c.interned),
@ -489,9 +489,9 @@ impl HirDisplay for Ty {
}; };
if parameters.len(Interner) > 0 { if parameters.len(Interner) > 0 {
let generics = generics(f.db.upcast(), def.into()); let generics = generics(f.db.upcast(), def.into());
let (parent_params, self_param, type_params, _impl_trait_params) = let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
generics.provenance_split(); generics.provenance_split();
let total_len = parent_params + self_param + type_params; let total_len = parent_params + self_param + type_params + const_params;
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
if total_len > 0 { if total_len > 0 {
write!(f, "<")?; write!(f, "<")?;
@ -680,7 +680,7 @@ impl HirDisplay for Ty {
TyKind::Placeholder(idx) => { TyKind::Placeholder(idx) => {
let id = from_placeholder_idx(f.db, *idx); let id = from_placeholder_idx(f.db, *idx);
let generics = generics(f.db.upcast(), id.parent); let generics = generics(f.db.upcast(), id.parent);
let param_data = &generics.params.types[id.local_id]; let param_data = &generics.params.tocs[id.local_id];
match param_data { match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => { TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {

View file

@ -1032,10 +1032,10 @@ impl<'a> InferenceContext<'a> {
def_generics: Generics, def_generics: Generics,
generic_args: Option<&GenericArgs>, generic_args: Option<&GenericArgs>,
) -> Substitution { ) -> Substitution {
let (parent_params, self_params, type_params, impl_trait_params) = let (parent_params, self_params, type_params, const_params, impl_trait_params) =
def_generics.provenance_split(); def_generics.provenance_split();
assert_eq!(self_params, 0); // method shouldn't have another Self param assert_eq!(self_params, 0); // method shouldn't have another Self param
let total_len = parent_params + type_params + impl_trait_params; let total_len = parent_params + type_params + const_params + impl_trait_params;
let mut substs = Vec::with_capacity(total_len); let mut substs = Vec::with_capacity(total_len);
// Parent arguments are unknown // Parent arguments are unknown
for (_id, param) in def_generics.iter_parent() { for (_id, param) in def_generics.iter_parent() {
@ -1044,7 +1044,8 @@ impl<'a> InferenceContext<'a> {
substs.push(self.table.new_type_var()); substs.push(self.table.new_type_var());
} }
TypeOrConstParamData::ConstParamData(_) => { TypeOrConstParamData::ConstParamData(_) => {
// FIXME: here we should do something // FIXME: here we should do something else
substs.push(self.table.new_type_var());
} }
} }
} }

View file

@ -286,16 +286,21 @@ impl<'a> TyLoweringContext<'a> {
let idx = self.impl_trait_counter.get(); let idx = self.impl_trait_counter.get();
// FIXME we're probably doing something wrong here // FIXME we're probably doing something wrong here
self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
let (parent_params, self_params, list_params, _impl_trait_params) = let (
if let Some(def) = self.resolver.generic_def() { parent_params,
let generics = generics(self.db.upcast(), def); self_params,
generics.provenance_split() list_params,
} else { const_params,
(0, 0, 0, 0) _impl_trait_params,
}; ) = if let Some(def) = self.resolver.generic_def() {
let generics = generics(self.db.upcast(), def);
generics.provenance_split()
} else {
(0, 0, 0, 0, 0)
};
TyKind::BoundVar(BoundVar::new( TyKind::BoundVar(BoundVar::new(
self.in_binders, self.in_binders,
idx as usize + parent_params + self_params + list_params, idx as usize + parent_params + self_params + list_params + const_params,
)) ))
.intern(Interner) .intern(Interner)
} }
@ -639,9 +644,10 @@ impl<'a> TyLoweringContext<'a> {
let mut substs = Vec::new(); let mut substs = Vec::new();
let def_generics = def_generic.map(|def| generics(self.db.upcast(), def)); let def_generics = def_generic.map(|def| generics(self.db.upcast(), def));
let (parent_params, self_params, type_params, impl_trait_params) = let (parent_params, self_params, type_params, const_params, impl_trait_params) =
def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); def_generics.map_or((0, 0, 0, 0, 0), |g| g.provenance_split());
let total_len = parent_params + self_params + type_params + impl_trait_params; let total_len =
parent_params + self_params + type_params + const_params + impl_trait_params;
substs.extend(iter::repeat(TyKind::Error.intern(Interner)).take(parent_params)); substs.extend(iter::repeat(TyKind::Error.intern(Interner)).take(parent_params));
@ -993,7 +999,7 @@ fn named_associated_type_shorthand_candidates<R>(
// Handle `Self::Type` referring to own associated type in trait definitions // Handle `Self::Type` referring to own associated type in trait definitions
if let GenericDefId::TraitId(trait_id) = param_id.parent() { if let GenericDefId::TraitId(trait_id) = param_id.parent() {
let generics = generics(db.upcast(), trait_id.into()); let generics = generics(db.upcast(), trait_id.into());
if generics.params.types[param_id.local_id()].is_trait_self() { if generics.params.tocs[param_id.local_id()].is_trait_self() {
let trait_ref = TyBuilder::trait_ref(db, trait_id) let trait_ref = TyBuilder::trait_ref(db, trait_id)
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
.build(); .build();
@ -1235,9 +1241,17 @@ pub(crate) fn generic_defaults_query(
let generic_params = generics(db.upcast(), def); let generic_params = generics(db.upcast(), def);
let defaults = generic_params let defaults = generic_params
.type_iter() .toc_iter()
.enumerate() .enumerate()
.map(|(idx, (_, p))| { .map(|(idx, (_, p))| {
let p = match p {
TypeOrConstParamData::TypeParamData(p) => p,
TypeOrConstParamData::ConstParamData(_) => {
// FIXME: here we should add const generic parameters
let ty = TyKind::Error.intern(Interner);
return crate::make_only_type_binders(idx, ty);
}
};
let mut ty = let mut ty =
p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t)); p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
@ -1269,7 +1283,7 @@ pub(crate) fn generic_defaults_recover(
// we still need one default per parameter // we still need one default per parameter
let defaults = generic_params let defaults = generic_params
.type_iter() .toc_iter()
.enumerate() .enumerate()
.map(|(idx, _)| { .map(|(idx, _)| {
let ty = TyKind::Error.intern(Interner); let ty = TyKind::Error.intern(Interner);
@ -1502,7 +1516,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
// returns None if def is a type arg // returns None if def is a type arg
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
let parent_data = db.generic_params(def.parent()); let parent_data = db.generic_params(def.parent());
let data = &parent_data.types[def.local_id()]; let data = &parent_data.tocs[def.local_id()];
let resolver = def.parent().resolver(db.upcast()); let resolver = def.parent().resolver(db.upcast());
let ctx = TyLoweringContext::new(db, &resolver); let ctx = TyLoweringContext::new(db, &resolver);
match data { match data {

View file

@ -1298,3 +1298,71 @@ impl<I: Iterator> IntoIterator for I {
"#, "#,
); );
} }
#[test]
fn bug_11659() {
check_infer(
r#"
struct LinkArray<const N: usize, LD>(LD);
fn f<const N: usize, LD>(x: LD) -> LinkArray<N, LD> {
let r = LinkArray::<N, LD>(x);
r
}
fn test() {
let x = f::<2, i32>(5);
let y = LinkArray::<52, LinkArray<2, i32>>(x);
}
"#,
expect![[r#"
67..68 'x': LD
94..138 '{ ... r }': LinkArray<{unknown}, LD>
104..105 'r': LinkArray<{unknown}, LD>
108..126 'LinkAr...N, LD>': LinkArray<{unknown}, LD>(LD) -> LinkArray<{unknown}, LD>
108..129 'LinkAr...LD>(x)': LinkArray<{unknown}, LD>
127..128 'x': LD
135..136 'r': LinkArray<{unknown}, LD>
150..232 '{ ...(x); }': ()
160..161 'x': LinkArray<{unknown}, {unknown}>
164..175 'f::<2, i32>': fn f<i32, i32>(i32) -> LinkArray<{unknown}, {unknown}>
164..178 'f::<2, i32>(5)': LinkArray<{unknown}, {unknown}>
176..177 '5': i32
188..189 'y': LinkArray<LinkArray<i32, {unknown}>, LinkArray<{unknown}, {unknown}>>
192..226 'LinkAr... i32>>': LinkArray<LinkArray<i32, {unknown}>, LinkArray<{unknown}, {unknown}>>(LinkArray<{unknown}, {unknown}>) -> LinkArray<LinkArray<i32, {unknown}>, LinkArray<{unknown}, {unknown}>>
192..229 'LinkAr...2>>(x)': LinkArray<LinkArray<i32, {unknown}>, LinkArray<{unknown}, {unknown}>>
227..228 'x': LinkArray<{unknown}, {unknown}>
"#]],
);
check_infer(
r#"
struct LinkArray<LD, const N: usize>(LD);
fn f<const N: usize, LD>(x: LD) -> LinkArray<LD, N> {
let r = LinkArray::<LD, N>(x);
r
}
fn test() {
let x = f::<i32, 2>(5);
let y = LinkArray::<LinkArray<i32, 2>, 52>(x);
}
"#,
expect![[r#"
67..68 'x': LD
94..138 '{ ... r }': LinkArray<LD, {unknown}>
104..105 'r': LinkArray<LD, {unknown}>
108..126 'LinkAr...LD, N>': LinkArray<LD, {unknown}>(LD) -> LinkArray<LD, {unknown}>
108..129 'LinkAr... N>(x)': LinkArray<LD, {unknown}>
127..128 'x': LD
135..136 'r': LinkArray<LD, {unknown}>
150..232 '{ ...(x); }': ()
160..161 'x': LinkArray<i32, {unknown}>
164..175 'f::<i32, 2>': fn f<i32, i32>(i32) -> LinkArray<i32, {unknown}>
164..178 'f::<i32, 2>(5)': LinkArray<i32, {unknown}>
176..177 '5': i32
188..189 'y': LinkArray<LinkArray<i32, {unknown}>, {unknown}>
192..226 'LinkAr...>, 52>': LinkArray<LinkArray<i32, {unknown}>, {unknown}>(LinkArray<i32, {unknown}>) -> LinkArray<LinkArray<i32, {unknown}>, {unknown}>
192..229 'LinkAr...52>(x)': LinkArray<LinkArray<i32, {unknown}>, {unknown}>
227..228 'x': LinkArray<i32, {unknown}>
"#]],
);
}

View file

@ -203,12 +203,30 @@ impl Generics {
) )
} }
pub(crate) fn toc_iter<'a>(
&'a self,
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
self.parent_generics
.as_ref()
.into_iter()
.flat_map(|it| {
it.params
.toc_iter()
.map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p))
})
.chain(
self.params.toc_iter().map(move |(local_id, p)| {
(TypeOrConstParamId { parent: self.def, local_id }, p)
}),
)
}
pub(crate) fn iter_parent<'a>( pub(crate) fn iter_parent<'a>(
&'a self, &'a self,
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a { ) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
self.parent_generics.as_ref().into_iter().flat_map(|it| { self.parent_generics.as_ref().into_iter().flat_map(|it| {
it.params it.params
.types .tocs
.iter() .iter()
.map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)) .map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p))
}) })
@ -221,36 +239,36 @@ impl Generics {
/// (total, parents, child) /// (total, parents, child)
pub(crate) fn len_split(&self) -> (usize, usize, usize) { pub(crate) fn len_split(&self) -> (usize, usize, usize) {
let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
// FIXME: we should not filter const generics here, but at now it breaks tests let child = self.params.tocs.len();
let child = self.params.types.iter().filter_map(|x| x.1.type_param()).count();
(parent + child, parent, child) (parent + child, parent, child)
} }
/// (parent total, self param, type param list, impl trait) /// (parent total, self param, type param list, const param list, impl trait)
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize) { pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); let parent = self.parent_generics.as_ref().map_or(0, |p| p.len());
let self_params = self let self_params = self
.params .params
.types .tocs
.iter() .iter()
.filter_map(|x| x.1.type_param()) .filter_map(|x| x.1.type_param())
.filter(|p| p.provenance == TypeParamProvenance::TraitSelf) .filter(|p| p.provenance == TypeParamProvenance::TraitSelf)
.count(); .count();
let list_params = self let type_params = self
.params .params
.types .tocs
.iter() .iter()
.filter_map(|x| x.1.type_param()) .filter_map(|x| x.1.type_param())
.filter(|p| p.provenance == TypeParamProvenance::TypeParamList) .filter(|p| p.provenance == TypeParamProvenance::TypeParamList)
.count(); .count();
let const_params = self.params.tocs.iter().filter_map(|x| x.1.const_param()).count();
let impl_trait_params = self let impl_trait_params = self
.params .params
.types .tocs
.iter() .iter()
.filter_map(|x| x.1.type_param()) .filter_map(|x| x.1.type_param())
.filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait) .filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait)
.count(); .count();
(parent, self_params, list_params, impl_trait_params) (parent, self_params, type_params, const_params, impl_trait_params)
} }
pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> { pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
@ -261,7 +279,7 @@ impl Generics {
if param.parent == self.def { if param.parent == self.def {
let (idx, (_local_id, data)) = self let (idx, (_local_id, data)) = self
.params .params
.types .tocs
.iter() .iter()
.enumerate() .enumerate()
.find(|(_, (idx, _))| *idx == param.local_id) .find(|(_, (idx, _))| *idx == param.local_id)
@ -277,7 +295,7 @@ impl Generics {
pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution { pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
self.type_iter() self.toc_iter()
.enumerate() .enumerate()
.map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner)), .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner)),
) )
@ -287,7 +305,7 @@ impl Generics {
pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution { pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution {
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
self.type_iter().map(|(id, _)| { self.toc_iter().map(|(id, _)| {
TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(Interner) TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(Interner)
}), }),
) )