Skip to content

Commit 0583aaa

Browse files
committed
Auto merge of rust-lang#16805 - dfireBird:lifetime_lowering, r=Veykril
feat: Implement resolving and lowering of Lifetimes (no inference yet)
2 parents e52bb8c + 0e54e2b commit 0583aaa

23 files changed

+571
-157
lines changed

crates/hir-def/src/generics.rs

+69-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use crate::{
2222
lower::LowerCtx,
2323
nameres::{DefMap, MacroSubNs},
2424
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
25-
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
26-
TypeOrConstParamId, TypeParamId,
25+
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
26+
LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
2727
};
2828

2929
/// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -102,6 +102,52 @@ impl TypeOrConstParamData {
102102

103103
impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
104104

105+
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
106+
pub enum GenericParamData {
107+
TypeParamData(TypeParamData),
108+
ConstParamData(ConstParamData),
109+
LifetimeParamData(LifetimeParamData),
110+
}
111+
112+
impl GenericParamData {
113+
pub fn name(&self) -> Option<&Name> {
114+
match self {
115+
GenericParamData::TypeParamData(it) => it.name.as_ref(),
116+
GenericParamData::ConstParamData(it) => Some(&it.name),
117+
GenericParamData::LifetimeParamData(it) => Some(&it.name),
118+
}
119+
}
120+
121+
pub fn type_param(&self) -> Option<&TypeParamData> {
122+
match self {
123+
GenericParamData::TypeParamData(it) => Some(it),
124+
_ => None,
125+
}
126+
}
127+
128+
pub fn const_param(&self) -> Option<&ConstParamData> {
129+
match self {
130+
GenericParamData::ConstParamData(it) => Some(it),
131+
_ => None,
132+
}
133+
}
134+
135+
pub fn lifetime_param(&self) -> Option<&LifetimeParamData> {
136+
match self {
137+
GenericParamData::LifetimeParamData(it) => Some(it),
138+
_ => None,
139+
}
140+
}
141+
}
142+
143+
impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData);
144+
145+
pub enum GenericParamDataRef<'a> {
146+
TypeParamData(&'a TypeParamData),
147+
ConstParamData(&'a ConstParamData),
148+
LifetimeParamData(&'a LifetimeParamData),
149+
}
150+
105151
/// Data about the generic parameters of a function, struct, impl, etc.
106152
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
107153
pub struct GenericParams {
@@ -365,6 +411,13 @@ impl GenericParams {
365411
self.type_or_consts.iter()
366412
}
367413

414+
/// Iterator of lifetimes field
415+
pub fn iter_lt(
416+
&self,
417+
) -> impl DoubleEndedIterator<Item = (Idx<LifetimeParamData>, &LifetimeParamData)> {
418+
self.lifetimes.iter()
419+
}
420+
368421
pub(crate) fn generic_params_query(
369422
db: &dyn DefDatabase,
370423
def: GenericDefId,
@@ -507,4 +560,18 @@ impl GenericParams {
507560
.then(|| id)
508561
})
509562
}
563+
564+
pub fn find_lifetime_by_name(
565+
&self,
566+
name: &Name,
567+
parent: GenericDefId,
568+
) -> Option<LifetimeParamId> {
569+
self.lifetimes.iter().find_map(|(id, p)| {
570+
if &p.name == name {
571+
Some(LifetimeParamId { local_id: id, parent })
572+
} else {
573+
None
574+
}
575+
})
576+
}
510577
}

crates/hir-def/src/resolver.rs

+20
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::{
2424
nameres::{DefMap, MacroSubNs},
2525
path::{ModPath, Path, PathKind},
2626
per_ns::PerNs,
27+
type_ref::LifetimeRef,
2728
visibility::{RawVisibility, Visibility},
2829
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
2930
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
@@ -120,6 +121,12 @@ pub enum ValueNs {
120121
GenericParam(ConstParamId),
121122
}
122123

124+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
125+
pub enum LifetimeNs {
126+
Static,
127+
LifetimeParam(LifetimeParamId),
128+
}
129+
123130
impl Resolver {
124131
/// Resolve known trait from std, like `std::futures::Future`
125132
pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
@@ -418,6 +425,19 @@ impl Resolver {
418425
self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
419426
}
420427

428+
pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
429+
if lifetime.name == name::known::STATIC_LIFETIME {
430+
return Some(LifetimeNs::Static);
431+
}
432+
433+
self.scopes().find_map(|scope| match scope {
434+
Scope::GenericParams { def, params } => {
435+
params.find_lifetime_by_name(&lifetime.name, *def).map(LifetimeNs::LifetimeParam)
436+
}
437+
_ => None,
438+
})
439+
}
440+
421441
/// Returns a set of names available in the current scope.
422442
///
423443
/// Note that this is a somewhat fuzzy concept -- internally, the compiler

crates/hir-ty/src/builder.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ use chalk_ir::{
99
AdtId, DebruijnIndex, Scalar,
1010
};
1111
use hir_def::{
12-
builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
13-
GenericDefId, TraitId, TypeAliasId,
12+
builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
1413
};
1514
use smallvec::SmallVec;
1615

1716
use crate::{
18-
consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
19-
to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
20-
GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
21-
TyKind,
17+
consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
18+
infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
19+
Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
20+
Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
2221
};
2322

2423
#[derive(Debug, Clone, PartialEq, Eq)]
2524
pub enum ParamKind {
2625
Type,
26+
Lifetime,
2727
Const(Ty),
2828
}
2929

@@ -107,6 +107,9 @@ impl<D> TyBuilder<D> {
107107
ParamKind::Const(ty) => {
108108
BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
109109
}
110+
ParamKind::Lifetime => {
111+
BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
112+
}
110113
});
111114
this.vec.extend(filler.take(this.remaining()).casted(Interner));
112115
assert_eq!(this.remaining(), 0);
@@ -119,6 +122,7 @@ impl<D> TyBuilder<D> {
119122
let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x {
120123
ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
121124
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
125+
ParamKind::Lifetime => error_lifetime().cast(Interner),
122126
});
123127
this.vec.extend(filler.casted(Interner));
124128
assert_eq!(this.remaining(), 0);
@@ -130,6 +134,7 @@ impl<D> TyBuilder<D> {
130134
self.fill(|x| match x {
131135
ParamKind::Type => table.new_type_var().cast(Interner),
132136
ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
137+
ParamKind::Lifetime => table.new_lifetime_var().cast(Interner),
133138
})
134139
}
135140

@@ -142,7 +147,8 @@ impl<D> TyBuilder<D> {
142147
fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
143148
match (a.data(Interner), e) {
144149
(GenericArgData::Ty(_), ParamKind::Type)
145-
| (GenericArgData::Const(_), ParamKind::Const(_)) => (),
150+
| (GenericArgData::Const(_), ParamKind::Const(_))
151+
| (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (),
146152
_ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
147153
}
148154
}
@@ -201,10 +207,11 @@ impl TyBuilder<()> {
201207
Substitution::from_iter(
202208
Interner,
203209
params.iter_id().map(|id| match id {
204-
either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
205-
either::Either::Right(id) => {
210+
GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
211+
GenericParamId::ConstParamId(id) => {
206212
unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
207213
}
214+
GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
208215
}),
209216
)
210217
}
@@ -219,11 +226,10 @@ impl TyBuilder<()> {
219226
assert!(generics.parent_generics().is_some() == parent_subst.is_some());
220227
let params = generics
221228
.iter_self()
222-
.map(|(id, data)| match data {
223-
TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
224-
TypeOrConstParamData::ConstParamData(_) => {
225-
ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
226-
}
229+
.map(|(id, _data)| match id {
230+
GenericParamId::TypeParamId(_) => ParamKind::Type,
231+
GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
232+
GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
227233
})
228234
.collect();
229235
TyBuilder::new((), params, parent_subst)

crates/hir-ty/src/display.rs

+39-15
Original file line numberDiff line numberDiff line change
@@ -938,18 +938,32 @@ impl HirDisplay for Ty {
938938
f.end_location_link();
939939
if parameters.len(Interner) > 0 {
940940
let generics = generics(db.upcast(), def.into());
941-
let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
942-
generics.provenance_split();
943-
let total_len = parent_params + self_param + type_params + const_params;
941+
let (
942+
parent_params,
943+
self_param,
944+
type_params,
945+
const_params,
946+
_impl_trait_params,
947+
lifetime_params,
948+
) = generics.provenance_split();
949+
let total_len =
950+
parent_params + self_param + type_params + const_params + lifetime_params;
944951
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
945952
if total_len > 0 {
946-
// `parameters` are in the order of fn's params (including impl traits),
953+
// `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
947954
// parent's params (those from enclosing impl or trait, if any).
948955
let parameters = parameters.as_slice(Interner);
949956
let fn_params_len = self_param + type_params + const_params;
957+
// This will give slice till last type or const
950958
let fn_params = parameters.get(..fn_params_len);
959+
let fn_lt_params =
960+
parameters.get(fn_params_len..(fn_params_len + lifetime_params));
951961
let parent_params = parameters.get(parameters.len() - parent_params..);
952-
let params = parent_params.into_iter().chain(fn_params).flatten();
962+
let params = parent_params
963+
.into_iter()
964+
.chain(fn_lt_params)
965+
.chain(fn_params)
966+
.flatten();
953967
write!(f, "<")?;
954968
f.write_joined(params, ", ")?;
955969
write!(f, ">")?;
@@ -1308,8 +1322,17 @@ fn hir_fmt_generics(
13081322
generic_def: Option<hir_def::GenericDefId>,
13091323
) -> Result<(), HirDisplayError> {
13101324
let db = f.db;
1311-
let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
1312-
if parameters.len(Interner) + lifetime_args_count > 0 {
1325+
if parameters.len(Interner) > 0 {
1326+
use std::cmp::Ordering;
1327+
let param_compare =
1328+
|a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) {
1329+
(crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => {
1330+
Ordering::Equal
1331+
}
1332+
(crate::GenericArgData::Lifetime(_), _) => Ordering::Less,
1333+
(_, crate::GenericArgData::Lifetime(_)) => Ordering::Less,
1334+
(_, _) => Ordering::Equal,
1335+
};
13131336
let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
13141337
match generic_def
13151338
.map(|generic_def_id| db.generic_defaults(generic_def_id))
@@ -1335,6 +1358,11 @@ fn hir_fmt_generics(
13351358
return true;
13361359
}
13371360
}
1361+
if parameter.lifetime(Interner).map(|it| it.data(Interner))
1362+
== Some(&crate::LifetimeData::Static)
1363+
{
1364+
return true;
1365+
}
13381366
let default_parameter = match default_parameters.get(i) {
13391367
Some(it) => it,
13401368
None => return true,
@@ -1355,16 +1383,12 @@ fn hir_fmt_generics(
13551383
} else {
13561384
parameters.as_slice(Interner)
13571385
};
1358-
if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
1386+
//FIXME: Should handle the ordering of lifetimes when creating substitutions
1387+
let mut parameters_to_write = parameters_to_write.to_vec();
1388+
parameters_to_write.sort_by(param_compare);
1389+
if !parameters_to_write.is_empty() {
13591390
write!(f, "<")?;
13601391
let mut first = true;
1361-
for _ in 0..lifetime_args_count {
1362-
if !first {
1363-
write!(f, ", ")?;
1364-
}
1365-
first = false;
1366-
write!(f, "'_")?;
1367-
}
13681392
for generic_arg in parameters_to_write {
13691393
if !first {
13701394
write!(f, ", ")?;

crates/hir-ty/src/infer.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use hir_def::{
4242
layout::Integer,
4343
path::{ModPath, Path},
4444
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
45-
type_ref::TypeRef,
45+
type_ref::{LifetimeRef, TypeRef},
4646
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
4747
TupleFieldId, TupleId, TypeAliasId, VariantId,
4848
};
@@ -1037,6 +1037,12 @@ impl<'a> InferenceContext<'a> {
10371037
self.result.standard_types.unknown.clone()
10381038
}
10391039

1040+
fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
1041+
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
1042+
let lt = ctx.lower_lifetime(lifetime_ref);
1043+
self.insert_type_vars(lt)
1044+
}
1045+
10401046
/// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
10411047
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
10421048
self.table.insert_type_vars_shallow(ty)

0 commit comments

Comments
 (0)