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, _, _) = ¤t.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.