summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_hir/src/arena.rs1
-rw-r--r--compiler/rustc_hir/src/def.rs22
-rw-r--r--compiler/rustc_hir/src/definitions.rs8
-rw-r--r--compiler/rustc_hir/src/hir.rs223
-rw-r--r--compiler/rustc_hir/src/hir_id.rs22
-rw-r--r--compiler/rustc_hir/src/intravisit.rs742
-rw-r--r--compiler/rustc_hir/src/lang_items.rs230
-rw-r--r--compiler/rustc_hir/src/lib.rs3
-rw-r--r--compiler/rustc_hir/src/pat_util.rs5
-rw-r--r--compiler/rustc_hir/src/tests.rs38
-rw-r--r--compiler/rustc_hir/src/weak_lang_items.rs59
11 files changed, 706 insertions, 647 deletions
diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs
index 44335b7f4..c89e7eb75 100644
--- a/compiler/rustc_hir/src/arena.rs
+++ b/compiler/rustc_hir/src/arena.rs
@@ -39,6 +39,7 @@ macro_rules! arena_types {
[] param: rustc_hir::Param<'tcx>,
[] pat: rustc_hir::Pat<'tcx>,
[] path: rustc_hir::Path<'tcx>,
+ [] use_path: rustc_hir::UsePath<'tcx>,
[] path_segment: rustc_hir::PathSegment<'tcx>,
[] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>,
[] qpath: rustc_hir::QPath<'tcx>,
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 4ef4aad90..149cf4ece 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -28,8 +28,6 @@ pub enum CtorKind {
Fn,
/// Constructor constant automatically created by a unit struct/variant.
Const,
- /// Unusable name in value namespace created by a struct variant.
- Fictive,
}
/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
@@ -132,13 +130,9 @@ impl DefKind {
DefKind::Variant => "variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
- DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
DefKind::Struct => "struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
- DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
- panic!("impossible struct constructor")
- }
DefKind::OpaqueTy => "opaque type",
DefKind::ImplTraitPlaceholder => "opaque type in trait",
DefKind::TyAlias => "type alias",
@@ -562,19 +556,11 @@ impl<T> PerNS<Option<T>> {
}
impl CtorKind {
- pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
- match *vdata {
- ast::VariantData::Tuple(..) => CtorKind::Fn,
- ast::VariantData::Unit(..) => CtorKind::Const,
- ast::VariantData::Struct(..) => CtorKind::Fictive,
- }
- }
-
- pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
+ pub fn from_ast(vdata: &ast::VariantData) -> Option<(CtorKind, NodeId)> {
match *vdata {
- hir::VariantData::Tuple(..) => CtorKind::Fn,
- hir::VariantData::Unit(..) => CtorKind::Const,
- hir::VariantData::Struct(..) => CtorKind::Fictive,
+ ast::VariantData::Tuple(_, node_id) => Some((CtorKind::Fn, node_id)),
+ ast::VariantData::Unit(node_id) => Some((CtorKind::Const, node_id)),
+ ast::VariantData::Struct(..) => None,
}
}
}
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index d85ac960f..dd37efb69 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -368,10 +368,6 @@ impl Definitions {
LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
}
- pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
- self.table.def_path_hashes.indices().map(|local_def_index| LocalDefId { local_def_index })
- }
-
#[inline(always)]
pub fn local_def_path_hash_to_def_id(
&self,
@@ -389,6 +385,10 @@ impl Definitions {
pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
&self.table.def_path_hash_to_index
}
+
+ pub fn num_definitions(&self) -> usize {
+ self.table.def_path_hashes.len()
+ }
}
#[derive(Copy, Clone, PartialEq, Debug)]
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index ef00c1ffc..8bc022e1e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -29,15 +29,16 @@ use std::fmt;
#[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 @@ impl 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 @@ impl LifetimeName {
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<T>`, 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
}
}
@@ -181,14 +183,17 @@ impl Lifetime {
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
#[derive(Debug, HashStable_Generic)]
-pub struct Path<'hir> {
+pub struct Path<'hir, R = Res> {
pub span: Span,
/// The resolution for the path.
- pub res: Res,
+ pub res: R,
/// The segments in the path: the things separated by `::`.
pub segments: &'hir [PathSegment<'hir>],
}
+/// Up to three resolutions for type, value and macro namespaces.
+pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
+
impl Path<'_> {
pub fn is_global(&self) -> bool {
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
@@ -267,7 +272,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 +289,7 @@ impl GenericArg<'_> {
}
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 {
@@ -388,6 +393,8 @@ impl<'hir> GenericArgs<'hir> {
}
#[inline]
+ /// This function returns the number of type and const generic params.
+ /// It should only be used for diagnostics.
pub fn num_generic_params(&self) -> usize {
self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
}
@@ -444,7 +451,7 @@ impl GenericBound<'_> {
match self {
GenericBound::Trait(t, ..) => t.span,
GenericBound::LangItemTrait(_, span, ..) => *span,
- GenericBound::Outlives(l) => l.span,
+ GenericBound::Outlives(l) => l.ident.span,
}
}
}
@@ -485,6 +492,7 @@ pub enum GenericParamKind<'hir> {
#[derive(Debug, HashStable_Generic)]
pub struct GenericParam<'hir> {
pub hir_id: HirId,
+ pub def_id: LocalDefId,
pub name: ParamName,
pub span: Span,
pub pure_wrt_drop: bool,
@@ -557,6 +565,19 @@ impl<'hir> Generics<'hir> {
}
/// If there are generic parameters, return where to introduce a new one.
+ pub fn span_for_lifetime_suggestion(&self) -> Option<Span> {
+ if let Some(first) = self.params.first()
+ && self.span.contains(first.span)
+ {
+ // `fn foo<A>(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<Span> {
if self.params.iter().any(|p| self.span.contains(p.span)) {
// `fn foo<A>(t: impl Trait)`
@@ -762,10 +783,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)
}
}
@@ -809,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> {
pub struct OwnerNodes<'tcx> {
/// Pre-computed hash of the full HIR.
pub hash_including_bodies: Fingerprint,
- /// Pre-computed hash of the item signature, sithout recursing into the body.
+ /// Pre-computed hash of the item signature, without recursing into the body.
pub hash_without_bodies: Fingerprint,
/// Full HIR for the current owner.
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
@@ -919,12 +937,16 @@ pub struct Crate<'hir> {
#[derive(Debug, HashStable_Generic)]
pub struct Closure<'hir> {
+ pub def_id: LocalDefId,
pub binder: ClosureBinder,
pub capture_clause: CaptureBy,
pub bound_generic_params: &'hir [GenericParam<'hir>],
pub fn_decl: &'hir FnDecl<'hir>,
pub body: BodyId,
+ /// The span of the declaration block: 'move |...| -> ...'
pub fn_decl_span: Span,
+ /// The span of the argument block `|...|`
+ pub fn_arg_span: Option<Span>,
pub movability: Option<Movability>,
}
@@ -965,8 +987,8 @@ pub struct Pat<'hir> {
pub hir_id: HirId,
pub kind: PatKind<'hir>,
pub span: Span,
- // Whether to use default binding modes.
- // At present, this is false only for destructuring assignment.
+ /// Whether to use default binding modes.
+ /// At present, this is false only for destructuring assignment.
pub default_binding_modes: bool,
}
@@ -1074,7 +1096,7 @@ impl fmt::Display for RangeEnd {
pub struct DotDotPos(u32);
impl DotDotPos {
- // Panics if n >= u32::MAX.
+ /// Panics if n >= u32::MAX.
pub fn new(n: Option<usize>) -> Self {
match n {
Some(n) => {
@@ -1510,9 +1532,9 @@ pub enum AsyncGeneratorKind {
impl fmt::Display for AsyncGeneratorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
- AsyncGeneratorKind::Block => "`async` block",
- AsyncGeneratorKind::Closure => "`async` closure body",
- AsyncGeneratorKind::Fn => "`async fn` body",
+ AsyncGeneratorKind::Block => "async block",
+ AsyncGeneratorKind::Closure => "async closure body",
+ AsyncGeneratorKind::Fn => "async fn body",
})
}
}
@@ -1613,7 +1635,7 @@ pub enum ArrayLen {
impl ArrayLen {
pub fn hir_id(&self) -> HirId {
match self {
- &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id,
+ &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, .. }) => hir_id,
}
}
}
@@ -1625,10 +1647,11 @@ impl ArrayLen {
/// explicit discriminant values for enum variants.
///
/// You can check if this anon const is a default in a const param
-/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_hir_id(..)`
+/// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_def_id(..)`
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
pub struct AnonConst {
pub hir_id: HirId,
+ pub def_id: LocalDefId,
pub body: BodyId,
}
@@ -1677,10 +1700,10 @@ impl Expr<'_> {
}
}
- // Whether this looks like a place expr, without checking for deref
- // adjustments.
- // This will return `true` in some potentially surprising cases such as
- // `CONSTANT.field`.
+ /// Whether this looks like a place expr, without checking for deref
+ /// adjustments.
+ /// This will return `true` in some potentially surprising cases such as
+ /// `CONSTANT.field`.
pub fn is_syntactic_place_expr(&self) -> bool {
self.is_place_expr(|_| true)
}
@@ -1821,7 +1844,7 @@ impl Expr<'_> {
}
}
- // To a first-order approximation, is this a pattern
+ /// To a first-order approximation, is this a pattern?
pub fn is_approximately_pattern(&self) -> bool {
match &self.kind {
ExprKind::Box(_)
@@ -2143,11 +2166,11 @@ impl fmt::Display for LoopIdError {
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub struct Destination {
- // This is `Some(_)` iff there is an explicit user-specified `label
+ /// This is `Some(_)` iff there is an explicit user-specified 'label
pub label: Option<Label>,
- // These errors are caught and then reported during the diagnostics pass in
- // librustc_passes/loops.rs
+ /// These errors are caught and then reported during the diagnostics pass in
+ /// `librustc_passes/loops.rs`
pub target_id: Result<HirId, LoopIdError>,
}
@@ -2318,7 +2341,7 @@ pub enum ImplItemKind<'hir> {
Type(&'hir Ty<'hir>),
}
-// The name of the associated type for `Fn` return types.
+/// The name of the associated type for `Fn` return types.
pub const FN_OUTPUT_NAME: Symbol = sym::Output;
/// Bind a type to an associated type (i.e., `A = Foo`).
@@ -2414,7 +2437,7 @@ impl<'hir> Ty<'hir> {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind {
- final_ty = &ty;
+ final_ty = ty;
}
final_ty
}
@@ -2683,6 +2706,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.
@@ -2715,6 +2740,12 @@ pub enum IsAsync {
NotAsync,
}
+impl IsAsync {
+ pub fn is_async(self) -> bool {
+ self == IsAsync::Async
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum Defaultness {
Default { has_value: bool },
@@ -2796,7 +2827,8 @@ pub struct Variant<'hir> {
/// Name of the variant.
pub ident: Ident,
/// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`).
- pub id: HirId,
+ pub hir_id: HirId,
+ pub def_id: LocalDefId,
/// Fields and constructor id of the variant.
pub data: VariantData<'hir>,
/// Explicit discriminant (e.g., `Foo = 1`).
@@ -2863,6 +2895,7 @@ pub struct FieldDef<'hir> {
pub vis_span: Span,
pub ident: Ident,
pub hir_id: HirId,
+ pub def_id: LocalDefId,
pub ty: &'hir Ty<'hir>,
}
@@ -2884,11 +2917,11 @@ pub enum VariantData<'hir> {
/// A tuple variant.
///
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
- Tuple(&'hir [FieldDef<'hir>], HirId),
+ Tuple(&'hir [FieldDef<'hir>], HirId, LocalDefId),
/// A unit variant.
///
/// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
- Unit(HirId),
+ Unit(HirId, LocalDefId),
}
impl<'hir> VariantData<'hir> {
@@ -2900,13 +2933,30 @@ impl<'hir> VariantData<'hir> {
}
}
- /// Return the `HirId` of this variant's constructor, if it has one.
- pub fn ctor_hir_id(&self) -> Option<HirId> {
+ pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> {
match *self {
- VariantData::Struct(_, _) => None,
- VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_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<CtorKind> {
+ 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<HirId> {
+ 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<LocalDefId> {
+ self.ctor().map(|(.., def_id)| def_id)
+ }
}
// The bodies for items are stored "out of line", in a separate
@@ -3024,7 +3074,7 @@ pub enum ItemKind<'hir> {
/// or just
///
/// `use foo::bar::baz;` (with `as baz` implicitly on the right).
- Use(&'hir Path<'hir>, UseKind),
+ Use(&'hir UsePath<'hir>, UseKind),
/// A `static` item.
Static(&'hir Ty<'hir>, Mutability, BodyId),
@@ -3217,7 +3267,7 @@ pub enum ForeignItemKind<'hir> {
/// A variable captured by a closure.
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Upvar {
- // First span where it is accessed (there can be multiple).
+ /// First span where it is accessed (there can be multiple).
pub span: Span,
}
@@ -3423,7 +3473,7 @@ impl<'hir> Node<'hir> {
| 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(..)
@@ -3530,7 +3580,7 @@ impl<'hir> Node<'hir> {
/// Get the fields for the tuple-constructor,
/// if this node is a tuple constructor, otherwise None
pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> {
- if let Node::Ctor(&VariantData::Tuple(fields, _)) = self { Some(fields) } else { None }
+ if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None }
}
}
@@ -3546,7 +3596,7 @@ mod size_asserts {
static_assert_size!(FnDecl<'_>, 40);
static_assert_size!(ForeignItem<'_>, 72);
static_assert_size!(ForeignItemKind<'_>, 40);
- static_assert_size!(GenericArg<'_>, 24);
+ static_assert_size!(GenericArg<'_>, 32);
static_assert_size!(GenericBound<'_>, 48);
static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 80);
@@ -3564,9 +3614,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
}
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 752f760ea..060f40919 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,5 +1,5 @@
-use crate::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_span::{def_id::DefPathHash, HashStableContext};
use std::fmt;
@@ -22,6 +22,18 @@ impl OwnerId {
}
}
+impl rustc_index::vec::Idx for OwnerId {
+ #[inline]
+ fn new(idx: usize) -> Self {
+ OwnerId { def_id: LocalDefId { local_def_index: DefIndex::from_usize(idx) } }
+ }
+
+ #[inline]
+ fn index(self) -> usize {
+ self.def_id.local_def_index.as_usize()
+ }
+}
+
impl<CTX: HashStableContext> HashStable<CTX> for OwnerId {
#[inline]
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
@@ -104,7 +116,7 @@ impl Ord for HirId {
impl PartialOrd for HirId {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
- Some(self.cmp(&other))
+ Some(self.cmp(other))
}
}
@@ -134,6 +146,10 @@ impl ItemLocalId {
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
}
+// Safety: Ord is implement as just comparing the LocalItemId's numerical
+// values and these are not changed by (de-)serialization.
+unsafe impl StableOrd for ItemLocalId {}
+
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
pub const CRATE_HIR_ID: HirId =
HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) };
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index be77e6fd3..938ace2c7 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -358,13 +358,16 @@ pub trait Visitor<'v>: Sized {
fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) {
walk_where_predicate(self, predicate)
}
+ fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) {
+ walk_fn_ret_ty(self, ret_ty)
+ }
fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) {
walk_fn_decl(self, fd)
}
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) {
walk_fn(self, fk, fd, b, id)
}
- fn visit_use(&mut self, path: &'v Path<'v>, hir_id: HirId) {
+ fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) {
walk_use(self, path, hir_id)
}
fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
@@ -410,12 +413,7 @@ pub trait Visitor<'v>: Sized {
walk_inf(self, inf);
}
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
- match generic_arg {
- GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
- GenericArg::Type(ty) => self.visit_ty(ty),
- GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
- GenericArg::Infer(inf) => self.visit_infer(inf),
- }
+ walk_generic_arg(self, generic_arg);
}
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
walk_lifetime(self, lifetime)
@@ -424,7 +422,7 @@ pub trait Visitor<'v>: Sized {
fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) {
walk_qpath(self, qpath, id)
}
- fn visit_path(&mut self, path: &'v Path<'v>, _id: HirId) {
+ fn visit_path(&mut self, path: &Path<'v>, _id: HirId) {
walk_path(self, path)
}
fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) {
@@ -448,66 +446,9 @@ pub trait Visitor<'v>: Sized {
}
}
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
- visitor.visit_id(mod_hir_id);
- for &item_id in module.item_ids {
- visitor.visit_nested_item(item_id);
- }
-}
-
-pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) {
- walk_list!(visitor, visit_param, body.params);
- visitor.visit_expr(&body.value);
-}
-
-pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) {
- // Intentionally visiting the expr first - the initialization expr
- // dominates the local's definition.
- walk_list!(visitor, visit_expr, &local.init);
- visitor.visit_id(local.hir_id);
- visitor.visit_pat(&local.pat);
- if let Some(els) = local.els {
- visitor.visit_block(els);
- }
- walk_list!(visitor, visit_ty, &local.ty);
-}
-
-pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) {
- visitor.visit_name(ident.name);
-}
-
-pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
- visitor.visit_ident(label.ident);
-}
-
-pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
- visitor.visit_id(lifetime.hir_id);
- match lifetime.name {
- LifetimeName::Param(_, ParamName::Plain(ident)) => {
- visitor.visit_ident(ident);
- }
- LifetimeName::Param(_, ParamName::Fresh)
- | LifetimeName::Param(_, ParamName::Error)
- | LifetimeName::Static
- | LifetimeName::Error
- | LifetimeName::ImplicitObjectLifetimeDefault
- | LifetimeName::Infer => {}
- }
-}
-
-pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) {
- walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
- visitor.visit_trait_ref(&trait_ref.trait_ref);
-}
-
-pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
- visitor.visit_id(trait_ref.hir_ref_id);
- visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
-}
-
pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) {
visitor.visit_id(param.hir_id);
- visitor.visit_pat(&param.pat);
+ visitor.visit_pat(param.pat);
}
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
@@ -529,7 +470,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
}
ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
FnKind::ItemFn(item.ident, generics, sig.header),
- &sig.decl,
+ sig.decl,
body_id,
item.span,
item.hir_id(),
@@ -601,142 +542,80 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
}
}
-pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) {
- for (op, op_sp) in asm.operands {
- match op {
- InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
- visitor.visit_expr(expr)
- }
- InlineAsmOperand::Out { expr, .. } => {
- if let Some(expr) = expr {
- visitor.visit_expr(expr);
- }
- }
- InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
- visitor.visit_expr(in_expr);
- if let Some(out_expr) = out_expr {
- visitor.visit_expr(out_expr);
- }
- }
- InlineAsmOperand::Const { anon_const, .. }
- | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
- InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
- }
- }
-}
-
-pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) {
- visitor.visit_id(hir_id);
- visitor.visit_path(path, hir_id);
+pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) {
+ walk_list!(visitor, visit_param, body.params);
+ visitor.visit_expr(body.value);
}
-pub fn walk_enum_def<'v, V: Visitor<'v>>(
- visitor: &mut V,
- enum_definition: &'v EnumDef<'v>,
- item_id: HirId,
-) {
- visitor.visit_id(item_id);
- walk_list!(visitor, visit_variant, enum_definition.variants);
+pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) {
+ visitor.visit_name(ident.name);
}
-pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) {
- visitor.visit_ident(variant.ident);
- visitor.visit_id(variant.id);
- visitor.visit_variant_data(&variant.data);
- walk_list!(visitor, visit_anon_const, &variant.disr_expr);
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
+ visitor.visit_id(mod_hir_id);
+ for &item_id in module.item_ids {
+ visitor.visit_nested_item(item_id);
+ }
}
-pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
- visitor.visit_id(typ.hir_id);
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
+ visitor.visit_id(foreign_item.hir_id());
+ visitor.visit_ident(foreign_item.ident);
- match typ.kind {
- TyKind::Slice(ref ty) => visitor.visit_ty(ty),
- TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
- TyKind::Rptr(ref lifetime, ref mutable_type) => {
- visitor.visit_lifetime(lifetime);
- visitor.visit_ty(&mutable_type.ty)
- }
- TyKind::Never => {}
- TyKind::Tup(tuple_element_types) => {
- walk_list!(visitor, visit_ty, tuple_element_types);
- }
- TyKind::BareFn(ref function_declaration) => {
- walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
- visitor.visit_fn_decl(&function_declaration.decl);
- }
- TyKind::Path(ref qpath) => {
- visitor.visit_qpath(qpath, typ.hir_id, typ.span);
- }
- TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
- visitor.visit_nested_item(item_id);
- walk_list!(visitor, visit_generic_arg, lifetimes);
- }
- TyKind::Array(ref ty, ref length) => {
- visitor.visit_ty(ty);
- visitor.visit_array_length(length)
- }
- TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
- for bound in bounds {
- visitor.visit_poly_trait_ref(bound);
+ match foreign_item.kind {
+ ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
+ visitor.visit_generics(generics);
+ visitor.visit_fn_decl(function_declaration);
+ for &param_name in param_names {
+ visitor.visit_ident(param_name);
}
- visitor.visit_lifetime(lifetime);
}
- TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
- TyKind::Infer | TyKind::Err => {}
+ ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
+ ForeignItemKind::Type => (),
}
}
-pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) {
- visitor.visit_id(inf.hir_id);
-}
-
-pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) {
- match *qpath {
- QPath::Resolved(ref maybe_qself, ref path) => {
- walk_list!(visitor, visit_ty, maybe_qself);
- visitor.visit_path(path, id)
- }
- QPath::TypeRelative(ref qself, ref segment) => {
- visitor.visit_ty(qself);
- visitor.visit_path_segment(segment);
- }
- QPath::LangItem(..) => {}
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) {
+ // Intentionally visiting the expr first - the initialization expr
+ // dominates the local's definition.
+ walk_list!(visitor, visit_expr, &local.init);
+ visitor.visit_id(local.hir_id);
+ visitor.visit_pat(local.pat);
+ if let Some(els) = local.els {
+ visitor.visit_block(els);
}
+ walk_list!(visitor, visit_ty, &local.ty);
}
-pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>) {
- for segment in path.segments {
- visitor.visit_path_segment(segment);
- }
+pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
+ visitor.visit_id(block.hir_id);
+ walk_list!(visitor, visit_stmt, block.stmts);
+ walk_list!(visitor, visit_expr, &block.expr);
}
-pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, segment: &'v PathSegment<'v>) {
- visitor.visit_ident(segment.ident);
- visitor.visit_id(segment.hir_id);
- if let Some(ref args) = segment.args {
- visitor.visit_generic_args(args);
+pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
+ visitor.visit_id(statement.hir_id);
+ match statement.kind {
+ StmtKind::Local(ref local) => visitor.visit_local(local),
+ StmtKind::Item(item) => visitor.visit_nested_item(item),
+ StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
+ visitor.visit_expr(expression)
+ }
}
}
-pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, generic_args: &'v GenericArgs<'v>) {
- walk_list!(visitor, visit_generic_arg, generic_args.args);
- walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings);
-}
-
-pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
- visitor: &mut V,
- type_binding: &'v TypeBinding<'v>,
-) {
- visitor.visit_id(type_binding.hir_id);
- visitor.visit_ident(type_binding.ident);
- visitor.visit_generic_args(type_binding.gen_args);
- match type_binding.kind {
- TypeBindingKind::Equality { ref term } => match term {
- Term::Ty(ref ty) => visitor.visit_ty(ty),
- Term::Const(ref c) => visitor.visit_anon_const(c),
- },
- TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds),
+pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
+ visitor.visit_id(arm.hir_id);
+ visitor.visit_pat(arm.pat);
+ if let Some(ref g) = arm.guard {
+ match g {
+ Guard::If(ref e) => visitor.visit_expr(e),
+ Guard::IfLet(ref l) => {
+ visitor.visit_let_expr(l);
+ }
+ }
}
+ visitor.visit_expr(arm.body);
}
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
@@ -781,36 +660,186 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) {
visitor.visit_id(field.hir_id);
visitor.visit_ident(field.ident);
- visitor.visit_pat(&field.pat)
+ visitor.visit_pat(field.pat)
}
-pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
- visitor.visit_id(foreign_item.hir_id());
- visitor.visit_ident(foreign_item.ident);
+pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
+ match len {
+ &ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id),
+ ArrayLen::Body(c) => visitor.visit_anon_const(c),
+ }
+}
- match foreign_item.kind {
- ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
- visitor.visit_generics(generics);
- visitor.visit_fn_decl(function_declaration);
- for &param_name in param_names {
- visitor.visit_ident(param_name);
- }
+pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
+ visitor.visit_id(constant.hir_id);
+ visitor.visit_nested_body(constant.body);
+}
+
+pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
+ visitor.visit_id(expression.hir_id);
+ match expression.kind {
+ ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
+ ExprKind::Array(subexpressions) => {
+ walk_list!(visitor, visit_expr, subexpressions);
}
- ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
- ForeignItemKind::Type => (),
+ ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
+ ExprKind::Repeat(ref element, ref count) => {
+ visitor.visit_expr(element);
+ visitor.visit_array_length(count)
+ }
+ ExprKind::Struct(ref qpath, fields, ref optional_base) => {
+ visitor.visit_qpath(qpath, expression.hir_id, expression.span);
+ walk_list!(visitor, visit_expr_field, fields);
+ walk_list!(visitor, visit_expr, optional_base);
+ }
+ ExprKind::Tup(subexpressions) => {
+ walk_list!(visitor, visit_expr, subexpressions);
+ }
+ ExprKind::Call(ref callee_expression, arguments) => {
+ visitor.visit_expr(callee_expression);
+ walk_list!(visitor, visit_expr, arguments);
+ }
+ ExprKind::MethodCall(ref segment, receiver, arguments, _) => {
+ visitor.visit_path_segment(segment);
+ visitor.visit_expr(receiver);
+ walk_list!(visitor, visit_expr, arguments);
+ }
+ ExprKind::Binary(_, ref left_expression, ref right_expression) => {
+ visitor.visit_expr(left_expression);
+ visitor.visit_expr(right_expression)
+ }
+ ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
+ visitor.visit_expr(subexpression)
+ }
+ ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
+ visitor.visit_expr(subexpression);
+ visitor.visit_ty(typ)
+ }
+ ExprKind::DropTemps(ref subexpression) => {
+ visitor.visit_expr(subexpression);
+ }
+ ExprKind::Let(ref let_expr) => visitor.visit_let_expr(let_expr),
+ ExprKind::If(ref cond, ref then, ref else_opt) => {
+ visitor.visit_expr(cond);
+ visitor.visit_expr(then);
+ walk_list!(visitor, visit_expr, else_opt);
+ }
+ ExprKind::Loop(ref block, ref opt_label, _, _) => {
+ walk_list!(visitor, visit_label, opt_label);
+ visitor.visit_block(block);
+ }
+ ExprKind::Match(ref subexpression, arms, _) => {
+ visitor.visit_expr(subexpression);
+ walk_list!(visitor, visit_arm, arms);
+ }
+ ExprKind::Closure(&Closure {
+ def_id: _,
+ binder: _,
+ bound_generic_params,
+ fn_decl,
+ body,
+ capture_clause: _,
+ fn_decl_span: _,
+ fn_arg_span: _,
+ movability: _,
+ }) => {
+ walk_list!(visitor, visit_generic_param, bound_generic_params);
+ visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
+ }
+ ExprKind::Block(ref block, ref opt_label) => {
+ walk_list!(visitor, visit_label, opt_label);
+ visitor.visit_block(block);
+ }
+ ExprKind::Assign(ref lhs, ref rhs, _) => {
+ visitor.visit_expr(rhs);
+ visitor.visit_expr(lhs)
+ }
+ ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
+ visitor.visit_expr(right_expression);
+ visitor.visit_expr(left_expression);
+ }
+ ExprKind::Field(ref subexpression, ident) => {
+ visitor.visit_expr(subexpression);
+ visitor.visit_ident(ident);
+ }
+ ExprKind::Index(ref main_expression, ref index_expression) => {
+ visitor.visit_expr(main_expression);
+ visitor.visit_expr(index_expression)
+ }
+ ExprKind::Path(ref qpath) => {
+ visitor.visit_qpath(qpath, expression.hir_id, expression.span);
+ }
+ ExprKind::Break(ref destination, ref opt_expr) => {
+ walk_list!(visitor, visit_label, &destination.label);
+ walk_list!(visitor, visit_expr, opt_expr);
+ }
+ ExprKind::Continue(ref destination) => {
+ walk_list!(visitor, visit_label, &destination.label);
+ }
+ ExprKind::Ret(ref optional_expression) => {
+ walk_list!(visitor, visit_expr, optional_expression);
+ }
+ ExprKind::InlineAsm(ref asm) => {
+ visitor.visit_inline_asm(asm, expression.hir_id);
+ }
+ ExprKind::Yield(ref subexpression, _) => {
+ visitor.visit_expr(subexpression);
+ }
+ ExprKind::Lit(_) | ExprKind::Err => {}
}
}
-pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) {
- match *bound {
- GenericBound::Trait(ref typ, _modifier) => {
- visitor.visit_poly_trait_ref(typ);
+pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) {
+ // match the visit order in walk_local
+ visitor.visit_expr(let_expr.init);
+ visitor.visit_id(let_expr.hir_id);
+ visitor.visit_pat(let_expr.pat);
+ walk_list!(visitor, visit_ty, let_expr.ty);
+}
+
+pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) {
+ visitor.visit_id(field.hir_id);
+ visitor.visit_ident(field.ident);
+ visitor.visit_expr(field.expr)
+}
+
+pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
+ visitor.visit_id(typ.hir_id);
+
+ match typ.kind {
+ TyKind::Slice(ref ty) => visitor.visit_ty(ty),
+ TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty),
+ TyKind::Rptr(ref lifetime, ref mutable_type) => {
+ visitor.visit_lifetime(lifetime);
+ visitor.visit_ty(mutable_type.ty)
}
- GenericBound::LangItemTrait(_, _span, hir_id, args) => {
- visitor.visit_id(hir_id);
- visitor.visit_generic_args(args);
+ TyKind::Never => {}
+ TyKind::Tup(tuple_element_types) => {
+ walk_list!(visitor, visit_ty, tuple_element_types);
}
- GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
+ TyKind::BareFn(ref function_declaration) => {
+ walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
+ visitor.visit_fn_decl(function_declaration.decl);
+ }
+ TyKind::Path(ref qpath) => {
+ visitor.visit_qpath(qpath, typ.hir_id, typ.span);
+ }
+ TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
+ visitor.visit_nested_item(item_id);
+ walk_list!(visitor, visit_generic_arg, lifetimes);
+ }
+ TyKind::Array(ref ty, ref length) => {
+ visitor.visit_ty(ty);
+ visitor.visit_array_length(length)
+ }
+ TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
+ for bound in bounds {
+ visitor.visit_poly_trait_ref(bound);
+ }
+ visitor.visit_lifetime(lifetime);
+ }
+ TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
+ TyKind::Infer | TyKind::Err => {}
}
}
@@ -875,25 +904,16 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
}
}
-pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) {
- if let FnRetTy::Return(ref output_ty) = *ret_ty {
- visitor.visit_ty(output_ty)
- }
-}
-
pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl<'v>) {
for ty in function_declaration.inputs {
visitor.visit_ty(ty)
}
- walk_fn_ret_ty(visitor, &function_declaration.output)
+ visitor.visit_fn_ret_ty(&function_declaration.output)
}
-pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
- match function_kind {
- FnKind::ItemFn(_, generics, ..) => {
- visitor.visit_generics(generics);
- }
- FnKind::Closure | FnKind::Method(..) => {}
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) {
+ if let FnRetTy::Return(ref output_ty) = *ret_ty {
+ visitor.visit_ty(output_ty)
}
}
@@ -910,13 +930,30 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
visitor.visit_nested_body(body_id)
}
+pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
+ match function_kind {
+ FnKind::ItemFn(_, generics, ..) => {
+ visitor.visit_generics(generics);
+ }
+ FnKind::Closure | FnKind::Method(..) => {}
+ }
+}
+
+pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) {
+ visitor.visit_id(hir_id);
+ let UsePath { segments, ref res, span } = *path;
+ for &res in res {
+ visitor.visit_path(&Path { segments, res, span }, hir_id);
+ }
+}
+
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
visitor.visit_ident(ident);
- visitor.visit_generics(&generics);
- visitor.visit_defaultness(&defaultness);
+ visitor.visit_generics(generics);
+ visitor.visit_defaultness(defaultness);
match *kind {
TraitItemKind::Const(ref ty, default) => {
visitor.visit_id(hir_id);
@@ -925,13 +962,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
}
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
visitor.visit_id(hir_id);
- visitor.visit_fn_decl(&sig.decl);
+ visitor.visit_fn_decl(sig.decl);
for &param_name in param_names {
visitor.visit_ident(param_name);
}
}
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
- visitor.visit_fn(FnKind::Method(ident, sig), &sig.decl, body_id, span, hir_id);
+ visitor.visit_fn(FnKind::Method(ident, sig), sig.decl, body_id, span, hir_id);
}
TraitItemKind::Type(bounds, ref default) => {
visitor.visit_id(hir_id);
@@ -973,7 +1010,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
ImplItemKind::Fn(ref sig, body_id) => {
visitor.visit_fn(
FnKind::Method(impl_item.ident, sig),
- &sig.decl,
+ sig.decl,
body_id,
impl_item.span,
impl_item.hir_id(),
@@ -1004,6 +1041,29 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'
visitor.visit_associated_item_kind(kind);
}
+pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
+ visitor.visit_id(trait_ref.hir_ref_id);
+ visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id)
+}
+
+pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) {
+ match *bound {
+ GenericBound::Trait(ref typ, _modifier) => {
+ visitor.visit_poly_trait_ref(typ);
+ }
+ GenericBound::LangItemTrait(_, _span, hir_id, args) => {
+ visitor.visit_id(hir_id);
+ visitor.visit_generic_args(args);
+ }
+ GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
+ }
+}
+
+pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) {
+ walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
+ visitor.visit_trait_ref(&trait_ref.trait_ref);
+}
+
pub fn walk_struct_def<'v, V: Visitor<'v>>(
visitor: &mut V,
struct_definition: &'v VariantData<'v>,
@@ -1015,176 +1075,94 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(
pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) {
visitor.visit_id(field.hir_id);
visitor.visit_ident(field.ident);
- visitor.visit_ty(&field.ty);
+ visitor.visit_ty(field.ty);
}
-pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
- visitor.visit_id(block.hir_id);
- walk_list!(visitor, visit_stmt, block.stmts);
- walk_list!(visitor, visit_expr, &block.expr);
+pub fn walk_enum_def<'v, V: Visitor<'v>>(
+ visitor: &mut V,
+ enum_definition: &'v EnumDef<'v>,
+ item_id: HirId,
+) {
+ visitor.visit_id(item_id);
+ walk_list!(visitor, visit_variant, enum_definition.variants);
}
-pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
- visitor.visit_id(statement.hir_id);
- match statement.kind {
- StmtKind::Local(ref local) => visitor.visit_local(local),
- StmtKind::Item(item) => visitor.visit_nested_item(item),
- StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
- visitor.visit_expr(expression)
- }
- }
+pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) {
+ visitor.visit_ident(variant.ident);
+ visitor.visit_id(variant.hir_id);
+ visitor.visit_variant_data(&variant.data);
+ walk_list!(visitor, visit_anon_const, &variant.disr_expr);
}
-pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
- match len {
- &ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id),
- ArrayLen::Body(c) => visitor.visit_anon_const(c),
- }
+pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
+ visitor.visit_ident(label.ident);
}
-pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
- visitor.visit_id(constant.hir_id);
- visitor.visit_nested_body(constant.body);
+pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) {
+ visitor.visit_id(inf.hir_id);
}
-pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) {
- // match the visit order in walk_local
- visitor.visit_expr(let_expr.init);
- visitor.visit_id(let_expr.hir_id);
- visitor.visit_pat(let_expr.pat);
- walk_list!(visitor, visit_ty, let_expr.ty);
+pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v GenericArg<'v>) {
+ match generic_arg {
+ GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
+ GenericArg::Type(ty) => visitor.visit_ty(ty),
+ GenericArg::Const(ct) => visitor.visit_anon_const(&ct.value),
+ GenericArg::Infer(inf) => visitor.visit_infer(inf),
+ }
}
-pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) {
- visitor.visit_id(field.hir_id);
- visitor.visit_ident(field.ident);
- visitor.visit_expr(&field.expr)
+pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+ visitor.visit_id(lifetime.hir_id);
+ visitor.visit_ident(lifetime.ident);
}
-pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
- visitor.visit_id(expression.hir_id);
- match expression.kind {
- ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
- ExprKind::Array(subexpressions) => {
- walk_list!(visitor, visit_expr, subexpressions);
- }
- ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const),
- ExprKind::Repeat(ref element, ref count) => {
- visitor.visit_expr(element);
- visitor.visit_array_length(count)
- }
- ExprKind::Struct(ref qpath, fields, ref optional_base) => {
- visitor.visit_qpath(qpath, expression.hir_id, expression.span);
- walk_list!(visitor, visit_expr_field, fields);
- walk_list!(visitor, visit_expr, optional_base);
- }
- ExprKind::Tup(subexpressions) => {
- walk_list!(visitor, visit_expr, subexpressions);
- }
- ExprKind::Call(ref callee_expression, arguments) => {
- visitor.visit_expr(callee_expression);
- walk_list!(visitor, visit_expr, arguments);
+pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) {
+ match *qpath {
+ QPath::Resolved(ref maybe_qself, ref path) => {
+ walk_list!(visitor, visit_ty, maybe_qself);
+ visitor.visit_path(path, id)
}
- ExprKind::MethodCall(ref segment, receiver, arguments, _) => {
+ QPath::TypeRelative(ref qself, ref segment) => {
+ visitor.visit_ty(qself);
visitor.visit_path_segment(segment);
- visitor.visit_expr(receiver);
- walk_list!(visitor, visit_expr, arguments);
- }
- ExprKind::Binary(_, ref left_expression, ref right_expression) => {
- visitor.visit_expr(left_expression);
- visitor.visit_expr(right_expression)
- }
- ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
- visitor.visit_expr(subexpression)
- }
- ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
- visitor.visit_expr(subexpression);
- visitor.visit_ty(typ)
- }
- ExprKind::DropTemps(ref subexpression) => {
- visitor.visit_expr(subexpression);
- }
- ExprKind::Let(ref let_expr) => visitor.visit_let_expr(let_expr),
- ExprKind::If(ref cond, ref then, ref else_opt) => {
- visitor.visit_expr(cond);
- visitor.visit_expr(then);
- walk_list!(visitor, visit_expr, else_opt);
- }
- ExprKind::Loop(ref block, ref opt_label, _, _) => {
- walk_list!(visitor, visit_label, opt_label);
- visitor.visit_block(block);
- }
- ExprKind::Match(ref subexpression, arms, _) => {
- visitor.visit_expr(subexpression);
- walk_list!(visitor, visit_arm, arms);
- }
- ExprKind::Closure(&Closure {
- binder: _,
- bound_generic_params,
- fn_decl,
- body,
- capture_clause: _,
- fn_decl_span: _,
- movability: _,
- }) => {
- walk_list!(visitor, visit_generic_param, bound_generic_params);
- visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
- }
- ExprKind::Block(ref block, ref opt_label) => {
- walk_list!(visitor, visit_label, opt_label);
- visitor.visit_block(block);
- }
- ExprKind::Assign(ref lhs, ref rhs, _) => {
- visitor.visit_expr(rhs);
- visitor.visit_expr(lhs)
- }
- ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
- visitor.visit_expr(right_expression);
- visitor.visit_expr(left_expression);
- }
- ExprKind::Field(ref subexpression, ident) => {
- visitor.visit_expr(subexpression);
- visitor.visit_ident(ident);
- }
- ExprKind::Index(ref main_expression, ref index_expression) => {
- visitor.visit_expr(main_expression);
- visitor.visit_expr(index_expression)
- }
- ExprKind::Path(ref qpath) => {
- visitor.visit_qpath(qpath, expression.hir_id, expression.span);
- }
- ExprKind::Break(ref destination, ref opt_expr) => {
- walk_list!(visitor, visit_label, &destination.label);
- walk_list!(visitor, visit_expr, opt_expr);
- }
- ExprKind::Continue(ref destination) => {
- walk_list!(visitor, visit_label, &destination.label);
- }
- ExprKind::Ret(ref optional_expression) => {
- walk_list!(visitor, visit_expr, optional_expression);
}
- ExprKind::InlineAsm(ref asm) => {
- visitor.visit_inline_asm(asm, expression.hir_id);
- }
- ExprKind::Yield(ref subexpression, _) => {
- visitor.visit_expr(subexpression);
- }
- ExprKind::Lit(_) | ExprKind::Err => {}
+ QPath::LangItem(..) => {}
}
}
-pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
- visitor.visit_id(arm.hir_id);
- visitor.visit_pat(&arm.pat);
- if let Some(ref g) = arm.guard {
- match g {
- Guard::If(ref e) => visitor.visit_expr(e),
- Guard::IfLet(ref l) => {
- visitor.visit_let_expr(l);
- }
- }
+pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) {
+ for segment in path.segments {
+ visitor.visit_path_segment(segment);
+ }
+}
+
+pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, segment: &'v PathSegment<'v>) {
+ visitor.visit_ident(segment.ident);
+ visitor.visit_id(segment.hir_id);
+ if let Some(ref args) = segment.args {
+ visitor.visit_generic_args(args);
+ }
+}
+
+pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, generic_args: &'v GenericArgs<'v>) {
+ walk_list!(visitor, visit_generic_arg, generic_args.args);
+ walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings);
+}
+
+pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
+ visitor: &mut V,
+ type_binding: &'v TypeBinding<'v>,
+) {
+ visitor.visit_id(type_binding.hir_id);
+ visitor.visit_ident(type_binding.ident);
+ visitor.visit_generic_args(type_binding.gen_args);
+ match type_binding.kind {
+ TypeBindingKind::Equality { ref term } => match term {
+ Term::Ty(ref ty) => visitor.visit_ty(ty),
+ Term::Const(ref c) => visitor.visit_anon_const(c),
+ },
+ TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds),
}
- visitor.visit_expr(&arm.body);
}
pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) {
@@ -1198,3 +1176,27 @@ pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) {
// the right thing to do, should content be added in the future,
// would be to walk it.
}
+
+pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) {
+ for (op, op_sp) in asm.operands {
+ match op {
+ InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
+ visitor.visit_expr(expr)
+ }
+ InlineAsmOperand::Out { expr, .. } => {
+ if let Some(expr) = expr {
+ visitor.visit_expr(expr);
+ }
+ }
+ InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
+ visitor.visit_expr(in_expr);
+ if let Some(out_expr) = out_expr {
+ visitor.visit_expr(out_expr);
+ }
+ }
+ InlineAsmOperand::Const { anon_const, .. }
+ | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
+ InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
+ }
+ }
+}
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index ca615a491..038509031 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -12,35 +12,56 @@ use crate::errors::LangItemError;
use crate::{MethodKind, Target};
use rustc_ast as ast;
-use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable_Generic;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use std::sync::LazyLock;
-
-pub enum LangItemGroup {
- Op,
- Fn,
+/// All of the language items, defined or not.
+/// Defined lang items can come from the current crate or its dependencies.
+#[derive(HashStable_Generic, Debug)]
+pub struct LanguageItems {
+ /// Mappings from lang items to their possibly found [`DefId`]s.
+ /// The index corresponds to the order in [`LangItem`].
+ items: [Option<DefId>; std::mem::variant_count::<LangItem>()],
+ /// Lang items that were not found during collection.
+ pub missing: Vec<LangItem>,
}
-const NUM_GROUPS: usize = 2;
+impl LanguageItems {
+ /// Construct an empty collection of lang items and no missing ones.
+ pub fn new() -> Self {
+ Self { items: [None; std::mem::variant_count::<LangItem>()], missing: Vec::new() }
+ }
+
+ pub fn get(&self, item: LangItem) -> Option<DefId> {
+ self.items[item as usize]
+ }
+
+ pub fn set(&mut self, item: LangItem, def_id: DefId) {
+ self.items[item as usize] = Some(def_id);
+ }
+
+ /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
+ /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
+ /// returns an error encapsulating the `LangItem`.
+ pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
+ self.get(it).ok_or_else(|| LangItemError(it))
+ }
-macro_rules! expand_group {
- () => {
- None
- };
- ($group:expr) => {
- Some($group)
- };
+ pub fn iter<'a>(&'a self) -> impl Iterator<Item = (LangItem, DefId)> + 'a {
+ self.items
+ .iter()
+ .enumerate()
+ .filter_map(|(i, id)| id.map(|id| (LangItem::from_u32(i as u32).unwrap(), id)))
+ }
}
// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! language_item_table {
(
- $( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
+ $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
) => {
enum_from_u32! {
@@ -66,66 +87,36 @@ macro_rules! language_item_table {
}
}
- /// The [group](LangItemGroup) that this lang item belongs to,
- /// or `None` if it doesn't belong to a group.
- pub fn group(self) -> Option<LangItemGroup> {
- use LangItemGroup::*;
- match self {
- $( LangItem::$variant => expand_group!($($group)*), )*
+ /// Opposite of [`LangItem::name`]
+ pub fn from_name(name: Symbol) -> Option<Self> {
+ match name {
+ $( $module::$name => Some(LangItem::$variant), )*
+ _ => None,
}
}
- pub fn required_generics(&self) -> GenericRequirement {
+ /// Returns the name of the `LangItem` enum variant.
+ // This method is used by Clippy for internal lints.
+ pub fn variant_name(self) -> &'static str {
match self {
- $( LangItem::$variant => $generics, )*
+ $( LangItem::$variant => stringify!($variant), )*
}
}
- }
-
- /// All of the language items, defined or not.
- /// Defined lang items can come from the current crate or its dependencies.
- #[derive(HashStable_Generic, Debug)]
- pub struct LanguageItems {
- /// Mappings from lang items to their possibly found [`DefId`]s.
- /// The index corresponds to the order in [`LangItem`].
- pub items: Vec<Option<DefId>>,
- /// Lang items that were not found during collection.
- pub missing: Vec<LangItem>,
- /// Mapping from [`LangItemGroup`] discriminants to all
- /// [`DefId`]s of lang items in that group.
- pub groups: [Vec<DefId>; NUM_GROUPS],
- }
- impl LanguageItems {
- /// Construct an empty collection of lang items and no missing ones.
- pub fn new() -> Self {
- fn init_none(_: LangItem) -> Option<DefId> { None }
- const EMPTY: Vec<DefId> = Vec::new();
-
- Self {
- items: vec![$(init_none(LangItem::$variant)),*],
- missing: Vec::new(),
- groups: [EMPTY; NUM_GROUPS],
+ pub fn target(self) -> Target {
+ match self {
+ $( LangItem::$variant => $target, )*
}
}
- /// Returns the mappings to the possibly found `DefId`s for each lang item.
- pub fn items(&self) -> &[Option<DefId>] {
- &*self.items
- }
-
- /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
- /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
- /// returns an error encapsulating the `LangItem`.
- pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
- self.items[it as usize].ok_or_else(|| LangItemError(it))
- }
-
- /// Returns the [`DefId`]s of all lang items in a group.
- pub fn group(&self, group: LangItemGroup) -> &[DefId] {
- self.groups[group as usize].as_ref()
+ pub fn required_generics(&self) -> GenericRequirement {
+ match self {
+ $( LangItem::$variant => $generics, )*
+ }
}
+ }
+ impl LanguageItems {
$(
#[doc = concat!("Returns the [`DefId`] of the `", stringify!($name), "` lang item if it is defined.")]
pub fn $method(&self) -> Option<DefId> {
@@ -133,15 +124,6 @@ macro_rules! language_item_table {
}
)*
}
-
- /// A mapping from the name of the lang item to its order and the form it must be of.
- pub static ITEM_REFS: LazyLock<FxIndexMap<Symbol, (usize, Target)>> = LazyLock::new(|| {
- let mut item_refs = FxIndexMap::default();
- $( item_refs.insert($module::$name, (LangItem::$variant as usize, $target)); )*
- item_refs
- });
-
-// End of the macro
}
}
@@ -152,14 +134,12 @@ impl<CTX> HashStable<CTX> for LangItem {
}
/// Extracts the first `lang = "$name"` out of a list of attributes.
-/// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
-/// are also extracted out when found.
+/// The `#[panic_handler]` attribute is also extracted out when found.
pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
attrs.iter().find_map(|attr| {
Some(match attr {
_ if attr.has_name(sym::lang) => (attr.value_str()?, attr.span),
_ if attr.has_name(sym::panic_handler) => (sym::panic_impl, attr.span),
- _ if attr.has_name(sym::alloc_error_handler) => (sym::oom, attr.span),
_ => return None,
})
})
@@ -196,30 +176,30 @@ language_item_table! {
TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
- Add(Op), sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
- Sub(Op), sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
- Mul(Op), sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
- Div(Op), sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
- Rem(Op), sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
- Neg(Op), sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
- Not(Op), sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
- BitXor(Op), sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
- BitAnd(Op), sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
- BitOr(Op), sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
- Shl(Op), sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
- Shr(Op), sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
- AddAssign(Op), sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- SubAssign(Op), sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- MulAssign(Op), sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- DivAssign(Op), sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- RemAssign(Op), sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- BitXorAssign(Op), sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- BitAndAssign(Op), sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- BitOrAssign(Op), sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- ShlAssign(Op), sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- ShrAssign(Op), sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
- Index(Op), sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
- IndexMut(Op), sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
+ Add, sym::add, add_trait, Target::Trait, GenericRequirement::Exact(1);
+ Sub, sym::sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
+ Mul, sym::mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
+ Div, sym::div, div_trait, Target::Trait, GenericRequirement::Exact(1);
+ Rem, sym::rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
+ Neg, sym::neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
+ Not, sym::not, not_trait, Target::Trait, GenericRequirement::Exact(0);
+ BitXor, sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitAnd, sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitOr, sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
+ Shl, sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
+ Shr, sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
+ AddAssign, sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ SubAssign, sym::sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ MulAssign, sym::mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ DivAssign, sym::div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ RemAssign, sym::rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitXorAssign, sym::bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitAndAssign, sym::bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitOrAssign, sym::bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ ShlAssign, sym::shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ ShrAssign, sym::shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ Index, sym::index, index_trait, Target::Trait, GenericRequirement::Exact(1);
+ IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
@@ -229,9 +209,9 @@ language_item_table! {
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
- Fn(Fn), kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
- FnMut(Fn), sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
- FnOnce(Fn), sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
+ Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
+ FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
+ FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
@@ -241,8 +221,8 @@ language_item_table! {
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
- PartialEq(Op), sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
- PartialOrd(Op), sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
+ PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
+ PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
// A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
// various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
@@ -266,7 +246,6 @@ language_item_table! {
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
- Oom, sym::oom, oom, Target::Fn, GenericRequirement::None;
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
@@ -299,10 +278,16 @@ language_item_table! {
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
+ PointerSized, sym::pointer_sized, pointer_sized, Target::Trait, GenericRequirement::Exact(0);
+
+ Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
- FromGenerator, sym::from_generator, from_generator_fn, Target::Fn, GenericRequirement::None;
+ // FIXME(swatinem): the following lang items are used for async lowering and
+ // should become obsolete eventually.
+ ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
+ IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
@@ -331,6 +316,8 @@ language_item_table! {
Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None;
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
+
+ String, sym::String, string, Target::Struct, GenericRequirement::None;
}
pub enum GenericRequirement {
@@ -338,3 +325,34 @@ pub enum GenericRequirement {
Minimum(usize),
Exact(usize),
}
+
+pub static FN_TRAITS: &'static [LangItem] = &[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
+
+pub static OPERATORS: &'static [LangItem] = &[
+ LangItem::Add,
+ LangItem::Sub,
+ LangItem::Mul,
+ LangItem::Div,
+ LangItem::Rem,
+ LangItem::Neg,
+ LangItem::Not,
+ LangItem::BitXor,
+ LangItem::BitAnd,
+ LangItem::BitOr,
+ LangItem::Shl,
+ LangItem::Shr,
+ LangItem::AddAssign,
+ LangItem::SubAssign,
+ LangItem::MulAssign,
+ LangItem::DivAssign,
+ LangItem::RemAssign,
+ LangItem::BitXorAssign,
+ LangItem::BitAndAssign,
+ LangItem::BitOrAssign,
+ LangItem::ShlAssign,
+ LangItem::ShrAssign,
+ LangItem::Index,
+ LangItem::IndexMut,
+ LangItem::PartialEq,
+ LangItem::PartialOrd,
+];
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 1c4aa420c..98d967cc0 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -5,10 +5,11 @@
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(const_btree_len)]
-#![feature(once_cell)]
+#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]
+#![feature(variant_count)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs
index 0c1819bb0..6e2fbf96c 100644
--- a/compiler/rustc_hir/src/pat_util.rs
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -130,10 +130,7 @@ impl hir::Pat<'_> {
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
let mut result = None;
self.each_binding(|annotation, _, _, _| match annotation {
- hir::BindingAnnotation::REF => match result {
- None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
- _ => {}
- },
+ hir::BindingAnnotation::REF if result.is_none() => result = Some(hir::Mutability::Not),
hir::BindingAnnotation::REF_MUT => result = Some(hir::Mutability::Mut),
_ => {}
});
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 4636d5152..d47911509 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,5 +1,7 @@
use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::edition::Edition;
+use rustc_span::{create_session_if_not_set_then, Symbol};
#[test]
fn def_path_hash_depends_on_crate_id() {
@@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() {
// the crate by changing the crate disambiguator (e.g. via bumping the
// crate's version number).
- let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
- let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+ create_session_if_not_set_then(Edition::Edition2024, |_| {
+ let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
+ let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
- let h0 = mk_test_hash(id0);
- let h1 = mk_test_hash(id1);
+ let h0 = mk_test_hash(id0);
+ let h1 = mk_test_hash(id1);
- assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
- assert_ne!(h0.local_hash(), h1.local_hash());
+ assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
+ assert_ne!(h0.local_hash(), h1.local_hash());
- fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
- let parent_hash = DefPathHash::new(stable_crate_id, 0);
+ fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+ let parent_hash = DefPathHash::new(stable_crate_id, 0);
- let key = DefKey {
- parent: None,
- disambiguated_data: DisambiguatedDefPathData {
- data: DefPathData::CrateRoot,
- disambiguator: 0,
- },
- };
+ let key = DefKey {
+ parent: None,
+ disambiguated_data: DisambiguatedDefPathData {
+ data: DefPathData::CrateRoot,
+ disambiguator: 0,
+ },
+ };
- key.compute_stable_hash(parent_hash)
- }
+ key.compute_stable_hash(parent_hash)
+ }
+ })
}
diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs
index da9c9c121..0cc50c6dd 100644
--- a/compiler/rustc_hir/src/weak_lang_items.rs
+++ b/compiler/rustc_hir/src/weak_lang_items.rs
@@ -1,53 +1,30 @@
//! Validity checking for weak lang items
-use crate::def_id::DefId;
-use crate::{lang_items, LangItem, LanguageItems};
+use crate::LangItem;
-use rustc_ast as ast;
-use rustc_data_structures::fx::FxIndexMap;
use rustc_span::symbol::{sym, Symbol};
-use std::sync::LazyLock;
-
macro_rules! weak_lang_items {
- ($($name:ident, $item:ident, $sym:ident;)*) => (
-
-pub static WEAK_ITEMS_REFS: LazyLock<FxIndexMap<Symbol, LangItem>> = LazyLock::new(|| {
- let mut map = FxIndexMap::default();
- $(map.insert(sym::$name, LangItem::$item);)*
- map
-});
-
-pub static WEAK_ITEMS_SYMBOLS: LazyLock<FxIndexMap<LangItem, Symbol>> = LazyLock::new(|| {
- let mut map = FxIndexMap::default();
- $(map.insert(LangItem::$item, sym::$sym);)*
- map
-});
-
-pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol>
-{
- lang_items::extract(attrs).and_then(|(name, _)| {
- $(if name == sym::$name {
- Some(sym::$sym)
- } else)* {
- None
+ ($($item:ident, $sym:ident;)*) => {
+ pub static WEAK_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
+
+ impl LangItem {
+ pub fn is_weak(self) -> bool {
+ matches!(self, $(LangItem::$item)|*)
+ }
+
+ pub fn link_name(self) -> Option<Symbol> {
+ match self {
+ $( LangItem::$item => Some(sym::$sym),)*
+ _ => None,
+ }
+ }
}
- })
-}
-
-impl LanguageItems {
- pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
- let did = Some(item_def_id);
-
- $(self.$name() == did)||*
}
}
-) }
-
weak_lang_items! {
- panic_impl, PanicImpl, rust_begin_unwind;
- eh_personality, EhPersonality, rust_eh_personality;
- eh_catch_typeinfo, EhCatchTypeinfo, rust_eh_catch_typeinfo;
- oom, Oom, rust_oom;
+ PanicImpl, rust_begin_unwind;
+ EhPersonality, rust_eh_personality;
+ EhCatchTypeinfo, rust_eh_catch_typeinfo;
}