mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27: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);
|
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 ¶ms.types[*id].name() {
|
WherePredicateTypeTarget::TypeOrConstParam(id) => match ¶ms.tocs[*id].name() {
|
||||||
Some(name) => write!(f, "{}", name),
|
Some(name) => write!(f, "{}", name),
|
||||||
None => write!(f, "{{unnamed}}"),
|
None => write!(f, "{{unnamed}}"),
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 ¶ms.types[self.id.local_id] {
|
match ¶ms.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() })
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 ¶ms.types[*id].name() {
|
match ¶ms.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()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) = ¶m.name() {
|
if let Some(name) = ¶m.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 {
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>(
|
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)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue