X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_hir%2Fsrc%2Fhir.rs;h=208d2fb42e42d7690205560fd3a7e7ee7dbf5dd7;hb=5de9c841402d40ef30426b096c7696b1e01f2892;hp=e0a3864506548f186e95c15387f8b7f7526ba1f0;hpb=20d6a44334e189989a99f2f914b243dd81e88968;p=rust.git diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e0a38645065..208d2fb42e4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -29,15 +29,16 @@ #[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)] pub struct Lifetime { pub hir_id: HirId, - pub span: Span, /// Either "`'a`", referring to a named lifetime definition, - /// or "``" (i.e., `kw::Empty`), for elision placeholders. + /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`), + /// or "``" (i.e., `kw::Empty`) when appearing in path. /// - /// HIR lowering inserts these placeholders in type paths that - /// refer to type definitions needing lifetime parameters, - /// `&T` and `&mut T`, and trait objects without `... + 'a`. - pub name: LifetimeName, + /// See `Lifetime::suggestion_position` for practical use. + pub ident: Ident, + + /// Semantics of this lifetime. + pub res: LifetimeName, } #[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)] @@ -88,7 +89,7 @@ pub fn normalize_to_macros_2_0(&self) -> ParamName { #[derive(HashStable_Generic)] pub enum LifetimeName { /// User-given names or fresh (synthetic) names. - Param(LocalDefId, ParamName), + Param(LocalDefId), /// Implicit lifetime in a context like `dyn Foo`. This is /// distinguished from implicit lifetimes elsewhere because the @@ -116,25 +117,6 @@ pub enum LifetimeName { } impl LifetimeName { - pub fn ident(&self) -> Ident { - match *self { - LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(), - LifetimeName::Infer => Ident::with_dummy_span(kw::UnderscoreLifetime), - LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), - LifetimeName::Param(_, param_name) => param_name.ident(), - } - } - - pub fn is_anonymous(&self) -> bool { - match *self { - LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Infer - | LifetimeName::Param(_, ParamName::Fresh) - | LifetimeName::Error => true, - LifetimeName::Static | LifetimeName::Param(..) => false, - } - } - pub fn is_elided(&self) -> bool { match self { LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true, @@ -146,34 +128,54 @@ pub fn is_elided(&self) -> bool { LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false, } } - - fn is_static(&self) -> bool { - self == &LifetimeName::Static - } - - pub fn normalize_to_macros_2_0(&self) -> LifetimeName { - match *self { - LifetimeName::Param(def_id, param_name) => { - LifetimeName::Param(def_id, param_name.normalize_to_macros_2_0()) - } - lifetime_name => lifetime_name, - } - } } impl fmt::Display for Lifetime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.name.ident().fmt(f) + if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) } } } +pub enum LifetimeSuggestionPosition { + /// The user wrote `'a` or `'_`. + Normal, + /// The user wrote `&type` or `&mut type`. + Ampersand, + /// The user wrote `Path` and omitted the `<'_>`. + ElidedPath, + /// The user wrote `Path`, and omitted the `'_,`. + ElidedPathArgument, + /// The user wrote `dyn Trait` and omitted the `+ '_`. + ObjectDefault, +} + impl Lifetime { pub fn is_elided(&self) -> bool { - self.name.is_elided() + self.res.is_elided() + } + + pub fn is_anonymous(&self) -> bool { + self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime + } + + pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) { + if self.ident.name == kw::Empty { + if self.ident.span.is_empty() { + (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span) + } else { + (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi()) + } + } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault { + (LifetimeSuggestionPosition::ObjectDefault, self.ident.span) + } else if self.ident.span.is_empty() { + (LifetimeSuggestionPosition::Ampersand, self.ident.span) + } else { + (LifetimeSuggestionPosition::Normal, self.ident.span) + } } pub fn is_static(&self) -> bool { - self.name.is_static() + self.res == LifetimeName::Static } } @@ -267,7 +269,7 @@ pub enum GenericArg<'hir> { impl GenericArg<'_> { pub fn span(&self) -> Span { match self { - GenericArg::Lifetime(l) => l.span, + GenericArg::Lifetime(l) => l.ident.span, GenericArg::Type(t) => t.span, GenericArg::Const(c) => c.span, GenericArg::Infer(i) => i.span, @@ -284,7 +286,7 @@ pub fn hir_id(&self) -> HirId { } pub fn is_synthetic(&self) -> bool { - matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty()) + matches!(self, GenericArg::Lifetime(lifetime) if lifetime.ident == Ident::empty()) } pub fn descr(&self) -> &'static str { @@ -446,7 +448,7 @@ pub fn span(&self) -> Span { match self { GenericBound::Trait(t, ..) => t.span, GenericBound::LangItemTrait(_, span, ..) => *span, - GenericBound::Outlives(l) => l.span, + GenericBound::Outlives(l) => l.ident.span, } } } @@ -559,6 +561,19 @@ pub fn spans(&self) -> MultiSpan { } } + /// If there are generic parameters, return where to introduce a new one. + pub fn span_for_lifetime_suggestion(&self) -> Option { + if let Some(first) = self.params.first() + && self.span.contains(first.span) + { + // `fn foo(t: impl Trait)` + // ^ suggest `'a, ` here + Some(first.span.shrink_to_lo()) + } else { + None + } + } + /// If there are generic parameters, return where to introduce a new one. pub fn span_for_param_suggestion(&self) -> Option { if self.params.iter().any(|p| self.span.contains(p.span)) { @@ -765,10 +780,7 @@ pub struct WhereRegionPredicate<'hir> { impl<'hir> WhereRegionPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `lifetime` of this predicate. pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool { - match self.lifetime.name { - LifetimeName::Param(id, _) => id == param_def_id, - _ => false, - } + self.lifetime.res == LifetimeName::Param(param_def_id) } } @@ -2688,6 +2700,8 @@ pub struct FnDecl<'hir> { pub c_variadic: bool, /// Does the function have an implicit self? pub implicit_self: ImplicitSelfKind, + /// Is lifetime elision allowed. + pub lifetime_elision_allowed: bool, } /// Represents what type of implicit self a function has, if any. @@ -2913,20 +2927,29 @@ pub fn fields(&self) -> &'hir [FieldDef<'hir>] { } } - /// Return the `LocalDefId` of this variant's constructor, if it has one. - pub fn ctor_def_id(&self) -> Option { + pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> { match *self { - VariantData::Struct(_, _) => None, - VariantData::Tuple(_, _, def_id) | VariantData::Unit(_, def_id) => Some(def_id), + VariantData::Tuple(_, hir_id, def_id) => Some((CtorKind::Fn, hir_id, def_id)), + VariantData::Unit(hir_id, def_id) => Some((CtorKind::Const, hir_id, def_id)), + VariantData::Struct(..) => None, } } + #[inline] + pub fn ctor_kind(&self) -> Option { + self.ctor().map(|(kind, ..)| kind) + } + /// Return the `HirId` of this variant's constructor, if it has one. + #[inline] pub fn ctor_hir_id(&self) -> Option { - match *self { - VariantData::Struct(_, _) => None, - VariantData::Tuple(_, hir_id, _) | VariantData::Unit(hir_id, _) => Some(hir_id), - } + self.ctor().map(|(_, hir_id, _)| hir_id) + } + + /// Return the `LocalDefId` of this variant's constructor, if it has one. + #[inline] + pub fn ctor_def_id(&self) -> Option { + self.ctor().map(|(.., def_id)| def_id) } } @@ -3444,7 +3467,7 @@ pub fn ident(&self) -> Option { | Node::Variant(Variant { ident, .. }) | Node::Item(Item { ident, .. }) | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), - Node::Lifetime(lt) => Some(lt.name.ident()), + Node::Lifetime(lt) => Some(lt.ident), Node::GenericParam(p) => Some(p.name.ident()), Node::TypeBinding(b) => Some(b.ident), Node::Param(..) @@ -3585,9 +3608,16 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); + // tidy-alphabetical-end + // FIXME: move the tidy directive to the end after the next bootstrap bump + #[cfg(bootstrap)] static_assert_size!(TraitItem<'_>, 88); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItem<'_>, 80); + #[cfg(bootstrap)] static_assert_size!(TraitItemKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); - // tidy-alphabetical-end }