mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Merge #11660
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:
commit
4fcaefa62a
12 changed files with 176 additions and 62 deletions
|
@ -293,7 +293,7 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
|
|||
let params = f.db.generic_params(def);
|
||||
if params.lifetimes.is_empty()
|
||||
&& params
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.filter_map(|x| x.1.type_param())
|
||||
.all(|param| !matches!(param.provenance, TypeParamProvenance::TypeParamList))
|
||||
|
@ -315,7 +315,7 @@ fn write_generic_params(def: GenericDefId, f: &mut HirFormatter) -> Result<(), H
|
|||
delim(f)?;
|
||||
write!(f, "{}", lifetime.name)?;
|
||||
}
|
||||
for (_, ty) in params.types.iter() {
|
||||
for (_, ty) in params.tocs.iter() {
|
||||
if let Some(name) = &ty.name() {
|
||||
match 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`.
|
||||
let is_unnamed_type_target = |target: &WherePredicateTypeTarget| match target {
|
||||
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
|
||||
|
@ -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 {
|
||||
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
|
||||
WherePredicateTypeTarget::TypeOrConstParam(id) => match ¶ms.types[*id].name() {
|
||||
WherePredicateTypeTarget::TypeOrConstParam(id) => match ¶ms.tocs[*id].name() {
|
||||
Some(name) => write!(f, "{}", name),
|
||||
None => write!(f, "{{unnamed}}"),
|
||||
},
|
||||
|
|
|
@ -2029,7 +2029,7 @@ impl_from!(
|
|||
impl GenericDef {
|
||||
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
|
||||
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 } };
|
||||
match toc.split(db) {
|
||||
Either::Left(x) => GenericParam::ConstParam(x),
|
||||
|
@ -2049,7 +2049,7 @@ impl GenericDef {
|
|||
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
|
||||
let generics = db.generic_params(self.into());
|
||||
generics
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.map(|(local_id, _)| TypeOrConstParam {
|
||||
id: TypeOrConstParamId { parent: self.into(), local_id },
|
||||
|
@ -2371,7 +2371,7 @@ impl ConstParam {
|
|||
|
||||
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||
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(),
|
||||
None => {
|
||||
never!();
|
||||
|
@ -2403,7 +2403,7 @@ pub struct TypeOrConstParam {
|
|||
impl TypeOrConstParam {
|
||||
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
||||
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(),
|
||||
_ => Name::missing(),
|
||||
}
|
||||
|
@ -2419,7 +2419,7 @@ impl TypeOrConstParam {
|
|||
|
||||
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
|
||||
let params = db.generic_params(self.id.parent);
|
||||
match ¶ms.types[self.id.local_id] {
|
||||
match ¶ms.tocs[self.id.local_id] {
|
||||
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
|
||||
Either::Right(TypeParam { id: self.id.into() })
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
match self {
|
||||
TypeOrConstParamData::TypeParamData(x) => {
|
||||
|
@ -92,7 +99,7 @@ impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
|
|||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
|
||||
pub struct GenericParams {
|
||||
pub types: Arena<TypeOrConstParamData>,
|
||||
pub tocs: Arena<TypeOrConstParamData>,
|
||||
pub lifetimes: Arena<LifetimeParamData>,
|
||||
pub where_predicates: Vec<WherePredicate>,
|
||||
}
|
||||
|
@ -131,7 +138,13 @@ impl GenericParams {
|
|||
pub fn type_iter<'a>(
|
||||
&'a self,
|
||||
) -> 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(
|
||||
|
@ -238,7 +251,7 @@ impl GenericParams {
|
|||
default,
|
||||
provenance: TypeParamProvenance::TypeParamList,
|
||||
};
|
||||
self.types.alloc(param.into());
|
||||
self.tocs.alloc(param.into());
|
||||
let type_ref = TypeRef::Path(name.into());
|
||||
self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
|
||||
}
|
||||
|
@ -248,7 +261,7 @@ impl GenericParams {
|
|||
.ty()
|
||||
.map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
|
||||
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,
|
||||
provenance: TypeParamProvenance::ArgumentImplTrait,
|
||||
};
|
||||
let param_id = self.types.alloc(param.into());
|
||||
let param_id = self.tocs.alloc(param.into());
|
||||
for bound in bounds {
|
||||
self.where_predicates.push(WherePredicate::TypeBound {
|
||||
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
|
||||
|
@ -359,27 +372,27 @@ impl GenericParams {
|
|||
}
|
||||
|
||||
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();
|
||||
types.shrink_to_fit();
|
||||
where_predicates.shrink_to_fit();
|
||||
}
|
||||
|
||||
pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeOrConstParamId> {
|
||||
self.types
|
||||
self.tocs
|
||||
.iter()
|
||||
.filter(|x| matches!(x.1, TypeOrConstParamData::TypeParamData(_)))
|
||||
.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> {
|
||||
self.types
|
||||
self.tocs
|
||||
.iter()
|
||||
.find_map(|(id, p)| if p.name().as_ref() == Some(&name) { Some(id) } else { None })
|
||||
}
|
||||
|
||||
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 p.provenance == TypeParamProvenance::TraitSelf {
|
||||
Some(id)
|
||||
|
@ -438,7 +451,7 @@ impl HasChildSource<LocalTypeOrConstParamId> for GenericDefId {
|
|||
db: &dyn DefDatabase,
|
||||
) -> InFile<ArenaMap<LocalTypeOrConstParamId, Self::Value>> {
|
||||
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);
|
||||
|
||||
|
@ -492,7 +505,7 @@ impl ChildBySource for GenericDefId {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
// For traits the first type index is `Self`, skip it.
|
||||
|
|
|
@ -582,7 +582,7 @@ impl<'a> Ctx<'a> {
|
|||
}
|
||||
GenericsOwner::Trait(trait_def) => {
|
||||
// traits get the Self type as an implicit first type parameter
|
||||
generics.types.alloc(
|
||||
generics.tocs.alloc(
|
||||
TypeParamData {
|
||||
name: Some(name![Self]),
|
||||
default: None,
|
||||
|
|
|
@ -626,7 +626,7 @@ impl<'a> Printer<'a> {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -639,7 +639,7 @@ impl<'a> Printer<'a> {
|
|||
first = false;
|
||||
w!(self, "{}", lt.name);
|
||||
}
|
||||
for (idx, x) in params.types.iter() {
|
||||
for (idx, x) in params.tocs.iter() {
|
||||
if !first {
|
||||
w!(self, ", ");
|
||||
}
|
||||
|
@ -701,7 +701,7 @@ impl<'a> Printer<'a> {
|
|||
match target {
|
||||
WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
|
||||
WherePredicateTypeTarget::TypeOrConstParam(id) => {
|
||||
match ¶ms.types[*id].name() {
|
||||
match ¶ms.tocs[*id].name() {
|
||||
Some(name) => w!(this, "{}", name),
|
||||
None => w!(this, "_anon_{}", id.into_raw()),
|
||||
}
|
||||
|
|
|
@ -518,10 +518,10 @@ impl Scope {
|
|||
}
|
||||
Scope::GenericParams { params, def: parent } => {
|
||||
let parent = *parent;
|
||||
for (local_id, param) in params.types.iter() {
|
||||
for (local_id, param) in params.tocs.iter() {
|
||||
if let Some(name) = ¶m.name() {
|
||||
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(
|
||||
name,
|
||||
ScopeDef::GenericParam(match data {
|
||||
|
|
|
@ -237,7 +237,7 @@ impl TyExt for Ty {
|
|||
TyKind::Placeholder(idx) => {
|
||||
let id = from_placeholder_idx(db, *idx);
|
||||
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 {
|
||||
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
|
||||
|
|
|
@ -320,7 +320,7 @@ impl HirDisplay for Const {
|
|||
ConstValue::Placeholder(idx) => {
|
||||
let id = from_placeholder_idx(f.db, idx);
|
||||
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())
|
||||
}
|
||||
ConstValue::Concrete(c) => write!(f, "{}", c.interned),
|
||||
|
@ -489,9 +489,9 @@ impl HirDisplay for Ty {
|
|||
};
|
||||
if parameters.len(Interner) > 0 {
|
||||
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();
|
||||
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?
|
||||
if total_len > 0 {
|
||||
write!(f, "<")?;
|
||||
|
@ -680,7 +680,7 @@ impl HirDisplay for Ty {
|
|||
TyKind::Placeholder(idx) => {
|
||||
let id = from_placeholder_idx(f.db, *idx);
|
||||
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 {
|
||||
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
||||
|
|
|
@ -1032,10 +1032,10 @@ impl<'a> InferenceContext<'a> {
|
|||
def_generics: Generics,
|
||||
generic_args: Option<&GenericArgs>,
|
||||
) -> 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();
|
||||
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);
|
||||
// Parent arguments are unknown
|
||||
for (_id, param) in def_generics.iter_parent() {
|
||||
|
@ -1044,7 +1044,8 @@ impl<'a> InferenceContext<'a> {
|
|||
substs.push(self.table.new_type_var());
|
||||
}
|
||||
TypeOrConstParamData::ConstParamData(_) => {
|
||||
// FIXME: here we should do something
|
||||
// FIXME: here we should do something else
|
||||
substs.push(self.table.new_type_var());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,16 +286,21 @@ impl<'a> TyLoweringContext<'a> {
|
|||
let idx = self.impl_trait_counter.get();
|
||||
// FIXME we're probably doing something wrong here
|
||||
self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
|
||||
let (parent_params, self_params, list_params, _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)
|
||||
};
|
||||
let (
|
||||
parent_params,
|
||||
self_params,
|
||||
list_params,
|
||||
const_params,
|
||||
_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(
|
||||
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)
|
||||
}
|
||||
|
@ -639,9 +644,10 @@ impl<'a> TyLoweringContext<'a> {
|
|||
let mut substs = Vec::new();
|
||||
let def_generics = def_generic.map(|def| generics(self.db.upcast(), def));
|
||||
|
||||
let (parent_params, self_params, type_params, impl_trait_params) =
|
||||
def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split());
|
||||
let total_len = 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, 0), |g| g.provenance_split());
|
||||
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));
|
||||
|
||||
|
@ -993,7 +999,7 @@ fn named_associated_type_shorthand_candidates<R>(
|
|||
// Handle `Self::Type` referring to own associated type in trait definitions
|
||||
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
|
||||
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)
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||
.build();
|
||||
|
@ -1235,9 +1241,17 @@ pub(crate) fn generic_defaults_query(
|
|||
let generic_params = generics(db.upcast(), def);
|
||||
|
||||
let defaults = generic_params
|
||||
.type_iter()
|
||||
.toc_iter()
|
||||
.enumerate()
|
||||
.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 =
|
||||
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
|
||||
let defaults = generic_params
|
||||
.type_iter()
|
||||
.toc_iter()
|
||||
.enumerate()
|
||||
.map(|(idx, _)| {
|
||||
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
|
||||
pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
|
||||
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 ctx = TyLoweringContext::new(db, &resolver);
|
||||
match data {
|
||||
|
|
|
@ -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}>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>(
|
||||
&'a self,
|
||||
) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
self.parent_generics.as_ref().into_iter().flat_map(|it| {
|
||||
it.params
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.map(move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p))
|
||||
})
|
||||
|
@ -221,36 +239,36 @@ impl Generics {
|
|||
/// (total, parents, child)
|
||||
pub(crate) fn len_split(&self) -> (usize, usize, usize) {
|
||||
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.types.iter().filter_map(|x| x.1.type_param()).count();
|
||||
let child = self.params.tocs.len();
|
||||
(parent + child, parent, child)
|
||||
}
|
||||
|
||||
/// (parent total, self param, type param list, impl trait)
|
||||
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize) {
|
||||
/// (parent total, self param, type param list, const param list, impl trait)
|
||||
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 self_params = self
|
||||
.params
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.filter_map(|x| x.1.type_param())
|
||||
.filter(|p| p.provenance == TypeParamProvenance::TraitSelf)
|
||||
.count();
|
||||
let list_params = self
|
||||
let type_params = self
|
||||
.params
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.filter_map(|x| x.1.type_param())
|
||||
.filter(|p| p.provenance == TypeParamProvenance::TypeParamList)
|
||||
.count();
|
||||
let const_params = self.params.tocs.iter().filter_map(|x| x.1.const_param()).count();
|
||||
let impl_trait_params = self
|
||||
.params
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.filter_map(|x| x.1.type_param())
|
||||
.filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait)
|
||||
.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> {
|
||||
|
@ -261,7 +279,7 @@ impl Generics {
|
|||
if param.parent == self.def {
|
||||
let (idx, (_local_id, data)) = self
|
||||
.params
|
||||
.types
|
||||
.tocs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, (idx, _))| *idx == param.local_id)
|
||||
|
@ -277,7 +295,7 @@ impl Generics {
|
|||
pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
|
||||
Substitution::from_iter(
|
||||
Interner,
|
||||
self.type_iter()
|
||||
self.toc_iter()
|
||||
.enumerate()
|
||||
.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 {
|
||||
Substitution::from_iter(
|
||||
Interner,
|
||||
self.type_iter().map(|(id, _)| {
|
||||
self.toc_iter().map(|(id, _)| {
|
||||
TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(Interner)
|
||||
}),
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue