include lifetime in ParamKind and in Generics::provenance_split

This commit is contained in:
dfireBird 2024-03-08 18:05:44 +05:30
parent e463a3e1cf
commit d6e3929841
No known key found for this signature in database
GPG key ID: 26D522CA5FC2B93D
10 changed files with 116 additions and 50 deletions

View file

@ -15,15 +15,16 @@ use hir_def::{
use smallvec::SmallVec;
use crate::{
consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
TyKind,
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
infer::unify::InferenceTable, primitive, static_lifetime, to_assoc_type_id, to_chalk_trait_id,
utils::generics, Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner,
ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParamKind {
Type,
Lifetime,
Const(Ty),
}
@ -107,6 +108,9 @@ impl<D> TyBuilder<D> {
ParamKind::Const(ty) => {
BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
}
ParamKind::Lifetime => {
BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
}
});
this.vec.extend(filler.take(this.remaining()).casted(Interner));
assert_eq!(this.remaining(), 0);
@ -119,6 +123,7 @@ impl<D> TyBuilder<D> {
let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x {
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
});
this.vec.extend(filler.casted(Interner));
assert_eq!(this.remaining(), 0);
@ -130,6 +135,8 @@ impl<D> TyBuilder<D> {
self.fill(|x| match x {
ParamKind::Type => table.new_type_var().cast(Interner),
ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
// FIXME: create new_lifetime_var in table
ParamKind::Lifetime => static_lifetime().cast(Interner),
})
}
@ -142,7 +149,8 @@ impl<D> TyBuilder<D> {
fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
match (a.data(Interner), e) {
(GenericArgData::Ty(_), ParamKind::Type)
| (GenericArgData::Const(_), ParamKind::Const(_)) => (),
| (GenericArgData::Const(_), ParamKind::Const(_))
| (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (),
_ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
}
}
@ -217,6 +225,7 @@ impl TyBuilder<()> {
) -> TyBuilder<()> {
let generics = generics(db.upcast(), def.into());
assert!(generics.parent_generics().is_some() == parent_subst.is_some());
let lt_iter = generics.iter_lt_self().map(|_| ParamKind::Lifetime);
let params = generics
.iter_self()
.map(|(id, data)| match data {
@ -225,6 +234,7 @@ impl TyBuilder<()> {
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
}
})
.chain(lt_iter)
.collect();
TyBuilder::new((), params, parent_subst)
}

View file

@ -938,15 +938,23 @@ impl HirDisplay for Ty {
f.end_location_link();
if parameters.len(Interner) > 0 {
let generics = generics(db.upcast(), def.into());
let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
generics.provenance_split();
let total_len = parent_params + self_param + type_params + const_params;
let (
parent_params,
self_param,
type_params,
const_params,
_impl_trait_params,
lifetime_params,
) = generics.provenance_split();
let total_len =
parent_params + self_param + type_params + const_params + lifetime_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 {
// `parameters` are in the order of fn's params (including impl traits),
// parent's params (those from enclosing impl or trait, if any).
let parameters = parameters.as_slice(Interner);
let fn_params_len = self_param + type_params + const_params;
let fn_params_len =
self_param + type_params + const_params + lifetime_params;
let fn_params = parameters.get(..fn_params_len);
let parent_params = parameters.get(parameters.len() - parent_params..);
let params = parent_params.into_iter().chain(fn_params).flatten();

View file

@ -13,7 +13,7 @@ use hir_def::{
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
},
lang_item::{LangItem, LangItemTarget},
path::{GenericArg, GenericArgs, Path},
path::{GenericArgs, Path},
BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
};
use hir_expand::name::{name, Name};
@ -1816,10 +1816,17 @@ impl InferenceContext<'_> {
def_generics: Generics,
generic_args: Option<&GenericArgs>,
) -> Substitution {
let (parent_params, self_params, type_params, const_params, impl_trait_params) =
def_generics.provenance_split();
let (
parent_params,
self_params,
type_params,
const_params,
impl_trait_params,
lifetime_params,
) = def_generics.provenance_split();
assert_eq!(self_params, 0); // method shouldn't have another Self param
let total_len = parent_params + type_params + const_params + impl_trait_params;
let total_len =
parent_params + type_params + const_params + impl_trait_params + lifetime_params;
let mut substs = Vec::with_capacity(total_len);
// handle provided arguments
@ -1828,9 +1835,8 @@ impl InferenceContext<'_> {
for (arg, kind_id) in generic_args
.args
.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.take(type_params + const_params)
.zip(def_generics.iter_id())
.take(type_params + const_params + lifetime_params)
.zip(def_generics.iter_id_with_lt())
{
if let Some(g) = generic_arg_to_chalk(
self.db,
@ -1850,6 +1856,8 @@ impl InferenceContext<'_> {
DebruijnIndex::INNERMOST,
)
},
// FIXME: create make_lifetimes and infer lifetimes
|_, _| static_lifetime(),
) {
substs.push(g);
}

View file

@ -11,7 +11,7 @@ use stdx::never;
use crate::{
builder::ParamKind,
consteval,
consteval, error_lifetime,
method_resolution::{self, VisibleFromModule},
to_chalk_trait_id,
utils::generics,
@ -111,6 +111,7 @@ impl InferenceContext<'_> {
it.next().unwrap_or_else(|| match x {
ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
})
})
.build();

View file

@ -807,6 +807,7 @@ impl<'a> InferenceTable<'a> {
.fill(|it| {
let arg = match it {
ParamKind::Type => self.new_type_var(),
ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"),
ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
};
arg_tys.push(arg.clone());

View file

@ -92,8 +92,8 @@ pub use lower::{
};
pub use mapping::{
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
to_placeholder_idx,
lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
to_foreign_def_id, to_placeholder_idx,
};
pub use method_resolution::check_orphan_rules;
pub use traits::TraitEnvironment;

View file

@ -34,9 +34,9 @@ use hir_def::{
ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
},
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
TypeParamId, UnionId, VariantId,
GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId,
Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
UnionId, VariantId,
};
use hir_expand::{name::Name, ExpandResult};
use intern::Interned;
@ -377,15 +377,20 @@ impl<'a> TyLoweringContext<'a> {
list_params,
const_params,
_impl_trait_params,
lifetime_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)
(0, 0, 0, 0, 0, 0)
};
TyKind::BoundVar(BoundVar::new(
self.in_binders,
idx as usize + self_params + list_params + const_params,
idx as usize
+ self_params
+ list_params
+ const_params
+ lifetime_params,
))
.intern(Interner)
}
@ -818,14 +823,21 @@ impl<'a> TyLoweringContext<'a> {
return Substitution::empty(Interner);
};
let def_generics = generics(self.db.upcast(), def);
let (parent_params, self_params, type_params, const_params, impl_trait_params) =
def_generics.provenance_split();
let item_len = self_params + type_params + const_params + impl_trait_params;
let (
parent_params,
self_params,
type_params,
const_params,
impl_trait_params,
lifetime_params,
) = def_generics.provenance_split();
let item_len =
self_params + type_params + const_params + impl_trait_params + lifetime_params;
let total_len = parent_params + item_len;
let ty_error = TyKind::Error.intern(Interner).cast(Interner);
let mut def_generic_iter = def_generics.iter_id();
let mut def_generic_iter = def_generics.iter_id_with_lt();
let fill_self_params = || {
for x in explicit_self_ty
@ -835,7 +847,10 @@ impl<'a> TyLoweringContext<'a> {
.take(self_params)
{
if let Some(id) = def_generic_iter.next() {
assert!(id.is_left());
assert!(matches!(
id,
GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
));
substs.push(x);
}
}
@ -847,19 +862,13 @@ impl<'a> TyLoweringContext<'a> {
fill_self_params();
}
let expected_num = if generic_args.has_self_type {
self_params + type_params + const_params
self_params + type_params + const_params + lifetime_params
} else {
type_params + const_params
};
let skip = if generic_args.has_self_type && self_params == 0 { 1 } else { 0 };
// if args are provided, it should be all of them, but we can't rely on that
for arg in generic_args
.args
.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.skip(skip)
.take(expected_num)
{
for arg in generic_args.args.iter().skip(skip).take(expected_num) {
if let Some(id) = def_generic_iter.next() {
if let Some(x) = generic_arg_to_chalk(
self.db,
@ -868,6 +877,7 @@ impl<'a> TyLoweringContext<'a> {
&mut (),
|_, type_ref| self.lower_ty(type_ref),
|_, const_ref, ty| self.lower_const(const_ref, ty),
|_, lifetime_ref| self.lower_lifetime(lifetime_ref),
) {
had_explicit_args = true;
substs.push(x);
@ -883,9 +893,12 @@ impl<'a> TyLoweringContext<'a> {
// These params include those of parent.
let remaining_params: SmallVec<[_; 2]> = def_generic_iter
.map(|eid| match eid {
Either::Left(_) => ty_error.clone(),
Either::Right(x) => unknown_const_as_generic(self.db.const_param_ty(x)),
.map(|id| match id {
GenericParamId::ConstParamId(x) => {
unknown_const_as_generic(self.db.const_param_ty(x))
}
GenericParamId::TypeParamId(_) => ty_error.clone(),
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
})
.collect();
assert_eq!(remaining_params.len() + substs.len(), total_len);
@ -1719,7 +1732,7 @@ pub(crate) fn generic_defaults_query(
let generic_params = generics(db.upcast(), def);
let parent_start_idx = generic_params.len_self();
let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
let toc_iter = generic_params.iter().enumerate().map(|(idx, (id, p))| {
match p {
TypeOrConstParamData::TypeParamData(p) => {
let mut ty =
@ -1747,7 +1760,14 @@ pub(crate) fn generic_defaults_query(
make_binders(db, &generic_params, val)
}
}
}));
});
let lt_iter = generic_params
.iter_lt()
.enumerate()
.map(|_| make_binders(db, &generic_params, static_lifetime().cast(Interner)));
let defaults = Arc::from_iter(toc_iter.chain(lt_iter));
defaults
}
@ -2127,23 +2147,29 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
/// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
pub(crate) fn generic_arg_to_chalk<'a, T>(
db: &dyn HirDatabase,
kind_id: Either<TypeParamId, ConstParamId>,
kind_id: GenericParamId,
arg: &'a GenericArg,
this: &mut T,
for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
) -> Option<crate::GenericArg> {
let kind = match kind_id {
Either::Left(_) => ParamKind::Type,
Either::Right(id) => {
GenericParamId::TypeParamId(_) => ParamKind::Type,
GenericParamId::ConstParamId(id) => {
let ty = db.const_param_ty(id);
ParamKind::Const(ty)
}
GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
};
Some(match (arg, kind) {
(GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
(GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
(GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
for_lifetime(this, lifetime_ref).cast(Interner)
}
(GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
(GenericArg::Lifetime(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
(GenericArg::Type(t), ParamKind::Const(c_ty)) => {
// We want to recover simple idents, which parser detects them
// as types. Maybe here is not the best place to do it, but
@ -2159,7 +2185,9 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
}
unknown_const_as_generic(c_ty)
}
(GenericArg::Lifetime(_), _) => return None,
(GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
(GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
(GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
})
}

View file

@ -151,7 +151,7 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
db.lookup_intern_lifetime_param_id(interned_id)
}
pub(crate) fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
let interned_id = db.intern_lifetime_param_id(id);
PlaceholderIndex {
ui: chalk_ir::UniverseIndex::ROOT,

View file

@ -367,11 +367,12 @@ impl Generics {
}
/// (parent total, self param, type param list, const param list, impl trait)
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
let mut self_params = 0;
let mut type_params = 0;
let mut impl_trait_params = 0;
let mut const_params = 0;
let mut lifetime_params = 0;
self.params.iter().for_each(|(_, data)| match data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
TypeParamProvenance::TypeParamList => type_params += 1,
@ -381,8 +382,10 @@ impl Generics {
TypeOrConstParamData::ConstParamData(_) => const_params += 1,
});
self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
let parent_len = self.parent_generics().map_or(0, Generics::len);
(parent_len, self_params, type_params, const_params, impl_trait_params)
(parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
}
pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {

View file

@ -65,7 +65,7 @@ use hir_ty::{
consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
db::InternedClosure,
diagnostics::BodyValidationDiagnostic,
known_const_to_ast,
error_lifetime, known_const_to_ast,
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
method_resolution::{self, TyFingerprint},
mir::{interpret_mir, MutBorrowKind},
@ -1106,6 +1106,7 @@ impl Field {
generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
}
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
})
.build();
let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
@ -1447,6 +1448,7 @@ impl Adt {
match x {
ParamKind::Type => r.cast(Interner),
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
}
})
.build();
@ -1865,6 +1867,7 @@ impl Function {
generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
}
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
};
let parent_substs =
@ -1963,6 +1966,7 @@ impl Function {
.unwrap_or_else(|| TyKind::Error.intern(Interner))
.cast(Interner),
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
})
.build()
});
@ -2221,6 +2225,7 @@ impl SelfParam {
generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
}
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
};
let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build();
@ -4114,6 +4119,7 @@ impl Type {
// FIXME: this code is not covered in tests.
unknown_const_as_generic(ty.clone())
}
ParamKind::Lifetime => error_lifetime().cast(Interner),
}
})
.build();
@ -4144,6 +4150,7 @@ impl Type {
match it {
ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner),
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
ParamKind::Lifetime => error_lifetime().cast(Interner),
}
})
.build();