compiler/rustc_ast/src/ast.rs RUST 4,347 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 4,347.
1//! The Rust abstract syntax tree module.2//!3//! This module contains common structures forming the language AST.4//! Two main entities in the module are [`Item`] (which represents an AST element with5//! additional metadata), and [`ItemKind`] (which represents a concrete type and contains6//! information specific to the type of the item).7//!8//! Other module items worth mentioning:9//! - [`Ty`] and [`TyKind`]: A parsed Rust type.10//! - [`Expr`] and [`ExprKind`]: A parsed Rust expression.11//! - [`Pat`] and [`PatKind`]: A parsed Rust pattern. Patterns are often dual to expressions.12//! - [`Stmt`] and [`StmtKind`]: An executable action that does not return a value.13//! - [`FnDecl`], [`FnHeader`] and [`Param`]: Metadata associated with a function declaration.14//! - [`Generics`], [`GenericParam`], [`WhereClause`]: Metadata associated with generic parameters.15//! - [`EnumDef`] and [`Variant`]: Enum declaration.16//! - [`MetaItemLit`] and [`LitKind`]: Literal expressions.17//! - [`MacroDef`], [`MacStmtStyle`], [`MacCall`]: Macro definition and invocation.18//! - [`Attribute`]: Metadata associated with item.19//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.2021use std::borrow::{Borrow, Cow};22use std::{cmp, fmt};2324pub use GenericArgs::*;25pub use UnsafeSource::*;26pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy};27use rustc_data_structures::packed::Pu128;28use rustc_data_structures::stable_hasher::{StableHash, StableHashCtxt, StableHasher};29use rustc_data_structures::stack::ensure_sufficient_stack;30use rustc_data_structures::tagged_ptr::Tag;31use rustc_macros::{Decodable, Encodable, StableHash, Walkable};32pub use rustc_span::AttrId;33use rustc_span::{34    ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, respan, sym,35};36use thin_vec::{ThinVec, thin_vec};3738use crate::attr::data_structures::CfgEntry;39pub use crate::format::*;40use crate::token::{self, CommentKind, Delimiter};41use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};42use crate::util::parser::{ExprPrecedence, Fixity};43use crate::visit::{AssocCtxt, BoundKind, LifetimeCtxt};4445/// A "Label" is an identifier of some point in sources,46/// e.g. in the following code:47///48/// ```rust49/// 'outer: loop {50///     break 'outer;51/// }52/// ```53///54/// `'outer` is a label.55#[derive(Clone, Encodable, Decodable, Copy, StableHash, Eq, PartialEq, Walkable)]56pub struct Label {57    pub ident: Ident,58}5960impl fmt::Debug for Label {61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {62        write!(f, "label({:?})", self.ident)63    }64}6566/// A "Lifetime" is an annotation of the scope in which variable67/// can be used, e.g. `'a` in `&'a i32`.68#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq, Hash, Walkable)]69pub struct Lifetime {70    pub id: NodeId,71    pub ident: Ident,72}7374impl fmt::Debug for Lifetime {75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {76        write!(f, "lifetime({}: {})", self.id, self)77    }78}7980impl fmt::Display for Lifetime {81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {82        write!(f, "{}", self.ident.name)83    }84}8586/// A "Path" is essentially Rust's notion of a name.87///88/// It's represented as a sequence of identifiers,89/// along with a bunch of supporting information.90///91/// E.g., `std::cmp::PartialEq`.92#[derive(Clone, Encodable, Decodable, Debug, Walkable)]93pub struct Path {94    pub span: Span,95    /// The segments in the path: the things separated by `::`.96    /// Global paths begin with `kw::PathRoot`.97    pub segments: ThinVec<PathSegment>,98    pub tokens: Option<LazyAttrTokenStream>,99}100101// Succeeds if the path has a single segment that is arg-free and matches the given symbol.102impl PartialEq<Symbol> for Path {103    #[inline]104    fn eq(&self, name: &Symbol) -> bool {105        if let [segment] = self.segments.as_ref()106            && segment == name107        {108            true109        } else {110            false111        }112    }113}114115// Succeeds if the path has segments that are arg-free and match the given symbols.116impl PartialEq<&[Symbol]> for Path {117    #[inline]118    fn eq(&self, names: &&[Symbol]) -> bool {119        self.segments.iter().eq(*names)120    }121}122123impl StableHash for Path {124    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {125        self.segments.len().stable_hash(hcx, hasher);126        for segment in &self.segments {127            segment.ident.stable_hash(hcx, hasher);128        }129    }130}131132impl Path {133    /// Convert a span and an identifier to the corresponding134    /// one-segment path.135    pub fn from_ident(ident: Ident) -> Path {136        Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }137    }138139    pub fn is_global(&self) -> bool {140        self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)141    }142143    /// Check if this path is potentially a trivial const arg, i.e., one that can _potentially_144    /// be represented without an anon const in the HIR.145    ///146    /// Returns true iff the path has exactly one segment, and it has no generic args147    /// (i.e., it is _potentially_ a const parameter).148    #[tracing::instrument(level = "debug", ret)]149    pub fn is_potential_trivial_const_arg(&self) -> bool {150        self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())151    }152}153154/// Joins multiple symbols with "::" into a path, e.g. "a::b::c". If the first155/// segment is `kw::PathRoot` it will be printed as empty, e.g. "::b::c".156///157/// The generics on the `path` argument mean it can accept many forms, such as:158/// - `&[Symbol]`159/// - `Vec<Symbol>`160/// - `Vec<&Symbol>`161/// - `impl Iterator<Item = Symbol>`162/// - `impl Iterator<Item = &Symbol>`163///164/// Panics if `path` is empty or a segment after the first is `kw::PathRoot`.165pub fn join_path_syms(path: impl IntoIterator<Item = impl Borrow<Symbol>>) -> String {166    // This is a guess at the needed capacity that works well in practice. It is slightly faster167    // than (a) starting with an empty string, or (b) computing the exact capacity required.168    // `8` works well because it's about the right size and jemalloc's size classes are all169    // multiples of 8.170    let mut iter = path.into_iter();171    let len_hint = iter.size_hint().1.unwrap_or(1);172    let mut s = String::with_capacity(len_hint * 8);173174    let first_sym = *iter.next().unwrap().borrow();175    if first_sym != kw::PathRoot {176        s.push_str(first_sym.as_str());177    }178    for sym in iter {179        let sym = *sym.borrow();180        debug_assert_ne!(sym, kw::PathRoot);181        s.push_str("::");182        s.push_str(sym.as_str());183    }184    s185}186187/// Like `join_path_syms`, but for `Ident`s. This function is necessary because188/// `Ident::to_string` does more than just print the symbol in the `name` field.189pub fn join_path_idents(path: impl IntoIterator<Item = impl Borrow<Ident>>) -> String {190    let mut iter = path.into_iter();191    let len_hint = iter.size_hint().1.unwrap_or(1);192    let mut s = String::with_capacity(len_hint * 8);193194    let first_ident = *iter.next().unwrap().borrow();195    if first_ident.name != kw::PathRoot {196        s.push_str(&first_ident.to_string());197    }198    for ident in iter {199        let ident = *ident.borrow();200        debug_assert_ne!(ident.name, kw::PathRoot);201        s.push_str("::");202        s.push_str(&ident.to_string());203    }204    s205}206207/// A segment of a path: an identifier, an optional lifetime, and a set of types.208///209/// E.g., `std`, `String` or `Box<T>`.210#[derive(Clone, Encodable, Decodable, Debug, Walkable)]211pub struct PathSegment {212    /// The identifier portion of this path segment.213    pub ident: Ident,214215    pub id: NodeId,216217    /// Type/lifetime parameters attached to this path. They come in218    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`.219    /// `None` means that no parameter list is supplied (`Path`),220    /// `Some` means that parameter list is supplied (`Path<X, Y>`)221    /// but it can be empty (`Path<>`).222    /// `P` is used as a size optimization for the common case with no parameters.223    pub args: Option<Box<GenericArgs>>,224}225226// Succeeds if the path segment is arg-free and matches the given symbol.227impl PartialEq<Symbol> for PathSegment {228    #[inline]229    fn eq(&self, name: &Symbol) -> bool {230        self.args.is_none() && self.ident.name == *name231    }232}233234impl PathSegment {235    pub fn from_ident(ident: Ident) -> Self {236        PathSegment { ident, id: DUMMY_NODE_ID, args: None }237    }238239    pub fn path_root(span: Span) -> Self {240        PathSegment::from_ident(Ident::new(kw::PathRoot, span))241    }242243    pub fn span(&self) -> Span {244        match &self.args {245            Some(args) => self.ident.span.to(args.span()),246            None => self.ident.span,247        }248    }249}250251/// The generic arguments and associated item constraints of a path segment.252///253/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.254#[derive(Clone, Encodable, Decodable, Debug, Walkable)]255pub enum GenericArgs {256    /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`.257    AngleBracketed(AngleBracketedArgs),258    /// The `(A, B)` and `C` in `Foo(A, B) -> C`.259    Parenthesized(ParenthesizedArgs),260    /// `(..)` in return type notation.261    ParenthesizedElided(Span),262}263264impl GenericArgs {265    pub fn is_angle_bracketed(&self) -> bool {266        matches!(self, AngleBracketed(..))267    }268269    pub fn span(&self) -> Span {270        match self {271            AngleBracketed(data) => data.span,272            Parenthesized(data) => data.span,273            ParenthesizedElided(span) => *span,274        }275    }276}277278/// Concrete argument in the sequence of generic args.279#[derive(Clone, Encodable, Decodable, Debug, Walkable)]280pub enum GenericArg {281    /// `'a` in `Foo<'a>`.282    Lifetime(#[visitable(extra = LifetimeCtxt::GenericArg)] Lifetime),283    /// `Bar` in `Foo<Bar>`.284    Type(Box<Ty>),285    /// `1` in `Foo<1>`.286    Const(AnonConst),287}288289impl GenericArg {290    pub fn span(&self) -> Span {291        match self {292            GenericArg::Lifetime(lt) => lt.ident.span,293            GenericArg::Type(ty) => ty.span,294            GenericArg::Const(ct) => ct.value.span,295        }296    }297}298299/// A path like `Foo<'a, T>`.300#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]301pub struct AngleBracketedArgs {302    /// The overall span.303    pub span: Span,304    /// The comma separated parts in the `<...>`.305    pub args: ThinVec<AngleBracketedArg>,306}307308/// Either an argument for a generic parameter or a constraint on an associated item.309#[derive(Clone, Encodable, Decodable, Debug, Walkable)]310pub enum AngleBracketedArg {311    /// A generic argument for a generic parameter.312    Arg(GenericArg),313    /// A constraint on an associated item.314    Constraint(AssocItemConstraint),315}316317impl AngleBracketedArg {318    pub fn span(&self) -> Span {319        match self {320            AngleBracketedArg::Arg(arg) => arg.span(),321            AngleBracketedArg::Constraint(constraint) => constraint.span,322        }323    }324}325326impl From<AngleBracketedArgs> for Box<GenericArgs> {327    fn from(val: AngleBracketedArgs) -> Self {328        Box::new(GenericArgs::AngleBracketed(val))329    }330}331332impl From<ParenthesizedArgs> for Box<GenericArgs> {333    fn from(val: ParenthesizedArgs) -> Self {334        Box::new(GenericArgs::Parenthesized(val))335    }336}337338/// A path like `Foo(A, B) -> C`.339#[derive(Clone, Encodable, Decodable, Debug, Walkable)]340pub struct ParenthesizedArgs {341    /// ```text342    /// Foo(A, B) -> C343    /// ^^^^^^^^^^^^^^344    /// ```345    pub span: Span,346347    /// `(A, B)`348    pub inputs: ThinVec<Box<Ty>>,349350    /// ```text351    /// Foo(A, B) -> C352    ///    ^^^^^^353    /// ```354    pub inputs_span: Span,355356    /// `C`357    pub output: FnRetTy,358}359360impl ParenthesizedArgs {361    pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {362        let args = self363            .inputs364            .iter()365            .cloned()366            .map(|input| AngleBracketedArg::Arg(GenericArg::Type(input)))367            .collect();368        AngleBracketedArgs { span: self.inputs_span, args }369    }370}371372pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId};373374/// Modifiers on a trait bound like `[const]`, `?` and `!`.375#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Walkable)]376pub struct TraitBoundModifiers {377    pub constness: BoundConstness,378    pub asyncness: BoundAsyncness,379    pub polarity: BoundPolarity,380}381382impl TraitBoundModifiers {383    pub const NONE: Self = Self {384        constness: BoundConstness::Never,385        asyncness: BoundAsyncness::Normal,386        polarity: BoundPolarity::Positive,387    };388}389390#[derive(Clone, Encodable, Decodable, Debug, Walkable)]391pub enum GenericBound {392    Trait(PolyTraitRef),393    Outlives(#[visitable(extra = LifetimeCtxt::Bound)] Lifetime),394    /// Precise capturing syntax: `impl Sized + use<'a>`395    Use(ThinVec<PreciseCapturingArg>, Span),396}397398impl GenericBound {399    pub fn span(&self) -> Span {400        match self {401            GenericBound::Trait(t, ..) => t.span,402            GenericBound::Outlives(l) => l.ident.span,403            GenericBound::Use(_, span) => *span,404        }405    }406}407408pub type GenericBounds = Vec<GenericBound>;409410/// Specifies the enforced ordering for generic parameters. In the future,411/// if we wanted to relax this order, we could override `PartialEq` and412/// `PartialOrd`, to allow the kinds to be unordered.413#[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]414pub enum ParamKindOrd {415    Lifetime,416    TypeOrConst,417}418419impl fmt::Display for ParamKindOrd {420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {421        match self {422            ParamKindOrd::Lifetime => "lifetime".fmt(f),423            ParamKindOrd::TypeOrConst => "type and const".fmt(f),424        }425    }426}427428#[derive(Clone, Encodable, Decodable, Debug, Walkable)]429pub enum GenericParamKind {430    /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).431    Lifetime,432    Type {433        default: Option<Box<Ty>>,434    },435    Const {436        ty: Box<Ty>,437        /// Span of the whole parameter definition, including default.438        span: Span,439        /// Optional default value for the const generic param.440        default: Option<AnonConst>,441    },442}443444#[derive(Clone, Encodable, Decodable, Debug, Walkable)]445pub struct GenericParam {446    pub id: NodeId,447    pub ident: Ident,448    pub attrs: AttrVec,449    #[visitable(extra = BoundKind::Bound)]450    pub bounds: GenericBounds,451    pub is_placeholder: bool,452    pub kind: GenericParamKind,453    pub colon_span: Option<Span>,454}455456impl GenericParam {457    pub fn span(&self) -> Span {458        match &self.kind {459            GenericParamKind::Lifetime | GenericParamKind::Type { default: None } => {460                self.ident.span461            }462            GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span),463            GenericParamKind::Const { span, .. } => *span,464        }465    }466}467468/// Represents lifetime, type and const parameters attached to a declaration of469/// a function, enum, trait, etc.470#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]471pub struct Generics {472    pub params: ThinVec<GenericParam>,473    pub where_clause: WhereClause,474    pub span: Span,475}476477/// A where-clause in a definition.478#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]479pub struct WhereClause {480    /// `true` if we ate a `where` token.481    ///482    /// This can happen if we parsed no predicates, e.g., `struct Foo where {}`.483    /// This allows us to pretty-print accurately and provide correct suggestion diagnostics.484    pub has_where_token: bool,485    pub predicates: ThinVec<WherePredicate>,486    pub span: Span,487}488489impl WhereClause {490    pub fn is_empty(&self) -> bool {491        !self.has_where_token && self.predicates.is_empty()492    }493}494495/// A single predicate in a where-clause.496#[derive(Clone, Encodable, Decodable, Debug, Walkable)]497pub struct WherePredicate {498    pub attrs: AttrVec,499    pub kind: WherePredicateKind,500    pub id: NodeId,501    pub span: Span,502    pub is_placeholder: bool,503}504505/// Predicate kind in where-clause.506#[derive(Clone, Encodable, Decodable, Debug, Walkable)]507pub enum WherePredicateKind {508    /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).509    BoundPredicate(WhereBoundPredicate),510    /// A lifetime predicate (e.g., `'a: 'b + 'c`).511    RegionPredicate(WhereRegionPredicate),512    /// An equality predicate (unsupported).513    EqPredicate(WhereEqPredicate),514}515516/// A type bound.517///518/// E.g., `for<'c> Foo: Send + Clone + 'c`.519#[derive(Clone, Encodable, Decodable, Debug, Walkable)]520pub struct WhereBoundPredicate {521    /// Any generics from a `for` binding.522    pub bound_generic_params: ThinVec<GenericParam>,523    /// The type being bounded.524    pub bounded_ty: Box<Ty>,525    /// Trait and lifetime bounds (`Clone + Send + 'static`).526    #[visitable(extra = BoundKind::Bound)]527    pub bounds: GenericBounds,528}529530/// A lifetime predicate.531///532/// E.g., `'a: 'b + 'c`.533#[derive(Clone, Encodable, Decodable, Debug, Walkable)]534pub struct WhereRegionPredicate {535    #[visitable(extra = LifetimeCtxt::Bound)]536    pub lifetime: Lifetime,537    #[visitable(extra = BoundKind::Bound)]538    pub bounds: GenericBounds,539}540541/// An equality predicate (unsupported).542///543/// E.g., `T = int`.544#[derive(Clone, Encodable, Decodable, Debug, Walkable)]545pub struct WhereEqPredicate {546    pub lhs_ty: Box<Ty>,547    pub rhs_ty: Box<Ty>,548}549550#[derive(Clone, Encodable, Decodable, Debug, Walkable)]551pub struct Crate {552    /// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold553    /// expansion placeholders or an unassigned value (`DUMMY_NODE_ID`) before that.554    pub id: NodeId,555    pub attrs: AttrVec,556    pub items: ThinVec<Box<Item>>,557    pub spans: ModSpans,558    pub is_placeholder: bool,559}560561/// A semantic representation of a meta item. A meta item is a slightly562/// restricted form of an attribute -- it can only contain expressions in563/// certain leaf positions, rather than arbitrary token streams -- that is used564/// for most built-in attributes.565///566/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.567#[derive(Clone, Encodable, Decodable, Debug, StableHash)]568pub struct MetaItem {569    pub unsafety: Safety,570    pub path: Path,571    pub kind: MetaItemKind,572    pub span: Span,573}574575/// The meta item kind, containing the data after the initial path.576#[derive(Clone, Encodable, Decodable, Debug, StableHash)]577pub enum MetaItemKind {578    /// Word meta item.579    ///580    /// E.g., `#[test]`, which lacks any arguments after `test`.581    Word,582583    /// List meta item.584    ///585    /// E.g., `#[derive(..)]`, where the field represents the `..`.586    List(ThinVec<MetaItemInner>),587588    /// Name value meta item.589    ///590    /// E.g., `#[feature = "foo"]`, where the field represents the `"foo"`.591    NameValue(MetaItemLit),592}593594/// Values inside meta item lists.595///596/// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`.597#[derive(Clone, Encodable, Decodable, Debug, StableHash)]598pub enum MetaItemInner {599    /// A full MetaItem, for recursive meta items.600    MetaItem(MetaItem),601602    /// A literal.603    ///604    /// E.g., `"foo"`, `64`, `true`.605    Lit(MetaItemLit),606}607608/// A block (`{ .. }`).609///610/// E.g., `{ .. }` as in `fn foo() { .. }`.611#[derive(Clone, Encodable, Decodable, Debug, Walkable)]612pub struct Block {613    /// The statements in the block.614    pub stmts: ThinVec<Stmt>,615    pub id: NodeId,616    /// Distinguishes between `unsafe { ... }` and `{ ... }`.617    pub rules: BlockCheckMode,618    pub span: Span,619    pub tokens: Option<LazyAttrTokenStream>,620}621622/// A match pattern.623///624/// Patterns appear in match statements and some other contexts, such as `let` and `if let`.625#[derive(Clone, Encodable, Decodable, Debug, Walkable)]626pub struct Pat {627    pub id: NodeId,628    pub kind: PatKind,629    pub span: Span,630    pub tokens: Option<LazyAttrTokenStream>,631}632633impl Pat {634    /// Attempt reparsing the pattern as a type.635    /// This is intended for use by diagnostics.636    pub fn to_ty(&self) -> Option<Box<Ty>> {637        let kind = match &self.kind {638            PatKind::Missing => unreachable!(),639            // In a type expression `_` is an inference variable.640            PatKind::Wild => TyKind::Infer,641            // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.642            PatKind::Ident(BindingMode::NONE, ident, None) => {643                TyKind::Path(None, Path::from_ident(*ident))644            }645            PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),646            PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()),647            // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.648            PatKind::Ref(pat, pinned, mutbl) => pat.to_ty().map(|ty| match pinned {649                Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }),650                Pinnedness::Pinned => TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }),651            })?,652            // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,653            // when `P` can be reparsed as a type `T`.654            PatKind::Slice(pats) if let [pat] = pats.as_slice() => {655                pat.to_ty().map(TyKind::Slice)?656            }657            // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`658            // assuming `T0` to `Tn` are all syntactically valid as types.659            PatKind::Tuple(pats) => {660                let tys = pats.iter().map(|pat| pat.to_ty()).collect::<Option<ThinVec<_>>>()?;661                TyKind::Tup(tys)662            }663            _ => return None,664        };665666        Some(Box::new(Ty { kind, id: self.id, span: self.span, tokens: None }))667    }668669    /// Walk top-down and call `it` in each place where a pattern occurs670    /// starting with the root pattern `walk` is called on. If `it` returns671    /// false then we will descend no further but siblings will be processed.672    pub fn walk<'ast>(&'ast self, it: &mut impl FnMut(&'ast Pat) -> bool) {673        if !it(self) {674            return;675        }676677        match &self.kind {678            // Walk into the pattern associated with `Ident` (if any).679            PatKind::Ident(_, _, Some(p)) => p.walk(it),680681            // Walk into each field of struct.682            PatKind::Struct(_, _, fields, _) => fields.iter().for_each(|field| field.pat.walk(it)),683684            // Sequence of patterns.685            PatKind::TupleStruct(_, _, s)686            | PatKind::Tuple(s)687            | PatKind::Slice(s)688            | PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)),689690            // Trivial wrappers over inner patterns.691            PatKind::Box(s)692            | PatKind::Deref(s)693            | PatKind::Ref(s, _, _)694            | PatKind::Paren(s)695            | PatKind::Guard(s, _) => s.walk(it),696697            // These patterns do not contain subpatterns, skip.698            PatKind::Missing699            | PatKind::Wild700            | PatKind::Rest701            | PatKind::Never702            | PatKind::Expr(_)703            | PatKind::Range(..)704            | PatKind::Ident(..)705            | PatKind::Path(..)706            | PatKind::MacCall(_)707            | PatKind::Err(_) => {}708        }709    }710711    /// Strip off all reference patterns (`&`, `&mut`) and return the inner pattern.712    pub fn peel_refs(&self) -> &Pat {713        let mut current = self;714        while let PatKind::Ref(inner, _, _) = &current.kind {715            current = inner;716        }717        current718    }719720    /// Is this a `..` pattern?721    pub fn is_rest(&self) -> bool {722        matches!(self.kind, PatKind::Rest)723    }724725    /// Whether this could be a never pattern, taking into account that a macro invocation can726    /// return a never pattern. Used to inform errors during parsing.727    pub fn could_be_never_pattern(&self) -> bool {728        let mut could_be_never_pattern = false;729        self.walk(&mut |pat| match &pat.kind {730            PatKind::Never | PatKind::MacCall(_) => {731                could_be_never_pattern = true;732                false733            }734            PatKind::Or(s) => {735                could_be_never_pattern = s.iter().all(|p| p.could_be_never_pattern());736                false737            }738            _ => true,739        });740        could_be_never_pattern741    }742743    /// Whether this contains a `!` pattern. This in particular means that a feature gate error will744    /// be raised if the feature is off. Used to avoid gating the feature twice.745    pub fn contains_never_pattern(&self) -> bool {746        let mut contains_never_pattern = false;747        self.walk(&mut |pat| {748            if matches!(pat.kind, PatKind::Never) {749                contains_never_pattern = true;750            }751            true752        });753        contains_never_pattern754    }755756    /// Return a name suitable for diagnostics.757    pub fn descr(&self) -> Option<String> {758        match &self.kind {759            PatKind::Missing => unreachable!(),760            PatKind::Wild => Some("_".to_string()),761            PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")),762            PatKind::Ref(pat, pinned, mutbl) => {763                pat.descr().map(|d| format!("&{}{d}", pinned.prefix_str(*mutbl)))764            }765            _ => None,766        }767    }768}769770impl From<Box<Pat>> for Pat {771    fn from(value: Box<Pat>) -> Self {772        *value773    }774}775776/// A single field in a struct pattern.777///778/// Patterns like the fields of `Foo { x, ref y, ref mut z }`779/// are treated the same as `x: x, y: ref y, z: ref mut z`,780/// except when `is_shorthand` is true.781#[derive(Clone, Encodable, Decodable, Debug, Walkable)]782pub struct PatField {783    /// The identifier for the field.784    pub ident: Ident,785    /// The pattern the field is destructured to.786    pub pat: Box<Pat>,787    pub is_shorthand: bool,788    pub attrs: AttrVec,789    pub id: NodeId,790    pub span: Span,791    pub is_placeholder: bool,792}793794#[derive(Clone, Copy, Debug, Eq, PartialEq)]795#[derive(Encodable, Decodable, StableHash, Walkable)]796pub enum ByRef {797    Yes(Pinnedness, Mutability),798    No,799}800801impl ByRef {802    #[must_use]803    pub fn cap_ref_mutability(mut self, mutbl: Mutability) -> Self {804        if let ByRef::Yes(_, old_mutbl) = &mut self {805            *old_mutbl = cmp::min(*old_mutbl, mutbl);806        }807        self808    }809}810811/// The mode of a binding (`mut`, `ref mut`, etc).812/// Used for both the explicit binding annotations given in the HIR for a binding813/// and the final binding mode that we infer after type inference/match ergonomics.814/// `.0` is the by-reference mode (`ref`, `ref mut`, or by value),815/// `.1` is the mutability of the binding.816#[derive(Clone, Copy, Debug, Eq, PartialEq)]817#[derive(Encodable, Decodable, StableHash, Walkable)]818pub struct BindingMode(pub ByRef, pub Mutability);819820impl BindingMode {821    pub const NONE: Self = Self(ByRef::No, Mutability::Not);822    pub const REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Not);823    pub const REF_PIN: Self =824        Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Not);825    pub const MUT: Self = Self(ByRef::No, Mutability::Mut);826    pub const REF_MUT: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Not);827    pub const REF_PIN_MUT: Self =828        Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Not);829    pub const MUT_REF: Self = Self(ByRef::Yes(Pinnedness::Not, Mutability::Not), Mutability::Mut);830    pub const MUT_REF_PIN: Self =831        Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Not), Mutability::Mut);832    pub const MUT_REF_MUT: Self =833        Self(ByRef::Yes(Pinnedness::Not, Mutability::Mut), Mutability::Mut);834    pub const MUT_REF_PIN_MUT: Self =835        Self(ByRef::Yes(Pinnedness::Pinned, Mutability::Mut), Mutability::Mut);836837    pub fn prefix_str(self) -> &'static str {838        match self {839            Self::NONE => "",840            Self::REF => "ref ",841            Self::REF_PIN => "ref pin const ",842            Self::MUT => "mut ",843            Self::REF_MUT => "ref mut ",844            Self::REF_PIN_MUT => "ref pin mut ",845            Self::MUT_REF => "mut ref ",846            Self::MUT_REF_PIN => "mut ref pin ",847            Self::MUT_REF_MUT => "mut ref mut ",848            Self::MUT_REF_PIN_MUT => "mut ref pin mut ",849        }850    }851}852853#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]854pub enum RangeEnd {855    /// `..=` or `...`856    Included(RangeSyntax),857    /// `..`858    Excluded,859}860861#[derive(Clone, Copy, Encodable, Decodable, Debug, Walkable)]862pub enum RangeSyntax {863    /// `...`864    DotDotDot,865    /// `..=`866    DotDotEq,867}868869/// All the different flavors of pattern that Rust recognizes.870//871// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.872#[derive(Clone, Encodable, Decodable, Debug, Walkable)]873pub enum PatKind {874    /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`.875    Missing,876877    /// Represents a wildcard pattern (`_`).878    Wild,879880    /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),881    /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third882    /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens883    /// during name resolution.884    Ident(BindingMode, Ident, Option<Box<Pat>>),885886    /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).887    Struct(Option<Box<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),888889    /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).890    TupleStruct(Option<Box<QSelf>>, Path, ThinVec<Pat>),891892    /// An or-pattern `A | B | C`.893    /// Invariant: `pats.len() >= 2`.894    Or(ThinVec<Pat>),895896    /// A possibly qualified path pattern.897    /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants898    /// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can899    /// only legally refer to associated constants.900    Path(Option<Box<QSelf>>, Path),901902    /// A tuple pattern (`(a, b)`).903    Tuple(ThinVec<Pat>),904905    /// A `box` pattern.906    Box(Box<Pat>),907908    /// A `deref` pattern (currently `deref!()` macro-based syntax).909    Deref(Box<Pat>),910911    /// A reference pattern (e.g., `&mut (a, b)`).912    Ref(Box<Pat>, Pinnedness, Mutability),913914    /// A literal, const block or path.915    Expr(Box<Expr>),916917    /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).918    Range(Option<Box<Expr>>, Option<Box<Expr>>, Spanned<RangeEnd>),919920    /// A slice pattern `[a, b, c]`.921    Slice(ThinVec<Pat>),922923    /// A rest pattern `..`.924    ///925    /// Syntactically it is valid anywhere.926    ///927    /// Semantically however, it only has meaning immediately inside:928    /// - a slice pattern: `[a, .., b]`,929    /// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`,930    /// - a tuple pattern: `(a, .., b)`,931    /// - a tuple struct/variant pattern: `$path(a, .., b)`.932    ///933    /// In all of these cases, an additional restriction applies,934    /// only one rest pattern may occur in the pattern sequences.935    Rest,936937    // A never pattern `!`.938    Never,939940    /// A guard pattern (e.g., `x if guard(x)`).941    Guard(Box<Pat>, Box<Guard>),942943    /// Parentheses in patterns used for grouping (i.e., `(PAT)`).944    Paren(Box<Pat>),945946    /// A macro pattern; pre-expansion.947    MacCall(Box<MacCall>),948949    /// Placeholder for a pattern that wasn't syntactically well formed in some way.950    Err(ErrorGuaranteed),951}952953/// Whether the `..` is present in a struct fields pattern.954#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)]955pub enum PatFieldsRest {956    /// `module::StructName { field, ..}`957    Rest(Span),958    /// `module::StructName { field, syntax error }`959    Recovered(ErrorGuaranteed),960    /// `module::StructName { field }`961    None,962}963964/// The kind of borrow in an `AddrOf` expression,965/// e.g., `&place` or `&raw const place`.966#[derive(Clone, Copy, PartialEq, Eq, Debug)]967#[derive(Encodable, Decodable, StableHash, Walkable)]968pub enum BorrowKind {969    /// A normal borrow, `&$expr` or `&mut $expr`.970    /// The resulting type is either `&'a T` or `&'a mut T`971    /// where `T = typeof($expr)` and `'a` is some lifetime.972    Ref,973    /// A raw borrow, `&raw const $expr` or `&raw mut $expr`.974    /// The resulting type is either `*const T` or `*mut T`975    /// where `T = typeof($expr)`.976    Raw,977    /// A pinned borrow, `&pin const $expr` or `&pin mut $expr`.978    /// The resulting type is either `Pin<&'a T>` or `Pin<&'a mut T>`979    /// where `T = typeof($expr)` and `'a` is some lifetime.980    Pin,981}982983#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, StableHash, Walkable)]984pub enum BinOpKind {985    /// The `+` operator (addition)986    Add,987    /// The `-` operator (subtraction)988    Sub,989    /// The `*` operator (multiplication)990    Mul,991    /// The `/` operator (division)992    Div,993    /// The `%` operator (modulus)994    Rem,995    /// The `&&` operator (logical and)996    And,997    /// The `||` operator (logical or)998    Or,999    /// The `^` operator (bitwise xor)1000    BitXor,1001    /// The `&` operator (bitwise and)1002    BitAnd,1003    /// The `|` operator (bitwise or)1004    BitOr,1005    /// The `<<` operator (shift left)1006    Shl,1007    /// The `>>` operator (shift right)1008    Shr,1009    /// The `==` operator (equality)1010    Eq,1011    /// The `<` operator (less than)1012    Lt,1013    /// The `<=` operator (less than or equal to)1014    Le,1015    /// The `!=` operator (not equal to)1016    Ne,1017    /// The `>=` operator (greater than or equal to)1018    Ge,1019    /// The `>` operator (greater than)1020    Gt,1021}10221023impl BinOpKind {1024    pub fn as_str(&self) -> &'static str {1025        use BinOpKind::*;1026        match self {1027            Add => "+",1028            Sub => "-",1029            Mul => "*",1030            Div => "/",1031            Rem => "%",1032            And => "&&",1033            Or => "||",1034            BitXor => "^",1035            BitAnd => "&",1036            BitOr => "|",1037            Shl => "<<",1038            Shr => ">>",1039            Eq => "==",1040            Lt => "<",1041            Le => "<=",1042            Ne => "!=",1043            Ge => ">=",1044            Gt => ">",1045        }1046    }10471048    pub fn is_lazy(&self) -> bool {1049        matches!(self, BinOpKind::And | BinOpKind::Or)1050    }10511052    pub fn precedence(&self) -> ExprPrecedence {1053        use BinOpKind::*;1054        match *self {1055            Mul | Div | Rem => ExprPrecedence::Product,1056            Add | Sub => ExprPrecedence::Sum,1057            Shl | Shr => ExprPrecedence::Shift,1058            BitAnd => ExprPrecedence::BitAnd,1059            BitXor => ExprPrecedence::BitXor,1060            BitOr => ExprPrecedence::BitOr,1061            Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare,1062            And => ExprPrecedence::LAnd,1063            Or => ExprPrecedence::LOr,1064        }1065    }10661067    pub fn fixity(&self) -> Fixity {1068        use BinOpKind::*;1069        match self {1070            Eq | Ne | Lt | Le | Gt | Ge => Fixity::None,1071            Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => {1072                Fixity::Left1073            }1074        }1075    }10761077    pub fn is_comparison(self) -> bool {1078        use BinOpKind::*;1079        match self {1080            Eq | Ne | Lt | Le | Gt | Ge => true,1081            Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false,1082        }1083    }10841085    /// Returns `true` if the binary operator takes its arguments by value.1086    pub fn is_by_value(self) -> bool {1087        !self.is_comparison()1088    }1089}10901091pub type BinOp = Spanned<BinOpKind>;10921093// Sometimes `BinOpKind` and `AssignOpKind` need the same treatment. The1094// operations covered by `AssignOpKind` are a subset of those covered by1095// `BinOpKind`, so it makes sense to convert `AssignOpKind` to `BinOpKind`.1096impl From<AssignOpKind> for BinOpKind {1097    fn from(op: AssignOpKind) -> BinOpKind {1098        match op {1099            AssignOpKind::AddAssign => BinOpKind::Add,1100            AssignOpKind::SubAssign => BinOpKind::Sub,1101            AssignOpKind::MulAssign => BinOpKind::Mul,1102            AssignOpKind::DivAssign => BinOpKind::Div,1103            AssignOpKind::RemAssign => BinOpKind::Rem,1104            AssignOpKind::BitXorAssign => BinOpKind::BitXor,1105            AssignOpKind::BitAndAssign => BinOpKind::BitAnd,1106            AssignOpKind::BitOrAssign => BinOpKind::BitOr,1107            AssignOpKind::ShlAssign => BinOpKind::Shl,1108            AssignOpKind::ShrAssign => BinOpKind::Shr,1109        }1110    }1111}11121113#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, StableHash, Walkable)]1114pub enum AssignOpKind {1115    /// The `+=` operator (addition)1116    AddAssign,1117    /// The `-=` operator (subtraction)1118    SubAssign,1119    /// The `*=` operator (multiplication)1120    MulAssign,1121    /// The `/=` operator (division)1122    DivAssign,1123    /// The `%=` operator (modulus)1124    RemAssign,1125    /// The `^=` operator (bitwise xor)1126    BitXorAssign,1127    /// The `&=` operator (bitwise and)1128    BitAndAssign,1129    /// The `|=` operator (bitwise or)1130    BitOrAssign,1131    /// The `<<=` operator (shift left)1132    ShlAssign,1133    /// The `>>=` operator (shift right)1134    ShrAssign,1135}11361137impl AssignOpKind {1138    pub fn as_str(&self) -> &'static str {1139        use AssignOpKind::*;1140        match self {1141            AddAssign => "+=",1142            SubAssign => "-=",1143            MulAssign => "*=",1144            DivAssign => "/=",1145            RemAssign => "%=",1146            BitXorAssign => "^=",1147            BitAndAssign => "&=",1148            BitOrAssign => "|=",1149            ShlAssign => "<<=",1150            ShrAssign => ">>=",1151        }1152    }11531154    /// AssignOps are always by value.1155    pub fn is_by_value(self) -> bool {1156        true1157    }1158}11591160pub type AssignOp = Spanned<AssignOpKind>;11611162/// Unary operator.1163///1164/// Note that `&data` is not an operator, it's an `AddrOf` expression.1165#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, StableHash, Walkable)]1166pub enum UnOp {1167    /// The `*` operator for dereferencing1168    Deref,1169    /// The `!` operator for logical inversion1170    Not,1171    /// The `-` operator for negation1172    Neg,1173}11741175impl UnOp {1176    pub fn as_str(&self) -> &'static str {1177        match self {1178            UnOp::Deref => "*",1179            UnOp::Not => "!",1180            UnOp::Neg => "-",1181        }1182    }11831184    /// Returns `true` if the unary operator takes its argument by value.1185    pub fn is_by_value(self) -> bool {1186        matches!(self, Self::Neg | Self::Not)1187    }1188}11891190/// A statement. No `attrs` or `tokens` fields because each `StmtKind` variant1191/// contains an AST node with those fields. (Except for `StmtKind::Empty`,1192/// which never has attrs or tokens)1193#[derive(Clone, Encodable, Decodable, Debug)]1194pub struct Stmt {1195    pub id: NodeId,1196    pub kind: StmtKind,1197    pub span: Span,1198}11991200impl Stmt {1201    pub fn has_trailing_semicolon(&self) -> bool {1202        match &self.kind {1203            StmtKind::Semi(_) => true,1204            StmtKind::MacCall(mac) => matches!(mac.style, MacStmtStyle::Semicolon),1205            _ => false,1206        }1207    }12081209    /// Converts a parsed `Stmt` to a `Stmt` with1210    /// a trailing semicolon.1211    ///1212    /// This only modifies the parsed AST struct, not the attached1213    /// `LazyAttrTokenStream`. The parser is responsible for calling1214    /// `ToAttrTokenStream::add_trailing_semi` when there is actually1215    /// a semicolon in the tokenstream.1216    pub fn add_trailing_semicolon(mut self) -> Self {1217        self.kind = match self.kind {1218            StmtKind::Expr(expr) => StmtKind::Semi(expr),1219            StmtKind::MacCall(mut mac) => {1220                mac.style = MacStmtStyle::Semicolon;1221                StmtKind::MacCall(mac)1222            }1223            kind => kind,1224        };12251226        self1227    }12281229    pub fn is_item(&self) -> bool {1230        matches!(self.kind, StmtKind::Item(_))1231    }12321233    pub fn is_expr(&self) -> bool {1234        matches!(self.kind, StmtKind::Expr(_))1235    }1236}12371238// Adding a new variant? Please update `test_stmt` in `tests/ui/macros/stringify.rs`.1239#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1240pub enum StmtKind {1241    /// A local (let) binding.1242    Let(Box<Local>),1243    /// An item definition.1244    Item(Box<Item>),1245    /// Expr without trailing semi-colon.1246    Expr(Box<Expr>),1247    /// Expr with a trailing semi-colon.1248    Semi(Box<Expr>),1249    /// Just a trailing semi-colon.1250    Empty,1251    /// Macro.1252    MacCall(Box<MacCallStmt>),1253}12541255impl StmtKind {1256    pub fn descr(&self) -> &'static str {1257        match self {1258            StmtKind::Let(_) => "local",1259            StmtKind::Item(_) => "item",1260            StmtKind::Expr(_) => "expression",1261            StmtKind::Semi(_) => "statement",1262            StmtKind::Empty => "semicolon",1263            StmtKind::MacCall(_) => "macro call",1264        }1265    }1266}12671268#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1269pub struct MacCallStmt {1270    pub mac: Box<MacCall>,1271    pub style: MacStmtStyle,1272    pub attrs: AttrVec,1273    pub tokens: Option<LazyAttrTokenStream>,1274}12751276#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, Walkable)]1277pub enum MacStmtStyle {1278    /// The macro statement had a trailing semicolon (e.g., `foo! { ... };`1279    /// `foo!(...);`, `foo![...];`).1280    Semicolon,1281    /// The macro statement had braces (e.g., `foo! { ... }`).1282    Braces,1283    /// The macro statement had parentheses or brackets and no semicolon (e.g.,1284    /// `foo!(...)`). All of these will end up being converted into macro1285    /// expressions.1286    NoBraces,1287}12881289/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`.1290#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1291pub struct Local {1292    pub id: NodeId,1293    pub super_: Option<Span>,1294    pub pat: Box<Pat>,1295    pub ty: Option<Box<Ty>>,1296    pub kind: LocalKind,1297    pub span: Span,1298    pub colon_sp: Option<Span>,1299    pub attrs: AttrVec,1300    pub tokens: Option<LazyAttrTokenStream>,1301}13021303#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1304pub enum LocalKind {1305    /// Local declaration.1306    /// Example: `let x;`1307    Decl,1308    /// Local declaration with an initializer.1309    /// Example: `let x = y;`1310    Init(Box<Expr>),1311    /// Local declaration with an initializer and an `else` clause.1312    /// Example: `let Some(x) = y else { return };`1313    InitElse(Box<Expr>, Box<Block>),1314}13151316impl LocalKind {1317    pub fn init(&self) -> Option<&Expr> {1318        match self {1319            Self::Decl => None,1320            Self::Init(i) | Self::InitElse(i, _) => Some(i),1321        }1322    }13231324    pub fn init_else_opt(&self) -> Option<(&Expr, Option<&Block>)> {1325        match self {1326            Self::Decl => None,1327            Self::Init(init) => Some((init, None)),1328            Self::InitElse(init, els) => Some((init, Some(els))),1329        }1330    }1331}13321333/// An arm of a 'match'.1334///1335/// E.g., `0..=10 => { println!("match!") }` as in1336///1337/// ```1338/// match 123 {1339///     0..=10 => { println!("match!") },1340///     _ => { println!("no match!") },1341/// }1342/// ```1343#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1344pub struct Arm {1345    pub attrs: AttrVec,1346    /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`.1347    pub pat: Box<Pat>,1348    /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`.1349    pub guard: Option<Box<Guard>>,1350    /// Match arm body. Omitted if the pattern is a never pattern.1351    pub body: Option<Box<Expr>>,1352    pub span: Span,1353    pub id: NodeId,1354    pub is_placeholder: bool,1355}13561357/// A single field in a struct expression, e.g. `x: value` and `y` in `Foo { x: value, y }`.1358#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1359pub struct ExprField {1360    pub attrs: AttrVec,1361    pub id: NodeId,1362    pub span: Span,1363    pub ident: Ident,1364    pub expr: Box<Expr>,1365    pub is_shorthand: bool,1366    pub is_placeholder: bool,1367}13681369#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]1370pub enum BlockCheckMode {1371    Default,1372    Unsafe(UnsafeSource),1373}13741375#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]1376pub enum UnsafeSource {1377    CompilerGenerated,1378    UserProvided,1379}13801381/// Track whether under `feature(min_generic_const_args)` this anon const1382/// was explicitly disambiguated as an anon const or not through the use of1383/// `const { ... }` syntax.1384#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]1385pub enum MgcaDisambiguation {1386    AnonConst,1387    Direct,1388}13891390/// A constant (expression) that's not an item or associated item,1391/// but needs its own `DefId` for type-checking, const-eval, etc.1392/// These are usually found nested inside types (e.g., array lengths)1393/// or expressions (e.g., repeat counts), and also used to define1394/// explicit discriminant values for enum variants.1395#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1396pub struct AnonConst {1397    pub id: NodeId,1398    pub value: Box<Expr>,1399    pub mgca_disambiguation: MgcaDisambiguation,1400}14011402/// An expression.1403#[derive(Clone, Encodable, Decodable, Debug)]1404pub struct Expr {1405    pub id: NodeId,1406    pub kind: ExprKind,1407    pub span: Span,1408    pub attrs: AttrVec,1409    pub tokens: Option<LazyAttrTokenStream>,1410}14111412impl Expr {1413    /// Check if this expression is potentially a trivial const arg, i.e., one that can _potentially_1414    /// be represented without an anon const in the HIR.1415    ///1416    /// This will unwrap at most one block level (curly braces). After that, if the expression1417    /// is a path, it mostly dispatches to [`Path::is_potential_trivial_const_arg`].1418    ///1419    /// This function will only allow paths with no qself, before dispatching to the `Path`1420    /// function of the same name.1421    ///1422    /// Does not ensure that the path resolves to a const param/item, the caller should check this.1423    /// This also does not consider macros, so it's only correct after macro-expansion.1424    pub fn is_potential_trivial_const_arg(&self) -> bool {1425        let this = self.maybe_unwrap_block();1426        if let ExprKind::Path(None, path) = &this.kind1427            && path.is_potential_trivial_const_arg()1428        {1429            true1430        } else {1431            false1432        }1433    }14341435    /// Returns an expression with (when possible) *one* outer brace removed1436    pub fn maybe_unwrap_block(&self) -> &Expr {1437        if let ExprKind::Block(block, None) = &self.kind1438            && let [stmt] = block.stmts.as_slice()1439            && let StmtKind::Expr(expr) = &stmt.kind1440        {1441            expr1442        } else {1443            self1444        }1445    }14461447    /// Determines whether this expression is a macro call optionally wrapped in braces . If1448    /// `already_stripped_block` is set then we do not attempt to peel off a layer of braces.1449    ///1450    /// Returns the [`NodeId`] of the macro call and whether a layer of braces has been peeled1451    /// either before, or part of, this function.1452    pub fn optionally_braced_mac_call(1453        &self,1454        already_stripped_block: bool,1455    ) -> Option<(bool, NodeId)> {1456        match &self.kind {1457            ExprKind::Block(block, None)1458                if let [stmt] = &*block.stmts1459                    && !already_stripped_block =>1460            {1461                match &stmt.kind {1462                    StmtKind::MacCall(_) => Some((true, stmt.id)),1463                    StmtKind::Expr(expr) if let ExprKind::MacCall(_) = &expr.kind => {1464                        Some((true, expr.id))1465                    }1466                    _ => None,1467                }1468            }1469            ExprKind::MacCall(_) => Some((already_stripped_block, self.id)),1470            _ => None,1471        }1472    }14731474    pub fn to_bound(&self) -> Option<GenericBound> {1475        match &self.kind {1476            ExprKind::Path(None, path) => Some(GenericBound::Trait(PolyTraitRef::new(1477                ThinVec::new(),1478                path.clone(),1479                TraitBoundModifiers::NONE,1480                self.span,1481                Parens::No,1482            ))),1483            _ => None,1484        }1485    }14861487    pub fn peel_parens(&self) -> &Expr {1488        let mut expr = self;1489        while let ExprKind::Paren(inner) = &expr.kind {1490            expr = inner;1491        }1492        expr1493    }14941495    pub fn peel_parens_and_refs(&self) -> &Expr {1496        let mut expr = self;1497        while let ExprKind::Paren(inner) | ExprKind::AddrOf(BorrowKind::Ref, _, inner) = &expr.kind1498        {1499            expr = inner;1500        }1501        expr1502    }15031504    /// Attempts to reparse as `Ty` (for diagnostic purposes).1505    pub fn to_ty(&self) -> Option<Box<Ty>> {1506        let kind = match &self.kind {1507            // Trivial conversions.1508            ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),1509            ExprKind::MacCall(mac) => TyKind::MacCall(mac.clone()),15101511            ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,15121513            ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => {1514                expr.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))?1515            }15161517            ExprKind::Repeat(expr, expr_len) => {1518                expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?1519            }15201521            ExprKind::Array(exprs) if let [expr] = exprs.as_slice() => {1522                expr.to_ty().map(TyKind::Slice)?1523            }15241525            ExprKind::Tup(exprs) => {1526                let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?;1527                TyKind::Tup(tys)1528            }15291530            // If binary operator is `Add` and both `lhs` and `rhs` are trait bounds,1531            // then type of result is trait object.1532            // Otherwise we don't assume the result type.1533            ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {1534                let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) else {1535                    return None;1536                };1537                TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)1538            }15391540            ExprKind::Underscore => TyKind::Infer,15411542            // This expression doesn't look like a type syntactically.1543            _ => return None,1544        };15451546        Some(Box::new(Ty { kind, id: self.id, span: self.span, tokens: None }))1547    }15481549    pub fn precedence(&self) -> ExprPrecedence {1550        fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence {1551            for attr in attrs {1552                if let AttrStyle::Outer = attr.style {1553                    return ExprPrecedence::Prefix;1554                }1555            }1556            ExprPrecedence::Unambiguous1557        }15581559        match &self.kind {1560            ExprKind::Closure(closure) => {1561                match closure.fn_decl.output {1562                    FnRetTy::Default(_) => ExprPrecedence::Jump,1563                    FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),1564                }1565            }15661567            ExprKind::Break(_ /*label*/, value)1568            | ExprKind::Ret(value)1569            | ExprKind::Yield(YieldKind::Prefix(value))1570            | ExprKind::Yeet(value) => match value {1571                Some(_) => ExprPrecedence::Jump,1572                None => prefix_attrs_precedence(&self.attrs),1573            },15741575            ExprKind::Become(_) => ExprPrecedence::Jump,15761577            // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to1578            // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence1579            // ensures that `pprust` will add parentheses in the right places to get the desired1580            // parse.1581            ExprKind::Range(..) => ExprPrecedence::Range,15821583            // Binop-like expr kinds, handled by `AssocOp`.1584            ExprKind::Binary(op, ..) => op.node.precedence(),1585            ExprKind::Cast(..) => ExprPrecedence::Cast,15861587            ExprKind::Assign(..) |1588            ExprKind::AssignOp(..) => ExprPrecedence::Assign,15891590            // Unary, prefix1591            ExprKind::AddrOf(..)1592            // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.1593            // However, this is not exactly right. When `let _ = a` is the LHS of a binop we1594            // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`1595            // but we need to print `(let _ = a) < b` as-is with parens.1596            | ExprKind::Let(..)1597            | ExprKind::Unary(..) => ExprPrecedence::Prefix,15981599            // Need parens if and only if there are prefix attributes.1600            ExprKind::Array(_)1601            | ExprKind::Await(..)1602            | ExprKind::Use(..)1603            | ExprKind::Block(..)1604            | ExprKind::Call(..)1605            | ExprKind::ConstBlock(_)1606            | ExprKind::Continue(..)1607            | ExprKind::Field(..)1608            | ExprKind::ForLoop { .. }1609            | ExprKind::FormatArgs(..)1610            | ExprKind::Gen(..)1611            | ExprKind::If(..)1612            | ExprKind::IncludedBytes(..)1613            | ExprKind::Index(..)1614            | ExprKind::InlineAsm(..)1615            | ExprKind::Lit(_)1616            | ExprKind::Loop(..)1617            | ExprKind::MacCall(..)1618            | ExprKind::Match(..)1619            | ExprKind::MethodCall(..)1620            | ExprKind::OffsetOf(..)1621            | ExprKind::Paren(..)1622            | ExprKind::Path(..)1623            | ExprKind::Repeat(..)1624            | ExprKind::Struct(..)1625            | ExprKind::Try(..)1626            | ExprKind::TryBlock(..)1627            | ExprKind::Tup(_)1628            | ExprKind::Type(..)1629            | ExprKind::Underscore1630            | ExprKind::UnsafeBinderCast(..)1631            | ExprKind::While(..)1632            | ExprKind::Yield(YieldKind::Postfix(..))1633            | ExprKind::Err(_)1634            | ExprKind::Dummy => prefix_attrs_precedence(&self.attrs),1635        }1636    }16371638    /// To a first-order approximation, is this a pattern?1639    pub fn is_approximately_pattern(&self) -> bool {1640        matches!(1641            &self.peel_parens().kind,1642            ExprKind::Array(_)1643                | ExprKind::Call(_, _)1644                | ExprKind::Tup(_)1645                | ExprKind::Lit(_)1646                | ExprKind::Range(_, _, _)1647                | ExprKind::Underscore1648                | ExprKind::Path(_, _)1649                | ExprKind::Struct(_)1650        )1651    }16521653    /// Creates a dummy `Expr`.1654    ///1655    /// Should only be used when it will be replaced afterwards or as a return value when an error was encountered.1656    pub fn dummy() -> Expr {1657        Expr {1658            id: DUMMY_NODE_ID,1659            kind: ExprKind::Dummy,1660            span: DUMMY_SP,1661            attrs: ThinVec::new(),1662            tokens: None,1663        }1664    }1665}16661667impl From<Box<Expr>> for Expr {1668    fn from(value: Box<Expr>) -> Self {1669        *value1670    }1671}16721673#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1674pub struct Closure {1675    pub binder: ClosureBinder,1676    pub capture_clause: CaptureBy,1677    pub constness: Const,1678    pub coroutine_kind: Option<CoroutineKind>,1679    pub movability: Movability,1680    pub fn_decl: Box<FnDecl>,1681    pub body: Box<Expr>,1682    /// The span of the declaration block: 'move |...| -> ...'1683    pub fn_decl_span: Span,1684    /// The span of the argument block `|...|`1685    pub fn_arg_span: Span,1686}16871688/// Limit types of a range (inclusive or exclusive).1689#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, Walkable)]1690pub enum RangeLimits {1691    /// Inclusive at the beginning, exclusive at the end.1692    HalfOpen,1693    /// Inclusive at the beginning and end.1694    Closed,1695}16961697impl RangeLimits {1698    pub fn as_str(&self) -> &'static str {1699        match self {1700            RangeLimits::HalfOpen => "..",1701            RangeLimits::Closed => "..=",1702        }1703    }1704}17051706/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).1707#[derive(Clone, Encodable, Decodable, Debug)]1708pub struct MethodCall {1709    /// The method name and its generic arguments, e.g. `foo::<Bar, Baz>`.1710    pub seg: PathSegment,1711    /// The receiver, e.g. `x`.1712    pub receiver: Box<Expr>,1713    /// The arguments, e.g. `a, b, c`.1714    pub args: ThinVec<Box<Expr>>,1715    /// The span of the function, without the dot and receiver e.g. `foo::<Bar,1716    /// Baz>(a, b, c)`.1717    pub span: Span,1718}17191720#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1721pub enum StructRest {1722    /// `..x`.1723    Base(Box<Expr>),1724    /// `..`.1725    Rest(Span),1726    /// No trailing `..` or expression.1727    None,1728    /// No trailing `..` or expression, and also, a parse error occurred inside the struct braces.1729    ///1730    /// This struct should be treated similarly to as if it had an `..` in it,1731    /// in particular rather than reporting missing fields, because the parse error1732    /// makes which fields the struct was intended to have not fully known.1733    NoneWithError(ErrorGuaranteed),1734}17351736#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1737pub struct StructExpr {1738    pub qself: Option<Box<QSelf>>,1739    pub path: Path,1740    pub fields: ThinVec<ExprField>,1741    pub rest: StructRest,1742}17431744// Adding a new variant? Please update `test_expr` in `tests/ui/macros/stringify.rs`.1745#[derive(Clone, Encodable, Decodable, Debug)]1746pub enum ExprKind {1747    /// An array (e.g, `[a, b, c, d]`).1748    Array(ThinVec<Box<Expr>>),1749    /// Allow anonymous constants from an inline `const` block.1750    ConstBlock(AnonConst),1751    /// A function call.1752    ///1753    /// The first field resolves to the function itself,1754    /// and the second field is the list of arguments.1755    /// This also represents calling the constructor of1756    /// tuple-like ADTs such as tuple structs and enum variants.1757    Call(Box<Expr>, ThinVec<Box<Expr>>),1758    /// A method call (e.g., `x.foo::<Bar, Baz>(a, b, c)`).1759    MethodCall(Box<MethodCall>),1760    /// A tuple (e.g., `(a, b, c, d)`).1761    Tup(ThinVec<Box<Expr>>),1762    /// A binary operation (e.g., `a + b`, `a * b`).1763    Binary(BinOp, Box<Expr>, Box<Expr>),1764    /// A unary operation (e.g., `!x`, `*x`).1765    Unary(UnOp, Box<Expr>),1766    /// A literal (e.g., `1`, `"foo"`).1767    Lit(token::Lit),1768    /// A cast (e.g., `foo as f64`).1769    Cast(Box<Expr>, Box<Ty>),1770    /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`).1771    ///1772    /// Usually not written directly in user code but1773    /// indirectly via the macro `type_ascribe!(...)`.1774    Type(Box<Expr>, Box<Ty>),1775    /// A `let pat = expr` expression that is only semantically allowed in the condition1776    /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).1777    ///1778    /// `Span` represents the whole `let pat = expr` statement.1779    Let(Box<Pat>, Box<Expr>, Span, Recovered),1780    /// An `if` block, with an optional `else` block.1781    ///1782    /// `if expr { block } else { expr }`1783    ///1784    /// If present, the "else" expr is always `ExprKind::Block` (for `else`) or1785    /// `ExprKind::If` (for `else if`).1786    If(Box<Expr>, Box<Block>, Option<Box<Expr>>),1787    /// A while loop, with an optional label.1788    ///1789    /// `'label: while expr { block }`1790    While(Box<Expr>, Box<Block>, Option<Label>),1791    /// A `for` loop, with an optional label.1792    ///1793    /// `'label: for await? pat in iter { block }`1794    ///1795    /// This is desugared to a combination of `loop` and `match` expressions.1796    ForLoop {1797        pat: Box<Pat>,1798        iter: Box<Expr>,1799        body: Box<Block>,1800        label: Option<Label>,1801        kind: ForLoopKind,1802    },1803    /// Conditionless loop (can be exited with `break`, `continue`, or `return`).1804    ///1805    /// `'label: loop { block }`1806    Loop(Box<Block>, Option<Label>, Span),1807    /// A `match` block.1808    Match(Box<Expr>, ThinVec<Arm>, MatchKind),1809    /// A closure (e.g., `move |a, b, c| a + b + c`).1810    Closure(Box<Closure>),1811    /// A block (`'label: { ... }`).1812    Block(Box<Block>, Option<Label>),1813    /// An `async` block (`async move { ... }`),1814    /// or a `gen` block (`gen move { ... }`).1815    ///1816    /// The span is the "decl", which is the header before the body `{ }`1817    /// including the `async`/`gen` keywords and possibly `move`.1818    Gen(CaptureBy, Box<Block>, GenBlockKind, Span),1819    /// An await expression (`my_future.await`). Span is of await keyword.1820    Await(Box<Expr>, Span),1821    /// A use expression (`x.use`). Span is of use keyword.1822    Use(Box<Expr>, Span),18231824    /// A try block (`try { ... }`), if the type is `None`, or1825    /// A try block (`try bikeshed Ty { ... }`) if the type is `Some`.1826    ///1827    /// Note that `try bikeshed` is a *deliberately ridiculous* placeholder1828    /// syntax to avoid deciding what keyword or symbol should go there.1829    /// It's that way for experimentation only; an RFC to decide the final1830    /// semantics and syntax would be needed to put it on stabilization-track.1831    TryBlock(Box<Block>, Option<Box<Ty>>),18321833    /// An assignment (`a = foo()`).1834    /// The `Span` argument is the span of the `=` token.1835    Assign(Box<Expr>, Box<Expr>, Span),1836    /// An assignment with an operator.1837    ///1838    /// E.g., `a += 1`.1839    AssignOp(AssignOp, Box<Expr>, Box<Expr>),1840    /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.1841    Field(Box<Expr>, Ident),1842    /// An indexing operation (e.g., `foo[2]`).1843    /// The span represents the span of the `[2]`, including brackets.1844    Index(Box<Expr>, Box<Expr>, Span),1845    /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assignment).1846    Range(Option<Box<Expr>>, Option<Box<Expr>>, RangeLimits),1847    /// An underscore, used in destructuring assignment to ignore a value.1848    Underscore,18491850    /// Variable reference, possibly containing `::` and/or type1851    /// parameters (e.g., `foo::bar::<baz>`).1852    ///1853    /// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`).1854    Path(Option<Box<QSelf>>, Path),18551856    /// A referencing operation (`&a`, `&mut a`, `&raw const a` or `&raw mut a`).1857    AddrOf(BorrowKind, Mutability, Box<Expr>),1858    /// A `break`, with an optional label to break, and an optional expression.1859    Break(Option<Label>, Option<Box<Expr>>),1860    /// A `continue`, with an optional label.1861    Continue(Option<Label>),1862    /// A `return`, with an optional value to be returned.1863    Ret(Option<Box<Expr>>),18641865    /// Output of the `asm!()` macro.1866    InlineAsm(Box<InlineAsm>),18671868    /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`).1869    ///1870    /// Usually not written directly in user code but1871    /// indirectly via the macro `core::mem::offset_of!(...)`.1872    OffsetOf(Box<Ty>, Vec<Ident>),18731874    /// A macro invocation; pre-expansion.1875    MacCall(Box<MacCall>),18761877    /// A struct literal expression.1878    ///1879    /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. rest}`.1880    Struct(Box<StructExpr>),18811882    /// An array literal constructed from one repeated element.1883    ///1884    /// E.g., `[1; 5]`. The expression is the element to be1885    /// repeated; the constant is the number of times to repeat it.1886    Repeat(Box<Expr>, AnonConst),18871888    /// No-op: used solely so we can pretty-print faithfully.1889    Paren(Box<Expr>),18901891    /// A try expression (`expr?`).1892    Try(Box<Expr>),18931894    /// A `yield`, with an optional value to be yielded.1895    Yield(YieldKind),18961897    /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),1898    /// with an optional value to be returned.1899    Yeet(Option<Box<Expr>>),19001901    /// A tail call return, with the value to be returned.1902    ///1903    /// While `.0` must be a function call, we check this later, after parsing.1904    Become(Box<Expr>),19051906    /// Bytes included via `include_bytes!`1907    ///1908    /// Added for optimization purposes to avoid the need to escape1909    /// large binary blobs - should always behave like [`ExprKind::Lit`]1910    /// with a `ByteStr` literal.1911    ///1912    /// The value is stored as a `ByteSymbol`. It's unfortunate that we need to1913    /// intern (hash) the bytes because they're likely to be large and unique.1914    /// But it's necessary because this will eventually be lowered to1915    /// `LitKind::ByteStr`, which needs a `ByteSymbol` to impl `Copy` and avoid1916    /// arena allocation.1917    IncludedBytes(ByteSymbol),19181919    /// A `format_args!()` expression.1920    FormatArgs(Box<FormatArgs>),19211922    UnsafeBinderCast(UnsafeBinderCastKind, Box<Expr>, Option<Box<Ty>>),19231924    /// Placeholder for an expression that wasn't syntactically well formed in some way.1925    Err(ErrorGuaranteed),19261927    /// Acts as a null expression. Lowering it will always emit a bug.1928    Dummy,1929}19301931/// Used to differentiate between `for` loops and `for await` loops.1932#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]1933pub enum ForLoopKind {1934    For,1935    ForAwait,1936}19371938/// Used to differentiate between `async {}` blocks and `gen {}` blocks.1939#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]1940pub enum GenBlockKind {1941    Async,1942    Gen,1943    AsyncGen,1944}19451946impl fmt::Display for GenBlockKind {1947    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {1948        self.modifier().fmt(f)1949    }1950}19511952impl GenBlockKind {1953    pub fn modifier(&self) -> &'static str {1954        match self {1955            GenBlockKind::Async => "async",1956            GenBlockKind::Gen => "gen",1957            GenBlockKind::AsyncGen => "async gen",1958        }1959    }1960}19611962/// Whether we're unwrapping or wrapping an unsafe binder1963#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]1964#[derive(Encodable, Decodable, StableHash, Walkable)]1965pub enum UnsafeBinderCastKind {1966    // e.g. `&i32` -> `unsafe<'a> &'a i32`1967    Wrap,1968    // e.g. `unsafe<'a> &'a i32` -> `&i32`1969    Unwrap,1970}19711972/// The explicit `Self` type in a "qualified path". The actual1973/// path, including the trait and the associated item, is stored1974/// separately. `position` represents the index of the associated1975/// item qualified with this `Self` type.1976///1977/// ```ignore (only-for-syntax-highlight)1978/// <Vec<T> as a::b::Trait>::AssociatedItem1979///  ^~~~~     ~~~~~~~~~~~~~~^1980///  ty        position = 31981///1982/// <Vec<T>>::AssociatedItem1983///  ^~~~~    ^1984///  ty       position = 01985/// ```1986#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1987pub struct QSelf {1988    pub ty: Box<Ty>,19891990    /// The span of `a::b::Trait` in a path like `<Vec<T> as1991    /// a::b::Trait>::AssociatedItem`; in the case where `position ==1992    /// 0`, this is an empty span.1993    pub path_span: Span,1994    pub position: usize,1995}19961997/// A capture clause used in closures and `async` blocks.1998#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)]1999pub enum CaptureBy {2000    /// `move |x| y + x`.

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.