Auto merge of #16805 - dfireBird:lifetime_lowering, r=Veykril
feat: Implement resolving and lowering of Lifetimes (no inference yet)
This commit is contained in:
commit
0583aaa555
23 changed files with 571 additions and 157 deletions
|
@ -22,8 +22,8 @@ use crate::{
|
|||
lower::LowerCtx,
|
||||
nameres::{DefMap, MacroSubNs},
|
||||
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
|
||||
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
|
||||
TypeOrConstParamId, TypeParamId,
|
||||
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
|
||||
LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
||||
};
|
||||
|
||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||
|
@ -102,6 +102,52 @@ impl TypeOrConstParamData {
|
|||
|
||||
impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum GenericParamData {
|
||||
TypeParamData(TypeParamData),
|
||||
ConstParamData(ConstParamData),
|
||||
LifetimeParamData(LifetimeParamData),
|
||||
}
|
||||
|
||||
impl GenericParamData {
|
||||
pub fn name(&self) -> Option<&Name> {
|
||||
match self {
|
||||
GenericParamData::TypeParamData(it) => it.name.as_ref(),
|
||||
GenericParamData::ConstParamData(it) => Some(&it.name),
|
||||
GenericParamData::LifetimeParamData(it) => Some(&it.name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_param(&self) -> Option<&TypeParamData> {
|
||||
match self {
|
||||
GenericParamData::TypeParamData(it) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_param(&self) -> Option<&ConstParamData> {
|
||||
match self {
|
||||
GenericParamData::ConstParamData(it) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lifetime_param(&self) -> Option<&LifetimeParamData> {
|
||||
match self {
|
||||
GenericParamData::LifetimeParamData(it) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData);
|
||||
|
||||
pub enum GenericParamDataRef<'a> {
|
||||
TypeParamData(&'a TypeParamData),
|
||||
ConstParamData(&'a ConstParamData),
|
||||
LifetimeParamData(&'a LifetimeParamData),
|
||||
}
|
||||
|
||||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct GenericParams {
|
||||
|
@ -365,6 +411,13 @@ impl GenericParams {
|
|||
self.type_or_consts.iter()
|
||||
}
|
||||
|
||||
/// Iterator of lifetimes field
|
||||
pub fn iter_lt(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (Idx<LifetimeParamData>, &LifetimeParamData)> {
|
||||
self.lifetimes.iter()
|
||||
}
|
||||
|
||||
pub(crate) fn generic_params_query(
|
||||
db: &dyn DefDatabase,
|
||||
def: GenericDefId,
|
||||
|
@ -507,4 +560,18 @@ impl GenericParams {
|
|||
.then(|| id)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn find_lifetime_by_name(
|
||||
&self,
|
||||
name: &Name,
|
||||
parent: GenericDefId,
|
||||
) -> Option<LifetimeParamId> {
|
||||
self.lifetimes.iter().find_map(|(id, p)| {
|
||||
if &p.name == name {
|
||||
Some(LifetimeParamId { local_id: id, parent })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ use crate::{
|
|||
nameres::{DefMap, MacroSubNs},
|
||||
path::{ModPath, Path, PathKind},
|
||||
per_ns::PerNs,
|
||||
type_ref::LifetimeRef,
|
||||
visibility::{RawVisibility, Visibility},
|
||||
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
|
||||
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
|
||||
|
@ -120,6 +121,12 @@ pub enum ValueNs {
|
|||
GenericParam(ConstParamId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum LifetimeNs {
|
||||
Static,
|
||||
LifetimeParam(LifetimeParamId),
|
||||
}
|
||||
|
||||
impl Resolver {
|
||||
/// Resolve known trait from std, like `std::futures::Future`
|
||||
pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
|
||||
|
@ -418,6 +425,19 @@ impl Resolver {
|
|||
self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
|
||||
}
|
||||
|
||||
pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
|
||||
if lifetime.name == name::known::STATIC_LIFETIME {
|
||||
return Some(LifetimeNs::Static);
|
||||
}
|
||||
|
||||
self.scopes().find_map(|scope| match scope {
|
||||
Scope::GenericParams { def, params } => {
|
||||
params.find_lifetime_by_name(&lifetime.name, *def).map(LifetimeNs::LifetimeParam)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a set of names available in the current scope.
|
||||
///
|
||||
/// Note that this is a somewhat fuzzy concept -- internally, the compiler
|
||||
|
|
|
@ -9,21 +9,21 @@ use chalk_ir::{
|
|||
AdtId, DebruijnIndex, Scalar,
|
||||
};
|
||||
use hir_def::{
|
||||
builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
|
||||
GenericDefId, TraitId, TypeAliasId,
|
||||
builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
|
||||
};
|
||||
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, 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 +107,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 +122,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 +134,7 @@ 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),
|
||||
ParamKind::Lifetime => table.new_lifetime_var().cast(Interner),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -142,7 +147,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),
|
||||
}
|
||||
}
|
||||
|
@ -201,10 +207,11 @@ impl TyBuilder<()> {
|
|||
Substitution::from_iter(
|
||||
Interner,
|
||||
params.iter_id().map(|id| match id {
|
||||
either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
|
||||
either::Either::Right(id) => {
|
||||
GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
|
||||
GenericParamId::ConstParamId(id) => {
|
||||
unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
|
||||
}
|
||||
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -219,11 +226,10 @@ impl TyBuilder<()> {
|
|||
assert!(generics.parent_generics().is_some() == parent_subst.is_some());
|
||||
let params = generics
|
||||
.iter_self()
|
||||
.map(|(id, data)| match data {
|
||||
TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
|
||||
TypeOrConstParamData::ConstParamData(_) => {
|
||||
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
|
||||
}
|
||||
.map(|(id, _data)| match id {
|
||||
GenericParamId::TypeParamId(_) => ParamKind::Type,
|
||||
GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
|
||||
GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
|
||||
})
|
||||
.collect();
|
||||
TyBuilder::new((), params, parent_subst)
|
||||
|
|
|
@ -938,18 +938,32 @@ 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),
|
||||
// `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
|
||||
// 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;
|
||||
// This will give slice till last type or const
|
||||
let fn_params = parameters.get(..fn_params_len);
|
||||
let fn_lt_params =
|
||||
parameters.get(fn_params_len..(fn_params_len + lifetime_params));
|
||||
let parent_params = parameters.get(parameters.len() - parent_params..);
|
||||
let params = parent_params.into_iter().chain(fn_params).flatten();
|
||||
let params = parent_params
|
||||
.into_iter()
|
||||
.chain(fn_lt_params)
|
||||
.chain(fn_params)
|
||||
.flatten();
|
||||
write!(f, "<")?;
|
||||
f.write_joined(params, ", ")?;
|
||||
write!(f, ">")?;
|
||||
|
@ -1308,8 +1322,17 @@ fn hir_fmt_generics(
|
|||
generic_def: Option<hir_def::GenericDefId>,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
let db = f.db;
|
||||
let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
|
||||
if parameters.len(Interner) + lifetime_args_count > 0 {
|
||||
if parameters.len(Interner) > 0 {
|
||||
use std::cmp::Ordering;
|
||||
let param_compare =
|
||||
|a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) {
|
||||
(crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => {
|
||||
Ordering::Equal
|
||||
}
|
||||
(crate::GenericArgData::Lifetime(_), _) => Ordering::Less,
|
||||
(_, crate::GenericArgData::Lifetime(_)) => Ordering::Less,
|
||||
(_, _) => Ordering::Equal,
|
||||
};
|
||||
let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
|
||||
match generic_def
|
||||
.map(|generic_def_id| db.generic_defaults(generic_def_id))
|
||||
|
@ -1335,6 +1358,11 @@ fn hir_fmt_generics(
|
|||
return true;
|
||||
}
|
||||
}
|
||||
if parameter.lifetime(Interner).map(|it| it.data(Interner))
|
||||
== Some(&crate::LifetimeData::Static)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
let default_parameter = match default_parameters.get(i) {
|
||||
Some(it) => it,
|
||||
None => return true,
|
||||
|
@ -1355,16 +1383,12 @@ fn hir_fmt_generics(
|
|||
} else {
|
||||
parameters.as_slice(Interner)
|
||||
};
|
||||
if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
|
||||
//FIXME: Should handle the ordering of lifetimes when creating substitutions
|
||||
let mut parameters_to_write = parameters_to_write.to_vec();
|
||||
parameters_to_write.sort_by(param_compare);
|
||||
if !parameters_to_write.is_empty() {
|
||||
write!(f, "<")?;
|
||||
let mut first = true;
|
||||
for _ in 0..lifetime_args_count {
|
||||
if !first {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
first = false;
|
||||
write!(f, "'_")?;
|
||||
}
|
||||
for generic_arg in parameters_to_write {
|
||||
if !first {
|
||||
write!(f, ", ")?;
|
||||
|
|
|
@ -42,7 +42,7 @@ use hir_def::{
|
|||
layout::Integer,
|
||||
path::{ModPath, Path},
|
||||
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||
type_ref::TypeRef,
|
||||
type_ref::{LifetimeRef, TypeRef},
|
||||
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
|
||||
TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
};
|
||||
|
@ -1037,6 +1037,12 @@ impl<'a> InferenceContext<'a> {
|
|||
self.result.standard_types.unknown.clone()
|
||||
}
|
||||
|
||||
fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
|
||||
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
|
||||
let lt = ctx.lower_lifetime(lifetime_ref);
|
||||
self.insert_type_vars(lt)
|
||||
}
|
||||
|
||||
/// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
|
||||
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
|
||||
self.table.insert_type_vars_shallow(ty)
|
||||
|
|
|
@ -8,13 +8,12 @@ use std::{
|
|||
use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
generics::TypeOrConstParamData,
|
||||
hir::{
|
||||
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
|
||||
},
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
path::{GenericArg, GenericArgs, Path},
|
||||
BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
|
||||
path::{GenericArgs, Path},
|
||||
BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use stdx::always;
|
||||
|
@ -1816,10 +1815,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,8 +1834,7 @@ impl InferenceContext<'_> {
|
|||
for (arg, kind_id) in generic_args
|
||||
.args
|
||||
.iter()
|
||||
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
|
||||
.take(type_params + const_params)
|
||||
.take(type_params + const_params + lifetime_params)
|
||||
.zip(def_generics.iter_id())
|
||||
{
|
||||
if let Some(g) = generic_arg_to_chalk(
|
||||
|
@ -1850,6 +1855,7 @@ impl InferenceContext<'_> {
|
|||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
},
|
||||
|this, lt_ref| this.make_lifetime(lt_ref),
|
||||
) {
|
||||
substs.push(g);
|
||||
}
|
||||
|
@ -1858,16 +1864,17 @@ impl InferenceContext<'_> {
|
|||
|
||||
// Handle everything else as unknown. This also handles generic arguments for the method's
|
||||
// parent (impl or trait), which should come after those for the method.
|
||||
for (id, data) in def_generics.iter().skip(substs.len()) {
|
||||
match data {
|
||||
TypeOrConstParamData::TypeParamData(_) => {
|
||||
for (id, _data) in def_generics.iter().skip(substs.len()) {
|
||||
match id {
|
||||
GenericParamId::TypeParamId(_) => {
|
||||
substs.push(self.table.new_type_var().cast(Interner))
|
||||
}
|
||||
TypeOrConstParamData::ConstParamData(_) => substs.push(
|
||||
self.table
|
||||
.new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id)))
|
||||
.cast(Interner),
|
||||
),
|
||||
GenericParamId::ConstParamId(id) => {
|
||||
substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
|
||||
}
|
||||
GenericParamId::LifetimeParamId(_) => {
|
||||
substs.push(self.table.new_lifetime_var().cast(Interner))
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(substs.len(), total_len);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -16,12 +16,12 @@ use triomphe::Arc;
|
|||
|
||||
use super::{InferOk, InferResult, InferenceContext, TypeError};
|
||||
use crate::{
|
||||
consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime,
|
||||
to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
|
||||
DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment,
|
||||
InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar,
|
||||
Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
|
||||
WhereClause,
|
||||
consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts,
|
||||
static_lifetime, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical,
|
||||
Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData,
|
||||
Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy,
|
||||
ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
|
||||
TyKind, VariableKind, WhereClause,
|
||||
};
|
||||
|
||||
impl InferenceContext<'_> {
|
||||
|
@ -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());
|
||||
|
@ -861,11 +862,16 @@ impl<'a> InferenceTable<'a> {
|
|||
where
|
||||
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
|
||||
{
|
||||
fold_tys_and_consts(
|
||||
fold_generic_args(
|
||||
ty,
|
||||
|it, _| match it {
|
||||
Either::Left(ty) => Either::Left(self.insert_type_vars_shallow(ty)),
|
||||
Either::Right(c) => Either::Right(self.insert_const_vars_shallow(c)),
|
||||
|arg, _| match arg {
|
||||
GenericArgData::Ty(ty) => GenericArgData::Ty(self.insert_type_vars_shallow(ty)),
|
||||
// FIXME: insert lifetime vars once LifetimeData::InferenceVar
|
||||
// and specific error variant for lifetimes start being constructed
|
||||
GenericArgData::Lifetime(lt) => GenericArgData::Lifetime(lt),
|
||||
GenericArgData::Const(c) => {
|
||||
GenericArgData::Const(self.insert_const_vars_shallow(c))
|
||||
}
|
||||
},
|
||||
DebruijnIndex::INNERMOST,
|
||||
)
|
||||
|
|
|
@ -90,8 +90,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;
|
||||
|
@ -335,11 +335,23 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
|
|||
generics: &Generics,
|
||||
value: T,
|
||||
) -> Binders<T> {
|
||||
let it = generics.iter_id().take(count).map(|id| match id {
|
||||
Either::Left(_) => None,
|
||||
Either::Right(id) => Some(db.const_param_ty(id)),
|
||||
});
|
||||
crate::make_type_and_const_binders(it, value)
|
||||
let it = generics.iter_id().take(count);
|
||||
|
||||
Binders::new(
|
||||
VariableKinds::from_iter(
|
||||
Interner,
|
||||
it.map(|x| match x {
|
||||
hir_def::GenericParamId::ConstParamId(id) => {
|
||||
chalk_ir::VariableKind::Const(db.const_param_ty(id))
|
||||
}
|
||||
hir_def::GenericParamId::TypeParamId(_) => {
|
||||
chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
|
||||
}
|
||||
hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
|
||||
}),
|
||||
),
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
|
||||
|
@ -609,6 +621,10 @@ pub fn static_lifetime() -> Lifetime {
|
|||
LifetimeData::Static.intern(Interner)
|
||||
}
|
||||
|
||||
pub fn error_lifetime() -> Lifetime {
|
||||
static_lifetime()
|
||||
}
|
||||
|
||||
pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
|
||||
t: T,
|
||||
for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
|
||||
|
@ -698,6 +714,55 @@ pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFold
|
|||
t.fold_with(&mut TyFolder(f), binders)
|
||||
}
|
||||
|
||||
pub(crate) fn fold_generic_args<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
|
||||
t: T,
|
||||
f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData,
|
||||
binders: DebruijnIndex,
|
||||
) -> T {
|
||||
use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
|
||||
#[derive(chalk_derive::FallibleTypeFolder)]
|
||||
#[has_interner(Interner)]
|
||||
struct TyFolder<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData>(F);
|
||||
impl<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData> TypeFolder<Interner>
|
||||
for TyFolder<F>
|
||||
{
|
||||
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
|
||||
self
|
||||
}
|
||||
|
||||
fn interner(&self) -> Interner {
|
||||
Interner
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
|
||||
let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
|
||||
self.0(GenericArgData::Ty(ty), outer_binder)
|
||||
.intern(Interner)
|
||||
.ty(Interner)
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
|
||||
self.0(GenericArgData::Const(c), outer_binder)
|
||||
.intern(Interner)
|
||||
.constant(Interner)
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime {
|
||||
let lt = lt.super_fold_with(self.as_dyn(), outer_binder);
|
||||
self.0(GenericArgData::Lifetime(lt), outer_binder)
|
||||
.intern(Interner)
|
||||
.lifetime(Interner)
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
t.fold_with(&mut TyFolder(f), binders)
|
||||
}
|
||||
|
||||
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
|
||||
/// ensures there are no unbound variables or inference variables anywhere in
|
||||
/// the `t`.
|
||||
|
|
|
@ -24,17 +24,20 @@ use hir_def::{
|
|||
data::adt::StructKind,
|
||||
expander::Expander,
|
||||
generics::{
|
||||
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
||||
GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
||||
WherePredicateTypeTarget,
|
||||
},
|
||||
lang_item::LangItem,
|
||||
nameres::MacroSubNs,
|
||||
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
|
||||
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
||||
type_ref::{
|
||||
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;
|
||||
|
@ -52,18 +55,18 @@ use crate::{
|
|||
unknown_const_as_generic,
|
||||
},
|
||||
db::HirDatabase,
|
||||
make_binders,
|
||||
mapping::{from_chalk_trait_id, ToChalk},
|
||||
error_lifetime, make_binders,
|
||||
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
|
||||
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
||||
utils::Generics,
|
||||
utils::{
|
||||
all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
|
||||
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
|
||||
InTypeConstIdMetadata,
|
||||
},
|
||||
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
||||
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind,
|
||||
PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution,
|
||||
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
|
||||
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
|
||||
LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
|
||||
QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
|
||||
TyKind, WhereClause,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -275,9 +278,11 @@ impl<'a> TyLoweringContext<'a> {
|
|||
let inner_ty = self.lower_ty(inner);
|
||||
TyKind::Slice(inner_ty).intern(Interner)
|
||||
}
|
||||
TypeRef::Reference(inner, _, mutability) => {
|
||||
TypeRef::Reference(inner, lifetime, mutability) => {
|
||||
let inner_ty = self.lower_ty(inner);
|
||||
let lifetime = static_lifetime();
|
||||
// FIXME: It should infer the eldided lifetimes instead of stubbing with static
|
||||
let lifetime =
|
||||
lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr));
|
||||
TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
|
||||
.intern(Interner)
|
||||
}
|
||||
|
@ -351,13 +356,18 @@ impl<'a> TyLoweringContext<'a> {
|
|||
.filter(|(_, data)| {
|
||||
matches!(
|
||||
data,
|
||||
TypeOrConstParamData::TypeParamData(data)
|
||||
GenericParamDataRef::TypeParamData(data)
|
||||
if data.provenance == TypeParamProvenance::ArgumentImplTrait
|
||||
)
|
||||
})
|
||||
.nth(idx as usize)
|
||||
.map_or(TyKind::Error, |(id, _)| {
|
||||
TyKind::Placeholder(to_placeholder_idx(self.db, id))
|
||||
if let GenericParamId::TypeParamId(id) = id {
|
||||
TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
|
||||
} else {
|
||||
// we just filtered them out
|
||||
unreachable!("Unexpected lifetime or const argument");
|
||||
}
|
||||
});
|
||||
param.intern(Interner)
|
||||
} else {
|
||||
|
@ -374,11 +384,12 @@ 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,
|
||||
|
@ -815,9 +826,16 @@ 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);
|
||||
|
@ -832,7 +850,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);
|
||||
}
|
||||
}
|
||||
|
@ -865,6 +886,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);
|
||||
|
@ -874,15 +896,45 @@ impl<'a> TyLoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for arg in generic_args
|
||||
.args
|
||||
.iter()
|
||||
.filter(|arg| matches!(arg, GenericArg::Lifetime(_)))
|
||||
.take(lifetime_params)
|
||||
{
|
||||
// Taking into the fact that def_generic_iter will always have lifetimes at the end
|
||||
// Should have some test cases tho to test this behaviour more properly
|
||||
if let Some(id) = def_generic_iter.next() {
|
||||
if let Some(x) = generic_arg_to_chalk(
|
||||
self.db,
|
||||
id,
|
||||
arg,
|
||||
&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);
|
||||
} else {
|
||||
// Never return a None explicitly
|
||||
never!("Unexpected None by generic_arg_to_chalk");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fill_self_params();
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
@ -1309,6 +1361,33 @@ impl<'a> TyLoweringContext<'a> {
|
|||
});
|
||||
ImplTrait { bounds: crate::make_single_type_binders(predicates) }
|
||||
}
|
||||
|
||||
pub fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
|
||||
match self.resolver.resolve_lifetime(lifetime) {
|
||||
Some(resolution) => match resolution {
|
||||
LifetimeNs::Static => static_lifetime(),
|
||||
LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
|
||||
ParamLoweringMode::Placeholder => {
|
||||
LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
|
||||
}
|
||||
ParamLoweringMode::Variable => {
|
||||
let generics = generics(
|
||||
self.db.upcast(),
|
||||
self.resolver.generic_def().expect("generics in scope"),
|
||||
);
|
||||
let idx = match generics.lifetime_idx(id) {
|
||||
None => return error_lifetime(),
|
||||
Some(idx) => idx,
|
||||
};
|
||||
|
||||
LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
|
||||
}
|
||||
}
|
||||
.intern(Interner),
|
||||
},
|
||||
None => error_lifetime(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
||||
|
@ -1691,7 +1770,7 @@ pub(crate) fn generic_defaults_query(
|
|||
|
||||
let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
|
||||
match p {
|
||||
TypeOrConstParamData::TypeParamData(p) => {
|
||||
GenericParamDataRef::TypeParamData(p) => {
|
||||
let mut ty =
|
||||
p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
|
||||
// Each default can only refer to previous parameters.
|
||||
|
@ -1700,13 +1779,13 @@ pub(crate) fn generic_defaults_query(
|
|||
ty = fallback_bound_vars(ty, idx, parent_start_idx);
|
||||
crate::make_binders(db, &generic_params, ty.cast(Interner))
|
||||
}
|
||||
TypeOrConstParamData::ConstParamData(p) => {
|
||||
GenericParamDataRef::ConstParamData(p) => {
|
||||
let GenericParamId::ConstParamId(id) = id else {
|
||||
unreachable!("Unexpected lifetime or type argument")
|
||||
};
|
||||
|
||||
let mut val = p.default.as_ref().map_or_else(
|
||||
|| {
|
||||
unknown_const_as_generic(
|
||||
db.const_param_ty(ConstParamId::from_unchecked(id)),
|
||||
)
|
||||
},
|
||||
|| unknown_const_as_generic(db.const_param_ty(id)),
|
||||
|c| {
|
||||
let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
|
||||
c.cast(Interner)
|
||||
|
@ -1716,6 +1795,10 @@ pub(crate) fn generic_defaults_query(
|
|||
val = fallback_bound_vars(val, idx, parent_start_idx);
|
||||
make_binders(db, &generic_params, val)
|
||||
}
|
||||
GenericParamDataRef::LifetimeParamData(_) => {
|
||||
// using static because it requires defaults
|
||||
make_binders(db, &generic_params, static_lifetime().cast(Interner))
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -1732,8 +1815,9 @@ pub(crate) fn generic_defaults_recover(
|
|||
// we still need one default per parameter
|
||||
let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
|
||||
let val = match id {
|
||||
Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
|
||||
Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
|
||||
GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
|
||||
GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
|
||||
GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner),
|
||||
};
|
||||
crate::make_binders(db, &generic_params, val)
|
||||
}));
|
||||
|
@ -2097,23 +2181,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
|
||||
|
@ -2129,7 +2219,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),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,14 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
|
|||
db.lookup_intern_lifetime_param_id(interned_id)
|
||||
}
|
||||
|
||||
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,
|
||||
idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
|
||||
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
|
||||
}
|
||||
|
|
|
@ -184,8 +184,16 @@ impl Filler<'_> {
|
|||
self.generics
|
||||
.as_ref()
|
||||
.and_then(|it| it.iter().nth(b.index))
|
||||
.unwrap()
|
||||
.0,
|
||||
.and_then(|(id, _)| match id {
|
||||
hir_def::GenericParamId::ConstParamId(id) => {
|
||||
Some(hir_def::TypeOrConstParamId::from(id))
|
||||
}
|
||||
hir_def::GenericParamId::TypeParamId(id) => {
|
||||
Some(hir_def::TypeOrConstParamId::from(id))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.unwrap(),
|
||||
self.subst.clone(),
|
||||
)
|
||||
})?
|
||||
|
|
|
@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
|
|||
trait Foo<'a> {}
|
||||
|
||||
fn foo(foo: &dyn for<'a> Foo<'a>) {}
|
||||
// ^^^ &dyn Foo
|
||||
// ^^^ &dyn Foo<'static>
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1109,7 +1109,7 @@ fn var_args() {
|
|||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f>;
|
||||
fn my_fn(foo: ...) {}
|
||||
//^^^ VaListImpl<'_>
|
||||
//^^^ VaListImpl<'static>
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -896,13 +896,13 @@ fn flush(&self) {
|
|||
"#,
|
||||
expect![[r#"
|
||||
123..127 'self': &Mutex<T>
|
||||
150..152 '{}': MutexGuard<'_, T>
|
||||
150..152 '{}': MutexGuard<'static, T>
|
||||
234..238 'self': &{unknown}
|
||||
240..290 '{ ...()); }': ()
|
||||
250..251 'w': &Mutex<BufWriter>
|
||||
276..287 '*(w.lock())': BufWriter
|
||||
278..279 'w': &Mutex<BufWriter>
|
||||
278..286 'w.lock()': MutexGuard<'_, BufWriter>
|
||||
278..286 'w.lock()': MutexGuard<'static, BufWriter>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3092,7 +3092,7 @@ fn main() {
|
|||
389..394 'boxed': Box<Foo<i32>>
|
||||
389..406 'boxed....nner()': &i32
|
||||
416..421 'good1': &i32
|
||||
424..438 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
|
||||
424..438 'Foo::get_inner': fn get_inner<i32, 'static>(&Box<Foo<i32>>) -> &i32
|
||||
424..446 'Foo::g...boxed)': &i32
|
||||
439..445 '&boxed': &Box<Foo<i32>>
|
||||
440..445 'boxed': Box<Foo<i32>>
|
||||
|
@ -3100,7 +3100,7 @@ fn main() {
|
|||
464..469 'boxed': Box<Foo<i32>>
|
||||
464..480 'boxed....self()': &Foo<i32>
|
||||
490..495 'good2': &Foo<i32>
|
||||
498..511 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
|
||||
498..511 'Foo::get_self': fn get_self<i32, 'static>(&Box<Foo<i32>>) -> &Foo<i32>
|
||||
498..519 'Foo::g...boxed)': &Foo<i32>
|
||||
512..518 '&boxed': &Box<Foo<i32>>
|
||||
513..518 'boxed': Box<Foo<i32>>
|
||||
|
@ -3659,7 +3659,7 @@ fn main() {
|
|||
let are = "are";
|
||||
let count = 10;
|
||||
builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'_>
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'static>
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
@ -9,18 +9,18 @@ use chalk_ir::{
|
|||
fold::{FallibleTypeFolder, Shift},
|
||||
BoundVar, DebruijnIndex,
|
||||
};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
db::DefDatabase,
|
||||
generics::{
|
||||
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
||||
WherePredicateTypeTarget,
|
||||
GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
|
||||
TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
|
||||
},
|
||||
lang_item::LangItem,
|
||||
resolver::{HasResolver, TypeNs},
|
||||
type_ref::{TraitBoundModifier, TypeRef},
|
||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
|
||||
OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
|
||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId,
|
||||
LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||
TypeParamId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::Interned;
|
||||
|
@ -270,64 +270,130 @@ pub(crate) struct Generics {
|
|||
}
|
||||
|
||||
impl Generics {
|
||||
pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ {
|
||||
self.iter().map(|(id, data)| match data {
|
||||
TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
|
||||
TypeOrConstParamData::ConstParamData(_) => {
|
||||
Either::Right(ConstParamId::from_unchecked(id))
|
||||
}
|
||||
})
|
||||
pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
|
||||
self.iter().map(|(id, _)| id)
|
||||
}
|
||||
|
||||
/// Iterator over types and const params of self, then parent.
|
||||
pub(crate) fn iter<'a>(
|
||||
&'a self,
|
||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
let to_toc_id = |it: &'a Generics| {
|
||||
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
|
||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
||||
let from_toc_id = |it: &'a Generics| {
|
||||
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
||||
let id = TypeOrConstParamId { parent: it.def, local_id };
|
||||
match p {
|
||||
TypeOrConstParamData::TypeParamData(p) => (
|
||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
||||
GenericParamDataRef::TypeParamData(p),
|
||||
),
|
||||
TypeOrConstParamData::ConstParamData(p) => (
|
||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
||||
GenericParamDataRef::ConstParamData(p),
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
|
||||
|
||||
let from_lt_id = |it: &'a Generics| {
|
||||
move |(local_id, p): (_, &'a LifetimeParamData)| {
|
||||
(
|
||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||
GenericParamDataRef::LifetimeParamData(p),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let lt_iter = self.params.iter_lt().map(from_lt_id(self));
|
||||
self.params.iter().map(from_toc_id(self)).chain(lt_iter).chain(self.iter_parent())
|
||||
}
|
||||
|
||||
/// Iterate over types and const params without parent params.
|
||||
pub(crate) fn iter_self<'a>(
|
||||
&'a self,
|
||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
|
||||
let to_toc_id = |it: &'a Generics| {
|
||||
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
|
||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
||||
let from_toc_id = |it: &'a Generics| {
|
||||
move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
||||
let id = TypeOrConstParamId { parent: it.def, local_id };
|
||||
match p {
|
||||
TypeOrConstParamData::TypeParamData(p) => (
|
||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
||||
GenericParamDataRef::TypeParamData(p),
|
||||
),
|
||||
TypeOrConstParamData::ConstParamData(p) => (
|
||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
||||
GenericParamDataRef::ConstParamData(p),
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
self.params.iter().map(to_toc_id(self))
|
||||
|
||||
let from_lt_id = |it: &'a Generics| {
|
||||
move |(local_id, p): (_, &'a LifetimeParamData)| {
|
||||
(
|
||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||
GenericParamDataRef::LifetimeParamData(p),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
|
||||
}
|
||||
|
||||
/// Iterator over types and const params of parent.
|
||||
pub(crate) fn iter_parent(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> {
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub(crate) fn iter_parent<'a>(
|
||||
&'a self,
|
||||
) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
|
||||
self.parent_generics().into_iter().flat_map(|it| {
|
||||
let to_toc_id =
|
||||
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
|
||||
it.params.iter().map(to_toc_id)
|
||||
let from_toc_id = move |(local_id, p): (_, &'a TypeOrConstParamData)| {
|
||||
let id = TypeOrConstParamId { parent: it.def, local_id };
|
||||
match p {
|
||||
TypeOrConstParamData::TypeParamData(p) => (
|
||||
GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
|
||||
GenericParamDataRef::TypeParamData(p),
|
||||
),
|
||||
TypeOrConstParamData::ConstParamData(p) => (
|
||||
GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
|
||||
GenericParamDataRef::ConstParamData(p),
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
let from_lt_id = move |(local_id, p): (_, &'a LifetimeParamData)| {
|
||||
(
|
||||
GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
|
||||
GenericParamDataRef::LifetimeParamData(p),
|
||||
)
|
||||
};
|
||||
let lt_iter = it.params.iter_lt().map(from_lt_id);
|
||||
it.params.iter().map(from_toc_id).chain(lt_iter)
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns total number of generic parameters in scope, including those from parent.
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
let parent = self.parent_generics().map_or(0, Generics::len);
|
||||
let child = self.params.type_or_consts.len();
|
||||
let child = self.params.type_or_consts.len() + self.params.lifetimes.len();
|
||||
parent + child
|
||||
}
|
||||
|
||||
/// Returns numbers of generic parameters excluding those from parent.
|
||||
/// Returns numbers of generic parameters and lifetimes excluding those from parent.
|
||||
pub(crate) fn len_self(&self) -> usize {
|
||||
self.params.type_or_consts.len() + self.params.lifetimes.len()
|
||||
}
|
||||
|
||||
/// Returns number of generic parameter excluding those from parent
|
||||
fn len_params(&self) -> usize {
|
||||
self.params.type_or_consts.len()
|
||||
}
|
||||
|
||||
/// (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,
|
||||
|
@ -337,8 +403,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> {
|
||||
|
@ -358,6 +426,26 @@ impl Generics {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
|
||||
Some(self.find_lifetime(lifetime)?.0)
|
||||
}
|
||||
|
||||
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
|
||||
if lifetime.parent == self.def {
|
||||
let (idx, (_local_id, data)) = self
|
||||
.params
|
||||
.iter_lt()
|
||||
.enumerate()
|
||||
.find(|(_, (idx, _))| *idx == lifetime.local_id)?;
|
||||
|
||||
Some((self.len_params() + idx, data))
|
||||
} else {
|
||||
self.parent_generics()
|
||||
.and_then(|g| g.find_lifetime(lifetime))
|
||||
.map(|(idx, data)| (self.len_self() + idx, data))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
|
||||
self.parent_generics.as_deref()
|
||||
}
|
||||
|
@ -371,10 +459,15 @@ impl Generics {
|
|||
Substitution::from_iter(
|
||||
Interner,
|
||||
self.iter_id().enumerate().map(|(idx, id)| match id {
|
||||
Either::Left(_) => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
|
||||
Either::Right(id) => BoundVar::new(debruijn, idx)
|
||||
GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
|
||||
.to_const(Interner, db.const_param_ty(id))
|
||||
.cast(Interner),
|
||||
GenericParamId::TypeParamId(_) => {
|
||||
BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
|
||||
}
|
||||
GenericParamId::LifetimeParamId(_) => {
|
||||
BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -384,12 +477,15 @@ impl Generics {
|
|||
Substitution::from_iter(
|
||||
Interner,
|
||||
self.iter_id().map(|id| match id {
|
||||
Either::Left(id) => {
|
||||
GenericParamId::TypeParamId(id) => {
|
||||
crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
|
||||
}
|
||||
Either::Right(id) => crate::to_placeholder_idx(db, id.into())
|
||||
GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
|
||||
.to_const(Interner, db.const_param_ty(id))
|
||||
.cast(Interner),
|
||||
GenericParamId::LifetimeParamId(id) => {
|
||||
crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
@ -1107,6 +1107,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);
|
||||
|
@ -1448,6 +1449,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();
|
||||
|
@ -1866,6 +1868,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 =
|
||||
|
@ -1964,6 +1967,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();
|
||||
|
@ -4139,6 +4144,7 @@ impl Type {
|
|||
// FIXME: this code is not covered in tests.
|
||||
unknown_const_as_generic(ty.clone())
|
||||
}
|
||||
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
||||
}
|
||||
})
|
||||
.build();
|
||||
|
@ -4169,6 +4175,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();
|
||||
|
|
|
@ -5617,7 +5617,7 @@ fn func<T: Debug>(i: Struct<'_, T>) {
|
|||
fun_name(i);
|
||||
}
|
||||
|
||||
fn $0fun_name(i: Struct<'_, T>) {
|
||||
fn $0fun_name(i: Struct<'static, T>) {
|
||||
foo(i);
|
||||
}
|
||||
"#,
|
||||
|
|
|
@ -614,7 +614,7 @@ struct Foo<'a, T> {
|
|||
}
|
||||
|
||||
impl<'a, T> Foo<'a, T> {
|
||||
$0fn bar(self, mut b: Vec<&'a Bar<'_, T>>) -> &'a Bar<'_, T> {
|
||||
$0fn bar(self, mut b: Vec<&'a Bar<'a, T>>) -> &'a Bar<'a, T> {
|
||||
self.field.bar(b)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
st Foo<…> Foo<'_, {unknown}, _>
|
||||
st Foo<…> Foo<'static, {unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
st Foo<…> Foo<'_, {unknown}, _>
|
||||
st Foo<…> Foo<'static, {unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
|
|
@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> {
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
sp Self Foo<'_, {unknown}, _>
|
||||
st Foo<…> Foo<'_, {unknown}, _>
|
||||
sp Self Foo<'static, {unknown}, _>
|
||||
st Foo<…> Foo<'static, {unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0);
|
|||
en Enum Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
sp Self Foo<'_, {unknown}, _>
|
||||
st Foo<…> Foo<'_, {unknown}, _>
|
||||
sp Self Foo<'static, {unknown}, _>
|
||||
st Foo<…> Foo<'static, {unknown}, _>
|
||||
st Record Record
|
||||
st Tuple Tuple
|
||||
st Unit Unit
|
||||
|
|
|
@ -279,7 +279,8 @@ impl flags::AnalysisStats {
|
|||
let mut all = 0;
|
||||
let mut fail = 0;
|
||||
for &a in adts {
|
||||
if db.generic_params(a.into()).iter().next().is_some() {
|
||||
let generic_params = db.generic_params(a.into());
|
||||
if generic_params.iter().next().is_some() || generic_params.iter_lt().next().is_some() {
|
||||
// Data types with generics don't have layout.
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue