compiler/rustc_ast/src/ast.rs RUST 4,420 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 4,420.
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_hash::{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::def_id::LocalDefId;34use rustc_span::{35    ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan,36    sym,37};38use thin_vec::{ThinVec, thin_vec};3940use crate::attr::data_structures::CfgEntry;41pub use crate::format::*;42use crate::token::{self, CommentKind, Delimiter};43use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};44use crate::util::parser::{ExprPrecedence, Fixity};45use crate::visit::{AssocCtxt, BoundKind, LifetimeCtxt};4647/// A "Label" is an identifier of some point in sources,48/// e.g. in the following code:49///50/// ```rust51/// 'outer: loop {52///     break 'outer;53/// }54/// ```55///56/// `'outer` is a label.57#[derive(Clone, Encodable, Decodable, Copy, StableHash, Eq, PartialEq, Walkable)]58pub struct Label {59    pub ident: Ident,60}6162impl fmt::Debug for Label {63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {64        write!(f, "label({:?})", self.ident)65    }66}6768/// A "Lifetime" is an annotation of the scope in which variable69/// can be used, e.g. `'a` in `&'a i32`.70#[derive(Clone, Encodable, Decodable, Copy, PartialEq, Eq, Hash, Walkable)]71pub struct Lifetime {72    pub id: NodeId,73    pub ident: Ident,74}7576impl fmt::Debug for Lifetime {77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {78        write!(f, "lifetime({}: {})", self.id, self)79    }80}8182impl fmt::Display for Lifetime {83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {84        write!(f, "{}", self.ident.name)85    }86}8788/// A "Path" is essentially Rust's notion of a name.89///90/// It's represented as a sequence of identifiers,91/// along with a bunch of supporting information.92///93/// E.g., `std::cmp::PartialEq`.94#[derive(Clone, Encodable, Decodable, Debug, Walkable)]95pub struct Path {96    pub span: Span,97    /// The segments in the path: the things separated by `::`.98    /// Global paths begin with `kw::PathRoot`.99    pub segments: ThinVec<PathSegment>,100    pub tokens: Option<LazyAttrTokenStream>,101}102103// Succeeds if the path has a single segment that is arg-free and matches the given symbol.104impl PartialEq<Symbol> for Path {105    #[inline]106    fn eq(&self, name: &Symbol) -> bool {107        if let [segment] = self.segments.as_ref()108            && segment == name109        {110            true111        } else {112            false113        }114    }115}116117// Succeeds if the path has segments that are arg-free and match the given symbols.118impl PartialEq<&[Symbol]> for Path {119    #[inline]120    fn eq(&self, names: &&[Symbol]) -> bool {121        self.segments.iter().eq(*names)122    }123}124125impl StableHash for Path {126    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {127        self.segments.len().stable_hash(hcx, hasher);128        for segment in &self.segments {129            segment.ident.stable_hash(hcx, hasher);130        }131    }132}133134impl Path {135    /// Convert a span and an identifier to the corresponding136    /// one-segment path.137    pub fn from_ident(ident: Ident) -> Path {138        Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }139    }140141    pub fn is_global(&self) -> bool {142        self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)143    }144145    /// Check if this path is potentially a trivial const arg, i.e., one that can _potentially_146    /// be represented without an anon const in the HIR.147    ///148    /// Returns true iff the path has exactly one segment, and it has no generic args149    /// (i.e., it is _potentially_ a const parameter).150    #[tracing::instrument(level = "debug", ret)]151    pub fn is_potential_trivial_const_arg(&self) -> bool {152        self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())153    }154}155156/// Joins multiple symbols with "::" into a path, e.g. "a::b::c". If the first157/// segment is `kw::PathRoot` it will be printed as empty, e.g. "::b::c".158///159/// The generics on the `path` argument mean it can accept many forms, such as:160/// - `&[Symbol]`161/// - `Vec<Symbol>`162/// - `Vec<&Symbol>`163/// - `impl Iterator<Item = Symbol>`164/// - `impl Iterator<Item = &Symbol>`165///166/// Panics if `path` is empty or a segment after the first is `kw::PathRoot`.167pub fn join_path_syms(path: impl IntoIterator<Item = impl Borrow<Symbol>>) -> String {168    // This is a guess at the needed capacity that works well in practice. It is slightly faster169    // than (a) starting with an empty string, or (b) computing the exact capacity required.170    // `8` works well because it's about the right size and jemalloc's size classes are all171    // multiples of 8.172    let mut iter = path.into_iter();173    let len_hint = iter.size_hint().1.unwrap_or(1);174    let mut s = String::with_capacity(len_hint * 8);175176    let first_sym = *iter.next().unwrap().borrow();177    if first_sym != kw::PathRoot {178        s.push_str(first_sym.as_str());179    }180    for sym in iter {181        let sym = *sym.borrow();182        debug_assert_ne!(sym, kw::PathRoot);183        s.push_str("::");184        s.push_str(sym.as_str());185    }186    s187}188189/// Like `join_path_syms`, but for `Ident`s. This function is necessary because190/// `Ident::to_string` does more than just print the symbol in the `name` field.191pub fn join_path_idents(path: impl IntoIterator<Item = impl Borrow<Ident>>) -> String {192    let mut iter = path.into_iter();193    let len_hint = iter.size_hint().1.unwrap_or(1);194    let mut s = String::with_capacity(len_hint * 8);195196    let first_ident = *iter.next().unwrap().borrow();197    if first_ident.name != kw::PathRoot {198        s.push_str(&first_ident.to_string());199    }200    for ident in iter {201        let ident = *ident.borrow();202        debug_assert_ne!(ident.name, kw::PathRoot);203        s.push_str("::");204        s.push_str(&ident.to_string());205    }206    s207}208209/// A segment of a path: an identifier, an optional lifetime, and a set of types.210///211/// E.g., `std`, `String` or `Box<T>`.212#[derive(Clone, Encodable, Decodable, Debug, Walkable)]213pub struct PathSegment {214    /// The identifier portion of this path segment.215    pub ident: Ident,216217    pub id: NodeId,218219    /// Type/lifetime parameters attached to this path. They come in220    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`.221    /// `None` means that no parameter list is supplied (`Path`),222    /// `Some` means that parameter list is supplied (`Path<X, Y>`)223    /// but it can be empty (`Path<>`).224    /// `P` is used as a size optimization for the common case with no parameters.225    pub args: Option<Box<GenericArgs>>,226}227228// Succeeds if the path segment is arg-free and matches the given symbol.229impl PartialEq<Symbol> for PathSegment {230    #[inline]231    fn eq(&self, name: &Symbol) -> bool {232        self.args.is_none() && self.ident.name == *name233    }234}235236impl PathSegment {237    pub fn from_ident(ident: Ident) -> Self {238        PathSegment { ident, id: DUMMY_NODE_ID, args: None }239    }240241    pub fn path_root(span: Span) -> Self {242        PathSegment::from_ident(Ident::new(kw::PathRoot, span))243    }244245    pub fn span(&self) -> Span {246        match &self.args {247            Some(args) => self.ident.span.to(args.span()),248            None => self.ident.span,249        }250    }251}252253/// The generic arguments and associated item constraints of a path segment.254///255/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.256#[derive(Clone, Encodable, Decodable, Debug, Walkable)]257pub enum GenericArgs {258    /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`.259    AngleBracketed(AngleBracketedArgs),260    /// The `(A, B)` and `C` in `Foo(A, B) -> C`.261    Parenthesized(ParenthesizedArgs),262    /// `(..)` in return type notation.263    ParenthesizedElided(Span),264}265266impl GenericArgs {267    pub fn is_angle_bracketed(&self) -> bool {268        matches!(self, AngleBracketed(..))269    }270271    pub fn span(&self) -> Span {272        match self {273            AngleBracketed(data) => data.span,274            Parenthesized(data) => data.span,275            ParenthesizedElided(span) => *span,276        }277    }278}279280/// Concrete argument in the sequence of generic args.281#[derive(Clone, Encodable, Decodable, Debug, Walkable)]282pub enum GenericArg {283    /// `'a` in `Foo<'a>`.284    Lifetime(#[visitable(extra = LifetimeCtxt::GenericArg)] Lifetime),285    /// `Bar` in `Foo<Bar>`.286    Type(Box<Ty>),287    /// `1` in `Foo<1>`.288    Const(AnonConst),289}290291impl GenericArg {292    pub fn span(&self) -> Span {293        match self {294            GenericArg::Lifetime(lt) => lt.ident.span,295            GenericArg::Type(ty) => ty.span,296            GenericArg::Const(ct) => ct.value.span,297        }298    }299}300301/// A path like `Foo<'a, T>`.302#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]303pub struct AngleBracketedArgs {304    /// The overall span.305    pub span: Span,306    /// The comma separated parts in the `<...>`.307    pub args: ThinVec<AngleBracketedArg>,308}309310/// Either an argument for a generic parameter or a constraint on an associated item.311#[derive(Clone, Encodable, Decodable, Debug, Walkable)]312pub enum AngleBracketedArg {313    /// A generic argument for a generic parameter.314    Arg(GenericArg),315    /// A constraint on an associated item.316    Constraint(AssocItemConstraint),317}318319impl AngleBracketedArg {320    pub fn span(&self) -> Span {321        match self {322            AngleBracketedArg::Arg(arg) => arg.span(),323            AngleBracketedArg::Constraint(constraint) => constraint.span,324        }325    }326}327328impl From<AngleBracketedArgs> for Box<GenericArgs> {329    fn from(val: AngleBracketedArgs) -> Self {330        Box::new(GenericArgs::AngleBracketed(val))331    }332}333334impl From<ParenthesizedArgs> for Box<GenericArgs> {335    fn from(val: ParenthesizedArgs) -> Self {336        Box::new(GenericArgs::Parenthesized(val))337    }338}339340/// A path like `Foo(A, B) -> C`.341#[derive(Clone, Encodable, Decodable, Debug, Walkable)]342pub struct ParenthesizedArgs {343    /// ```text344    /// Foo(A, B) -> C345    /// ^^^^^^^^^^^^^^346    /// ```347    pub span: Span,348349    /// `(A, B)`350    pub inputs: ThinVec<Box<Ty>>,351352    /// ```text353    /// Foo(A, B) -> C354    ///    ^^^^^^355    /// ```356    pub inputs_span: Span,357358    /// `C`359    pub output: FnRetTy,360}361362impl ParenthesizedArgs {363    pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {364        let args = self365            .inputs366            .iter()367            .cloned()368            .map(|input| AngleBracketedArg::Arg(GenericArg::Type(input)))369            .collect();370        AngleBracketedArgs { span: self.inputs_span, args }371    }372}373374pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId};375376/// Modifiers on a trait bound like `[const]`, `?` and `!`.377#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Walkable)]378pub struct TraitBoundModifiers {379    pub constness: BoundConstness,380    pub asyncness: BoundAsyncness,381    pub polarity: BoundPolarity,382}383384impl TraitBoundModifiers {385    pub const NONE: Self = Self {386        constness: BoundConstness::Never,387        asyncness: BoundAsyncness::Normal,388        polarity: BoundPolarity::Positive,389    };390}391392#[derive(Clone, Encodable, Decodable, Debug, Walkable)]393pub enum GenericBound {394    Trait(PolyTraitRef),395    Outlives(#[visitable(extra = LifetimeCtxt::Bound)] Lifetime),396    /// Precise capturing syntax: `impl Sized + use<'a>`397    Use(ThinVec<PreciseCapturingArg>, Span),398}399400impl GenericBound {401    pub fn span(&self) -> Span {402        match self {403            GenericBound::Trait(t, ..) => t.span,404            GenericBound::Outlives(l) => l.ident.span,405            GenericBound::Use(_, span) => *span,406        }407    }408}409410pub type GenericBounds = Vec<GenericBound>;411412/// Specifies the enforced ordering for generic parameters. In the future,413/// if we wanted to relax this order, we could override `PartialEq` and414/// `PartialOrd`, to allow the kinds to be unordered.415#[derive(Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]416pub enum ParamKindOrd {417    Lifetime,418    TypeOrConst,419}420421impl fmt::Display for ParamKindOrd {422    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {423        match self {424            ParamKindOrd::Lifetime => "lifetime".fmt(f),425            ParamKindOrd::TypeOrConst => "type and const".fmt(f),426        }427    }428}429430#[derive(Clone, Encodable, Decodable, Debug, Walkable)]431pub enum GenericParamKind {432    /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).433    Lifetime,434    Type {435        default: Option<Box<Ty>>,436    },437    Const {438        ty: Box<Ty>,439        /// Span of the whole parameter definition, including default.440        span: Span,441        /// Optional default value for the const generic param.442        default: Option<AnonConst>,443    },444}445446#[derive(Clone, Encodable, Decodable, Debug, Walkable)]447pub struct GenericParam {448    pub id: NodeId,449    pub ident: Ident,450    pub attrs: AttrVec,451    #[visitable(extra = BoundKind::Bound)]452    pub bounds: GenericBounds,453    pub is_placeholder: bool,454    pub kind: GenericParamKind,455    pub colon_span: Option<Span>,456}457458impl GenericParam {459    pub fn span(&self) -> Span {460        match &self.kind {461            GenericParamKind::Lifetime | GenericParamKind::Type { default: None } => {462                self.ident.span463            }464            GenericParamKind::Type { default: Some(ty) } => self.ident.span.to(ty.span),465            GenericParamKind::Const { span, .. } => *span,466        }467    }468}469470/// Represents lifetime, type and const parameters attached to a declaration of471/// a function, enum, trait, etc.472#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]473pub struct Generics {474    pub params: ThinVec<GenericParam>,475    pub where_clause: WhereClause,476    pub span: Span,477}478479/// A where-clause in a definition.480#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]481pub struct WhereClause {482    /// `true` if we ate a `where` token.483    ///484    /// This can happen if we parsed no predicates, e.g., `struct Foo where {}`.485    /// This allows us to pretty-print accurately and provide correct suggestion diagnostics.486    pub has_where_token: bool,487    pub predicates: ThinVec<WherePredicate>,488    pub span: Span,489}490491impl WhereClause {492    pub fn is_empty(&self) -> bool {493        !self.has_where_token && self.predicates.is_empty()494    }495}496497/// A single predicate in a where-clause.498#[derive(Clone, Encodable, Decodable, Debug, Walkable)]499pub struct WherePredicate {500    pub attrs: AttrVec,501    pub kind: WherePredicateKind,502    pub id: NodeId,503    pub span: Span,504    pub is_placeholder: bool,505}506507/// Predicate kind in where-clause.508#[derive(Clone, Encodable, Decodable, Debug, Walkable)]509pub enum WherePredicateKind {510    /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).511    BoundPredicate(WhereBoundPredicate),512    /// A lifetime predicate (e.g., `'a: 'b + 'c`).513    RegionPredicate(WhereRegionPredicate),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) => match closure.fn_decl.output {1561                FnRetTy::Default(_) => ExprPrecedence::Jump,1562                FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),1563            },15641565            ExprKind::Break(_ /*label*/, value)1566            | ExprKind::Ret(value)1567            | ExprKind::Yield(YieldKind::Prefix(value))1568            | ExprKind::Yeet(value) => match value {1569                Some(_) => ExprPrecedence::Jump,1570                None => prefix_attrs_precedence(&self.attrs),1571            },15721573            ExprKind::Become(_) => ExprPrecedence::Jump,15741575            // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to1576            // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence1577            // ensures that `pprust` will add parentheses in the right places to get the desired1578            // parse.1579            ExprKind::Range(..) => ExprPrecedence::Range,15801581            // Binop-like expr kinds, handled by `AssocOp`.1582            ExprKind::Binary(op, ..) => op.node.precedence(),1583            ExprKind::Cast(..) => ExprPrecedence::Cast,15841585            ExprKind::Assign(..) | ExprKind::AssignOp(..) => ExprPrecedence::Assign,15861587            // Unary, prefix1588            ExprKind::AddrOf(..) => ExprPrecedence::Prefix,15891590            // Here `let pats = expr` has `let pats =` as a "unary" prefix of `expr`.1591            // However, this is not exactly right. When `let _ = a` is the LHS of a binop we1592            // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b`1593            // but we need to print `(let _ = a) < b` as-is with parens.1594            ExprKind::Let(..) | ExprKind::Move(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix,15951596            // Need parens if and only if there are prefix attributes.1597            ExprKind::Array(_)1598            | ExprKind::Await(..)1599            | ExprKind::Use(..)1600            | ExprKind::Block(..)1601            | ExprKind::Call(..)1602            | ExprKind::ConstBlock(_)1603            | ExprKind::Continue(..)1604            | ExprKind::Field(..)1605            | ExprKind::ForLoop { .. }1606            | ExprKind::FormatArgs(..)1607            | ExprKind::Gen(..)1608            | ExprKind::If(..)1609            | ExprKind::IncludedBytes(..)1610            | ExprKind::Index(..)1611            | ExprKind::InlineAsm(..)1612            | ExprKind::Lit(_)1613            | ExprKind::Loop(..)1614            | ExprKind::MacCall(..)1615            | ExprKind::Match(..)1616            | ExprKind::MethodCall(..)1617            | ExprKind::OffsetOf(..)1618            | ExprKind::Paren(..)1619            | ExprKind::Path(..)1620            | ExprKind::Repeat(..)1621            | ExprKind::Struct(..)1622            | ExprKind::Try(..)1623            | ExprKind::TryBlock(..)1624            | ExprKind::Tup(_)1625            | ExprKind::Type(..)1626            | ExprKind::Underscore1627            | ExprKind::UnsafeBinderCast(..)1628            | ExprKind::While(..)1629            | ExprKind::Yield(YieldKind::Postfix(..))1630            | ExprKind::Err(_)1631            | ExprKind::Dummy => prefix_attrs_precedence(&self.attrs),1632        }1633    }16341635    /// To a first-order approximation, is this a pattern?1636    pub fn is_approximately_pattern(&self) -> bool {1637        matches!(1638            &self.peel_parens().kind,1639            ExprKind::Array(_)1640                | ExprKind::Call(_, _)1641                | ExprKind::Tup(_)1642                | ExprKind::Lit(_)1643                | ExprKind::Range(_, _, _)1644                | ExprKind::Underscore1645                | ExprKind::Path(_, _)1646                | ExprKind::Struct(_)1647        )1648    }16491650    /// Creates a dummy `Expr`.1651    ///1652    /// Should only be used when it will be replaced afterwards or as a return value when an error was encountered.1653    pub fn dummy() -> Expr {1654        Expr {1655            id: DUMMY_NODE_ID,1656            kind: ExprKind::Dummy,1657            span: DUMMY_SP,1658            attrs: ThinVec::new(),1659            tokens: None,1660        }1661    }1662}16631664impl From<Box<Expr>> for Expr {1665    fn from(value: Box<Expr>) -> Self {1666        *value1667    }1668}16691670#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1671pub struct Closure {1672    pub binder: ClosureBinder,1673    pub capture_clause: CaptureBy,1674    pub constness: Const,1675    pub coroutine_kind: Option<CoroutineKind>,1676    pub movability: Movability,1677    pub fn_decl: Box<FnDecl>,1678    pub body: Box<Expr>,1679    /// The span of the declaration block: 'move |...| -> ...'1680    pub fn_decl_span: Span,1681    /// The span of the argument block `|...|`1682    pub fn_arg_span: Span,1683}16841685/// Limit types of a range (inclusive or exclusive).1686#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, Walkable)]1687pub enum RangeLimits {1688    /// Inclusive at the beginning, exclusive at the end.1689    HalfOpen,1690    /// Inclusive at the beginning and end.1691    Closed,1692}16931694impl RangeLimits {1695    pub fn as_str(&self) -> &'static str {1696        match self {1697            RangeLimits::HalfOpen => "..",1698            RangeLimits::Closed => "..=",1699        }1700    }1701}17021703/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).1704#[derive(Clone, Encodable, Decodable, Debug)]1705pub struct MethodCall {1706    /// The method name and its generic arguments, e.g. `foo::<Bar, Baz>`.1707    pub seg: PathSegment,1708    /// The receiver, e.g. `x`.1709    pub receiver: Box<Expr>,1710    /// The arguments, e.g. `a, b, c`.1711    pub args: ThinVec<Box<Expr>>,1712    /// The span of the function, without the dot and receiver e.g. `foo::<Bar,1713    /// Baz>(a, b, c)`.1714    pub span: Span,1715}17161717#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1718pub enum StructRest {1719    /// `..x`.1720    Base(Box<Expr>),1721    /// `..`.1722    Rest(Span),1723    /// No trailing `..` or expression.1724    None,1725    /// No trailing `..` or expression, and also, a parse error occurred inside the struct braces.1726    ///1727    /// This struct should be treated similarly to as if it had an `..` in it,1728    /// in particular rather than reporting missing fields, because the parse error1729    /// makes which fields the struct was intended to have not fully known.1730    NoneWithError(ErrorGuaranteed),1731}17321733#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1734pub struct StructExpr {1735    pub qself: Option<Box<QSelf>>,1736    pub path: Path,1737    pub fields: ThinVec<ExprField>,1738    pub rest: StructRest,1739}17401741// Adding a new variant? Please update `test_expr` in `tests/ui/macros/stringify.rs`.1742#[derive(Clone, Encodable, Decodable, Debug)]1743pub enum ExprKind {1744    /// An array (e.g, `[a, b, c, d]`).1745    Array(ThinVec<Box<Expr>>),1746    /// Allow anonymous constants from an inline `const` block.1747    ConstBlock(AnonConst),1748    /// A function call.1749    ///1750    /// The first field resolves to the function itself,1751    /// and the second field is the list of arguments.1752    /// This also represents calling the constructor of1753    /// tuple-like ADTs such as tuple structs and enum variants.1754    Call(Box<Expr>, ThinVec<Box<Expr>>),1755    /// A method call (e.g., `x.foo::<Bar, Baz>(a, b, c)`).1756    MethodCall(Box<MethodCall>),1757    /// A tuple (e.g., `(a, b, c, d)`).1758    Tup(ThinVec<Box<Expr>>),1759    /// A binary operation (e.g., `a + b`, `a * b`).1760    Binary(BinOp, Box<Expr>, Box<Expr>),1761    /// A unary operation (e.g., `!x`, `*x`).1762    Unary(UnOp, Box<Expr>),1763    /// A `move(expr)` expression.1764    Move(Box<Expr>, Span),1765    /// A literal (e.g., `1`, `"foo"`).1766    Lit(token::Lit),1767    /// A cast (e.g., `foo as f64`).1768    Cast(Box<Expr>, Box<Ty>),1769    /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`).1770    ///1771    /// Usually not written directly in user code but1772    /// indirectly via the macro `type_ascribe!(...)`.1773    Type(Box<Expr>, Box<Ty>),1774    /// A `let pat = expr` expression that is only semantically allowed in the condition1775    /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).1776    ///1777    /// `Span` represents the whole `let pat = expr` statement.1778    Let(Box<Pat>, Box<Expr>, Span, Recovered),1779    /// An `if` block, with an optional `else` block.1780    ///1781    /// `if expr { block } else { expr }`1782    ///1783    /// If present, the "else" expr is always `ExprKind::Block` (for `else`) or1784    /// `ExprKind::If` (for `else if`).1785    If(Box<Expr>, Box<Block>, Option<Box<Expr>>),1786    /// A while loop, with an optional label.1787    ///1788    /// `'label: while expr { block }`1789    While(Box<Expr>, Box<Block>, Option<Label>),1790    /// A `for` loop, with an optional label.1791    ///1792    /// `'label: for await? pat in iter { block }`1793    ///1794    /// This is desugared to a combination of `loop` and `match` expressions.1795    ForLoop {1796        pat: Box<Pat>,1797        iter: Box<Expr>,1798        body: Box<Block>,1799        label: Option<Label>,1800        kind: ForLoopKind,1801    },1802    /// Conditionless loop (can be exited with `break`, `continue`, or `return`).1803    ///1804    /// `'label: loop { block }`1805    Loop(Box<Block>, Option<Label>, Span),1806    /// A `match` block.1807    Match(Box<Expr>, ThinVec<Arm>, MatchKind),1808    /// A closure (e.g., `move |a, b, c| a + b + c`).1809    Closure(Box<Closure>),1810    /// A block (`'label: { ... }`).1811    Block(Box<Block>, Option<Label>),1812    /// An `async` block (`async move { ... }`),1813    /// or a `gen` block (`gen move { ... }`).1814    ///1815    /// The span is the "decl", which is the header before the body `{ }`1816    /// including the `async`/`gen` keywords and possibly `move`.1817    Gen(CaptureBy, Box<Block>, GenBlockKind, Span),1818    /// An await expression (`my_future.await`). Span is of await keyword.1819    Await(Box<Expr>, Span),1820    /// A use expression (`x.use`). Span is of use keyword.1821    Use(Box<Expr>, Span),18221823    /// A try block (`try { ... }`), if the type is `None`, or1824    /// A try block (`try bikeshed Ty { ... }`) if the type is `Some`.1825    ///1826    /// Note that `try bikeshed` is a *deliberately ridiculous* placeholder1827    /// syntax to avoid deciding what keyword or symbol should go there.1828    /// It's that way for experimentation only; an RFC to decide the final1829    /// semantics and syntax would be needed to put it on stabilization-track.1830    TryBlock(Box<Block>, Option<Box<Ty>>),18311832    /// An assignment (`a = foo()`).1833    /// The `Span` argument is the span of the `=` token.1834    Assign(Box<Expr>, Box<Expr>, Span),1835    /// An assignment with an operator.1836    ///1837    /// E.g., `a += 1`.1838    AssignOp(AssignOp, Box<Expr>, Box<Expr>),1839    /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.1840    Field(Box<Expr>, Ident),1841    /// An indexing operation (e.g., `foo[2]`).1842    /// The span represents the span of the `[2]`, including brackets.1843    Index(Box<Expr>, Box<Expr>, Span),1844    /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assignment).1845    Range(Option<Box<Expr>>, Option<Box<Expr>>, RangeLimits),1846    /// An underscore, used in destructuring assignment to ignore a value.1847    Underscore,18481849    /// Variable reference, possibly containing `::` and/or type1850    /// parameters (e.g., `foo::bar::<baz>`).1851    ///1852    /// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`).1853    Path(Option<Box<QSelf>>, Path),18541855    /// A referencing operation (`&a`, `&mut a`, `&raw const a` or `&raw mut a`).1856    AddrOf(BorrowKind, Mutability, Box<Expr>),1857    /// A `break`, with an optional label to break, and an optional expression.1858    Break(Option<Label>, Option<Box<Expr>>),1859    /// A `continue`, with an optional label.1860    Continue(Option<Label>),1861    /// A `return`, with an optional value to be returned.1862    Ret(Option<Box<Expr>>),18631864    /// Output of the `asm!()` macro.1865    InlineAsm(Box<InlineAsm>),18661867    /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`).1868    ///1869    /// Usually not written directly in user code but1870    /// indirectly via the macro `core::mem::offset_of!(...)`.1871    OffsetOf(Box<Ty>, Vec<Ident>),18721873    /// A macro invocation; pre-expansion.1874    MacCall(Box<MacCall>),18751876    /// A struct literal expression.1877    ///1878    /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. rest}`.1879    Struct(Box<StructExpr>),18801881    /// An array literal constructed from one repeated element.1882    ///1883    /// E.g., `[1; 5]`. The expression is the element to be1884    /// repeated; the constant is the number of times to repeat it.1885    Repeat(Box<Expr>, AnonConst),18861887    /// No-op: used solely so we can pretty-print faithfully.1888    Paren(Box<Expr>),18891890    /// A try expression (`expr?`).1891    Try(Box<Expr>),18921893    /// A `yield`, with an optional value to be yielded.1894    Yield(YieldKind),18951896    /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),1897    /// with an optional value to be returned.1898    Yeet(Option<Box<Expr>>),18991900    /// A tail call return, with the value to be returned.1901    ///1902    /// While `.0` must be a function call, we check this later, after parsing.1903    Become(Box<Expr>),19041905    /// Bytes included via `include_bytes!`1906    ///1907    /// Added for optimization purposes to avoid the need to escape1908    /// large binary blobs - should always behave like [`ExprKind::Lit`]1909    /// with a `ByteStr` literal.1910    ///1911    /// The value is stored as a `ByteSymbol`. It's unfortunate that we need to1912    /// intern (hash) the bytes because they're likely to be large and unique.1913    /// But it's necessary because this will eventually be lowered to1914    /// `LitKind::ByteStr`, which needs a `ByteSymbol` to impl `Copy` and avoid1915    /// arena allocation.1916    IncludedBytes(ByteSymbol),19171918    /// A `format_args!()` expression.1919    FormatArgs(Box<FormatArgs>),19201921    UnsafeBinderCast(UnsafeBinderCastKind, Box<Expr>, Option<Box<Ty>>),19221923    /// Placeholder for an expression that wasn't syntactically well formed in some way.1924    Err(ErrorGuaranteed),19251926    /// Acts as a null expression. Lowering it will always emit a bug.1927    Dummy,1928}19291930/// Used to differentiate between `for` loops and `for await` loops.1931#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]1932pub enum ForLoopKind {1933    For,1934    ForAwait,1935}19361937/// Used to differentiate between `async {}` blocks and `gen {}` blocks.1938#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]1939pub enum GenBlockKind {1940    Async,1941    Gen,1942    AsyncGen,1943}19441945impl fmt::Display for GenBlockKind {1946    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {1947        self.modifier().fmt(f)1948    }1949}19501951impl GenBlockKind {1952    pub fn modifier(&self) -> &'static str {1953        match self {1954            GenBlockKind::Async => "async",1955            GenBlockKind::Gen => "gen",1956            GenBlockKind::AsyncGen => "async gen",1957        }1958    }1959}19601961/// Whether we're unwrapping or wrapping an unsafe binder1962#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]1963#[derive(Encodable, Decodable, StableHash, Walkable)]1964pub enum UnsafeBinderCastKind {1965    // e.g. `&i32` -> `unsafe<'a> &'a i32`1966    Wrap,1967    // e.g. `unsafe<'a> &'a i32` -> `&i32`1968    Unwrap,1969}19701971/// The explicit `Self` type in a "qualified path". The actual1972/// path, including the trait and the associated item, is stored1973/// separately. `position` represents the index of the associated1974/// item qualified with this `Self` type.1975///1976/// ```ignore (only-for-syntax-highlight)1977/// <Vec<T> as a::b::Trait>::AssociatedItem1978///  ^~~~~     ~~~~~~~~~~~~~~^1979///  ty        position = 31980///1981/// <Vec<T>>::AssociatedItem1982///  ^~~~~    ^1983///  ty       position = 01984/// ```1985#[derive(Clone, Encodable, Decodable, Debug, Walkable)]1986pub struct QSelf {1987    pub ty: Box<Ty>,19881989    /// The span of `a::b::Trait` in a path like `<Vec<T> as1990    /// a::b::Trait>::AssociatedItem`; in the case where `position ==1991    /// 0`, this is an empty span.1992    pub path_span: Span,1993    pub position: usize,1994}19951996/// A capture clause used in closures and `async` blocks.1997#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, StableHash, Walkable)]1998pub enum CaptureBy {1999    /// `move |x| y + x`.2000    Value {

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.