diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs index 05dfe8dde378..68bc44048b0f 100644 --- a/crates/hir-def/src/expr_store/lower.rs +++ b/crates/hir-def/src/expr_store/lower.rs @@ -544,13 +544,19 @@ impl ExprCollector<'_> { } 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) -> LifetimeRef { match lifetime { - Some(lifetime) => LifetimeRef::new(&lifetime), - None => LifetimeRef::missing(), + Some(lifetime) => self.lower_lifetime_ref(lifetime), + None => LifetimeRef::Placeholder, } } @@ -590,7 +596,7 @@ impl ExprCollector<'_> { } ast::Type::RefType(inner) => { let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn); - let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(<)); + let lifetime = inner.lifetime().map(|lt| self.lower_lifetime_ref(lt)); let mutability = Mutability::from_mutable(inner.mut_token().is_some()); TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability })) } @@ -824,7 +830,7 @@ impl ExprCollector<'_> { } ast::GenericArg::LifetimeArg(lifetime_arg) => { 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)) } } @@ -911,7 +917,7 @@ impl ExprCollector<'_> { let lt_refs = match for_type.generic_param_list() { Some(gpl) => gpl .lifetime_params() - .flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(<))) + .flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(<.text()))) .collect(), None => Box::default(), }; @@ -932,14 +938,14 @@ impl ExprCollector<'_> { gal.use_bound_generic_args() .map(|p| match p { 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()), }) .collect(), ), 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 { 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(<.text())), }; self.alloc_label(label, AstPtr::new(&ast_label)) } @@ -2511,7 +2520,7 @@ impl ExprCollector<'_> { (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() { match &rib.kind { diff --git a/crates/hir-def/src/expr_store/lower/generics.rs b/crates/hir-def/src/expr_store/lower/generics.rs index 67d1793bc97d..18cec77b94d5 100644 --- a/crates/hir-def/src/expr_store/lower/generics.rs +++ b/crates/hir-def/src/expr_store/lower/generics.rs @@ -123,12 +123,14 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> { ast::GenericParam::LifetimeParam(lifetime_param) => { let lifetime_ref = self.expr_collector.lower_lifetime_ref_opt(lifetime_param.lifetime()); - let param = LifetimeParamData { name: lifetime_ref.name.clone() }; - let _idx = self.lifetimes.alloc(param); - self.lower_bounds( - lifetime_param.type_bound_list(), - Either::Right(lifetime_ref), - ); + if let LifetimeRef::Named(name) = &lifetime_ref { + let param = LifetimeParamData { name: name.clone() }; + let _idx = self.lifetimes.alloc(param); + self.lower_bounds( + lifetime_param.type_bound_list(), + Either::Right(lifetime_ref), + ); + } } } } @@ -151,7 +153,7 @@ impl<'db, 'c> GenericParamsCollector<'db, 'c> { .map(|lifetime_param| { lifetime_param .lifetime() - .map_or_else(Name::missing, |lt| Name::new_lifetime(<)) + .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())) }) .collect() }); diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs index e0eccb6cd0f4..b0807356796e 100644 --- a/crates/hir-def/src/expr_store/pretty.rs +++ b/crates/hir-def/src/expr_store/pretty.rs @@ -19,7 +19,7 @@ use crate::{ }, lang_item::LangItemTarget, signatures::{FnFlags, FunctionSignature, StructSignature}, - type_ref::{ConstRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, + type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef}, }; use super::*; @@ -268,12 +268,9 @@ fn print_where_clauses(db: &dyn DefDatabase, generic_params: &GenericParams, p: } }, WherePredicate::Lifetime { target, bound } => { - w!( - p, - "{}: {}", - target.name.display(db.upcast(), p.edition), - bound.name.display(db.upcast(), p.edition) - ); + p.print_lifetime_ref(target); + w!(p, ": "); + p.print_lifetime_ref(bound); } WherePredicate::ForLifetime { lifetimes, target, bound } => { w!(p, "for<"); @@ -1140,9 +1137,7 @@ impl Printer<'_> { match arg { GenericArg::Type(ty) => self.print_type_ref(*ty), GenericArg::Const(ConstRef { expr }) => self.print_expr(*expr), - GenericArg::Lifetime(lt) => { - w!(self, "{}", lt.name.display(self.db.upcast(), self.edition)) - } + GenericArg::Lifetime(lt) => self.print_lifetime_ref(lt), } } @@ -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) { // FIXME: deduplicate with `HirDisplay` impl match &self.store[type_ref] { @@ -1187,7 +1193,8 @@ impl Printer<'_> { }; w!(self, "&"); 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}"); self.print_type_ref(ref_.ty); @@ -1269,9 +1276,7 @@ impl Printer<'_> { ); self.print_path(&self.store[*path]); } - TypeBound::Lifetime(lt) => { - w!(self, "{}", lt.name.display(self.db.upcast(), self.edition)) - } + TypeBound::Lifetime(lt) => self.print_lifetime_ref(lt), TypeBound::Use(args) => { w!(self, "use<"); let mut first = true; @@ -1283,9 +1288,7 @@ impl Printer<'_> { UseArgRef::Name(it) => { w!(self, "{}", it.display(self.db.upcast(), self.edition)) } - UseArgRef::Lifetime(it) => { - w!(self, "{}", it.name.display(self.db.upcast(), self.edition)) - } + UseArgRef::Lifetime(it) => self.print_lifetime_ref(it), } } w!(self, ">") diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs index 524051108ec9..1fd878ab9b6c 100644 --- a/crates/hir-def/src/hir/type_ref.rs +++ b/crates/hir-def/src/hir/type_ref.rs @@ -6,7 +6,6 @@ use std::fmt::Write; use hir_expand::name::Name; use intern::Symbol; use la_arena::Idx; -use syntax::ast; use thin_vec::ThinVec; use crate::{ @@ -145,18 +144,11 @@ const _: () = assert!(size_of::() == 16); pub type TypeRefId = Idx; #[derive(Clone, PartialEq, Eq, Hash, Debug)] -pub struct LifetimeRef { - pub name: Name, -} - -impl LifetimeRef { - pub(crate) fn new(lifetime: &ast::Lifetime) -> Self { - LifetimeRef { name: Name::new_lifetime(lifetime) } - } - - pub fn missing() -> LifetimeRef { - LifetimeRef { name: Name::missing() } - } +pub enum LifetimeRef { + Named(Name), + Static, + Placeholder, + Error, } #[derive(Clone, PartialEq, Eq, Hash, Debug)] diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index ea0eaf04bb89..ae185759a5f6 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -501,16 +501,16 @@ impl Resolver { } pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option { - if lifetime.name == sym::tick_static.clone() { - return Some(LifetimeNs::Static); + match lifetime { + 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. diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 23ca77f5a0d8..482c3116c42c 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -114,11 +114,10 @@ impl Name { Name { symbol, ctx: () } } - pub fn new_lifetime(lt: &ast::Lifetime) -> Name { - let text = lt.text(); - match text.strip_prefix("'r#") { - Some(text) => Self::new_text(&format_smolstr!("'{text}")), - None => Self::new_text(text.as_str()), + pub fn new_lifetime(lt: &str) -> Name { + match lt.strip_prefix("'r#") { + Some(lt) => Self::new_text(&format_smolstr!("'{lt}")), + None => Self::new_text(lt), } } diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index c1f5e2371bdf..d74acb8ca350 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -24,7 +24,9 @@ use hir_def::{ lang_item::{LangItem, LangItemTarget}, nameres::DefMap, signatures::VariantFields, - type_ref::{ConstRef, TraitBoundModifier, TypeBound, TypeRef, TypeRefId, UseArgRef}, + type_ref::{ + ConstRef, LifetimeRef, TraitBoundModifier, TypeBound, TypeRef, TypeRefId, UseArgRef, + }, visibility::Visibility, }; use hir_expand::{mod_path::PathKind, name::Name}; @@ -2100,7 +2102,20 @@ impl HirDisplay for ExpressionStoreAdapter<'_, 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 { fn hir_fmt( &self, @@ -2161,7 +2176,8 @@ impl HirDisplayWithExpressionStore for TypeRefId { }; write!(f, "&")?; 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}")?; ref_.ty.hir_fmt(f, store)?; @@ -2255,9 +2271,7 @@ impl HirDisplayWithExpressionStore for TypeBound { } store[path].hir_fmt(f, store) } - TypeBound::Lifetime(lifetime) => { - write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition())) - } + TypeBound::Lifetime(lifetime) => lifetime.hir_fmt(f, store), TypeBound::ForLifetime(lifetimes, path) => { let edition = f.edition(); write!( @@ -2269,16 +2283,17 @@ impl HirDisplayWithExpressionStore for TypeBound { } TypeBound::Use(args) => { let edition = f.edition(); - write!( - f, - "use<{}> ", - args.iter() - .map(|it| match it { - UseArgRef::Lifetime(lt) => lt.name.display(f.db.upcast(), edition), - UseArgRef::Name(n) => n.display(f.db.upcast(), edition), - }) - .format(", ") - ) + let last = args.len().saturating_sub(1); + for (idx, arg) in args.iter().enumerate() { + match arg { + UseArgRef::Lifetime(lt) => lt.hir_fmt(f, store)?, + UseArgRef::Name(n) => write!(f, "{}", n.display(f.db.upcast(), edition))?, + } + if idx != last { + write!(f, ", ")?; + } + } + write!(f, "> ") } 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, "") } - hir_def::expr_store::path::GenericArg::Lifetime(lifetime) => { - write!(f, "{}", lifetime.name.display(f.db.upcast(), f.edition())) - } + hir_def::expr_store::path::GenericArg::Lifetime(lifetime) => lifetime.hir_fmt(f, store), } } } diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 472437c9e754..88d4b6f6bc80 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -213,7 +213,8 @@ impl HirDisplay for SelfParam { { f.write_char('&')?; 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 { f.write_str("mut ")?; @@ -685,9 +686,9 @@ fn write_where_predicates( bound.hir_fmt(f, store)?; } Lifetime { target, bound } => { - let target = target.name.display(f.db.upcast(), f.edition()); - let bound = bound.name.display(f.db.upcast(), f.edition()); - write!(f, "{target}: {bound}")?; + target.hir_fmt(f, store)?; + write!(f, ": ")?; + bound.hir_fmt(f, store)?; } ForLifetime { lifetimes, target, bound } => { let lifetimes = @@ -703,9 +704,7 @@ fn write_where_predicates( f.write_str(" + ")?; match nxt { TypeBound { bound, .. } | ForLifetime { bound, .. } => bound.hir_fmt(f, store)?, - Lifetime { bound, .. } => { - write!(f, "{}", bound.name.display(f.db.upcast(), f.edition()))? - } + Lifetime { bound, .. } => bound.hir_fmt(f, store)?, } } f.write_str(",")?;