1use std::fmt;
2
3use rustc_abi::ExternAbi;
4use rustc_ast::attr::AttributeExt;
6use rustc_ast::token::CommentKind;
7use rustc_ast::util::parser::{AssocOp, ExprPrecedence};
8use rustc_ast::{
9 self as ast, AttrId, AttrStyle, DelimArgs, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece,
10 IntTy, Label, LitIntType, LitKind, MetaItemInner, MetaItemLit, TraitObjectSyntax, UintTy,
11};
12pub use rustc_ast::{
13 BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
14 ImplPolarity, IsAuto, Movability, Mutability, UnOp, UnsafeBinderCastKind,
15};
16use rustc_data_structures::fingerprint::Fingerprint;
17use rustc_data_structures::sorted_map::SortedMap;
18use rustc_data_structures::tagged_ptr::TaggedRef;
19use rustc_index::IndexVec;
20use rustc_macros::{Decodable, Encodable, HashStable_Generic};
21use rustc_span::def_id::LocalDefId;
22use rustc_span::hygiene::MacroKind;
23use rustc_span::source_map::Spanned;
24use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
25use rustc_target::asm::InlineAsmRegOrRegClass;
26use smallvec::SmallVec;
27use thin_vec::ThinVec;
28use tracing::debug;
29
30use crate::LangItem;
31use crate::def::{CtorKind, DefKind, Res};
32use crate::def_id::{DefId, LocalDefIdMap};
33pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
34use crate::intravisit::{FnKind, VisitorExt};
35
36#[derive(Debug, Copy, Clone, HashStable_Generic)]
37pub struct Lifetime {
38 #[stable_hasher(ignore)]
39 pub hir_id: HirId,
40
41 pub ident: Ident,
47
48 pub res: LifetimeName,
50}
51
52#[derive(Debug, Copy, Clone, HashStable_Generic)]
53pub enum ParamName {
54 Plain(Ident),
56
57 Error(Ident),
63
64 Fresh,
79}
80
81impl ParamName {
82 pub fn ident(&self) -> Ident {
83 match *self {
84 ParamName::Plain(ident) | ParamName::Error(ident) => ident,
85 ParamName::Fresh => Ident::with_dummy_span(kw::UnderscoreLifetime),
86 }
87 }
88}
89
90#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
91pub enum LifetimeName {
92 Param(LocalDefId),
94
95 ImplicitObjectLifetimeDefault,
107
108 Error,
111
112 Infer,
115
116 Static,
118}
119
120impl LifetimeName {
121 fn is_elided(&self) -> bool {
122 match self {
123 LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
124
125 LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false,
130 }
131 }
132}
133
134impl fmt::Display for Lifetime {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) }
137 }
138}
139
140pub enum LifetimeSuggestionPosition {
141 Normal,
143 Ampersand,
145 ElidedPath,
147 ElidedPathArgument,
149 ObjectDefault,
151}
152
153impl Lifetime {
154 pub fn is_elided(&self) -> bool {
155 self.res.is_elided()
156 }
157
158 pub fn is_anonymous(&self) -> bool {
159 self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime
160 }
161
162 pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
163 if self.ident.name == kw::Empty {
164 if self.ident.span.is_empty() {
165 (LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span)
166 } else {
167 (LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi())
168 }
169 } else if self.res == LifetimeName::ImplicitObjectLifetimeDefault {
170 (LifetimeSuggestionPosition::ObjectDefault, self.ident.span)
171 } else if self.ident.span.is_empty() {
172 (LifetimeSuggestionPosition::Ampersand, self.ident.span)
173 } else {
174 (LifetimeSuggestionPosition::Normal, self.ident.span)
175 }
176 }
177
178 pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
179 debug_assert!(new_lifetime.starts_with('\''));
180 let (pos, span) = self.suggestion_position();
181 let code = match pos {
182 LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"),
183 LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "),
184 LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"),
185 LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "),
186 LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"),
187 };
188 (span, code)
189 }
190}
191
192#[derive(Debug, Clone, Copy, HashStable_Generic)]
196pub struct Path<'hir, R = Res> {
197 pub span: Span,
198 pub res: R,
200 pub segments: &'hir [PathSegment<'hir>],
202}
203
204pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
206
207impl Path<'_> {
208 pub fn is_global(&self) -> bool {
209 self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
210 }
211}
212
213#[derive(Debug, Clone, Copy, HashStable_Generic)]
216pub struct PathSegment<'hir> {
217 pub ident: Ident,
219 #[stable_hasher(ignore)]
220 pub hir_id: HirId,
221 pub res: Res,
222
223 pub args: Option<&'hir GenericArgs<'hir>>,
229
230 pub infer_args: bool,
235}
236
237impl<'hir> PathSegment<'hir> {
238 pub fn new(ident: Ident, hir_id: HirId, res: Res) -> PathSegment<'hir> {
240 PathSegment { ident, hir_id, res, infer_args: true, args: None }
241 }
242
243 pub fn invalid() -> Self {
244 Self::new(Ident::empty(), HirId::INVALID, Res::Err)
245 }
246
247 pub fn args(&self) -> &GenericArgs<'hir> {
248 if let Some(ref args) = self.args {
249 args
250 } else {
251 const DUMMY: &GenericArgs<'_> = &GenericArgs::none();
252 DUMMY
253 }
254 }
255}
256
257#[derive(Clone, Copy, Debug, HashStable_Generic)]
273#[repr(C)]
274pub struct ConstArg<'hir, Unambig = ()> {
275 #[stable_hasher(ignore)]
276 pub hir_id: HirId,
277 pub kind: ConstArgKind<'hir, Unambig>,
278}
279
280impl<'hir> ConstArg<'hir, AmbigArg> {
281 pub fn as_unambig_ct(&self) -> &ConstArg<'hir> {
292 let ptr = self as *const ConstArg<'hir, AmbigArg> as *const ConstArg<'hir, ()>;
295 unsafe { &*ptr }
296 }
297}
298
299impl<'hir> ConstArg<'hir> {
300 pub fn try_as_ambig_ct(&self) -> Option<&ConstArg<'hir, AmbigArg>> {
306 if let ConstArgKind::Infer(_, ()) = self.kind {
307 return None;
308 }
309
310 let ptr = self as *const ConstArg<'hir> as *const ConstArg<'hir, AmbigArg>;
314 Some(unsafe { &*ptr })
315 }
316}
317
318impl<'hir, Unambig> ConstArg<'hir, Unambig> {
319 pub fn anon_const_hir_id(&self) -> Option<HirId> {
320 match self.kind {
321 ConstArgKind::Anon(ac) => Some(ac.hir_id),
322 _ => None,
323 }
324 }
325
326 pub fn span(&self) -> Span {
327 match self.kind {
328 ConstArgKind::Path(path) => path.span(),
329 ConstArgKind::Anon(anon) => anon.span,
330 ConstArgKind::Infer(span, _) => span,
331 }
332 }
333}
334
335#[derive(Clone, Copy, Debug, HashStable_Generic)]
337#[repr(u8, C)]
338pub enum ConstArgKind<'hir, Unambig = ()> {
339 Path(QPath<'hir>),
345 Anon(&'hir AnonConst),
346 Infer(Span, Unambig),
349}
350
351#[derive(Clone, Copy, Debug, HashStable_Generic)]
352pub struct InferArg {
353 #[stable_hasher(ignore)]
354 pub hir_id: HirId,
355 pub span: Span,
356}
357
358impl InferArg {
359 pub fn to_ty(&self) -> Ty<'static> {
360 Ty { kind: TyKind::Infer(()), span: self.span, hir_id: self.hir_id }
361 }
362}
363
364#[derive(Debug, Clone, Copy, HashStable_Generic)]
365pub enum GenericArg<'hir> {
366 Lifetime(&'hir Lifetime),
367 Type(&'hir Ty<'hir, AmbigArg>),
368 Const(&'hir ConstArg<'hir, AmbigArg>),
369 Infer(InferArg),
379}
380
381impl GenericArg<'_> {
382 pub fn span(&self) -> Span {
383 match self {
384 GenericArg::Lifetime(l) => l.ident.span,
385 GenericArg::Type(t) => t.span,
386 GenericArg::Const(c) => c.span(),
387 GenericArg::Infer(i) => i.span,
388 }
389 }
390
391 pub fn hir_id(&self) -> HirId {
392 match self {
393 GenericArg::Lifetime(l) => l.hir_id,
394 GenericArg::Type(t) => t.hir_id,
395 GenericArg::Const(c) => c.hir_id,
396 GenericArg::Infer(i) => i.hir_id,
397 }
398 }
399
400 pub fn descr(&self) -> &'static str {
401 match self {
402 GenericArg::Lifetime(_) => "lifetime",
403 GenericArg::Type(_) => "type",
404 GenericArg::Const(_) => "constant",
405 GenericArg::Infer(_) => "placeholder",
406 }
407 }
408
409 pub fn to_ord(&self) -> ast::ParamKindOrd {
410 match self {
411 GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
412 GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => {
413 ast::ParamKindOrd::TypeOrConst
414 }
415 }
416 }
417
418 pub fn is_ty_or_const(&self) -> bool {
419 match self {
420 GenericArg::Lifetime(_) => false,
421 GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true,
422 }
423 }
424}
425
426#[derive(Debug, Clone, Copy, HashStable_Generic)]
428pub struct GenericArgs<'hir> {
429 pub args: &'hir [GenericArg<'hir>],
431 pub constraints: &'hir [AssocItemConstraint<'hir>],
433 pub parenthesized: GenericArgsParentheses,
438 pub span_ext: Span,
451}
452
453impl<'hir> GenericArgs<'hir> {
454 pub const fn none() -> Self {
455 Self {
456 args: &[],
457 constraints: &[],
458 parenthesized: GenericArgsParentheses::No,
459 span_ext: DUMMY_SP,
460 }
461 }
462
463 pub fn paren_sugar_inputs_output(&self) -> Option<(&[Ty<'hir>], &Ty<'hir>)> {
468 if self.parenthesized != GenericArgsParentheses::ParenSugar {
469 return None;
470 }
471
472 let inputs = self
473 .args
474 .iter()
475 .find_map(|arg| {
476 let GenericArg::Type(ty) = arg else { return None };
477 let TyKind::Tup(tys) = &ty.kind else { return None };
478 Some(tys)
479 })
480 .unwrap();
481
482 Some((inputs, self.paren_sugar_output_inner()))
483 }
484
485 pub fn paren_sugar_output(&self) -> Option<&Ty<'hir>> {
490 (self.parenthesized == GenericArgsParentheses::ParenSugar)
491 .then(|| self.paren_sugar_output_inner())
492 }
493
494 fn paren_sugar_output_inner(&self) -> &Ty<'hir> {
495 let [constraint] = self.constraints.try_into().unwrap();
496 debug_assert_eq!(constraint.ident.name, sym::Output);
497 constraint.ty().unwrap()
498 }
499
500 pub fn has_err(&self) -> Option<ErrorGuaranteed> {
501 self.args
502 .iter()
503 .find_map(|arg| {
504 let GenericArg::Type(ty) = arg else { return None };
505 let TyKind::Err(guar) = ty.kind else { return None };
506 Some(guar)
507 })
508 .or_else(|| {
509 self.constraints.iter().find_map(|constraint| {
510 let TyKind::Err(guar) = constraint.ty()?.kind else { return None };
511 Some(guar)
512 })
513 })
514 }
515
516 #[inline]
517 pub fn num_lifetime_params(&self) -> usize {
518 self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count()
519 }
520
521 #[inline]
522 pub fn has_lifetime_params(&self) -> bool {
523 self.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
524 }
525
526 #[inline]
527 pub fn num_generic_params(&self) -> usize {
530 self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
531 }
532
533 pub fn span(&self) -> Option<Span> {
539 let span_ext = self.span_ext()?;
540 Some(span_ext.with_lo(span_ext.lo() + BytePos(1)).with_hi(span_ext.hi() - BytePos(1)))
541 }
542
543 pub fn span_ext(&self) -> Option<Span> {
545 Some(self.span_ext).filter(|span| !span.is_empty())
546 }
547
548 pub fn is_empty(&self) -> bool {
549 self.args.is_empty()
550 }
551}
552
553#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
554pub enum GenericArgsParentheses {
555 No,
556 ReturnTypeNotation,
559 ParenSugar,
561}
562
563#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
565pub struct TraitBoundModifiers {
566 pub constness: BoundConstness,
567 pub polarity: BoundPolarity,
568}
569
570impl TraitBoundModifiers {
571 pub const NONE: Self =
572 TraitBoundModifiers { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
573}
574
575#[derive(Clone, Copy, Debug, HashStable_Generic)]
576pub enum GenericBound<'hir> {
577 Trait(PolyTraitRef<'hir>),
578 Outlives(&'hir Lifetime),
579 Use(&'hir [PreciseCapturingArg<'hir>], Span),
580}
581
582impl GenericBound<'_> {
583 pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
584 match self {
585 GenericBound::Trait(data) => Some(&data.trait_ref),
586 _ => None,
587 }
588 }
589
590 pub fn span(&self) -> Span {
591 match self {
592 GenericBound::Trait(t, ..) => t.span,
593 GenericBound::Outlives(l) => l.ident.span,
594 GenericBound::Use(_, span) => *span,
595 }
596 }
597}
598
599pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
600
601#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic, Debug)]
602pub enum MissingLifetimeKind {
603 Underscore,
605 Ampersand,
607 Comma,
609 Brackets,
611}
612
613#[derive(Copy, Clone, Debug, HashStable_Generic)]
614pub enum LifetimeParamKind {
615 Explicit,
618
619 Elided(MissingLifetimeKind),
622
623 Error,
625}
626
627#[derive(Debug, Clone, Copy, HashStable_Generic)]
628pub enum GenericParamKind<'hir> {
629 Lifetime {
631 kind: LifetimeParamKind,
632 },
633 Type {
634 default: Option<&'hir Ty<'hir>>,
635 synthetic: bool,
636 },
637 Const {
638 ty: &'hir Ty<'hir>,
639 default: Option<&'hir ConstArg<'hir>>,
641 synthetic: bool,
642 },
643}
644
645#[derive(Debug, Clone, Copy, HashStable_Generic)]
646pub struct GenericParam<'hir> {
647 #[stable_hasher(ignore)]
648 pub hir_id: HirId,
649 pub def_id: LocalDefId,
650 pub name: ParamName,
651 pub span: Span,
652 pub pure_wrt_drop: bool,
653 pub kind: GenericParamKind<'hir>,
654 pub colon_span: Option<Span>,
655 pub source: GenericParamSource,
656}
657
658impl<'hir> GenericParam<'hir> {
659 pub fn is_impl_trait(&self) -> bool {
663 matches!(self.kind, GenericParamKind::Type { synthetic: true, .. })
664 }
665
666 pub fn is_elided_lifetime(&self) -> bool {
670 matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) })
671 }
672}
673
674#[derive(Debug, Clone, Copy, HashStable_Generic)]
681pub enum GenericParamSource {
682 Generics,
684 Binder,
686}
687
688#[derive(Default)]
689pub struct GenericParamCount {
690 pub lifetimes: usize,
691 pub types: usize,
692 pub consts: usize,
693 pub infer: usize,
694}
695
696#[derive(Debug, Clone, Copy, HashStable_Generic)]
699pub struct Generics<'hir> {
700 pub params: &'hir [GenericParam<'hir>],
701 pub predicates: &'hir [WherePredicate<'hir>],
702 pub has_where_clause_predicates: bool,
703 pub where_clause_span: Span,
704 pub span: Span,
705}
706
707impl<'hir> Generics<'hir> {
708 pub const fn empty() -> &'hir Generics<'hir> {
709 const NOPE: Generics<'_> = Generics {
710 params: &[],
711 predicates: &[],
712 has_where_clause_predicates: false,
713 where_clause_span: DUMMY_SP,
714 span: DUMMY_SP,
715 };
716 &NOPE
717 }
718
719 pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
720 self.params.iter().find(|¶m| name == param.name.ident().name)
721 }
722
723 pub fn span_for_lifetime_suggestion(&self) -> Option<Span> {
725 if let Some(first) = self.params.first()
726 && self.span.contains(first.span)
727 {
728 Some(first.span.shrink_to_lo())
731 } else {
732 None
733 }
734 }
735
736 pub fn span_for_param_suggestion(&self) -> Option<Span> {
738 self.params.iter().any(|p| self.span.contains(p.span)).then(|| {
739 self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo()
742 })
743 }
744
745 pub fn tail_span_for_predicate_suggestion(&self) -> Span {
748 let end = self.where_clause_span.shrink_to_hi();
749 if self.has_where_clause_predicates {
750 self.predicates
751 .iter()
752 .rfind(|&p| p.kind.in_where_clause())
753 .map_or(end, |p| p.span)
754 .shrink_to_hi()
755 .to(end)
756 } else {
757 end
758 }
759 }
760
761 pub fn add_where_or_trailing_comma(&self) -> &'static str {
762 if self.has_where_clause_predicates {
763 ","
764 } else if self.where_clause_span.is_empty() {
765 " where"
766 } else {
767 ""
769 }
770 }
771
772 pub fn bounds_for_param(
773 &self,
774 param_def_id: LocalDefId,
775 ) -> impl Iterator<Item = &WhereBoundPredicate<'hir>> {
776 self.predicates.iter().filter_map(move |pred| match pred.kind {
777 WherePredicateKind::BoundPredicate(bp)
778 if bp.is_param_bound(param_def_id.to_def_id()) =>
779 {
780 Some(bp)
781 }
782 _ => None,
783 })
784 }
785
786 pub fn outlives_for_param(
787 &self,
788 param_def_id: LocalDefId,
789 ) -> impl Iterator<Item = &WhereRegionPredicate<'_>> {
790 self.predicates.iter().filter_map(move |pred| match pred.kind {
791 WherePredicateKind::RegionPredicate(rp) if rp.is_param_bound(param_def_id) => Some(rp),
792 _ => None,
793 })
794 }
795
796 pub fn bounds_span_for_suggestions(
807 &self,
808 param_def_id: LocalDefId,
809 ) -> Option<(Span, Option<Span>)> {
810 self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
811 |bound| {
812 let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref()
813 && let [.., segment] = trait_ref.path.segments
814 && let Some(ret_ty) = segment.args().paren_sugar_output()
815 && let ret_ty = ret_ty.peel_refs()
816 && let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind
817 && let TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar = tagged_ptr.tag()
818 && ret_ty.span.can_be_used_for_suggestions()
819 {
820 Some(ret_ty.span)
821 } else {
822 None
823 };
824
825 span_for_parentheses.map_or_else(
826 || {
827 let bs = bound.span();
830 bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None))
831 },
832 |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))),
833 )
834 },
835 )
836 }
837
838 pub fn span_for_predicate_removal(&self, pos: usize) -> Span {
839 let predicate = &self.predicates[pos];
840 let span = predicate.span;
841
842 if !predicate.kind.in_where_clause() {
843 return span;
846 }
847
848 if pos < self.predicates.len() - 1 {
850 let next_pred = &self.predicates[pos + 1];
851 if next_pred.kind.in_where_clause() {
852 return span.until(next_pred.span);
855 }
856 }
857
858 if pos > 0 {
859 let prev_pred = &self.predicates[pos - 1];
860 if prev_pred.kind.in_where_clause() {
861 return prev_pred.span.shrink_to_hi().to(span);
864 }
865 }
866
867 self.where_clause_span
871 }
872
873 pub fn span_for_bound_removal(&self, predicate_pos: usize, bound_pos: usize) -> Span {
874 let predicate = &self.predicates[predicate_pos];
875 let bounds = predicate.kind.bounds();
876
877 if bounds.len() == 1 {
878 return self.span_for_predicate_removal(predicate_pos);
879 }
880
881 let bound_span = bounds[bound_pos].span();
882 if bound_pos < bounds.len() - 1 {
883 bound_span.to(bounds[bound_pos + 1].span().shrink_to_lo())
889 } else {
890 bound_span.with_lo(bounds[bound_pos - 1].span().hi())
896 }
897 }
898}
899
900#[derive(Debug, Clone, Copy, HashStable_Generic)]
902pub struct WherePredicate<'hir> {
903 #[stable_hasher(ignore)]
904 pub hir_id: HirId,
905 pub span: Span,
906 pub kind: &'hir WherePredicateKind<'hir>,
907}
908
909#[derive(Debug, Clone, Copy, HashStable_Generic)]
911pub enum WherePredicateKind<'hir> {
912 BoundPredicate(WhereBoundPredicate<'hir>),
914 RegionPredicate(WhereRegionPredicate<'hir>),
916 EqPredicate(WhereEqPredicate<'hir>),
918}
919
920impl<'hir> WherePredicateKind<'hir> {
921 pub fn in_where_clause(&self) -> bool {
922 match self {
923 WherePredicateKind::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause,
924 WherePredicateKind::RegionPredicate(p) => p.in_where_clause,
925 WherePredicateKind::EqPredicate(_) => false,
926 }
927 }
928
929 pub fn bounds(&self) -> GenericBounds<'hir> {
930 match self {
931 WherePredicateKind::BoundPredicate(p) => p.bounds,
932 WherePredicateKind::RegionPredicate(p) => p.bounds,
933 WherePredicateKind::EqPredicate(_) => &[],
934 }
935 }
936}
937
938#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
939pub enum PredicateOrigin {
940 WhereClause,
941 GenericParam,
942 ImplTrait,
943}
944
945#[derive(Debug, Clone, Copy, HashStable_Generic)]
947pub struct WhereBoundPredicate<'hir> {
948 pub origin: PredicateOrigin,
950 pub bound_generic_params: &'hir [GenericParam<'hir>],
952 pub bounded_ty: &'hir Ty<'hir>,
954 pub bounds: GenericBounds<'hir>,
956}
957
958impl<'hir> WhereBoundPredicate<'hir> {
959 pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
961 self.bounded_ty.as_generic_param().is_some_and(|(def_id, _)| def_id == param_def_id)
962 }
963}
964
965#[derive(Debug, Clone, Copy, HashStable_Generic)]
967pub struct WhereRegionPredicate<'hir> {
968 pub in_where_clause: bool,
969 pub lifetime: &'hir Lifetime,
970 pub bounds: GenericBounds<'hir>,
971}
972
973impl<'hir> WhereRegionPredicate<'hir> {
974 fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
976 self.lifetime.res == LifetimeName::Param(param_def_id)
977 }
978}
979
980#[derive(Debug, Clone, Copy, HashStable_Generic)]
982pub struct WhereEqPredicate<'hir> {
983 pub lhs_ty: &'hir Ty<'hir>,
984 pub rhs_ty: &'hir Ty<'hir>,
985}
986
987#[derive(Clone, Copy, Debug)]
991pub struct ParentedNode<'tcx> {
992 pub parent: ItemLocalId,
993 pub node: Node<'tcx>,
994}
995
996#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
998pub enum AttrArgs {
999 Empty,
1001 Delimited(DelimArgs),
1003 Eq {
1005 eq_span: Span,
1007 expr: MetaItemLit,
1009 },
1010}
1011
1012#[derive(Clone, Debug, Encodable, Decodable)]
1013pub enum AttrKind {
1014 Normal(Box<AttrItem>),
1016
1017 DocComment(CommentKind, Symbol),
1021}
1022
1023#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
1024pub struct AttrPath {
1025 pub segments: Box<[Ident]>,
1026 pub span: Span,
1027}
1028
1029#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
1030pub struct AttrItem {
1031 pub unsafety: Safety,
1032 pub path: AttrPath,
1034 pub args: AttrArgs,
1035}
1036
1037#[derive(Clone, Debug, Encodable, Decodable)]
1038pub struct Attribute {
1039 pub kind: AttrKind,
1040 pub id: AttrId,
1041 pub style: AttrStyle,
1044 pub span: Span,
1045}
1046
1047impl Attribute {
1048 pub fn get_normal_item(&self) -> &AttrItem {
1049 match &self.kind {
1050 AttrKind::Normal(normal) => &normal,
1051 AttrKind::DocComment(..) => panic!("unexpected doc comment"),
1052 }
1053 }
1054
1055 pub fn unwrap_normal_item(self) -> AttrItem {
1056 match self.kind {
1057 AttrKind::Normal(normal) => *normal,
1058 AttrKind::DocComment(..) => panic!("unexpected doc comment"),
1059 }
1060 }
1061
1062 pub fn value_lit(&self) -> Option<&MetaItemLit> {
1063 match &self.kind {
1064 AttrKind::Normal(box AttrItem { args: AttrArgs::Eq { expr, .. }, .. }) => Some(expr),
1065 _ => None,
1066 }
1067 }
1068}
1069
1070impl AttributeExt for Attribute {
1071 fn id(&self) -> AttrId {
1072 self.id
1073 }
1074
1075 fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
1076 match &self.kind {
1077 AttrKind::Normal(box AttrItem { args: AttrArgs::Delimited(d), .. }) => {
1078 ast::MetaItemKind::list_from_tokens(d.tokens.clone())
1079 }
1080 _ => None,
1081 }
1082 }
1083
1084 fn value_str(&self) -> Option<Symbol> {
1085 self.value_lit().and_then(|x| x.value_str())
1086 }
1087
1088 fn value_span(&self) -> Option<Span> {
1089 self.value_lit().map(|i| i.span)
1090 }
1091
1092 fn ident(&self) -> Option<Ident> {
1094 match &self.kind {
1095 AttrKind::Normal(box AttrItem {
1096 path: AttrPath { segments: box [ident], .. }, ..
1097 }) => Some(*ident),
1098 _ => None,
1099 }
1100 }
1101
1102 fn path_matches(&self, name: &[Symbol]) -> bool {
1103 match &self.kind {
1104 AttrKind::Normal(n) => n.path.segments.iter().map(|segment| &segment.name).eq(name),
1105 AttrKind::DocComment(..) => false,
1106 }
1107 }
1108
1109 fn is_doc_comment(&self) -> bool {
1110 matches!(self.kind, AttrKind::DocComment(..))
1111 }
1112
1113 fn span(&self) -> Span {
1114 self.span
1115 }
1116
1117 fn is_word(&self) -> bool {
1118 matches!(self.kind, AttrKind::Normal(box AttrItem { args: AttrArgs::Empty, .. }))
1119 }
1120
1121 fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
1122 match &self.kind {
1123 AttrKind::Normal(n) => Some(n.path.segments.iter().copied().collect()),
1124 AttrKind::DocComment(..) => None,
1125 }
1126 }
1127
1128 fn doc_str(&self) -> Option<Symbol> {
1129 match &self.kind {
1130 AttrKind::DocComment(.., data) => Some(*data),
1131 AttrKind::Normal(_) if self.has_name(sym::doc) => self.value_str(),
1132 _ => None,
1133 }
1134 }
1135 fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
1136 match &self.kind {
1137 AttrKind::DocComment(kind, data) => Some((*data, *kind)),
1138 AttrKind::Normal(_) if self.name_or_empty() == sym::doc => {
1139 self.value_str().map(|s| (s, CommentKind::Line))
1140 }
1141 _ => None,
1142 }
1143 }
1144
1145 fn style(&self) -> AttrStyle {
1146 self.style
1147 }
1148}
1149
1150impl Attribute {
1152 pub fn id(&self) -> AttrId {
1153 AttributeExt::id(self)
1154 }
1155
1156 pub fn name_or_empty(&self) -> Symbol {
1157 AttributeExt::name_or_empty(self)
1158 }
1159
1160 pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
1161 AttributeExt::meta_item_list(self)
1162 }
1163
1164 pub fn value_str(&self) -> Option<Symbol> {
1165 AttributeExt::value_str(self)
1166 }
1167
1168 pub fn value_span(&self) -> Option<Span> {
1169 AttributeExt::value_span(self)
1170 }
1171
1172 pub fn ident(&self) -> Option<Ident> {
1173 AttributeExt::ident(self)
1174 }
1175
1176 pub fn path_matches(&self, name: &[Symbol]) -> bool {
1177 AttributeExt::path_matches(self, name)
1178 }
1179
1180 pub fn is_doc_comment(&self) -> bool {
1181 AttributeExt::is_doc_comment(self)
1182 }
1183
1184 #[inline]
1185 pub fn has_name(&self, name: Symbol) -> bool {
1186 AttributeExt::has_name(self, name)
1187 }
1188
1189 pub fn span(&self) -> Span {
1190 AttributeExt::span(self)
1191 }
1192
1193 pub fn is_word(&self) -> bool {
1194 AttributeExt::is_word(self)
1195 }
1196
1197 pub fn path(&self) -> SmallVec<[Symbol; 1]> {
1198 AttributeExt::path(self)
1199 }
1200
1201 pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
1202 AttributeExt::ident_path(self)
1203 }
1204
1205 pub fn doc_str(&self) -> Option<Symbol> {
1206 AttributeExt::doc_str(self)
1207 }
1208
1209 pub fn is_proc_macro_attr(&self) -> bool {
1210 AttributeExt::is_proc_macro_attr(self)
1211 }
1212
1213 pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
1214 AttributeExt::doc_str_and_comment_kind(self)
1215 }
1216
1217 pub fn style(&self) -> AttrStyle {
1218 AttributeExt::style(self)
1219 }
1220}
1221
1222#[derive(Debug)]
1224pub struct AttributeMap<'tcx> {
1225 pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
1226 pub opt_hash: Option<Fingerprint>,
1228}
1229
1230impl<'tcx> AttributeMap<'tcx> {
1231 pub const EMPTY: &'static AttributeMap<'static> =
1232 &AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) };
1233
1234 #[inline]
1235 pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
1236 self.map.get(&id).copied().unwrap_or(&[])
1237 }
1238}
1239
1240pub struct OwnerNodes<'tcx> {
1244 pub opt_hash_including_bodies: Option<Fingerprint>,
1247 pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
1252 pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
1254}
1255
1256impl<'tcx> OwnerNodes<'tcx> {
1257 pub fn node(&self) -> OwnerNode<'tcx> {
1258 self.nodes[ItemLocalId::ZERO].node.as_owner().unwrap()
1260 }
1261}
1262
1263impl fmt::Debug for OwnerNodes<'_> {
1264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1265 f.debug_struct("OwnerNodes")
1266 .field("node", &self.nodes[ItemLocalId::ZERO])
1268 .field(
1269 "parents",
1270 &fmt::from_fn(|f| {
1271 f.debug_list()
1272 .entries(self.nodes.iter_enumerated().map(|(id, parented_node)| {
1273 fmt::from_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
1274 }))
1275 .finish()
1276 }),
1277 )
1278 .field("bodies", &self.bodies)
1279 .field("opt_hash_including_bodies", &self.opt_hash_including_bodies)
1280 .finish()
1281 }
1282}
1283
1284#[derive(Debug, HashStable_Generic)]
1286pub struct OwnerInfo<'hir> {
1287 pub nodes: OwnerNodes<'hir>,
1289 pub parenting: LocalDefIdMap<ItemLocalId>,
1291 pub attrs: AttributeMap<'hir>,
1293 pub trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
1296}
1297
1298impl<'tcx> OwnerInfo<'tcx> {
1299 #[inline]
1300 pub fn node(&self) -> OwnerNode<'tcx> {
1301 self.nodes.node()
1302 }
1303}
1304
1305#[derive(Copy, Clone, Debug, HashStable_Generic)]
1306pub enum MaybeOwner<'tcx> {
1307 Owner(&'tcx OwnerInfo<'tcx>),
1308 NonOwner(HirId),
1309 Phantom,
1311}
1312
1313impl<'tcx> MaybeOwner<'tcx> {
1314 pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> {
1315 match self {
1316 MaybeOwner::Owner(i) => Some(i),
1317 MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None,
1318 }
1319 }
1320
1321 pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> {
1322 self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner"))
1323 }
1324}
1325
1326#[derive(Debug)]
1333pub struct Crate<'hir> {
1334 pub owners: IndexVec<LocalDefId, MaybeOwner<'hir>>,
1335 pub opt_hir_hash: Option<Fingerprint>,
1337}
1338
1339#[derive(Debug, Clone, Copy, HashStable_Generic)]
1340pub struct Closure<'hir> {
1341 pub def_id: LocalDefId,
1342 pub binder: ClosureBinder,
1343 pub constness: Constness,
1344 pub capture_clause: CaptureBy,
1345 pub bound_generic_params: &'hir [GenericParam<'hir>],
1346 pub fn_decl: &'hir FnDecl<'hir>,
1347 pub body: BodyId,
1348 pub fn_decl_span: Span,
1350 pub fn_arg_span: Option<Span>,
1352 pub kind: ClosureKind,
1353}
1354
1355#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
1356pub enum ClosureKind {
1357 Closure,
1359 Coroutine(CoroutineKind),
1364 CoroutineClosure(CoroutineDesugaring),
1369}
1370
1371#[derive(Debug, Clone, Copy, HashStable_Generic)]
1375pub struct Block<'hir> {
1376 pub stmts: &'hir [Stmt<'hir>],
1378 pub expr: Option<&'hir Expr<'hir>>,
1381 #[stable_hasher(ignore)]
1382 pub hir_id: HirId,
1383 pub rules: BlockCheckMode,
1385 pub span: Span,
1387 pub targeted_by_break: bool,
1391}
1392
1393impl<'hir> Block<'hir> {
1394 pub fn innermost_block(&self) -> &Block<'hir> {
1395 let mut block = self;
1396 while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr {
1397 block = inner_block;
1398 }
1399 block
1400 }
1401}
1402
1403#[derive(Debug, Clone, Copy, HashStable_Generic)]
1404pub struct TyPat<'hir> {
1405 #[stable_hasher(ignore)]
1406 pub hir_id: HirId,
1407 pub kind: TyPatKind<'hir>,
1408 pub span: Span,
1409}
1410
1411#[derive(Debug, Clone, Copy, HashStable_Generic)]
1412pub struct Pat<'hir> {
1413 #[stable_hasher(ignore)]
1414 pub hir_id: HirId,
1415 pub kind: PatKind<'hir>,
1416 pub span: Span,
1417 pub default_binding_modes: bool,
1420}
1421
1422impl<'hir> Pat<'hir> {
1423 fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
1424 if !it(self) {
1425 return false;
1426 }
1427
1428 use PatKind::*;
1429 match self.kind {
1430 Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
1431 Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
1432 Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
1433 TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
1434 Slice(before, slice, after) => {
1435 before.iter().chain(slice).chain(after.iter()).all(|p| p.walk_short_(it))
1436 }
1437 }
1438 }
1439
1440 pub fn walk_short(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) -> bool {
1447 self.walk_short_(&mut it)
1448 }
1449
1450 fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
1451 if !it(self) {
1452 return;
1453 }
1454
1455 use PatKind::*;
1456 match self.kind {
1457 Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
1458 Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
1459 Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
1460 TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
1461 Slice(before, slice, after) => {
1462 before.iter().chain(slice).chain(after.iter()).for_each(|p| p.walk_(it))
1463 }
1464 }
1465 }
1466
1467 pub fn walk(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) {
1471 self.walk_(&mut it)
1472 }
1473
1474 pub fn walk_always(&self, mut it: impl FnMut(&Pat<'_>)) {
1478 self.walk(|p| {
1479 it(p);
1480 true
1481 })
1482 }
1483
1484 pub fn is_never_pattern(&self) -> bool {
1486 let mut is_never_pattern = false;
1487 self.walk(|pat| match &pat.kind {
1488 PatKind::Never => {
1489 is_never_pattern = true;
1490 false
1491 }
1492 PatKind::Or(s) => {
1493 is_never_pattern = s.iter().all(|p| p.is_never_pattern());
1494 false
1495 }
1496 _ => true,
1497 });
1498 is_never_pattern
1499 }
1500}
1501
1502#[derive(Debug, Clone, Copy, HashStable_Generic)]
1508pub struct PatField<'hir> {
1509 #[stable_hasher(ignore)]
1510 pub hir_id: HirId,
1511 pub ident: Ident,
1513 pub pat: &'hir Pat<'hir>,
1515 pub is_shorthand: bool,
1516 pub span: Span,
1517}
1518
1519#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
1520pub enum RangeEnd {
1521 Included,
1522 Excluded,
1523}
1524
1525impl fmt::Display for RangeEnd {
1526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1527 f.write_str(match self {
1528 RangeEnd::Included => "..=",
1529 RangeEnd::Excluded => "..",
1530 })
1531 }
1532}
1533
1534#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable_Generic)]
1538pub struct DotDotPos(u32);
1539
1540impl DotDotPos {
1541 pub fn new(n: Option<usize>) -> Self {
1543 match n {
1544 Some(n) => {
1545 assert!(n < u32::MAX as usize);
1546 Self(n as u32)
1547 }
1548 None => Self(u32::MAX),
1549 }
1550 }
1551
1552 pub fn as_opt_usize(&self) -> Option<usize> {
1553 if self.0 == u32::MAX { None } else { Some(self.0 as usize) }
1554 }
1555}
1556
1557impl fmt::Debug for DotDotPos {
1558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1559 self.as_opt_usize().fmt(f)
1560 }
1561}
1562
1563#[derive(Debug, Clone, Copy, HashStable_Generic)]
1564pub struct PatExpr<'hir> {
1565 #[stable_hasher(ignore)]
1566 pub hir_id: HirId,
1567 pub span: Span,
1568 pub kind: PatExprKind<'hir>,
1569}
1570
1571#[derive(Debug, Clone, Copy, HashStable_Generic)]
1572pub enum PatExprKind<'hir> {
1573 Lit {
1574 lit: &'hir Lit,
1575 negated: bool,
1578 },
1579 ConstBlock(ConstBlock),
1580 Path(QPath<'hir>),
1582}
1583
1584#[derive(Debug, Clone, Copy, HashStable_Generic)]
1585pub enum TyPatKind<'hir> {
1586 Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd),
1588
1589 Err(ErrorGuaranteed),
1591}
1592
1593#[derive(Debug, Clone, Copy, HashStable_Generic)]
1594pub enum PatKind<'hir> {
1595 Wild,
1597
1598 Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>),
1603
1604 Struct(QPath<'hir>, &'hir [PatField<'hir>], bool),
1607
1608 TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], DotDotPos),
1612
1613 Or(&'hir [Pat<'hir>]),
1616
1617 Never,
1619
1620 Tuple(&'hir [Pat<'hir>], DotDotPos),
1624
1625 Box(&'hir Pat<'hir>),
1627
1628 Deref(&'hir Pat<'hir>),
1630
1631 Ref(&'hir Pat<'hir>, Mutability),
1633
1634 Expr(&'hir PatExpr<'hir>),
1636
1637 Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
1639
1640 Range(Option<&'hir PatExpr<'hir>>, Option<&'hir PatExpr<'hir>>, RangeEnd),
1642
1643 Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
1653
1654 Err(ErrorGuaranteed),
1656}
1657
1658#[derive(Debug, Clone, Copy, HashStable_Generic)]
1660pub struct Stmt<'hir> {
1661 #[stable_hasher(ignore)]
1662 pub hir_id: HirId,
1663 pub kind: StmtKind<'hir>,
1664 pub span: Span,
1665}
1666
1667#[derive(Debug, Clone, Copy, HashStable_Generic)]
1669pub enum StmtKind<'hir> {
1670 Let(&'hir LetStmt<'hir>),
1672
1673 Item(ItemId),
1675
1676 Expr(&'hir Expr<'hir>),
1678
1679 Semi(&'hir Expr<'hir>),
1681}
1682
1683#[derive(Debug, Clone, Copy, HashStable_Generic)]
1685pub struct LetStmt<'hir> {
1686 pub pat: &'hir Pat<'hir>,
1687 pub ty: Option<&'hir Ty<'hir>>,
1689 pub init: Option<&'hir Expr<'hir>>,
1691 pub els: Option<&'hir Block<'hir>>,
1693 #[stable_hasher(ignore)]
1694 pub hir_id: HirId,
1695 pub span: Span,
1696 pub source: LocalSource,
1700}
1701
1702#[derive(Debug, Clone, Copy, HashStable_Generic)]
1705pub struct Arm<'hir> {
1706 #[stable_hasher(ignore)]
1707 pub hir_id: HirId,
1708 pub span: Span,
1709 pub pat: &'hir Pat<'hir>,
1711 pub guard: Option<&'hir Expr<'hir>>,
1713 pub body: &'hir Expr<'hir>,
1715}
1716
1717#[derive(Debug, Clone, Copy, HashStable_Generic)]
1723pub struct LetExpr<'hir> {
1724 pub span: Span,
1725 pub pat: &'hir Pat<'hir>,
1726 pub ty: Option<&'hir Ty<'hir>>,
1727 pub init: &'hir Expr<'hir>,
1728 pub recovered: ast::Recovered,
1731}
1732
1733#[derive(Debug, Clone, Copy, HashStable_Generic)]
1734pub struct ExprField<'hir> {
1735 #[stable_hasher(ignore)]
1736 pub hir_id: HirId,
1737 pub ident: Ident,
1738 pub expr: &'hir Expr<'hir>,
1739 pub span: Span,
1740 pub is_shorthand: bool,
1741}
1742
1743#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
1744pub enum BlockCheckMode {
1745 DefaultBlock,
1746 UnsafeBlock(UnsafeSource),
1747}
1748
1749#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
1750pub enum UnsafeSource {
1751 CompilerGenerated,
1752 UserProvided,
1753}
1754
1755#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
1756pub struct BodyId {
1757 pub hir_id: HirId,
1758}
1759
1760#[derive(Debug, Clone, Copy, HashStable_Generic)]
1782pub struct Body<'hir> {
1783 pub params: &'hir [Param<'hir>],
1784 pub value: &'hir Expr<'hir>,
1785}
1786
1787impl<'hir> Body<'hir> {
1788 pub fn id(&self) -> BodyId {
1789 BodyId { hir_id: self.value.hir_id }
1790 }
1791}
1792
1793#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
1795pub enum CoroutineKind {
1796 Desugared(CoroutineDesugaring, CoroutineSource),
1798
1799 Coroutine(Movability),
1801}
1802
1803impl CoroutineKind {
1804 pub fn movability(self) -> Movability {
1805 match self {
1806 CoroutineKind::Desugared(CoroutineDesugaring::Async, _)
1807 | CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => Movability::Static,
1808 CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => Movability::Movable,
1809 CoroutineKind::Coroutine(mov) => mov,
1810 }
1811 }
1812}
1813
1814impl CoroutineKind {
1815 pub fn is_fn_like(self) -> bool {
1816 matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn))
1817 }
1818}
1819
1820impl fmt::Display for CoroutineKind {
1821 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1822 match self {
1823 CoroutineKind::Desugared(d, k) => {
1824 d.fmt(f)?;
1825 k.fmt(f)
1826 }
1827 CoroutineKind::Coroutine(_) => f.write_str("coroutine"),
1828 }
1829 }
1830}
1831
1832#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy, HashStable_Generic, Encodable, Decodable)]
1838pub enum CoroutineSource {
1839 Block,
1841
1842 Closure,
1844
1845 Fn,
1847}
1848
1849impl fmt::Display for CoroutineSource {
1850 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1851 match self {
1852 CoroutineSource::Block => "block",
1853 CoroutineSource::Closure => "closure body",
1854 CoroutineSource::Fn => "fn body",
1855 }
1856 .fmt(f)
1857 }
1858}
1859
1860#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
1861pub enum CoroutineDesugaring {
1862 Async,
1864
1865 Gen,
1867
1868 AsyncGen,
1871}
1872
1873impl fmt::Display for CoroutineDesugaring {
1874 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1875 match self {
1876 CoroutineDesugaring::Async => {
1877 if f.alternate() {
1878 f.write_str("`async` ")?;
1879 } else {
1880 f.write_str("async ")?
1881 }
1882 }
1883 CoroutineDesugaring::Gen => {
1884 if f.alternate() {
1885 f.write_str("`gen` ")?;
1886 } else {
1887 f.write_str("gen ")?
1888 }
1889 }
1890 CoroutineDesugaring::AsyncGen => {
1891 if f.alternate() {
1892 f.write_str("`async gen` ")?;
1893 } else {
1894 f.write_str("async gen ")?
1895 }
1896 }
1897 }
1898
1899 Ok(())
1900 }
1901}
1902
1903#[derive(Copy, Clone, Debug)]
1904pub enum BodyOwnerKind {
1905 Fn,
1907
1908 Closure,
1910
1911 Const { inline: bool },
1913
1914 Static(Mutability),
1916}
1917
1918impl BodyOwnerKind {
1919 pub fn is_fn_or_closure(self) -> bool {
1920 match self {
1921 BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
1922 BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
1923 }
1924 }
1925}
1926
1927#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1929pub enum ConstContext {
1930 ConstFn,
1932
1933 Static(Mutability),
1935
1936 Const { inline: bool },
1946}
1947
1948impl ConstContext {
1949 pub fn keyword_name(self) -> &'static str {
1953 match self {
1954 Self::Const { .. } => "const",
1955 Self::Static(Mutability::Not) => "static",
1956 Self::Static(Mutability::Mut) => "static mut",
1957 Self::ConstFn => "const fn",
1958 }
1959 }
1960}
1961
1962impl fmt::Display for ConstContext {
1965 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1966 match *self {
1967 Self::Const { .. } => write!(f, "constant"),
1968 Self::Static(_) => write!(f, "static"),
1969 Self::ConstFn => write!(f, "constant function"),
1970 }
1971 }
1972}
1973
1974pub type Lit = Spanned<LitKind>;
1979
1980#[derive(Copy, Clone, Debug, HashStable_Generic)]
1989pub struct AnonConst {
1990 #[stable_hasher(ignore)]
1991 pub hir_id: HirId,
1992 pub def_id: LocalDefId,
1993 pub body: BodyId,
1994 pub span: Span,
1995}
1996
1997#[derive(Copy, Clone, Debug, HashStable_Generic)]
1999pub struct ConstBlock {
2000 #[stable_hasher(ignore)]
2001 pub hir_id: HirId,
2002 pub def_id: LocalDefId,
2003 pub body: BodyId,
2004}
2005
2006#[derive(Debug, Clone, Copy, HashStable_Generic)]
2015pub struct Expr<'hir> {
2016 #[stable_hasher(ignore)]
2017 pub hir_id: HirId,
2018 pub kind: ExprKind<'hir>,
2019 pub span: Span,
2020}
2021
2022impl Expr<'_> {
2023 pub fn precedence(&self) -> ExprPrecedence {
2024 match &self.kind {
2025 ExprKind::Closure(closure) => {
2026 match closure.fn_decl.output {
2027 FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump,
2028 FnRetTy::Return(_) => ExprPrecedence::Unambiguous,
2029 }
2030 }
2031
2032 ExprKind::Break(..)
2033 | ExprKind::Ret(..)
2034 | ExprKind::Yield(..)
2035 | ExprKind::Become(..) => ExprPrecedence::Jump,
2036
2037 ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
2039 ExprKind::Cast(..) => ExprPrecedence::Cast,
2040
2041 ExprKind::Assign(..) |
2042 ExprKind::AssignOp(..) => ExprPrecedence::Assign,
2043
2044 ExprKind::AddrOf(..)
2046 | ExprKind::Let(..)
2051 | ExprKind::Unary(..) => ExprPrecedence::Prefix,
2052
2053 ExprKind::Array(_)
2055 | ExprKind::Block(..)
2056 | ExprKind::Call(..)
2057 | ExprKind::ConstBlock(_)
2058 | ExprKind::Continue(..)
2059 | ExprKind::Field(..)
2060 | ExprKind::If(..)
2061 | ExprKind::Index(..)
2062 | ExprKind::InlineAsm(..)
2063 | ExprKind::Lit(_)
2064 | ExprKind::Loop(..)
2065 | ExprKind::Match(..)
2066 | ExprKind::MethodCall(..)
2067 | ExprKind::OffsetOf(..)
2068 | ExprKind::Path(..)
2069 | ExprKind::Repeat(..)
2070 | ExprKind::Struct(..)
2071 | ExprKind::Tup(_)
2072 | ExprKind::Type(..)
2073 | ExprKind::UnsafeBinderCast(..)
2074 | ExprKind::Err(_) => ExprPrecedence::Unambiguous,
2075
2076 ExprKind::DropTemps(expr, ..) => expr.precedence(),
2077 }
2078 }
2079
2080 pub fn is_syntactic_place_expr(&self) -> bool {
2085 self.is_place_expr(|_| true)
2086 }
2087
2088 pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
2093 match self.kind {
2094 ExprKind::Path(QPath::Resolved(_, ref path)) => {
2095 matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static { .. }, _) | Res::Err)
2096 }
2097
2098 ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
2102
2103 ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from),
2105
2106 ExprKind::Unary(UnOp::Deref, _) => true,
2107
2108 ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => {
2109 allow_projections_from(base) || base.is_place_expr(allow_projections_from)
2110 }
2111
2112 ExprKind::Path(QPath::LangItem(..)) => false,
2114
2115 ExprKind::Path(QPath::TypeRelative(..))
2118 | ExprKind::Call(..)
2119 | ExprKind::MethodCall(..)
2120 | ExprKind::Struct(..)
2121 | ExprKind::Tup(..)
2122 | ExprKind::If(..)
2123 | ExprKind::Match(..)
2124 | ExprKind::Closure { .. }
2125 | ExprKind::Block(..)
2126 | ExprKind::Repeat(..)
2127 | ExprKind::Array(..)
2128 | ExprKind::Break(..)
2129 | ExprKind::Continue(..)
2130 | ExprKind::Ret(..)
2131 | ExprKind::Become(..)
2132 | ExprKind::Let(..)
2133 | ExprKind::Loop(..)
2134 | ExprKind::Assign(..)
2135 | ExprKind::InlineAsm(..)
2136 | ExprKind::OffsetOf(..)
2137 | ExprKind::AssignOp(..)
2138 | ExprKind::Lit(_)
2139 | ExprKind::ConstBlock(..)
2140 | ExprKind::Unary(..)
2141 | ExprKind::AddrOf(..)
2142 | ExprKind::Binary(..)
2143 | ExprKind::Yield(..)
2144 | ExprKind::Cast(..)
2145 | ExprKind::DropTemps(..)
2146 | ExprKind::Err(_) => false,
2147 }
2148 }
2149
2150 pub fn is_size_lit(&self) -> bool {
2153 matches!(
2154 self.kind,
2155 ExprKind::Lit(Lit {
2156 node: LitKind::Int(_, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::Usize)),
2157 ..
2158 })
2159 )
2160 }
2161
2162 pub fn peel_drop_temps(&self) -> &Self {
2168 let mut expr = self;
2169 while let ExprKind::DropTemps(inner) = &expr.kind {
2170 expr = inner;
2171 }
2172 expr
2173 }
2174
2175 pub fn peel_blocks(&self) -> &Self {
2176 let mut expr = self;
2177 while let ExprKind::Block(Block { expr: Some(inner), .. }, _) = &expr.kind {
2178 expr = inner;
2179 }
2180 expr
2181 }
2182
2183 pub fn peel_borrows(&self) -> &Self {
2184 let mut expr = self;
2185 while let ExprKind::AddrOf(.., inner) = &expr.kind {
2186 expr = inner;
2187 }
2188 expr
2189 }
2190
2191 pub fn can_have_side_effects(&self) -> bool {
2192 match self.peel_drop_temps().kind {
2193 ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false,
2194 ExprKind::Type(base, _)
2195 | ExprKind::Unary(_, base)
2196 | ExprKind::Field(base, _)
2197 | ExprKind::Index(base, _, _)
2198 | ExprKind::AddrOf(.., base)
2199 | ExprKind::Cast(base, _)
2200 | ExprKind::UnsafeBinderCast(_, base, _) => {
2201 base.can_have_side_effects()
2205 }
2206 ExprKind::Struct(_, fields, init) => {
2207 let init_side_effects = match init {
2208 StructTailExpr::Base(init) => init.can_have_side_effects(),
2209 StructTailExpr::DefaultFields(_) | StructTailExpr::None => false,
2210 };
2211 fields.iter().map(|field| field.expr).any(|e| e.can_have_side_effects())
2212 || init_side_effects
2213 }
2214
2215 ExprKind::Array(args)
2216 | ExprKind::Tup(args)
2217 | ExprKind::Call(
2218 Expr {
2219 kind:
2220 ExprKind::Path(QPath::Resolved(
2221 None,
2222 Path { res: Res::Def(DefKind::Ctor(_, CtorKind::Fn), _), .. },
2223 )),
2224 ..
2225 },
2226 args,
2227 ) => args.iter().any(|arg| arg.can_have_side_effects()),
2228 ExprKind::If(..)
2229 | ExprKind::Match(..)
2230 | ExprKind::MethodCall(..)
2231 | ExprKind::Call(..)
2232 | ExprKind::Closure { .. }
2233 | ExprKind::Block(..)
2234 | ExprKind::Repeat(..)
2235 | ExprKind::Break(..)
2236 | ExprKind::Continue(..)
2237 | ExprKind::Ret(..)
2238 | ExprKind::Become(..)
2239 | ExprKind::Let(..)
2240 | ExprKind::Loop(..)
2241 | ExprKind::Assign(..)
2242 | ExprKind::InlineAsm(..)
2243 | ExprKind::AssignOp(..)
2244 | ExprKind::ConstBlock(..)
2245 | ExprKind::Binary(..)
2246 | ExprKind::Yield(..)
2247 | ExprKind::DropTemps(..)
2248 | ExprKind::Err(_) => true,
2249 }
2250 }
2251
2252 pub fn is_approximately_pattern(&self) -> bool {
2254 match &self.kind {
2255 ExprKind::Array(_)
2256 | ExprKind::Call(..)
2257 | ExprKind::Tup(_)
2258 | ExprKind::Lit(_)
2259 | ExprKind::Path(_)
2260 | ExprKind::Struct(..) => true,
2261 _ => false,
2262 }
2263 }
2264
2265 pub fn equivalent_for_indexing(&self, other: &Expr<'_>) -> bool {
2270 match (self.kind, other.kind) {
2271 (ExprKind::Lit(lit1), ExprKind::Lit(lit2)) => lit1.node == lit2.node,
2272 (
2273 ExprKind::Path(QPath::LangItem(item1, _)),
2274 ExprKind::Path(QPath::LangItem(item2, _)),
2275 ) => item1 == item2,
2276 (
2277 ExprKind::Path(QPath::Resolved(None, path1)),
2278 ExprKind::Path(QPath::Resolved(None, path2)),
2279 ) => path1.res == path2.res,
2280 (
2281 ExprKind::Struct(
2282 QPath::LangItem(LangItem::RangeTo, _),
2283 [val1],
2284 StructTailExpr::None,
2285 ),
2286 ExprKind::Struct(
2287 QPath::LangItem(LangItem::RangeTo, _),
2288 [val2],
2289 StructTailExpr::None,
2290 ),
2291 )
2292 | (
2293 ExprKind::Struct(
2294 QPath::LangItem(LangItem::RangeToInclusive, _),
2295 [val1],
2296 StructTailExpr::None,
2297 ),
2298 ExprKind::Struct(
2299 QPath::LangItem(LangItem::RangeToInclusive, _),
2300 [val2],
2301 StructTailExpr::None,
2302 ),
2303 )
2304 | (
2305 ExprKind::Struct(
2306 QPath::LangItem(LangItem::RangeFrom, _),
2307 [val1],
2308 StructTailExpr::None,
2309 ),
2310 ExprKind::Struct(
2311 QPath::LangItem(LangItem::RangeFrom, _),
2312 [val2],
2313 StructTailExpr::None,
2314 ),
2315 )
2316 | (
2317 ExprKind::Struct(
2318 QPath::LangItem(LangItem::RangeFromCopy, _),
2319 [val1],
2320 StructTailExpr::None,
2321 ),
2322 ExprKind::Struct(
2323 QPath::LangItem(LangItem::RangeFromCopy, _),
2324 [val2],
2325 StructTailExpr::None,
2326 ),
2327 ) => val1.expr.equivalent_for_indexing(val2.expr),
2328 (
2329 ExprKind::Struct(
2330 QPath::LangItem(LangItem::Range, _),
2331 [val1, val3],
2332 StructTailExpr::None,
2333 ),
2334 ExprKind::Struct(
2335 QPath::LangItem(LangItem::Range, _),
2336 [val2, val4],
2337 StructTailExpr::None,
2338 ),
2339 )
2340 | (
2341 ExprKind::Struct(
2342 QPath::LangItem(LangItem::RangeCopy, _),
2343 [val1, val3],
2344 StructTailExpr::None,
2345 ),
2346 ExprKind::Struct(
2347 QPath::LangItem(LangItem::RangeCopy, _),
2348 [val2, val4],
2349 StructTailExpr::None,
2350 ),
2351 )
2352 | (
2353 ExprKind::Struct(
2354 QPath::LangItem(LangItem::RangeInclusiveCopy, _),
2355 [val1, val3],
2356 StructTailExpr::None,
2357 ),
2358 ExprKind::Struct(
2359 QPath::LangItem(LangItem::RangeInclusiveCopy, _),
2360 [val2, val4],
2361 StructTailExpr::None,
2362 ),
2363 ) => {
2364 val1.expr.equivalent_for_indexing(val2.expr)
2365 && val3.expr.equivalent_for_indexing(val4.expr)
2366 }
2367 _ => false,
2368 }
2369 }
2370
2371 pub fn method_ident(&self) -> Option<Ident> {
2372 match self.kind {
2373 ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
2374 ExprKind::Unary(_, expr) | ExprKind::AddrOf(.., expr) => expr.method_ident(),
2375 _ => None,
2376 }
2377 }
2378}
2379
2380pub fn is_range_literal(expr: &Expr<'_>) -> bool {
2383 match expr.kind {
2384 ExprKind::Struct(ref qpath, _, _) => matches!(
2386 **qpath,
2387 QPath::LangItem(
2388 LangItem::Range
2389 | LangItem::RangeTo
2390 | LangItem::RangeFrom
2391 | LangItem::RangeFull
2392 | LangItem::RangeToInclusive
2393 | LangItem::RangeCopy
2394 | LangItem::RangeFromCopy
2395 | LangItem::RangeInclusiveCopy,
2396 ..
2397 )
2398 ),
2399
2400 ExprKind::Call(ref func, _) => {
2402 matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
2403 }
2404
2405 _ => false,
2406 }
2407}
2408
2409pub fn expr_needs_parens(expr: &Expr<'_>) -> bool {
2416 match expr.kind {
2417 ExprKind::Cast(_, _) | ExprKind::Binary(_, _, _) => true,
2419 _ if is_range_literal(expr) => true,
2421 _ => false,
2422 }
2423}
2424
2425#[derive(Debug, Clone, Copy, HashStable_Generic)]
2426pub enum ExprKind<'hir> {
2427 ConstBlock(ConstBlock),
2429 Array(&'hir [Expr<'hir>]),
2431 Call(&'hir Expr<'hir>, &'hir [Expr<'hir>]),
2438 MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
2455 Tup(&'hir [Expr<'hir>]),
2457 Binary(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
2459 Unary(UnOp, &'hir Expr<'hir>),
2461 Lit(&'hir Lit),
2463 Cast(&'hir Expr<'hir>, &'hir Ty<'hir>),
2465 Type(&'hir Expr<'hir>, &'hir Ty<'hir>),
2467 DropTemps(&'hir Expr<'hir>),
2473 Let(&'hir LetExpr<'hir>),
2478 If(&'hir Expr<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
2482 Loop(&'hir Block<'hir>, Option<Label>, LoopSource, Span),
2488 Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
2491 Closure(&'hir Closure<'hir>),
2498 Block(&'hir Block<'hir>, Option<Label>),
2500
2501 Assign(&'hir Expr<'hir>, &'hir Expr<'hir>, Span),
2503 AssignOp(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
2507 Field(&'hir Expr<'hir>, Ident),
2509 Index(&'hir Expr<'hir>, &'hir Expr<'hir>, Span),
2513
2514 Path(QPath<'hir>),
2516
2517 AddrOf(BorrowKind, Mutability, &'hir Expr<'hir>),
2519 Break(Destination, Option<&'hir Expr<'hir>>),
2521 Continue(Destination),
2523 Ret(Option<&'hir Expr<'hir>>),
2525 Become(&'hir Expr<'hir>),
2527
2528 InlineAsm(&'hir InlineAsm<'hir>),
2530
2531 OffsetOf(&'hir Ty<'hir>, &'hir [Ident]),
2533
2534 Struct(&'hir QPath<'hir>, &'hir [ExprField<'hir>], StructTailExpr<'hir>),
2539
2540 Repeat(&'hir Expr<'hir>, &'hir ConstArg<'hir>),
2545
2546 Yield(&'hir Expr<'hir>, YieldSource),
2548
2549 UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),
2552
2553 Err(rustc_span::ErrorGuaranteed),
2555}
2556
2557#[derive(Debug, Clone, Copy, HashStable_Generic)]
2558pub enum StructTailExpr<'hir> {
2559 None,
2561 Base(&'hir Expr<'hir>),
2564 DefaultFields(Span),
2568}
2569
2570#[derive(Debug, Clone, Copy, HashStable_Generic)]
2576pub enum QPath<'hir> {
2577 Resolved(Option<&'hir Ty<'hir>>, &'hir Path<'hir>),
2584
2585 TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
2592
2593 LangItem(LangItem, Span),
2595}
2596
2597impl<'hir> QPath<'hir> {
2598 pub fn span(&self) -> Span {
2600 match *self {
2601 QPath::Resolved(_, path) => path.span,
2602 QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span),
2603 QPath::LangItem(_, span) => span,
2604 }
2605 }
2606
2607 pub fn qself_span(&self) -> Span {
2610 match *self {
2611 QPath::Resolved(_, path) => path.span,
2612 QPath::TypeRelative(qself, _) => qself.span,
2613 QPath::LangItem(_, span) => span,
2614 }
2615 }
2616}
2617
2618#[derive(Copy, Clone, Debug, HashStable_Generic)]
2620pub enum LocalSource {
2621 Normal,
2623 AsyncFn,
2634 AwaitDesugar,
2636 AssignDesugar(Span),
2639 Contract,
2641}
2642
2643#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic, Encodable, Decodable)]
2645pub enum MatchSource {
2646 Normal,
2648 Postfix,
2650 ForLoopDesugar,
2652 TryDesugar(HirId),
2654 AwaitDesugar,
2656 FormatArgs,
2658}
2659
2660impl MatchSource {
2661 #[inline]
2662 pub const fn name(self) -> &'static str {
2663 use MatchSource::*;
2664 match self {
2665 Normal => "match",
2666 Postfix => ".match",
2667 ForLoopDesugar => "for",
2668 TryDesugar(_) => "?",
2669 AwaitDesugar => ".await",
2670 FormatArgs => "format_args!()",
2671 }
2672 }
2673}
2674
2675#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
2677pub enum LoopSource {
2678 Loop,
2680 While,
2682 ForLoop,
2684}
2685
2686impl LoopSource {
2687 pub fn name(self) -> &'static str {
2688 match self {
2689 LoopSource::Loop => "loop",
2690 LoopSource::While => "while",
2691 LoopSource::ForLoop => "for",
2692 }
2693 }
2694}
2695
2696#[derive(Copy, Clone, Debug, PartialEq, HashStable_Generic)]
2697pub enum LoopIdError {
2698 OutsideLoopScope,
2699 UnlabeledCfInWhileCondition,
2700 UnresolvedLabel,
2701}
2702
2703impl fmt::Display for LoopIdError {
2704 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2705 f.write_str(match self {
2706 LoopIdError::OutsideLoopScope => "not inside loop scope",
2707 LoopIdError::UnlabeledCfInWhileCondition => {
2708 "unlabeled control flow (break or continue) in while condition"
2709 }
2710 LoopIdError::UnresolvedLabel => "label not found",
2711 })
2712 }
2713}
2714
2715#[derive(Copy, Clone, Debug, HashStable_Generic)]
2716pub struct Destination {
2717 pub label: Option<Label>,
2719
2720 pub target_id: Result<HirId, LoopIdError>,
2723}
2724
2725#[derive(Copy, Clone, Debug, HashStable_Generic)]
2727pub enum YieldSource {
2728 Await { expr: Option<HirId> },
2730 Yield,
2732}
2733
2734impl fmt::Display for YieldSource {
2735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2736 f.write_str(match self {
2737 YieldSource::Await { .. } => "`await`",
2738 YieldSource::Yield => "`yield`",
2739 })
2740 }
2741}
2742
2743#[derive(Debug, Clone, Copy, HashStable_Generic)]
2746pub struct MutTy<'hir> {
2747 pub ty: &'hir Ty<'hir>,
2748 pub mutbl: Mutability,
2749}
2750
2751#[derive(Debug, Clone, Copy, HashStable_Generic)]
2754pub struct FnSig<'hir> {
2755 pub header: FnHeader,
2756 pub decl: &'hir FnDecl<'hir>,
2757 pub span: Span,
2758}
2759
2760#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
2764pub struct TraitItemId {
2765 pub owner_id: OwnerId,
2766}
2767
2768impl TraitItemId {
2769 #[inline]
2770 pub fn hir_id(&self) -> HirId {
2771 HirId::make_owner(self.owner_id.def_id)
2773 }
2774}
2775
2776#[derive(Debug, Clone, Copy, HashStable_Generic)]
2781pub struct TraitItem<'hir> {
2782 pub ident: Ident,
2783 pub owner_id: OwnerId,
2784 pub generics: &'hir Generics<'hir>,
2785 pub kind: TraitItemKind<'hir>,
2786 pub span: Span,
2787 pub defaultness: Defaultness,
2788}
2789
2790macro_rules! expect_methods_self_kind {
2791 ( $( $name:ident, $ret_ty:ty, $pat:pat, $ret_val:expr; )* ) => {
2792 $(
2793 #[track_caller]
2794 pub fn $name(&self) -> $ret_ty {
2795 let $pat = &self.kind else { expect_failed(stringify!($ident), self) };
2796 $ret_val
2797 }
2798 )*
2799 }
2800}
2801
2802macro_rules! expect_methods_self {
2803 ( $( $name:ident, $ret_ty:ty, $pat:pat, $ret_val:expr; )* ) => {
2804 $(
2805 #[track_caller]
2806 pub fn $name(&self) -> $ret_ty {
2807 let $pat = self else { expect_failed(stringify!($ident), self) };
2808 $ret_val
2809 }
2810 )*
2811 }
2812}
2813
2814#[track_caller]
2815fn expect_failed<T: fmt::Debug>(ident: &'static str, found: T) -> ! {
2816 panic!("{ident}: found {found:?}")
2817}
2818
2819impl<'hir> TraitItem<'hir> {
2820 #[inline]
2821 pub fn hir_id(&self) -> HirId {
2822 HirId::make_owner(self.owner_id.def_id)
2824 }
2825
2826 pub fn trait_item_id(&self) -> TraitItemId {
2827 TraitItemId { owner_id: self.owner_id }
2828 }
2829
2830 expect_methods_self_kind! {
2831 expect_const, (&'hir Ty<'hir>, Option<BodyId>),
2832 TraitItemKind::Const(ty, body), (ty, *body);
2833
2834 expect_fn, (&FnSig<'hir>, &TraitFn<'hir>),
2835 TraitItemKind::Fn(ty, trfn), (ty, trfn);
2836
2837 expect_type, (GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
2838 TraitItemKind::Type(bounds, ty), (bounds, *ty);
2839 }
2840}
2841
2842#[derive(Debug, Clone, Copy, HashStable_Generic)]
2844pub enum TraitFn<'hir> {
2845 Required(&'hir [Ident]),
2847
2848 Provided(BodyId),
2850}
2851
2852#[derive(Debug, Clone, Copy, HashStable_Generic)]
2854pub enum TraitItemKind<'hir> {
2855 Const(&'hir Ty<'hir>, Option<BodyId>),
2857 Fn(FnSig<'hir>, TraitFn<'hir>),
2859 Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
2862}
2863
2864#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
2868pub struct ImplItemId {
2869 pub owner_id: OwnerId,
2870}
2871
2872impl ImplItemId {
2873 #[inline]
2874 pub fn hir_id(&self) -> HirId {
2875 HirId::make_owner(self.owner_id.def_id)
2877 }
2878}
2879
2880#[derive(Debug, Clone, Copy, HashStable_Generic)]
2884pub struct ImplItem<'hir> {
2885 pub ident: Ident,
2886 pub owner_id: OwnerId,
2887 pub generics: &'hir Generics<'hir>,
2888 pub kind: ImplItemKind<'hir>,
2889 pub defaultness: Defaultness,
2890 pub span: Span,
2891 pub vis_span: Span,
2892}
2893
2894impl<'hir> ImplItem<'hir> {
2895 #[inline]
2896 pub fn hir_id(&self) -> HirId {
2897 HirId::make_owner(self.owner_id.def_id)
2899 }
2900
2901 pub fn impl_item_id(&self) -> ImplItemId {
2902 ImplItemId { owner_id: self.owner_id }
2903 }
2904
2905 expect_methods_self_kind! {
2906 expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body);
2907 expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body);
2908 expect_type, &'hir Ty<'hir>, ImplItemKind::Type(ty), ty;
2909 }
2910}
2911
2912#[derive(Debug, Clone, Copy, HashStable_Generic)]
2914pub enum ImplItemKind<'hir> {
2915 Const(&'hir Ty<'hir>, BodyId),
2918 Fn(FnSig<'hir>, BodyId),
2920 Type(&'hir Ty<'hir>),
2922}
2923
2924#[derive(Debug, Clone, Copy, HashStable_Generic)]
2935pub struct AssocItemConstraint<'hir> {
2936 #[stable_hasher(ignore)]
2937 pub hir_id: HirId,
2938 pub ident: Ident,
2939 pub gen_args: &'hir GenericArgs<'hir>,
2940 pub kind: AssocItemConstraintKind<'hir>,
2941 pub span: Span,
2942}
2943
2944impl<'hir> AssocItemConstraint<'hir> {
2945 pub fn ty(self) -> Option<&'hir Ty<'hir>> {
2947 match self.kind {
2948 AssocItemConstraintKind::Equality { term: Term::Ty(ty) } => Some(ty),
2949 _ => None,
2950 }
2951 }
2952
2953 pub fn ct(self) -> Option<&'hir ConstArg<'hir>> {
2955 match self.kind {
2956 AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
2957 _ => None,
2958 }
2959 }
2960}
2961
2962#[derive(Debug, Clone, Copy, HashStable_Generic)]
2963pub enum Term<'hir> {
2964 Ty(&'hir Ty<'hir>),
2965 Const(&'hir ConstArg<'hir>),
2966}
2967
2968impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
2969 fn from(ty: &'hir Ty<'hir>) -> Self {
2970 Term::Ty(ty)
2971 }
2972}
2973
2974impl<'hir> From<&'hir ConstArg<'hir>> for Term<'hir> {
2975 fn from(c: &'hir ConstArg<'hir>) -> Self {
2976 Term::Const(c)
2977 }
2978}
2979
2980#[derive(Debug, Clone, Copy, HashStable_Generic)]
2982pub enum AssocItemConstraintKind<'hir> {
2983 Equality { term: Term<'hir> },
2990 Bound { bounds: &'hir [GenericBound<'hir>] },
2992}
2993
2994impl<'hir> AssocItemConstraintKind<'hir> {
2995 pub fn descr(&self) -> &'static str {
2996 match self {
2997 AssocItemConstraintKind::Equality { .. } => "binding",
2998 AssocItemConstraintKind::Bound { .. } => "constraint",
2999 }
3000 }
3001}
3002
3003#[derive(Debug, Clone, Copy, HashStable_Generic)]
3007pub enum AmbigArg {}
3008
3009#[derive(Debug, Clone, Copy, HashStable_Generic)]
3010#[repr(C)]
3011pub struct Ty<'hir, Unambig = ()> {
3018 #[stable_hasher(ignore)]
3019 pub hir_id: HirId,
3020 pub span: Span,
3021 pub kind: TyKind<'hir, Unambig>,
3022}
3023
3024impl<'hir> Ty<'hir, AmbigArg> {
3025 pub fn as_unambig_ty(&self) -> &Ty<'hir> {
3036 let ptr = self as *const Ty<'hir, AmbigArg> as *const Ty<'hir, ()>;
3039 unsafe { &*ptr }
3040 }
3041}
3042
3043impl<'hir> Ty<'hir> {
3044 pub fn try_as_ambig_ty(&self) -> Option<&Ty<'hir, AmbigArg>> {
3050 if let TyKind::Infer(()) = self.kind {
3051 return None;
3052 }
3053
3054 let ptr = self as *const Ty<'hir> as *const Ty<'hir, AmbigArg>;
3058 Some(unsafe { &*ptr })
3059 }
3060}
3061
3062impl<'hir> Ty<'hir, AmbigArg> {
3063 pub fn peel_refs(&self) -> &Ty<'hir> {
3064 let mut final_ty = self.as_unambig_ty();
3065 while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
3066 final_ty = ty;
3067 }
3068 final_ty
3069 }
3070}
3071
3072impl<'hir> Ty<'hir> {
3073 pub fn peel_refs(&self) -> &Self {
3074 let mut final_ty = self;
3075 while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
3076 final_ty = ty;
3077 }
3078 final_ty
3079 }
3080
3081 pub fn as_generic_param(&self) -> Option<(DefId, Ident)> {
3083 let TyKind::Path(QPath::Resolved(None, path)) = self.kind else {
3084 return None;
3085 };
3086 let [segment] = &path.segments else {
3087 return None;
3088 };
3089 match path.res {
3090 Res::Def(DefKind::TyParam, def_id) | Res::SelfTyParam { trait_: def_id } => {
3091 Some((def_id, segment.ident))
3092 }
3093 _ => None,
3094 }
3095 }
3096
3097 pub fn find_self_aliases(&self) -> Vec<Span> {
3098 use crate::intravisit::Visitor;
3099 struct MyVisitor(Vec<Span>);
3100 impl<'v> Visitor<'v> for MyVisitor {
3101 fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) {
3102 if matches!(
3103 &t.kind,
3104 TyKind::Path(QPath::Resolved(
3105 _,
3106 Path { res: crate::def::Res::SelfTyAlias { .. }, .. },
3107 ))
3108 ) {
3109 self.0.push(t.span);
3110 return;
3111 }
3112 crate::intravisit::walk_ty(self, t);
3113 }
3114 }
3115
3116 let mut my_visitor = MyVisitor(vec![]);
3117 my_visitor.visit_ty_unambig(self);
3118 my_visitor.0
3119 }
3120
3121 pub fn is_suggestable_infer_ty(&self) -> bool {
3124 fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool {
3125 generic_args.iter().any(|arg| match arg {
3126 GenericArg::Type(ty) => ty.as_unambig_ty().is_suggestable_infer_ty(),
3127 GenericArg::Infer(_) => true,
3128 _ => false,
3129 })
3130 }
3131 debug!(?self);
3132 match &self.kind {
3133 TyKind::Infer(()) => true,
3134 TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
3135 TyKind::Array(ty, length) => {
3136 ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..))
3137 }
3138 TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
3139 TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
3140 TyKind::Path(QPath::TypeRelative(ty, segment)) => {
3141 ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
3142 }
3143 TyKind::Path(QPath::Resolved(ty_opt, Path { segments, .. })) => {
3144 ty_opt.is_some_and(Self::is_suggestable_infer_ty)
3145 || segments
3146 .iter()
3147 .any(|segment| are_suggestable_generic_args(segment.args().args))
3148 }
3149 _ => false,
3150 }
3151 }
3152}
3153
3154#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
3156pub enum PrimTy {
3157 Int(IntTy),
3158 Uint(UintTy),
3159 Float(FloatTy),
3160 Str,
3161 Bool,
3162 Char,
3163}
3164
3165impl PrimTy {
3166 pub const ALL: [Self; 19] = [
3168 Self::Int(IntTy::I8),
3170 Self::Int(IntTy::I16),
3171 Self::Int(IntTy::I32),
3172 Self::Int(IntTy::I64),
3173 Self::Int(IntTy::I128),
3174 Self::Int(IntTy::Isize),
3175 Self::Uint(UintTy::U8),
3176 Self::Uint(UintTy::U16),
3177 Self::Uint(UintTy::U32),
3178 Self::Uint(UintTy::U64),
3179 Self::Uint(UintTy::U128),
3180 Self::Uint(UintTy::Usize),
3181 Self::Float(FloatTy::F16),
3182 Self::Float(FloatTy::F32),
3183 Self::Float(FloatTy::F64),
3184 Self::Float(FloatTy::F128),
3185 Self::Bool,
3186 Self::Char,
3187 Self::Str,
3188 ];
3189
3190 pub fn name_str(self) -> &'static str {
3194 match self {
3195 PrimTy::Int(i) => i.name_str(),
3196 PrimTy::Uint(u) => u.name_str(),
3197 PrimTy::Float(f) => f.name_str(),
3198 PrimTy::Str => "str",
3199 PrimTy::Bool => "bool",
3200 PrimTy::Char => "char",
3201 }
3202 }
3203
3204 pub fn name(self) -> Symbol {
3205 match self {
3206 PrimTy::Int(i) => i.name(),
3207 PrimTy::Uint(u) => u.name(),
3208 PrimTy::Float(f) => f.name(),
3209 PrimTy::Str => sym::str,
3210 PrimTy::Bool => sym::bool,
3211 PrimTy::Char => sym::char,
3212 }
3213 }
3214
3215 pub fn from_name(name: Symbol) -> Option<Self> {
3218 let ty = match name {
3219 sym::i8 => Self::Int(IntTy::I8),
3221 sym::i16 => Self::Int(IntTy::I16),
3222 sym::i32 => Self::Int(IntTy::I32),
3223 sym::i64 => Self::Int(IntTy::I64),
3224 sym::i128 => Self::Int(IntTy::I128),
3225 sym::isize => Self::Int(IntTy::Isize),
3226 sym::u8 => Self::Uint(UintTy::U8),
3227 sym::u16 => Self::Uint(UintTy::U16),
3228 sym::u32 => Self::Uint(UintTy::U32),
3229 sym::u64 => Self::Uint(UintTy::U64),
3230 sym::u128 => Self::Uint(UintTy::U128),
3231 sym::usize => Self::Uint(UintTy::Usize),
3232 sym::f16 => Self::Float(FloatTy::F16),
3233 sym::f32 => Self::Float(FloatTy::F32),
3234 sym::f64 => Self::Float(FloatTy::F64),
3235 sym::f128 => Self::Float(FloatTy::F128),
3236 sym::bool => Self::Bool,
3237 sym::char => Self::Char,
3238 sym::str => Self::Str,
3239 _ => return None,
3240 };
3241 Some(ty)
3242 }
3243}
3244
3245#[derive(Debug, Clone, Copy, HashStable_Generic)]
3246pub struct BareFnTy<'hir> {
3247 pub safety: Safety,
3248 pub abi: ExternAbi,
3249 pub generic_params: &'hir [GenericParam<'hir>],
3250 pub decl: &'hir FnDecl<'hir>,
3251 pub param_names: &'hir [Ident],
3252}
3253
3254#[derive(Debug, Clone, Copy, HashStable_Generic)]
3255pub struct UnsafeBinderTy<'hir> {
3256 pub generic_params: &'hir [GenericParam<'hir>],
3257 pub inner_ty: &'hir Ty<'hir>,
3258}
3259
3260#[derive(Debug, Clone, Copy, HashStable_Generic)]
3261pub struct OpaqueTy<'hir> {
3262 #[stable_hasher(ignore)]
3263 pub hir_id: HirId,
3264 pub def_id: LocalDefId,
3265 pub bounds: GenericBounds<'hir>,
3266 pub origin: OpaqueTyOrigin<LocalDefId>,
3267 pub span: Span,
3268}
3269
3270#[derive(Debug, Clone, Copy, HashStable_Generic)]
3271pub enum PreciseCapturingArg<'hir> {
3272 Lifetime(&'hir Lifetime),
3273 Param(PreciseCapturingNonLifetimeArg),
3275}
3276
3277impl PreciseCapturingArg<'_> {
3278 pub fn hir_id(self) -> HirId {
3279 match self {
3280 PreciseCapturingArg::Lifetime(lt) => lt.hir_id,
3281 PreciseCapturingArg::Param(param) => param.hir_id,
3282 }
3283 }
3284
3285 pub fn name(self) -> Symbol {
3286 match self {
3287 PreciseCapturingArg::Lifetime(lt) => lt.ident.name,
3288 PreciseCapturingArg::Param(param) => param.ident.name,
3289 }
3290 }
3291}
3292
3293#[derive(Debug, Clone, Copy, HashStable_Generic)]
3298pub struct PreciseCapturingNonLifetimeArg {
3299 #[stable_hasher(ignore)]
3300 pub hir_id: HirId,
3301 pub ident: Ident,
3302 pub res: Res,
3303}
3304
3305#[derive(Copy, Clone, PartialEq, Eq, Debug)]
3306#[derive(HashStable_Generic, Encodable, Decodable)]
3307pub enum RpitContext {
3308 Trait,
3309 TraitImpl,
3310}
3311
3312#[derive(Copy, Clone, PartialEq, Eq, Debug)]
3314#[derive(HashStable_Generic, Encodable, Decodable)]
3315pub enum OpaqueTyOrigin<D> {
3316 FnReturn {
3318 parent: D,
3320 in_trait_or_impl: Option<RpitContext>,
3322 },
3323 AsyncFn {
3325 parent: D,
3327 in_trait_or_impl: Option<RpitContext>,
3329 },
3330 TyAlias {
3332 parent: D,
3334 in_assoc_ty: bool,
3336 },
3337}
3338
3339#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
3340pub enum InferDelegationKind {
3341 Input(usize),
3342 Output,
3343}
3344
3345#[derive(Debug, Clone, Copy, HashStable_Generic)]
3347#[repr(u8, C)]
3349pub enum TyKind<'hir, Unambig = ()> {
3350 InferDelegation(DefId, InferDelegationKind),
3352 Slice(&'hir Ty<'hir>),
3354 Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>),
3356 Ptr(MutTy<'hir>),
3358 Ref(&'hir Lifetime, MutTy<'hir>),
3360 BareFn(&'hir BareFnTy<'hir>),
3362 UnsafeBinder(&'hir UnsafeBinderTy<'hir>),
3364 Never,
3366 Tup(&'hir [Ty<'hir>]),
3368 Path(QPath<'hir>),
3373 OpaqueDef(&'hir OpaqueTy<'hir>),
3375 TraitAscription(GenericBounds<'hir>),
3377 TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>),
3383 Typeof(&'hir AnonConst),
3385 Err(rustc_span::ErrorGuaranteed),
3387 Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
3389 Infer(Unambig),
3395}
3396
3397#[derive(Debug, Clone, Copy, HashStable_Generic)]
3398pub enum InlineAsmOperand<'hir> {
3399 In {
3400 reg: InlineAsmRegOrRegClass,
3401 expr: &'hir Expr<'hir>,
3402 },
3403 Out {
3404 reg: InlineAsmRegOrRegClass,
3405 late: bool,
3406 expr: Option<&'hir Expr<'hir>>,
3407 },
3408 InOut {
3409 reg: InlineAsmRegOrRegClass,
3410 late: bool,
3411 expr: &'hir Expr<'hir>,
3412 },
3413 SplitInOut {
3414 reg: InlineAsmRegOrRegClass,
3415 late: bool,
3416 in_expr: &'hir Expr<'hir>,
3417 out_expr: Option<&'hir Expr<'hir>>,
3418 },
3419 Const {
3420 anon_const: &'hir AnonConst,
3421 },
3422 SymFn {
3423 anon_const: &'hir AnonConst,
3424 },
3425 SymStatic {
3426 path: QPath<'hir>,
3427 def_id: DefId,
3428 },
3429 Label {
3430 block: &'hir Block<'hir>,
3431 },
3432}
3433
3434impl<'hir> InlineAsmOperand<'hir> {
3435 pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
3436 match *self {
3437 Self::In { reg, .. }
3438 | Self::Out { reg, .. }
3439 | Self::InOut { reg, .. }
3440 | Self::SplitInOut { reg, .. } => Some(reg),
3441 Self::Const { .. }
3442 | Self::SymFn { .. }
3443 | Self::SymStatic { .. }
3444 | Self::Label { .. } => None,
3445 }
3446 }
3447
3448 pub fn is_clobber(&self) -> bool {
3449 matches!(
3450 self,
3451 InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None }
3452 )
3453 }
3454}
3455
3456#[derive(Debug, Clone, Copy, HashStable_Generic)]
3457pub struct InlineAsm<'hir> {
3458 pub asm_macro: ast::AsmMacro,
3459 pub template: &'hir [InlineAsmTemplatePiece],
3460 pub template_strs: &'hir [(Symbol, Option<Symbol>, Span)],
3461 pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
3462 pub options: InlineAsmOptions,
3463 pub line_spans: &'hir [Span],
3464}
3465
3466impl InlineAsm<'_> {
3467 pub fn contains_label(&self) -> bool {
3468 self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. }))
3469 }
3470}
3471
3472#[derive(Debug, Clone, Copy, HashStable_Generic)]
3474pub struct Param<'hir> {
3475 #[stable_hasher(ignore)]
3476 pub hir_id: HirId,
3477 pub pat: &'hir Pat<'hir>,
3478 pub ty_span: Span,
3479 pub span: Span,
3480}
3481
3482#[derive(Debug, Clone, Copy, HashStable_Generic)]
3484pub struct FnDecl<'hir> {
3485 pub inputs: &'hir [Ty<'hir>],
3489 pub output: FnRetTy<'hir>,
3490 pub c_variadic: bool,
3491 pub implicit_self: ImplicitSelfKind,
3493 pub lifetime_elision_allowed: bool,
3495}
3496
3497impl<'hir> FnDecl<'hir> {
3498 pub fn opt_delegation_sig_id(&self) -> Option<DefId> {
3499 if let FnRetTy::Return(ty) = self.output
3500 && let TyKind::InferDelegation(sig_id, _) = ty.kind
3501 {
3502 return Some(sig_id);
3503 }
3504 None
3505 }
3506}
3507
3508#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
3510pub enum ImplicitSelfKind {
3511 Imm,
3513 Mut,
3515 RefImm,
3517 RefMut,
3519 None,
3522}
3523
3524impl ImplicitSelfKind {
3525 pub fn has_implicit_self(&self) -> bool {
3527 !matches!(*self, ImplicitSelfKind::None)
3528 }
3529}
3530
3531#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
3532pub enum IsAsync {
3533 Async(Span),
3534 NotAsync,
3535}
3536
3537impl IsAsync {
3538 pub fn is_async(self) -> bool {
3539 matches!(self, IsAsync::Async(_))
3540 }
3541}
3542
3543#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
3544pub enum Defaultness {
3545 Default { has_value: bool },
3546 Final,
3547}
3548
3549impl Defaultness {
3550 pub fn has_value(&self) -> bool {
3551 match *self {
3552 Defaultness::Default { has_value } => has_value,
3553 Defaultness::Final => true,
3554 }
3555 }
3556
3557 pub fn is_final(&self) -> bool {
3558 *self == Defaultness::Final
3559 }
3560
3561 pub fn is_default(&self) -> bool {
3562 matches!(*self, Defaultness::Default { .. })
3563 }
3564}
3565
3566#[derive(Debug, Clone, Copy, HashStable_Generic)]
3567pub enum FnRetTy<'hir> {
3568 DefaultReturn(Span),
3574 Return(&'hir Ty<'hir>),
3576}
3577
3578impl<'hir> FnRetTy<'hir> {
3579 #[inline]
3580 pub fn span(&self) -> Span {
3581 match *self {
3582 Self::DefaultReturn(span) => span,
3583 Self::Return(ref ty) => ty.span,
3584 }
3585 }
3586
3587 pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> {
3588 if let Self::Return(ty) = self
3589 && ty.is_suggestable_infer_ty()
3590 {
3591 return Some(*ty);
3592 }
3593 None
3594 }
3595}
3596
3597#[derive(Copy, Clone, Debug, HashStable_Generic)]
3599pub enum ClosureBinder {
3600 Default,
3602 For { span: Span },
3606}
3607
3608#[derive(Debug, Clone, Copy, HashStable_Generic)]
3609pub struct Mod<'hir> {
3610 pub spans: ModSpans,
3611 pub item_ids: &'hir [ItemId],
3612}
3613
3614#[derive(Copy, Clone, Debug, HashStable_Generic)]
3615pub struct ModSpans {
3616 pub inner_span: Span,
3620 pub inject_use_span: Span,
3621}
3622
3623#[derive(Debug, Clone, Copy, HashStable_Generic)]
3624pub struct EnumDef<'hir> {
3625 pub variants: &'hir [Variant<'hir>],
3626}
3627
3628#[derive(Debug, Clone, Copy, HashStable_Generic)]
3629pub struct Variant<'hir> {
3630 pub ident: Ident,
3632 #[stable_hasher(ignore)]
3634 pub hir_id: HirId,
3635 pub def_id: LocalDefId,
3636 pub data: VariantData<'hir>,
3638 pub disr_expr: Option<&'hir AnonConst>,
3640 pub span: Span,
3642}
3643
3644#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
3645pub enum UseKind {
3646 Single,
3650
3651 Glob,
3653
3654 ListStem,
3658}
3659
3660#[derive(Clone, Debug, Copy, HashStable_Generic)]
3667pub struct TraitRef<'hir> {
3668 pub path: &'hir Path<'hir>,
3669 #[stable_hasher(ignore)]
3671 pub hir_ref_id: HirId,
3672}
3673
3674impl TraitRef<'_> {
3675 pub fn trait_def_id(&self) -> Option<DefId> {
3677 match self.path.res {
3678 Res::Def(DefKind::Trait | DefKind::TraitAlias, did) => Some(did),
3679 Res::Err => None,
3680 res => panic!("{res:?} did not resolve to a trait or trait alias"),
3681 }
3682 }
3683}
3684
3685#[derive(Clone, Debug, Copy, HashStable_Generic)]
3686pub struct PolyTraitRef<'hir> {
3687 pub bound_generic_params: &'hir [GenericParam<'hir>],
3689
3690 pub modifiers: TraitBoundModifiers,
3694
3695 pub trait_ref: TraitRef<'hir>,
3697
3698 pub span: Span,
3699}
3700
3701#[derive(Debug, Clone, Copy, HashStable_Generic)]
3702pub struct FieldDef<'hir> {
3703 pub span: Span,
3704 pub vis_span: Span,
3705 pub ident: Ident,
3706 #[stable_hasher(ignore)]
3707 pub hir_id: HirId,
3708 pub def_id: LocalDefId,
3709 pub ty: &'hir Ty<'hir>,
3710 pub safety: Safety,
3711 pub default: Option<&'hir AnonConst>,
3712}
3713
3714impl FieldDef<'_> {
3715 pub fn is_positional(&self) -> bool {
3717 self.ident.as_str().as_bytes()[0].is_ascii_digit()
3718 }
3719}
3720
3721#[derive(Debug, Clone, Copy, HashStable_Generic)]
3723pub enum VariantData<'hir> {
3724 Struct { fields: &'hir [FieldDef<'hir>], recovered: ast::Recovered },
3728 Tuple(&'hir [FieldDef<'hir>], #[stable_hasher(ignore)] HirId, LocalDefId),
3732 Unit(#[stable_hasher(ignore)] HirId, LocalDefId),
3736}
3737
3738impl<'hir> VariantData<'hir> {
3739 pub fn fields(&self) -> &'hir [FieldDef<'hir>] {
3741 match *self {
3742 VariantData::Struct { fields, .. } | VariantData::Tuple(fields, ..) => fields,
3743 _ => &[],
3744 }
3745 }
3746
3747 pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> {
3748 match *self {
3749 VariantData::Tuple(_, hir_id, def_id) => Some((CtorKind::Fn, hir_id, def_id)),
3750 VariantData::Unit(hir_id, def_id) => Some((CtorKind::Const, hir_id, def_id)),
3751 VariantData::Struct { .. } => None,
3752 }
3753 }
3754
3755 #[inline]
3756 pub fn ctor_kind(&self) -> Option<CtorKind> {
3757 self.ctor().map(|(kind, ..)| kind)
3758 }
3759
3760 #[inline]
3762 pub fn ctor_hir_id(&self) -> Option<HirId> {
3763 self.ctor().map(|(_, hir_id, _)| hir_id)
3764 }
3765
3766 #[inline]
3768 pub fn ctor_def_id(&self) -> Option<LocalDefId> {
3769 self.ctor().map(|(.., def_id)| def_id)
3770 }
3771}
3772
3773#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
3777pub struct ItemId {
3778 pub owner_id: OwnerId,
3779}
3780
3781impl ItemId {
3782 #[inline]
3783 pub fn hir_id(&self) -> HirId {
3784 HirId::make_owner(self.owner_id.def_id)
3786 }
3787}
3788
3789#[derive(Debug, Clone, Copy, HashStable_Generic)]
3800pub struct Item<'hir> {
3801 pub ident: Ident,
3802 pub owner_id: OwnerId,
3803 pub kind: ItemKind<'hir>,
3804 pub span: Span,
3805 pub vis_span: Span,
3806}
3807
3808impl<'hir> Item<'hir> {
3809 #[inline]
3810 pub fn hir_id(&self) -> HirId {
3811 HirId::make_owner(self.owner_id.def_id)
3813 }
3814
3815 pub fn item_id(&self) -> ItemId {
3816 ItemId { owner_id: self.owner_id }
3817 }
3818
3819 pub fn is_adt(&self) -> bool {
3822 matches!(self.kind, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..))
3823 }
3824
3825 pub fn is_struct_or_union(&self) -> bool {
3827 matches!(self.kind, ItemKind::Struct(..) | ItemKind::Union(..))
3828 }
3829
3830 expect_methods_self_kind! {
3831 expect_extern_crate, Option<Symbol>, ItemKind::ExternCrate(s), *s;
3832
3833 expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk);
3834
3835 expect_static, (&'hir Ty<'hir>, Mutability, BodyId),
3836 ItemKind::Static(ty, mutbl, body), (ty, *mutbl, *body);
3837
3838 expect_const, (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
3839 ItemKind::Const(ty, generics, body), (ty, generics, *body);
3840
3841 expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId),
3842 ItemKind::Fn { sig, generics, body, .. }, (sig, generics, *body);
3843
3844 expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk);
3845
3846 expect_mod, &'hir Mod<'hir>, ItemKind::Mod(m), m;
3847
3848 expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]),
3849 ItemKind::ForeignMod { abi, items }, (*abi, items);
3850
3851 expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm;
3852
3853 expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>),
3854 ItemKind::TyAlias(ty, generics), (ty, generics);
3855
3856 expect_enum, (&EnumDef<'hir>, &'hir Generics<'hir>), ItemKind::Enum(def, generics), (def, generics);
3857
3858 expect_struct, (&VariantData<'hir>, &'hir Generics<'hir>),
3859 ItemKind::Struct(data, generics), (data, generics);
3860
3861 expect_union, (&VariantData<'hir>, &'hir Generics<'hir>),
3862 ItemKind::Union(data, generics), (data, generics);
3863
3864 expect_trait,
3865 (IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
3866 ItemKind::Trait(is_auto, safety, generics, bounds, items),
3867 (*is_auto, *safety, generics, bounds, items);
3868
3869 expect_trait_alias, (&'hir Generics<'hir>, GenericBounds<'hir>),
3870 ItemKind::TraitAlias(generics, bounds), (generics, bounds);
3871
3872 expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp;
3873 }
3874}
3875
3876#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
3877#[derive(Encodable, Decodable, HashStable_Generic)]
3878pub enum Safety {
3879 Unsafe,
3880 Safe,
3881}
3882
3883impl Safety {
3884 pub fn prefix_str(self) -> &'static str {
3885 match self {
3886 Self::Unsafe => "unsafe ",
3887 Self::Safe => "",
3888 }
3889 }
3890
3891 #[inline]
3892 pub fn is_unsafe(self) -> bool {
3893 !self.is_safe()
3894 }
3895
3896 #[inline]
3897 pub fn is_safe(self) -> bool {
3898 match self {
3899 Self::Unsafe => false,
3900 Self::Safe => true,
3901 }
3902 }
3903}
3904
3905impl fmt::Display for Safety {
3906 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3907 f.write_str(match *self {
3908 Self::Unsafe => "unsafe",
3909 Self::Safe => "safe",
3910 })
3911 }
3912}
3913
3914#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
3915pub enum Constness {
3916 Const,
3917 NotConst,
3918}
3919
3920impl fmt::Display for Constness {
3921 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3922 f.write_str(match *self {
3923 Self::Const => "const",
3924 Self::NotConst => "non-const",
3925 })
3926 }
3927}
3928
3929#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
3934pub enum HeaderSafety {
3935 SafeTargetFeatures,
3941 Normal(Safety),
3942}
3943
3944impl From<Safety> for HeaderSafety {
3945 fn from(v: Safety) -> Self {
3946 Self::Normal(v)
3947 }
3948}
3949
3950#[derive(Copy, Clone, Debug, HashStable_Generic)]
3951pub struct FnHeader {
3952 pub safety: HeaderSafety,
3953 pub constness: Constness,
3954 pub asyncness: IsAsync,
3955 pub abi: ExternAbi,
3956}
3957
3958impl FnHeader {
3959 pub fn is_async(&self) -> bool {
3960 matches!(self.asyncness, IsAsync::Async(_))
3961 }
3962
3963 pub fn is_const(&self) -> bool {
3964 matches!(self.constness, Constness::Const)
3965 }
3966
3967 pub fn is_unsafe(&self) -> bool {
3968 self.safety().is_unsafe()
3969 }
3970
3971 pub fn is_safe(&self) -> bool {
3972 self.safety().is_safe()
3973 }
3974
3975 pub fn safety(&self) -> Safety {
3976 match self.safety {
3977 HeaderSafety::SafeTargetFeatures => Safety::Unsafe,
3978 HeaderSafety::Normal(safety) => safety,
3979 }
3980 }
3981}
3982
3983#[derive(Debug, Clone, Copy, HashStable_Generic)]
3984pub enum ItemKind<'hir> {
3985 ExternCrate(Option<Symbol>),
3989
3990 Use(&'hir UsePath<'hir>, UseKind),
3996
3997 Static(&'hir Ty<'hir>, Mutability, BodyId),
3999 Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
4001 Fn {
4003 sig: FnSig<'hir>,
4004 generics: &'hir Generics<'hir>,
4005 body: BodyId,
4006 has_body: bool,
4010 },
4011 Macro(&'hir ast::MacroDef, MacroKind),
4013 Mod(&'hir Mod<'hir>),
4015 ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] },
4017 GlobalAsm(&'hir InlineAsm<'hir>),
4019 TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
4021 Enum(EnumDef<'hir>, &'hir Generics<'hir>),
4023 Struct(VariantData<'hir>, &'hir Generics<'hir>),
4025 Union(VariantData<'hir>, &'hir Generics<'hir>),
4027 Trait(IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
4029 TraitAlias(&'hir Generics<'hir>, GenericBounds<'hir>),
4031
4032 Impl(&'hir Impl<'hir>),
4034}
4035
4036#[derive(Debug, Clone, Copy, HashStable_Generic)]
4041pub struct Impl<'hir> {
4042 pub constness: Constness,
4043 pub safety: Safety,
4044 pub polarity: ImplPolarity,
4045 pub defaultness: Defaultness,
4046 pub defaultness_span: Option<Span>,
4049 pub generics: &'hir Generics<'hir>,
4050
4051 pub of_trait: Option<TraitRef<'hir>>,
4053
4054 pub self_ty: &'hir Ty<'hir>,
4055 pub items: &'hir [ImplItemRef],
4056}
4057
4058impl ItemKind<'_> {
4059 pub fn generics(&self) -> Option<&Generics<'_>> {
4060 Some(match self {
4061 ItemKind::Fn { generics, .. }
4062 | ItemKind::TyAlias(_, generics)
4063 | ItemKind::Const(_, generics, _)
4064 | ItemKind::Enum(_, generics)
4065 | ItemKind::Struct(_, generics)
4066 | ItemKind::Union(_, generics)
4067 | ItemKind::Trait(_, _, generics, _, _)
4068 | ItemKind::TraitAlias(generics, _)
4069 | ItemKind::Impl(Impl { generics, .. }) => generics,
4070 _ => return None,
4071 })
4072 }
4073
4074 pub fn descr(&self) -> &'static str {
4075 match self {
4076 ItemKind::ExternCrate(..) => "extern crate",
4077 ItemKind::Use(..) => "`use` import",
4078 ItemKind::Static(..) => "static item",
4079 ItemKind::Const(..) => "constant item",
4080 ItemKind::Fn { .. } => "function",
4081 ItemKind::Macro(..) => "macro",
4082 ItemKind::Mod(..) => "module",
4083 ItemKind::ForeignMod { .. } => "extern block",
4084 ItemKind::GlobalAsm(..) => "global asm item",
4085 ItemKind::TyAlias(..) => "type alias",
4086 ItemKind::Enum(..) => "enum",
4087 ItemKind::Struct(..) => "struct",
4088 ItemKind::Union(..) => "union",
4089 ItemKind::Trait(..) => "trait",
4090 ItemKind::TraitAlias(..) => "trait alias",
4091 ItemKind::Impl(..) => "implementation",
4092 }
4093 }
4094}
4095
4096#[derive(Debug, Clone, Copy, HashStable_Generic)]
4103pub struct TraitItemRef {
4104 pub id: TraitItemId,
4105 pub ident: Ident,
4106 pub kind: AssocItemKind,
4107 pub span: Span,
4108}
4109
4110#[derive(Debug, Clone, Copy, HashStable_Generic)]
4117pub struct ImplItemRef {
4118 pub id: ImplItemId,
4119 pub ident: Ident,
4120 pub kind: AssocItemKind,
4121 pub span: Span,
4122 pub trait_item_def_id: Option<DefId>,
4124}
4125
4126#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
4127pub enum AssocItemKind {
4128 Const,
4129 Fn { has_self: bool },
4130 Type,
4131}
4132
4133#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
4137pub struct ForeignItemId {
4138 pub owner_id: OwnerId,
4139}
4140
4141impl ForeignItemId {
4142 #[inline]
4143 pub fn hir_id(&self) -> HirId {
4144 HirId::make_owner(self.owner_id.def_id)
4146 }
4147}
4148
4149#[derive(Debug, Clone, Copy, HashStable_Generic)]
4156pub struct ForeignItemRef {
4157 pub id: ForeignItemId,
4158 pub ident: Ident,
4159 pub span: Span,
4160}
4161
4162#[derive(Debug, Clone, Copy, HashStable_Generic)]
4163pub struct ForeignItem<'hir> {
4164 pub ident: Ident,
4165 pub kind: ForeignItemKind<'hir>,
4166 pub owner_id: OwnerId,
4167 pub span: Span,
4168 pub vis_span: Span,
4169}
4170
4171impl ForeignItem<'_> {
4172 #[inline]
4173 pub fn hir_id(&self) -> HirId {
4174 HirId::make_owner(self.owner_id.def_id)
4176 }
4177
4178 pub fn foreign_item_id(&self) -> ForeignItemId {
4179 ForeignItemId { owner_id: self.owner_id }
4180 }
4181}
4182
4183#[derive(Debug, Clone, Copy, HashStable_Generic)]
4185pub enum ForeignItemKind<'hir> {
4186 Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>),
4188 Static(&'hir Ty<'hir>, Mutability, Safety),
4190 Type,
4192}
4193
4194#[derive(Debug, Copy, Clone, HashStable_Generic)]
4196pub struct Upvar {
4197 pub span: Span,
4199}
4200
4201#[derive(Debug, Clone, HashStable_Generic)]
4205pub struct TraitCandidate {
4206 pub def_id: DefId,
4207 pub import_ids: SmallVec<[LocalDefId; 1]>,
4208}
4209
4210#[derive(Copy, Clone, Debug, HashStable_Generic)]
4211pub enum OwnerNode<'hir> {
4212 Item(&'hir Item<'hir>),
4213 ForeignItem(&'hir ForeignItem<'hir>),
4214 TraitItem(&'hir TraitItem<'hir>),
4215 ImplItem(&'hir ImplItem<'hir>),
4216 Crate(&'hir Mod<'hir>),
4217 Synthetic,
4218}
4219
4220impl<'hir> OwnerNode<'hir> {
4221 pub fn ident(&self) -> Option<Ident> {
4222 match self {
4223 OwnerNode::Item(Item { ident, .. })
4224 | OwnerNode::ForeignItem(ForeignItem { ident, .. })
4225 | OwnerNode::ImplItem(ImplItem { ident, .. })
4226 | OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
4227 OwnerNode::Crate(..) | OwnerNode::Synthetic => None,
4228 }
4229 }
4230
4231 pub fn span(&self) -> Span {
4232 match self {
4233 OwnerNode::Item(Item { span, .. })
4234 | OwnerNode::ForeignItem(ForeignItem { span, .. })
4235 | OwnerNode::ImplItem(ImplItem { span, .. })
4236 | OwnerNode::TraitItem(TraitItem { span, .. }) => *span,
4237 OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span,
4238 OwnerNode::Synthetic => unreachable!(),
4239 }
4240 }
4241
4242 pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
4243 match self {
4244 OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4245 | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4246 | OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4247 | OwnerNode::ForeignItem(ForeignItem {
4248 kind: ForeignItemKind::Fn(fn_sig, _, _), ..
4249 }) => Some(fn_sig),
4250 _ => None,
4251 }
4252 }
4253
4254 pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
4255 match self {
4256 OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4257 | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4258 | OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4259 | OwnerNode::ForeignItem(ForeignItem {
4260 kind: ForeignItemKind::Fn(fn_sig, _, _), ..
4261 }) => Some(fn_sig.decl),
4262 _ => None,
4263 }
4264 }
4265
4266 pub fn body_id(&self) -> Option<BodyId> {
4267 match self {
4268 OwnerNode::Item(Item {
4269 kind:
4270 ItemKind::Static(_, _, body)
4271 | ItemKind::Const(_, _, body)
4272 | ItemKind::Fn { body, .. },
4273 ..
4274 })
4275 | OwnerNode::TraitItem(TraitItem {
4276 kind:
4277 TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
4278 ..
4279 })
4280 | OwnerNode::ImplItem(ImplItem {
4281 kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
4282 ..
4283 }) => Some(*body),
4284 _ => None,
4285 }
4286 }
4287
4288 pub fn generics(self) -> Option<&'hir Generics<'hir>> {
4289 Node::generics(self.into())
4290 }
4291
4292 pub fn def_id(self) -> OwnerId {
4293 match self {
4294 OwnerNode::Item(Item { owner_id, .. })
4295 | OwnerNode::TraitItem(TraitItem { owner_id, .. })
4296 | OwnerNode::ImplItem(ImplItem { owner_id, .. })
4297 | OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id,
4298 OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
4299 OwnerNode::Synthetic => unreachable!(),
4300 }
4301 }
4302
4303 pub fn is_impl_block(&self) -> bool {
4305 matches!(self, OwnerNode::Item(Item { kind: ItemKind::Impl(_), .. }))
4306 }
4307
4308 expect_methods_self! {
4309 expect_item, &'hir Item<'hir>, OwnerNode::Item(n), n;
4310 expect_foreign_item, &'hir ForeignItem<'hir>, OwnerNode::ForeignItem(n), n;
4311 expect_impl_item, &'hir ImplItem<'hir>, OwnerNode::ImplItem(n), n;
4312 expect_trait_item, &'hir TraitItem<'hir>, OwnerNode::TraitItem(n), n;
4313 }
4314}
4315
4316impl<'hir> From<&'hir Item<'hir>> for OwnerNode<'hir> {
4317 fn from(val: &'hir Item<'hir>) -> Self {
4318 OwnerNode::Item(val)
4319 }
4320}
4321
4322impl<'hir> From<&'hir ForeignItem<'hir>> for OwnerNode<'hir> {
4323 fn from(val: &'hir ForeignItem<'hir>) -> Self {
4324 OwnerNode::ForeignItem(val)
4325 }
4326}
4327
4328impl<'hir> From<&'hir ImplItem<'hir>> for OwnerNode<'hir> {
4329 fn from(val: &'hir ImplItem<'hir>) -> Self {
4330 OwnerNode::ImplItem(val)
4331 }
4332}
4333
4334impl<'hir> From<&'hir TraitItem<'hir>> for OwnerNode<'hir> {
4335 fn from(val: &'hir TraitItem<'hir>) -> Self {
4336 OwnerNode::TraitItem(val)
4337 }
4338}
4339
4340impl<'hir> From<OwnerNode<'hir>> for Node<'hir> {
4341 fn from(val: OwnerNode<'hir>) -> Self {
4342 match val {
4343 OwnerNode::Item(n) => Node::Item(n),
4344 OwnerNode::ForeignItem(n) => Node::ForeignItem(n),
4345 OwnerNode::ImplItem(n) => Node::ImplItem(n),
4346 OwnerNode::TraitItem(n) => Node::TraitItem(n),
4347 OwnerNode::Crate(n) => Node::Crate(n),
4348 OwnerNode::Synthetic => Node::Synthetic,
4349 }
4350 }
4351}
4352
4353#[derive(Copy, Clone, Debug, HashStable_Generic)]
4354pub enum Node<'hir> {
4355 Param(&'hir Param<'hir>),
4356 Item(&'hir Item<'hir>),
4357 ForeignItem(&'hir ForeignItem<'hir>),
4358 TraitItem(&'hir TraitItem<'hir>),
4359 ImplItem(&'hir ImplItem<'hir>),
4360 Variant(&'hir Variant<'hir>),
4361 Field(&'hir FieldDef<'hir>),
4362 AnonConst(&'hir AnonConst),
4363 ConstBlock(&'hir ConstBlock),
4364 ConstArg(&'hir ConstArg<'hir>),
4365 Expr(&'hir Expr<'hir>),
4366 ExprField(&'hir ExprField<'hir>),
4367 Stmt(&'hir Stmt<'hir>),
4368 PathSegment(&'hir PathSegment<'hir>),
4369 Ty(&'hir Ty<'hir>),
4370 AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
4371 TraitRef(&'hir TraitRef<'hir>),
4372 OpaqueTy(&'hir OpaqueTy<'hir>),
4373 TyPat(&'hir TyPat<'hir>),
4374 Pat(&'hir Pat<'hir>),
4375 PatField(&'hir PatField<'hir>),
4376 PatExpr(&'hir PatExpr<'hir>),
4380 Arm(&'hir Arm<'hir>),
4381 Block(&'hir Block<'hir>),
4382 LetStmt(&'hir LetStmt<'hir>),
4383 Ctor(&'hir VariantData<'hir>),
4386 Lifetime(&'hir Lifetime),
4387 GenericParam(&'hir GenericParam<'hir>),
4388 Crate(&'hir Mod<'hir>),
4389 Infer(&'hir InferArg),
4390 WherePredicate(&'hir WherePredicate<'hir>),
4391 PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg),
4392 Synthetic,
4394 Err(Span),
4395}
4396
4397impl<'hir> Node<'hir> {
4398 pub fn ident(&self) -> Option<Ident> {
4413 match self {
4414 Node::TraitItem(TraitItem { ident, .. })
4415 | Node::ImplItem(ImplItem { ident, .. })
4416 | Node::ForeignItem(ForeignItem { ident, .. })
4417 | Node::Field(FieldDef { ident, .. })
4418 | Node::Variant(Variant { ident, .. })
4419 | Node::Item(Item { ident, .. })
4420 | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
4421 Node::Lifetime(lt) => Some(lt.ident),
4422 Node::GenericParam(p) => Some(p.name.ident()),
4423 Node::AssocItemConstraint(c) => Some(c.ident),
4424 Node::PatField(f) => Some(f.ident),
4425 Node::ExprField(f) => Some(f.ident),
4426 Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
4427 Node::Param(..)
4428 | Node::AnonConst(..)
4429 | Node::ConstBlock(..)
4430 | Node::ConstArg(..)
4431 | Node::Expr(..)
4432 | Node::Stmt(..)
4433 | Node::Block(..)
4434 | Node::Ctor(..)
4435 | Node::Pat(..)
4436 | Node::TyPat(..)
4437 | Node::PatExpr(..)
4438 | Node::Arm(..)
4439 | Node::LetStmt(..)
4440 | Node::Crate(..)
4441 | Node::Ty(..)
4442 | Node::TraitRef(..)
4443 | Node::OpaqueTy(..)
4444 | Node::Infer(..)
4445 | Node::WherePredicate(..)
4446 | Node::Synthetic
4447 | Node::Err(..) => None,
4448 }
4449 }
4450
4451 pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
4452 match self {
4453 Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4454 | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4455 | Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4456 | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
4457 Some(fn_sig.decl)
4458 }
4459 Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) => {
4460 Some(fn_decl)
4461 }
4462 _ => None,
4463 }
4464 }
4465
4466 pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
4468 if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self
4469 && let Some(trait_ref) = impl_block.of_trait
4470 && let Some(trait_id) = trait_ref.trait_def_id()
4471 && trait_id == trait_def_id
4472 {
4473 Some(impl_block)
4474 } else {
4475 None
4476 }
4477 }
4478
4479 pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
4480 match self {
4481 Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4482 | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4483 | Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4484 | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
4485 Some(fn_sig)
4486 }
4487 _ => None,
4488 }
4489 }
4490
4491 pub fn ty(self) -> Option<&'hir Ty<'hir>> {
4493 match self {
4494 Node::Item(it) => match it.kind {
4495 ItemKind::TyAlias(ty, _)
4496 | ItemKind::Static(ty, _, _)
4497 | ItemKind::Const(ty, _, _) => Some(ty),
4498 ItemKind::Impl(impl_item) => Some(&impl_item.self_ty),
4499 _ => None,
4500 },
4501 Node::TraitItem(it) => match it.kind {
4502 TraitItemKind::Const(ty, _) => Some(ty),
4503 TraitItemKind::Type(_, ty) => ty,
4504 _ => None,
4505 },
4506 Node::ImplItem(it) => match it.kind {
4507 ImplItemKind::Const(ty, _) => Some(ty),
4508 ImplItemKind::Type(ty) => Some(ty),
4509 _ => None,
4510 },
4511 _ => None,
4512 }
4513 }
4514
4515 pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
4516 match self {
4517 Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),
4518 _ => None,
4519 }
4520 }
4521
4522 #[inline]
4523 pub fn associated_body(&self) -> Option<(LocalDefId, BodyId)> {
4524 match self {
4525 Node::Item(Item {
4526 owner_id,
4527 kind:
4528 ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. },
4529 ..
4530 })
4531 | Node::TraitItem(TraitItem {
4532 owner_id,
4533 kind:
4534 TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
4535 ..
4536 })
4537 | Node::ImplItem(ImplItem {
4538 owner_id,
4539 kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
4540 ..
4541 }) => Some((owner_id.def_id, *body)),
4542
4543 Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
4544 Some((*def_id, *body))
4545 }
4546
4547 Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
4548 Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
4549
4550 _ => None,
4551 }
4552 }
4553
4554 pub fn body_id(&self) -> Option<BodyId> {
4555 Some(self.associated_body()?.1)
4556 }
4557
4558 pub fn generics(self) -> Option<&'hir Generics<'hir>> {
4559 match self {
4560 Node::ForeignItem(ForeignItem {
4561 kind: ForeignItemKind::Fn(_, _, generics), ..
4562 })
4563 | Node::TraitItem(TraitItem { generics, .. })
4564 | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
4565 Node::Item(item) => item.kind.generics(),
4566 _ => None,
4567 }
4568 }
4569
4570 pub fn as_owner(self) -> Option<OwnerNode<'hir>> {
4571 match self {
4572 Node::Item(i) => Some(OwnerNode::Item(i)),
4573 Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)),
4574 Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
4575 Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
4576 Node::Crate(i) => Some(OwnerNode::Crate(i)),
4577 Node::Synthetic => Some(OwnerNode::Synthetic),
4578 _ => None,
4579 }
4580 }
4581
4582 pub fn fn_kind(self) -> Option<FnKind<'hir>> {
4583 match self {
4584 Node::Item(i) => match i.kind {
4585 ItemKind::Fn { sig, generics, .. } => {
4586 Some(FnKind::ItemFn(i.ident, generics, sig.header))
4587 }
4588 _ => None,
4589 },
4590 Node::TraitItem(ti) => match ti.kind {
4591 TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)),
4592 _ => None,
4593 },
4594 Node::ImplItem(ii) => match ii.kind {
4595 ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig)),
4596 _ => None,
4597 },
4598 Node::Expr(e) => match e.kind {
4599 ExprKind::Closure { .. } => Some(FnKind::Closure),
4600 _ => None,
4601 },
4602 _ => None,
4603 }
4604 }
4605
4606 expect_methods_self! {
4607 expect_param, &'hir Param<'hir>, Node::Param(n), n;
4608 expect_item, &'hir Item<'hir>, Node::Item(n), n;
4609 expect_foreign_item, &'hir ForeignItem<'hir>, Node::ForeignItem(n), n;
4610 expect_trait_item, &'hir TraitItem<'hir>, Node::TraitItem(n), n;
4611 expect_impl_item, &'hir ImplItem<'hir>, Node::ImplItem(n), n;
4612 expect_variant, &'hir Variant<'hir>, Node::Variant(n), n;
4613 expect_field, &'hir FieldDef<'hir>, Node::Field(n), n;
4614 expect_anon_const, &'hir AnonConst, Node::AnonConst(n), n;
4615 expect_inline_const, &'hir ConstBlock, Node::ConstBlock(n), n;
4616 expect_expr, &'hir Expr<'hir>, Node::Expr(n), n;
4617 expect_expr_field, &'hir ExprField<'hir>, Node::ExprField(n), n;
4618 expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n;
4619 expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n;
4620 expect_ty, &'hir Ty<'hir>, Node::Ty(n), n;
4621 expect_assoc_item_constraint, &'hir AssocItemConstraint<'hir>, Node::AssocItemConstraint(n), n;
4622 expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n;
4623 expect_opaque_ty, &'hir OpaqueTy<'hir>, Node::OpaqueTy(n), n;
4624 expect_pat, &'hir Pat<'hir>, Node::Pat(n), n;
4625 expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n;
4626 expect_arm, &'hir Arm<'hir>, Node::Arm(n), n;
4627 expect_block, &'hir Block<'hir>, Node::Block(n), n;
4628 expect_let_stmt, &'hir LetStmt<'hir>, Node::LetStmt(n), n;
4629 expect_ctor, &'hir VariantData<'hir>, Node::Ctor(n), n;
4630 expect_lifetime, &'hir Lifetime, Node::Lifetime(n), n;
4631 expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n;
4632 expect_crate, &'hir Mod<'hir>, Node::Crate(n), n;
4633 expect_infer, &'hir InferArg, Node::Infer(n), n;
4634 expect_closure, &'hir Closure<'hir>, Node::Expr(Expr { kind: ExprKind::Closure(n), .. }), n;
4635 }
4636}
4637
4638#[cfg(target_pointer_width = "64")]
4640mod size_asserts {
4641 use rustc_data_structures::static_assert_size;
4642
4643 use super::*;
4644 static_assert_size!(Block<'_>, 48);
4646 static_assert_size!(Body<'_>, 24);
4647 static_assert_size!(Expr<'_>, 64);
4648 static_assert_size!(ExprKind<'_>, 48);
4649 static_assert_size!(FnDecl<'_>, 40);
4650 static_assert_size!(ForeignItem<'_>, 88);
4651 static_assert_size!(ForeignItemKind<'_>, 56);
4652 static_assert_size!(GenericArg<'_>, 16);
4653 static_assert_size!(GenericBound<'_>, 64);
4654 static_assert_size!(Generics<'_>, 56);
4655 static_assert_size!(Impl<'_>, 80);
4656 static_assert_size!(ImplItem<'_>, 88);
4657 static_assert_size!(ImplItemKind<'_>, 40);
4658 static_assert_size!(Item<'_>, 88);
4659 static_assert_size!(ItemKind<'_>, 56);
4660 static_assert_size!(LetStmt<'_>, 64);
4661 static_assert_size!(Param<'_>, 32);
4662 static_assert_size!(Pat<'_>, 72);
4663 static_assert_size!(Path<'_>, 40);
4664 static_assert_size!(PathSegment<'_>, 48);
4665 static_assert_size!(PatKind<'_>, 48);
4666 static_assert_size!(QPath<'_>, 24);
4667 static_assert_size!(Res, 12);
4668 static_assert_size!(Stmt<'_>, 32);
4669 static_assert_size!(StmtKind<'_>, 16);
4670 static_assert_size!(TraitItem<'_>, 88);
4671 static_assert_size!(TraitItemKind<'_>, 48);
4672 static_assert_size!(Ty<'_>, 48);
4673 static_assert_size!(TyKind<'_>, 32);
4674 }
4676
4677#[cfg(test)]
4678mod tests;