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