refactor: Turn LifetimeRef into an enum

This makes things more structured
This commit is contained in:
Lukas Wirth 2025-04-09 12:26:09 +02:00
parent dc363f7f77
commit 07212140db
8 changed files with 104 additions and 87 deletions

View File

@ -544,13 +544,19 @@ impl ExprCollector<'_> {
} }
pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRef { pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRef {
LifetimeRef::new(&lifetime) // FIXME: Keyword check?
match &*lifetime.text() {
"" | "'" => LifetimeRef::Error,
"'static" => LifetimeRef::Static,
"'_" => LifetimeRef::Placeholder,
text => LifetimeRef::Named(Name::new_lifetime(text)),
}
} }
pub fn lower_lifetime_ref_opt(&mut self, lifetime: Option<ast::Lifetime>) -> LifetimeRef { pub fn lower_lifetime_ref_opt(&mut self, lifetime: Option<ast::Lifetime>) -> LifetimeRef {
match lifetime { match lifetime {
Some(lifetime) => LifetimeRef::new(&lifetime), Some(lifetime) => self.lower_lifetime_ref(lifetime),
None => LifetimeRef::missing(), None => LifetimeRef::Placeholder,
} }
} }
@ -590,7 +596,7 @@ impl ExprCollector<'_> {
} }
ast::Type::RefType(inner) => { ast::Type::RefType(inner) => {
let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(&lt)); let lifetime = inner.lifetime().map(|lt| self.lower_lifetime_ref(lt));
let mutability = Mutability::from_mutable(inner.mut_token().is_some()); let mutability = Mutability::from_mutable(inner.mut_token().is_some());
TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability })) TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability }))
} }
@ -824,7 +830,7 @@ impl ExprCollector<'_> {
} }
ast::GenericArg::LifetimeArg(lifetime_arg) => { ast::GenericArg::LifetimeArg(lifetime_arg) => {
if let Some(lifetime) = lifetime_arg.lifetime() { if let Some(lifetime) = lifetime_arg.lifetime() {
let lifetime_ref = LifetimeRef::new(&lifetime); let lifetime_ref = self.lower_lifetime_ref(lifetime);
args.push(GenericArg::Lifetime(lifetime_ref)) args.push(GenericArg::Lifetime(lifetime_ref))
} }
} }
@ -911,7 +917,7 @@ impl ExprCollector<'_> {
let lt_refs = match for_type.generic_param_list() { let lt_refs = match for_type.generic_param_list() {
Some(gpl) => gpl Some(gpl) => gpl
.lifetime_params() .lifetime_params()
.flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(&lt))) .flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(&lt.text())))
.collect(), .collect(),
None => Box::default(), None => Box::default(),
}; };
@ -932,14 +938,14 @@ impl ExprCollector<'_> {
gal.use_bound_generic_args() gal.use_bound_generic_args()
.map(|p| match p { .map(|p| match p {
ast::UseBoundGenericArg::Lifetime(l) => { ast::UseBoundGenericArg::Lifetime(l) => {
UseArgRef::Lifetime(LifetimeRef::new(&l)) UseArgRef::Lifetime(self.lower_lifetime_ref(l))
} }
ast::UseBoundGenericArg::NameRef(n) => UseArgRef::Name(n.as_name()), ast::UseBoundGenericArg::NameRef(n) => UseArgRef::Name(n.as_name()),
}) })
.collect(), .collect(),
), ),
ast::TypeBoundKind::Lifetime(lifetime) => { ast::TypeBoundKind::Lifetime(lifetime) => {
TypeBound::Lifetime(LifetimeRef::new(&lifetime)) TypeBound::Lifetime(self.lower_lifetime_ref(lifetime))
} }
} }
} }
@ -2491,7 +2497,10 @@ impl ExprCollector<'_> {
fn collect_label(&mut self, ast_label: ast::Label) -> LabelId { fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
let label = Label { let label = Label {
name: ast_label.lifetime().as_ref().map_or_else(Name::missing, Name::new_lifetime), name: ast_label
.lifetime()
.as_ref()
.map_or_else(Name::missing, |lt| Name::new_lifetime(&lt.text())),
}; };
self.alloc_label(label, AstPtr::new(&ast_label)) self.alloc_label(label, AstPtr::new(&ast_label))
} }
@ -2511,7 +2520,7 @@ impl ExprCollector<'_> {
(hygiene_id.lookup().parent(self.db), expansion.def) (hygiene_id.lookup().parent(self.db), expansion.def)
}) })
}; };
let name = Name::new_lifetime(&lifetime); let name = Name::new_lifetime(&lifetime.text());
for (rib_idx, rib) in self.label_ribs.iter().enumerate().rev() { for (rib_idx, rib) in self.label_ribs.iter().enumerate().rev() {
match &rib.kind { match &rib.kind {

View File

@ -123,12 +123,14 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
ast::GenericParam::LifetimeParam(lifetime_param) => { ast::GenericParam::LifetimeParam(lifetime_param) => {
let lifetime_ref = let lifetime_ref =
self.expr_collector.lower_lifetime_ref_opt(lifetime_param.lifetime()); self.expr_collector.lower_lifetime_ref_opt(lifetime_param.lifetime());
let param = LifetimeParamData { name: lifetime_ref.name.clone() }; if let LifetimeRef::Named(name) = &lifetime_ref {
let _idx = self.lifetimes.alloc(param); let param = LifetimeParamData { name: name.clone() };
self.lower_bounds( let _idx = self.lifetimes.alloc(param);
lifetime_param.type_bound_list(), self.lower_bounds(
Either::Right(lifetime_ref), lifetime_param.type_bound_list(),
); Either::Right(lifetime_ref),
);
}
} }
} }
} }
@ -151,7 +153,7 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> {
.map(|lifetime_param| { .map(|lifetime_param| {
lifetime_param lifetime_param
.lifetime() .lifetime()
.map_or_else(Name::missing, |lt| Name::new_lifetime(&lt)) .map_or_else(Name::missing, |lt| Name::new_lifetime(&lt.text()))
}) })
.collect() .collect()
}); });

View File

@ -19,7 +19,7 @@ use crate::{
}, },
lang_item::LangItemTarget, lang_item::LangItemTarget,
signatures::{FnFlags, FunctionSignature, StructSignature}, signatures::{FnFlags, FunctionSignature, StructSignature},
type_ref::{ConstRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef},
}; };
use super::*; use super::*;
@ -268,12 +268,9 @@ fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p:
} }
}, },
WherePredicate::Lifetime { target, bound } => { WherePredicate::Lifetime { target, bound } => {
w!( p.print_lifetime_ref(target);
p, w!(p, ": ");
"{}: {}", p.print_lifetime_ref(bound);
target.name.display(db.upcast(), p.edition),
bound.name.display(db.upcast(), p.edition)
);
} }
WherePredicate::ForLifetime { lifetimes, target, bound } => { WherePredicate::ForLifetime { lifetimes, target, bound } => {
w!(p, "for<"); w!(p, "for<");
@ -1140,9 +1137,7 @@ impl Printer<'_> {
match arg { match arg {
GenericArg::Type(ty) => self.print_type_ref(*ty), GenericArg::Type(ty) => self.print_type_ref(*ty),
GenericArg::Const(ConstRef { expr }) => self.print_expr(*expr), GenericArg::Const(ConstRef { expr }) => self.print_expr(*expr),
GenericArg::Lifetime(lt) => { GenericArg::Lifetime(lt) => self.print_lifetime_ref(lt),
w!(self, "{}", lt.name.display(self.db.upcast(), self.edition))
}
} }
} }
@ -1155,6 +1150,17 @@ impl Printer<'_> {
} }
} }
pub(crate) fn print_lifetime_ref(&mut self, lt_ref: &LifetimeRef) {
match lt_ref {
LifetimeRef::Static => w!(self, "'static"),
LifetimeRef::Named(lt) => {
w!(self, "{}", lt.display(self.db.upcast(), self.edition))
}
LifetimeRef::Placeholder => w!(self, "'_"),
LifetimeRef::Error => w!(self, "'{{error}}"),
}
}
pub(crate) fn print_type_ref(&mut self, type_ref: TypeRefId) { pub(crate) fn print_type_ref(&mut self, type_ref: TypeRefId) {
// FIXME: deduplicate with `HirDisplay` impl // FIXME: deduplicate with `HirDisplay` impl
match &self.store[type_ref] { match &self.store[type_ref] {
@ -1187,7 +1193,8 @@ impl Printer<'_> {
}; };
w!(self, "&"); w!(self, "&");
if let Some(lt) = &ref_.lifetime { if let Some(lt) = &ref_.lifetime {
w!(self, "{} ", lt.name.display(self.db.upcast(), self.edition)); self.print_lifetime_ref(lt);
w!(self, " ");
} }
w!(self, "{mtbl}"); w!(self, "{mtbl}");
self.print_type_ref(ref_.ty); self.print_type_ref(ref_.ty);
@ -1269,9 +1276,7 @@ impl Printer<'_> {
); );
self.print_path(&self.store[*path]); self.print_path(&self.store[*path]);
} }
TypeBound::Lifetime(lt) => { TypeBound::Lifetime(lt) => self.print_lifetime_ref(lt),
w!(self, "{}", lt.name.display(self.db.upcast(), self.edition))
}
TypeBound::Use(args) => { TypeBound::Use(args) => {
w!(self, "use<"); w!(self, "use<");
let mut first = true; let mut first = true;
@ -1283,9 +1288,7 @@ impl Printer<'_> {
UseArgRef::Name(it) => { UseArgRef::Name(it) => {
w!(self, "{}", it.display(self.db.upcast(), self.edition)) w!(self, "{}", it.display(self.db.upcast(), self.edition))
} }
UseArgRef::Lifetime(it) => { UseArgRef::Lifetime(it) => self.print_lifetime_ref(it),
w!(self, "{}", it.name.display(self.db.upcast(), self.edition))
}
} }
} }
w!(self, ">") w!(self, ">")

View File

@ -6,7 +6,6 @@ use std::fmt::Write;
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::Symbol; use intern::Symbol;
use la_arena::Idx; use la_arena::Idx;
use syntax::ast;
use thin_vec::ThinVec; use thin_vec::ThinVec;
use crate::{ use crate::{
@ -145,18 +144,11 @@ const _: () = assert!(size_of::<TypeRef>() == 16);
pub type TypeRefId = Idx<TypeRef>; pub type TypeRefId = Idx<TypeRef>;
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct LifetimeRef { pub enum LifetimeRef {
pub name: Name, Named(Name),
} Static,
Placeholder,
impl LifetimeRef { Error,
pub(crate) fn new(lifetime: &ast::Lifetime) -> Self {
LifetimeRef { name: Name::new_lifetime(lifetime) }
}
pub fn missing() -> LifetimeRef {
LifetimeRef { name: Name::missing() }
}
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]

View File

@ -501,16 +501,16 @@ impl Resolver {
} }
pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> { pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
if lifetime.name == sym::tick_static.clone() { match lifetime {
return Some(LifetimeNs::Static); LifetimeRef::Static => Some(LifetimeNs::Static),
LifetimeRef::Named(name) => self.scopes().find_map(|scope| match scope {
Scope::GenericParams { def, params } => {
params.find_lifetime_by_name(name, *def).map(LifetimeNs::LifetimeParam)
}
_ => None,
}),
LifetimeRef::Placeholder | LifetimeRef::Error => None,
} }
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. /// Returns a set of names available in the current scope.

View File

@ -114,11 +114,10 @@ impl Name {
Name { symbol, ctx: () } Name { symbol, ctx: () }
} }
pub fn new_lifetime(lt: &ast::Lifetime) -> Name { pub fn new_lifetime(lt: &str) -> Name {
let text = lt.text(); match lt.strip_prefix("'r#") {
match text.strip_prefix("'r#") { Some(lt) => Self::new_text(&format_smolstr!("'{lt}")),
Some(text) => Self::new_text(&format_smolstr!("'{text}")), None => Self::new_text(lt),
None => Self::new_text(text.as_str()),
} }
} }

View File

@ -24,7 +24,9 @@ use hir_def::{
lang_item::{LangItem, LangItemTarget}, lang_item::{LangItem, LangItemTarget},
nameres::DefMap, nameres::DefMap,
signatures::VariantFields, signatures::VariantFields,
type_ref::{ConstRef, TraitBoundModifier, TypeBound, TypeRef, TypeRefId, UseArgRef}, type_ref::{
ConstRef, LifetimeRef, TraitBoundModifier, TypeBound, TypeRef, TypeRefId, UseArgRef,
},
visibility::Visibility, visibility::Visibility,
}; };
use hir_expand::{mod_path::PathKind, name::Name}; use hir_expand::{mod_path::PathKind, name::Name};
@ -2100,7 +2102,20 @@ impl<T: HirDisplayWithExpressionStore> HirDisplay for ExpressionStoreAdapter<'_,
T::hir_fmt(&self.0, f, self.1) T::hir_fmt(&self.0, f, self.1)
} }
} }
impl HirDisplayWithExpressionStore for LifetimeRef {
fn hir_fmt(
&self,
f: &mut HirFormatter<'_>,
_store: &ExpressionStore,
) -> Result<(), HirDisplayError> {
match self {
LifetimeRef::Named(name) => write!(f, "{}", name.display(f.db.upcast(), f.edition())),
LifetimeRef::Static => write!(f, "'static"),
LifetimeRef::Placeholder => write!(f, "'_"),
LifetimeRef::Error => write!(f, "'{{error}}"),
}
}
}
impl HirDisplayWithExpressionStore for TypeRefId { impl HirDisplayWithExpressionStore for TypeRefId {
fn hir_fmt( fn hir_fmt(
&self, &self,
@ -2161,7 +2176,8 @@ impl HirDisplayWithExpressionStore for TypeRefId {
}; };
write!(f, "&")?; write!(f, "&")?;
if let Some(lifetime) = &ref_.lifetime { if let Some(lifetime) = &ref_.lifetime {
write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?; lifetime.hir_fmt(f, store)?;
write!(f, " ")?;
} }
write!(f, "{mutability}")?; write!(f, "{mutability}")?;
ref_.ty.hir_fmt(f, store)?; ref_.ty.hir_fmt(f, store)?;
@ -2255,9 +2271,7 @@ impl HirDisplayWithExpressionStore for TypeBound {
} }
store[path].hir_fmt(f, store) store[path].hir_fmt(f, store)
} }
TypeBound::Lifetime(lifetime) => { TypeBound::Lifetime(lifetime) => lifetime.hir_fmt(f, store),
write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
}
TypeBound::ForLifetime(lifetimes, path) => { TypeBound::ForLifetime(lifetimes, path) => {
let edition = f.edition(); let edition = f.edition();
write!( write!(
@ -2269,16 +2283,17 @@ impl HirDisplayWithExpressionStore for TypeBound {
} }
TypeBound::Use(args) => { TypeBound::Use(args) => {
let edition = f.edition(); let edition = f.edition();
write!( let last = args.len().saturating_sub(1);
f, for (idx, arg) in args.iter().enumerate() {
"use<{}> ", match arg {
args.iter() UseArgRef::Lifetime(lt) => lt.hir_fmt(f, store)?,
.map(|it| match it { UseArgRef::Name(n) => write!(f, "{}", n.display(f.db.upcast(), edition))?,
UseArgRef::Lifetime(lt) => lt.name.display(f.db.upcast(), edition), }
UseArgRef::Name(n) => n.display(f.db.upcast(), edition), if idx != last {
}) write!(f, ", ")?;
.format(", ") }
) }
write!(f, "> ")
} }
TypeBound::Error => write!(f, "{{error}}"), TypeBound::Error => write!(f, "{{error}}"),
} }
@ -2449,9 +2464,7 @@ impl HirDisplayWithExpressionStore for hir_def::expr_store::path::GenericArg {
// write!(f, "{}", c.display(f.db.upcast(), f.edition())) // write!(f, "{}", c.display(f.db.upcast(), f.edition()))
write!(f, "<expr>") write!(f, "<expr>")
} }
hir_def::expr_store::path::GenericArg::Lifetime(lifetime) => { hir_def::expr_store::path::GenericArg::Lifetime(lifetime) => lifetime.hir_fmt(f, store),
write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition()))
}
} }
} }
} }

View File

@ -213,7 +213,8 @@ impl HirDisplay for SelfParam {
{ {
f.write_char('&')?; f.write_char('&')?;
if let Some(lifetime) = &ref_.lifetime { if let Some(lifetime) = &ref_.lifetime {
write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?; lifetime.hir_fmt(f, &data.store)?;
f.write_char(' ')?;
} }
if let hir_def::type_ref::Mutability::Mut = ref_.mutability { if let hir_def::type_ref::Mutability::Mut = ref_.mutability {
f.write_str("mut ")?; f.write_str("mut ")?;
@ -685,9 +686,9 @@ fn write_where_predicates(
bound.hir_fmt(f, store)?; bound.hir_fmt(f, store)?;
} }
Lifetime { target, bound } => { Lifetime { target, bound } => {
let target = target.name.display(f.db.upcast(), f.edition()); target.hir_fmt(f, store)?;
let bound = bound.name.display(f.db.upcast(), f.edition()); write!(f, ": ")?;
write!(f, "{target}: {bound}")?; bound.hir_fmt(f, store)?;
} }
ForLifetime { lifetimes, target, bound } => { ForLifetime { lifetimes, target, bound } => {
let lifetimes = let lifetimes =
@ -703,9 +704,7 @@ fn write_where_predicates(
f.write_str(" + ")?; f.write_str(" + ")?;
match nxt { match nxt {
TypeBound { bound, .. } | ForLifetime { bound, .. } => bound.hir_fmt(f, store)?, TypeBound { bound, .. } | ForLifetime { bound, .. } => bound.hir_fmt(f, store)?,
Lifetime { bound, .. } => { Lifetime { bound, .. } => bound.hir_fmt(f, store)?,
write!(f, "{}", bound.name.display(f.db.upcast(), f.edition()))?
}
} }
} }
f.write_str(",")?; f.write_str(",")?;