1use std::borrow::Cow;
3use std::fmt;
4
5use rustc_abi::ExternAbi;
6use rustc_ast::attr::AttributeExt;
7use rustc_ast::token::CommentKind;
8use rustc_ast::util::parser::ExprPrecedence;
9use rustc_ast::{
10 self as ast, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitIntType,
11 LitKind, TraitObjectSyntax, UintTy, UnsafeBinderCastKind, join_path_idents,
12};
13pub use rustc_ast::{
14 AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind,
15 BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto,
16 MetaItemInner, MetaItemLit, Movability, Mutability, UnOp,
17};
18use rustc_data_structures::fingerprint::Fingerprint;
19use rustc_data_structures::sorted_map::SortedMap;
20use rustc_data_structures::tagged_ptr::TaggedRef;
21use rustc_error_messages::{DiagArgValue, IntoDiagArg};
22use rustc_index::IndexVec;
23use rustc_macros::{Decodable, Encodable, HashStable_Generic};
24use rustc_span::def_id::LocalDefId;
25use rustc_span::source_map::Spanned;
26use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
27use rustc_target::asm::InlineAsmRegOrRegClass;
28use smallvec::SmallVec;
29use thin_vec::ThinVec;
30use tracing::debug;
31
32use crate::LangItem;
33use crate::attrs::AttributeKind;
34use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res};
35use crate::def_id::{DefId, LocalDefIdMap};
36pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
37use crate::intravisit::{FnKind, VisitorExt};
38use crate::lints::DelayedLints;
39
40#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
41pub enum AngleBrackets {
42 Missing,
44 Empty,
46 Full,
48}
49
50#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
51pub enum LifetimeSource {
52 Reference,
54
55 Path { angle_brackets: AngleBrackets },
58
59 OutlivesBound,
61
62 PreciseCapturing,
64
65 Other,
72}
73
74#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
75pub enum LifetimeSyntax {
76 Implicit,
78
79 ExplicitAnonymous,
81
82 ExplicitBound,
84}
85
86impl From<Ident> for LifetimeSyntax {
87 fn from(ident: Ident) -> Self {
88 let name = ident.name;
89
90 if name == sym::empty {
91 unreachable!("A lifetime name should never be empty");
92 } else if name == kw::UnderscoreLifetime {
93 LifetimeSyntax::ExplicitAnonymous
94 } else {
95 debug_assert!(name.as_str().starts_with('\''));
96 LifetimeSyntax::ExplicitBound
97 }
98 }
99}
100
101#[derive(Debug, Copy, Clone, HashStable_Generic)]
152#[repr(align(4))]
157pub struct Lifetime {
158 #[stable_hasher(ignore)]
159 pub hir_id: HirId,
160
161 pub ident: Ident,
165
166 pub kind: LifetimeKind,
168
169 pub source: LifetimeSource,
172
173 pub syntax: LifetimeSyntax,
176}
177
178#[derive(Debug, Copy, Clone, HashStable_Generic)]
179pub enum ParamName {
180 Plain(Ident),
182
183 Error(Ident),
189
190 Fresh,
205}
206
207impl ParamName {
208 pub fn ident(&self) -> Ident {
209 match *self {
210 ParamName::Plain(ident) | ParamName::Error(ident) => ident,
211 ParamName::Fresh => Ident::with_dummy_span(kw::UnderscoreLifetime),
212 }
213 }
214}
215
216#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
217pub enum LifetimeKind {
218 Param(LocalDefId),
220
221 ImplicitObjectLifetimeDefault,
233
234 Error,
237
238 Infer,
242
243 Static,
245}
246
247impl LifetimeKind {
248 fn is_elided(&self) -> bool {
249 match self {
250 LifetimeKind::ImplicitObjectLifetimeDefault | LifetimeKind::Infer => true,
251
252 LifetimeKind::Error | LifetimeKind::Param(..) | LifetimeKind::Static => false,
257 }
258 }
259}
260
261impl fmt::Display for Lifetime {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 self.ident.name.fmt(f)
264 }
265}
266
267impl Lifetime {
268 pub fn new(
269 hir_id: HirId,
270 ident: Ident,
271 kind: LifetimeKind,
272 source: LifetimeSource,
273 syntax: LifetimeSyntax,
274 ) -> Lifetime {
275 let lifetime = Lifetime { hir_id, ident, kind, source, syntax };
276
277 #[cfg(debug_assertions)]
279 match (lifetime.is_elided(), lifetime.is_anonymous()) {
280 (false, false) => {} (false, true) => {} (true, true) => {} (true, false) => panic!("bad Lifetime"),
284 }
285
286 lifetime
287 }
288
289 pub fn is_elided(&self) -> bool {
290 self.kind.is_elided()
291 }
292
293 pub fn is_anonymous(&self) -> bool {
294 self.ident.name == kw::UnderscoreLifetime
295 }
296
297 pub fn is_implicit(&self) -> bool {
298 matches!(self.syntax, LifetimeSyntax::Implicit)
299 }
300
301 pub fn is_static(&self) -> bool {
302 self.kind == LifetimeKind::Static
303 }
304
305 pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
306 use LifetimeSource::*;
307 use LifetimeSyntax::*;
308
309 debug_assert!(new_lifetime.starts_with('\''));
310
311 match (self.syntax, self.source) {
312 (ExplicitBound | ExplicitAnonymous, _) => (self.ident.span, format!("{new_lifetime}")),
314
315 (Implicit, Path { angle_brackets: AngleBrackets::Full }) => {
317 (self.ident.span, format!("{new_lifetime}, "))
318 }
319
320 (Implicit, Path { angle_brackets: AngleBrackets::Empty }) => {
322 (self.ident.span, format!("{new_lifetime}"))
323 }
324
325 (Implicit, Path { angle_brackets: AngleBrackets::Missing }) => {
327 (self.ident.span.shrink_to_hi(), format!("<{new_lifetime}>"))
328 }
329
330 (Implicit, Reference) => (self.ident.span, format!("{new_lifetime} ")),
332
333 (Implicit, source) => {
334 unreachable!("can't suggest for a implicit lifetime of {source:?}")
335 }
336 }
337 }
338}
339
340#[derive(Debug, Clone, Copy, HashStable_Generic)]
344pub struct Path<'hir, R = Res> {
345 pub span: Span,
346 pub res: R,
348 pub segments: &'hir [PathSegment<'hir>],
350}
351
352pub type UsePath<'hir> = Path<'hir, PerNS<Option<Res>>>;
354
355impl Path<'_> {
356 pub fn is_global(&self) -> bool {
357 self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
358 }
359}
360
361#[derive(Debug, Clone, Copy, HashStable_Generic)]
364pub struct PathSegment<'hir> {
365 pub ident: Ident,
367 #[stable_hasher(ignore)]
368 pub hir_id: HirId,
369 pub res: Res,
370
371 pub args: Option<&'hir GenericArgs<'hir>>,
377
378 pub infer_args: bool,
383}
384
385impl<'hir> PathSegment<'hir> {
386 pub fn new(ident: Ident, hir_id: HirId, res: Res) -> PathSegment<'hir> {
388 PathSegment { ident, hir_id, res, infer_args: true, args: None }
389 }
390
391 pub fn invalid() -> Self {
392 Self::new(Ident::dummy(), HirId::INVALID, Res::Err)
393 }
394
395 pub fn args(&self) -> &GenericArgs<'hir> {
396 if let Some(ref args) = self.args {
397 args
398 } else {
399 const DUMMY: &GenericArgs<'_> = &GenericArgs::none();
400 DUMMY
401 }
402 }
403}
404
405#[derive(Clone, Copy, Debug, HashStable_Generic)]
419#[repr(C)]
420pub struct ConstArg<'hir, Unambig = ()> {
421 #[stable_hasher(ignore)]
422 pub hir_id: HirId,
423 pub kind: ConstArgKind<'hir, Unambig>,
424}
425
426impl<'hir> ConstArg<'hir, AmbigArg> {
427 pub fn as_unambig_ct(&self) -> &ConstArg<'hir> {
438 let ptr = self as *const ConstArg<'hir, AmbigArg> as *const ConstArg<'hir, ()>;
441 unsafe { &*ptr }
442 }
443}
444
445impl<'hir> ConstArg<'hir> {
446 pub fn try_as_ambig_ct(&self) -> Option<&ConstArg<'hir, AmbigArg>> {
452 if let ConstArgKind::Infer(_, ()) = self.kind {
453 return None;
454 }
455
456 let ptr = self as *const ConstArg<'hir> as *const ConstArg<'hir, AmbigArg>;
460 Some(unsafe { &*ptr })
461 }
462}
463
464impl<'hir, Unambig> ConstArg<'hir, Unambig> {
465 pub fn anon_const_hir_id(&self) -> Option<HirId> {
466 match self.kind {
467 ConstArgKind::Anon(ac) => Some(ac.hir_id),
468 _ => None,
469 }
470 }
471
472 pub fn span(&self) -> Span {
473 match self.kind {
474 ConstArgKind::Path(path) => path.span(),
475 ConstArgKind::Anon(anon) => anon.span,
476 ConstArgKind::Infer(span, _) => span,
477 }
478 }
479}
480
481#[derive(Clone, Copy, Debug, HashStable_Generic)]
483#[repr(u8, C)]
484pub enum ConstArgKind<'hir, Unambig = ()> {
485 Path(QPath<'hir>),
491 Anon(&'hir AnonConst),
492 Infer(Span, Unambig),
495}
496
497#[derive(Clone, Copy, Debug, HashStable_Generic)]
498pub struct InferArg {
499 #[stable_hasher(ignore)]
500 pub hir_id: HirId,
501 pub span: Span,
502}
503
504impl InferArg {
505 pub fn to_ty(&self) -> Ty<'static> {
506 Ty { kind: TyKind::Infer(()), span: self.span, hir_id: self.hir_id }
507 }
508}
509
510#[derive(Debug, Clone, Copy, HashStable_Generic)]
511pub enum GenericArg<'hir> {
512 Lifetime(&'hir Lifetime),
513 Type(&'hir Ty<'hir, AmbigArg>),
514 Const(&'hir ConstArg<'hir, AmbigArg>),
515 Infer(InferArg),
525}
526
527impl GenericArg<'_> {
528 pub fn span(&self) -> Span {
529 match self {
530 GenericArg::Lifetime(l) => l.ident.span,
531 GenericArg::Type(t) => t.span,
532 GenericArg::Const(c) => c.span(),
533 GenericArg::Infer(i) => i.span,
534 }
535 }
536
537 pub fn hir_id(&self) -> HirId {
538 match self {
539 GenericArg::Lifetime(l) => l.hir_id,
540 GenericArg::Type(t) => t.hir_id,
541 GenericArg::Const(c) => c.hir_id,
542 GenericArg::Infer(i) => i.hir_id,
543 }
544 }
545
546 pub fn descr(&self) -> &'static str {
547 match self {
548 GenericArg::Lifetime(_) => "lifetime",
549 GenericArg::Type(_) => "type",
550 GenericArg::Const(_) => "constant",
551 GenericArg::Infer(_) => "placeholder",
552 }
553 }
554
555 pub fn to_ord(&self) -> ast::ParamKindOrd {
556 match self {
557 GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
558 GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => {
559 ast::ParamKindOrd::TypeOrConst
560 }
561 }
562 }
563
564 pub fn is_ty_or_const(&self) -> bool {
565 match self {
566 GenericArg::Lifetime(_) => false,
567 GenericArg::Type(_) | GenericArg::Const(_) | GenericArg::Infer(_) => true,
568 }
569 }
570}
571
572#[derive(Debug, Clone, Copy, HashStable_Generic)]
574pub struct GenericArgs<'hir> {
575 pub args: &'hir [GenericArg<'hir>],
577 pub constraints: &'hir [AssocItemConstraint<'hir>],
579 pub parenthesized: GenericArgsParentheses,
584 pub span_ext: Span,
597}
598
599impl<'hir> GenericArgs<'hir> {
600 pub const fn none() -> Self {
601 Self {
602 args: &[],
603 constraints: &[],
604 parenthesized: GenericArgsParentheses::No,
605 span_ext: DUMMY_SP,
606 }
607 }
608
609 pub fn paren_sugar_inputs_output(&self) -> Option<(&[Ty<'hir>], &Ty<'hir>)> {
614 if self.parenthesized != GenericArgsParentheses::ParenSugar {
615 return None;
616 }
617
618 let inputs = self
619 .args
620 .iter()
621 .find_map(|arg| {
622 let GenericArg::Type(ty) = arg else { return None };
623 let TyKind::Tup(tys) = &ty.kind else { return None };
624 Some(tys)
625 })
626 .unwrap();
627
628 Some((inputs, self.paren_sugar_output_inner()))
629 }
630
631 pub fn paren_sugar_output(&self) -> Option<&Ty<'hir>> {
636 (self.parenthesized == GenericArgsParentheses::ParenSugar)
637 .then(|| self.paren_sugar_output_inner())
638 }
639
640 fn paren_sugar_output_inner(&self) -> &Ty<'hir> {
641 let [constraint] = self.constraints.try_into().unwrap();
642 debug_assert_eq!(constraint.ident.name, sym::Output);
643 constraint.ty().unwrap()
644 }
645
646 pub fn has_err(&self) -> Option<ErrorGuaranteed> {
647 self.args
648 .iter()
649 .find_map(|arg| {
650 let GenericArg::Type(ty) = arg else { return None };
651 let TyKind::Err(guar) = ty.kind else { return None };
652 Some(guar)
653 })
654 .or_else(|| {
655 self.constraints.iter().find_map(|constraint| {
656 let TyKind::Err(guar) = constraint.ty()?.kind else { return None };
657 Some(guar)
658 })
659 })
660 }
661
662 #[inline]
663 pub fn num_lifetime_params(&self) -> usize {
664 self.args.iter().filter(|arg| matches!(arg, GenericArg::Lifetime(_))).count()
665 }
666
667 #[inline]
668 pub fn has_lifetime_params(&self) -> bool {
669 self.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
670 }
671
672 #[inline]
673 pub fn num_generic_params(&self) -> usize {
676 self.args.iter().filter(|arg| !matches!(arg, GenericArg::Lifetime(_))).count()
677 }
678
679 pub fn span(&self) -> Option<Span> {
685 let span_ext = self.span_ext()?;
686 Some(span_ext.with_lo(span_ext.lo() + BytePos(1)).with_hi(span_ext.hi() - BytePos(1)))
687 }
688
689 pub fn span_ext(&self) -> Option<Span> {
691 Some(self.span_ext).filter(|span| !span.is_empty())
692 }
693
694 pub fn is_empty(&self) -> bool {
695 self.args.is_empty()
696 }
697}
698
699#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
700pub enum GenericArgsParentheses {
701 No,
702 ReturnTypeNotation,
705 ParenSugar,
707}
708
709#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
711pub struct TraitBoundModifiers {
712 pub constness: BoundConstness,
713 pub polarity: BoundPolarity,
714}
715
716impl TraitBoundModifiers {
717 pub const NONE: Self =
718 TraitBoundModifiers { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
719}
720
721#[derive(Clone, Copy, Debug, HashStable_Generic)]
722pub enum GenericBound<'hir> {
723 Trait(PolyTraitRef<'hir>),
724 Outlives(&'hir Lifetime),
725 Use(&'hir [PreciseCapturingArg<'hir>], Span),
726}
727
728impl GenericBound<'_> {
729 pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
730 match self {
731 GenericBound::Trait(data) => Some(&data.trait_ref),
732 _ => None,
733 }
734 }
735
736 pub fn span(&self) -> Span {
737 match self {
738 GenericBound::Trait(t, ..) => t.span,
739 GenericBound::Outlives(l) => l.ident.span,
740 GenericBound::Use(_, span) => *span,
741 }
742 }
743}
744
745pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
746
747#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic, Debug)]
748pub enum MissingLifetimeKind {
749 Underscore,
751 Ampersand,
753 Comma,
755 Brackets,
757}
758
759#[derive(Copy, Clone, Debug, HashStable_Generic)]
760pub enum LifetimeParamKind {
761 Explicit,
764
765 Elided(MissingLifetimeKind),
768
769 Error,
771}
772
773#[derive(Debug, Clone, Copy, HashStable_Generic)]
774pub enum GenericParamKind<'hir> {
775 Lifetime {
777 kind: LifetimeParamKind,
778 },
779 Type {
780 default: Option<&'hir Ty<'hir>>,
781 synthetic: bool,
782 },
783 Const {
784 ty: &'hir Ty<'hir>,
785 default: Option<&'hir ConstArg<'hir>>,
787 synthetic: bool,
788 },
789}
790
791#[derive(Debug, Clone, Copy, HashStable_Generic)]
792pub struct GenericParam<'hir> {
793 #[stable_hasher(ignore)]
794 pub hir_id: HirId,
795 pub def_id: LocalDefId,
796 pub name: ParamName,
797 pub span: Span,
798 pub pure_wrt_drop: bool,
799 pub kind: GenericParamKind<'hir>,
800 pub colon_span: Option<Span>,
801 pub source: GenericParamSource,
802}
803
804impl<'hir> GenericParam<'hir> {
805 pub fn is_impl_trait(&self) -> bool {
809 matches!(self.kind, GenericParamKind::Type { synthetic: true, .. })
810 }
811
812 pub fn is_elided_lifetime(&self) -> bool {
816 matches!(self.kind, GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) })
817 }
818}
819
820#[derive(Debug, Clone, Copy, HashStable_Generic)]
827pub enum GenericParamSource {
828 Generics,
830 Binder,
832}
833
834#[derive(Default)]
835pub struct GenericParamCount {
836 pub lifetimes: usize,
837 pub types: usize,
838 pub consts: usize,
839 pub infer: usize,
840}
841
842#[derive(Debug, Clone, Copy, HashStable_Generic)]
845pub struct Generics<'hir> {
846 pub params: &'hir [GenericParam<'hir>],
847 pub predicates: &'hir [WherePredicate<'hir>],
848 pub has_where_clause_predicates: bool,
849 pub where_clause_span: Span,
850 pub span: Span,
851}
852
853impl<'hir> Generics<'hir> {
854 pub const fn empty() -> &'hir Generics<'hir> {
855 const NOPE: Generics<'_> = Generics {
856 params: &[],
857 predicates: &[],
858 has_where_clause_predicates: false,
859 where_clause_span: DUMMY_SP,
860 span: DUMMY_SP,
861 };
862 &NOPE
863 }
864
865 pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'hir>> {
866 self.params.iter().find(|¶m| name == param.name.ident().name)
867 }
868
869 pub fn span_for_lifetime_suggestion(&self) -> Option<Span> {
871 if let Some(first) = self.params.first()
872 && self.span.contains(first.span)
873 {
874 Some(first.span.shrink_to_lo())
877 } else {
878 None
879 }
880 }
881
882 pub fn span_for_param_suggestion(&self) -> Option<Span> {
884 self.params.iter().any(|p| self.span.contains(p.span)).then(|| {
885 self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo()
888 })
889 }
890
891 pub fn tail_span_for_predicate_suggestion(&self) -> Span {
894 let end = self.where_clause_span.shrink_to_hi();
895 if self.has_where_clause_predicates {
896 self.predicates
897 .iter()
898 .rfind(|&p| p.kind.in_where_clause())
899 .map_or(end, |p| p.span)
900 .shrink_to_hi()
901 .to(end)
902 } else {
903 end
904 }
905 }
906
907 pub fn add_where_or_trailing_comma(&self) -> &'static str {
908 if self.has_where_clause_predicates {
909 ","
910 } else if self.where_clause_span.is_empty() {
911 " where"
912 } else {
913 ""
915 }
916 }
917
918 pub fn bounds_for_param(
919 &self,
920 param_def_id: LocalDefId,
921 ) -> impl Iterator<Item = &WhereBoundPredicate<'hir>> {
922 self.predicates.iter().filter_map(move |pred| match pred.kind {
923 WherePredicateKind::BoundPredicate(bp)
924 if bp.is_param_bound(param_def_id.to_def_id()) =>
925 {
926 Some(bp)
927 }
928 _ => None,
929 })
930 }
931
932 pub fn outlives_for_param(
933 &self,
934 param_def_id: LocalDefId,
935 ) -> impl Iterator<Item = &WhereRegionPredicate<'_>> {
936 self.predicates.iter().filter_map(move |pred| match pred.kind {
937 WherePredicateKind::RegionPredicate(rp) if rp.is_param_bound(param_def_id) => Some(rp),
938 _ => None,
939 })
940 }
941
942 pub fn bounds_span_for_suggestions(
953 &self,
954 param_def_id: LocalDefId,
955 ) -> Option<(Span, Option<Span>)> {
956 self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
957 |bound| {
958 let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref()
959 && let [.., segment] = trait_ref.path.segments
960 && let Some(ret_ty) = segment.args().paren_sugar_output()
961 && let ret_ty = ret_ty.peel_refs()
962 && let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind
963 && let TraitObjectSyntax::Dyn = tagged_ptr.tag()
964 && ret_ty.span.can_be_used_for_suggestions()
965 {
966 Some(ret_ty.span)
967 } else {
968 None
969 };
970
971 span_for_parentheses.map_or_else(
972 || {
973 let bs = bound.span();
976 bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None))
977 },
978 |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))),
979 )
980 },
981 )
982 }
983
984 pub fn span_for_predicate_removal(&self, pos: usize) -> Span {
985 let predicate = &self.predicates[pos];
986 let span = predicate.span;
987
988 if !predicate.kind.in_where_clause() {
989 return span;
992 }
993
994 if pos < self.predicates.len() - 1 {
996 let next_pred = &self.predicates[pos + 1];
997 if next_pred.kind.in_where_clause() {
998 return span.until(next_pred.span);
1001 }
1002 }
1003
1004 if pos > 0 {
1005 let prev_pred = &self.predicates[pos - 1];
1006 if prev_pred.kind.in_where_clause() {
1007 return prev_pred.span.shrink_to_hi().to(span);
1010 }
1011 }
1012
1013 self.where_clause_span
1017 }
1018
1019 pub fn span_for_bound_removal(&self, predicate_pos: usize, bound_pos: usize) -> Span {
1020 let predicate = &self.predicates[predicate_pos];
1021 let bounds = predicate.kind.bounds();
1022
1023 if bounds.len() == 1 {
1024 return self.span_for_predicate_removal(predicate_pos);
1025 }
1026
1027 let bound_span = bounds[bound_pos].span();
1028 if bound_pos < bounds.len() - 1 {
1029 bound_span.to(bounds[bound_pos + 1].span().shrink_to_lo())
1035 } else {
1036 bound_span.with_lo(bounds[bound_pos - 1].span().hi())
1042 }
1043 }
1044}
1045
1046#[derive(Debug, Clone, Copy, HashStable_Generic)]
1048pub struct WherePredicate<'hir> {
1049 #[stable_hasher(ignore)]
1050 pub hir_id: HirId,
1051 pub span: Span,
1052 pub kind: &'hir WherePredicateKind<'hir>,
1053}
1054
1055#[derive(Debug, Clone, Copy, HashStable_Generic)]
1057pub enum WherePredicateKind<'hir> {
1058 BoundPredicate(WhereBoundPredicate<'hir>),
1060 RegionPredicate(WhereRegionPredicate<'hir>),
1062 EqPredicate(WhereEqPredicate<'hir>),
1064}
1065
1066impl<'hir> WherePredicateKind<'hir> {
1067 pub fn in_where_clause(&self) -> bool {
1068 match self {
1069 WherePredicateKind::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause,
1070 WherePredicateKind::RegionPredicate(p) => p.in_where_clause,
1071 WherePredicateKind::EqPredicate(_) => false,
1072 }
1073 }
1074
1075 pub fn bounds(&self) -> GenericBounds<'hir> {
1076 match self {
1077 WherePredicateKind::BoundPredicate(p) => p.bounds,
1078 WherePredicateKind::RegionPredicate(p) => p.bounds,
1079 WherePredicateKind::EqPredicate(_) => &[],
1080 }
1081 }
1082}
1083
1084#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
1085pub enum PredicateOrigin {
1086 WhereClause,
1087 GenericParam,
1088 ImplTrait,
1089}
1090
1091#[derive(Debug, Clone, Copy, HashStable_Generic)]
1093pub struct WhereBoundPredicate<'hir> {
1094 pub origin: PredicateOrigin,
1096 pub bound_generic_params: &'hir [GenericParam<'hir>],
1098 pub bounded_ty: &'hir Ty<'hir>,
1100 pub bounds: GenericBounds<'hir>,
1102}
1103
1104impl<'hir> WhereBoundPredicate<'hir> {
1105 pub fn is_param_bound(&self, param_def_id: DefId) -> bool {
1107 self.bounded_ty.as_generic_param().is_some_and(|(def_id, _)| def_id == param_def_id)
1108 }
1109}
1110
1111#[derive(Debug, Clone, Copy, HashStable_Generic)]
1113pub struct WhereRegionPredicate<'hir> {
1114 pub in_where_clause: bool,
1115 pub lifetime: &'hir Lifetime,
1116 pub bounds: GenericBounds<'hir>,
1117}
1118
1119impl<'hir> WhereRegionPredicate<'hir> {
1120 fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
1122 self.lifetime.kind == LifetimeKind::Param(param_def_id)
1123 }
1124}
1125
1126#[derive(Debug, Clone, Copy, HashStable_Generic)]
1128pub struct WhereEqPredicate<'hir> {
1129 pub lhs_ty: &'hir Ty<'hir>,
1130 pub rhs_ty: &'hir Ty<'hir>,
1131}
1132
1133#[derive(Clone, Copy, Debug)]
1137pub struct ParentedNode<'tcx> {
1138 pub parent: ItemLocalId,
1139 pub node: Node<'tcx>,
1140}
1141
1142#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
1144pub enum AttrArgs {
1145 Empty,
1147 Delimited(DelimArgs),
1149 Eq {
1151 eq_span: Span,
1153 expr: MetaItemLit,
1155 },
1156}
1157
1158#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
1159pub struct AttrPath {
1160 pub segments: Box<[Ident]>,
1161 pub span: Span,
1162}
1163
1164impl IntoDiagArg for AttrPath {
1165 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
1166 self.to_string().into_diag_arg(path)
1167 }
1168}
1169
1170impl AttrPath {
1171 pub fn from_ast(path: &ast::Path) -> Self {
1172 AttrPath {
1173 segments: path.segments.iter().map(|i| i.ident).collect::<Vec<_>>().into_boxed_slice(),
1174 span: path.span,
1175 }
1176 }
1177}
1178
1179impl fmt::Display for AttrPath {
1180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1181 write!(f, "{}", join_path_idents(&self.segments))
1182 }
1183}
1184
1185#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
1186pub struct AttrItem {
1187 pub path: AttrPath,
1189 pub args: AttrArgs,
1190 pub id: HashIgnoredAttrId,
1191 pub style: AttrStyle,
1194 pub span: Span,
1196}
1197
1198#[derive(Copy, Debug, Encodable, Decodable, Clone)]
1201pub struct HashIgnoredAttrId {
1202 pub attr_id: AttrId,
1203}
1204
1205#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
1206pub enum Attribute {
1207 Parsed(AttributeKind),
1213
1214 Unparsed(Box<AttrItem>),
1217}
1218
1219impl Attribute {
1220 pub fn get_normal_item(&self) -> &AttrItem {
1221 match &self {
1222 Attribute::Unparsed(normal) => &normal,
1223 _ => panic!("unexpected parsed attribute"),
1224 }
1225 }
1226
1227 pub fn unwrap_normal_item(self) -> AttrItem {
1228 match self {
1229 Attribute::Unparsed(normal) => *normal,
1230 _ => panic!("unexpected parsed attribute"),
1231 }
1232 }
1233
1234 pub fn value_lit(&self) -> Option<&MetaItemLit> {
1235 match &self {
1236 Attribute::Unparsed(n) => match n.as_ref() {
1237 AttrItem { args: AttrArgs::Eq { eq_span: _, expr }, .. } => Some(expr),
1238 _ => None,
1239 },
1240 _ => None,
1241 }
1242 }
1243
1244 pub fn is_parsed_attr(&self) -> bool {
1245 match self {
1246 Attribute::Parsed(_) => true,
1247 Attribute::Unparsed(_) => false,
1248 }
1249 }
1250}
1251
1252impl AttributeExt for Attribute {
1253 #[inline]
1254 fn id(&self) -> AttrId {
1255 match &self {
1256 Attribute::Unparsed(u) => u.id.attr_id,
1257 _ => panic!(),
1258 }
1259 }
1260
1261 #[inline]
1262 fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
1263 match &self {
1264 Attribute::Unparsed(n) => match n.as_ref() {
1265 AttrItem { args: AttrArgs::Delimited(d), .. } => {
1266 ast::MetaItemKind::list_from_tokens(d.tokens.clone())
1267 }
1268 _ => None,
1269 },
1270 _ => None,
1271 }
1272 }
1273
1274 #[inline]
1275 fn value_str(&self) -> Option<Symbol> {
1276 self.value_lit().and_then(|x| x.value_str())
1277 }
1278
1279 #[inline]
1280 fn value_span(&self) -> Option<Span> {
1281 self.value_lit().map(|i| i.span)
1282 }
1283
1284 #[inline]
1286 fn ident(&self) -> Option<Ident> {
1287 match &self {
1288 Attribute::Unparsed(n) => {
1289 if let [ident] = n.path.segments.as_ref() {
1290 Some(*ident)
1291 } else {
1292 None
1293 }
1294 }
1295 _ => None,
1296 }
1297 }
1298
1299 #[inline]
1300 fn path_matches(&self, name: &[Symbol]) -> bool {
1301 match &self {
1302 Attribute::Unparsed(n) => {
1303 n.path.segments.len() == name.len()
1304 && n.path.segments.iter().zip(name).all(|(s, n)| s.name == *n)
1305 }
1306 _ => false,
1307 }
1308 }
1309
1310 #[inline]
1311 fn is_doc_comment(&self) -> bool {
1312 matches!(self, Attribute::Parsed(AttributeKind::DocComment { .. }))
1313 }
1314
1315 #[inline]
1316 fn span(&self) -> Span {
1317 match &self {
1318 Attribute::Unparsed(u) => u.span,
1319 Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
1321 Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span,
1322 Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span,
1323 Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span,
1324 a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
1325 }
1326 }
1327
1328 #[inline]
1329 fn is_word(&self) -> bool {
1330 match &self {
1331 Attribute::Unparsed(n) => {
1332 matches!(n.args, AttrArgs::Empty)
1333 }
1334 _ => false,
1335 }
1336 }
1337
1338 #[inline]
1339 fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
1340 match &self {
1341 Attribute::Unparsed(n) => Some(n.path.segments.iter().copied().collect()),
1342 _ => None,
1343 }
1344 }
1345
1346 #[inline]
1347 fn doc_str(&self) -> Option<Symbol> {
1348 match &self {
1349 Attribute::Parsed(AttributeKind::DocComment { comment, .. }) => Some(*comment),
1350 Attribute::Unparsed(_) if self.has_name(sym::doc) => self.value_str(),
1351 _ => None,
1352 }
1353 }
1354
1355 fn is_automatically_derived_attr(&self) -> bool {
1356 matches!(self, Attribute::Parsed(AttributeKind::AutomaticallyDerived(..)))
1357 }
1358
1359 #[inline]
1360 fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
1361 match &self {
1362 Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => {
1363 Some((*comment, *kind))
1364 }
1365 Attribute::Unparsed(_) if self.has_name(sym::doc) => {
1366 self.value_str().map(|s| (s, CommentKind::Line))
1367 }
1368 _ => None,
1369 }
1370 }
1371
1372 fn doc_resolution_scope(&self) -> Option<AttrStyle> {
1373 match self {
1374 Attribute::Parsed(AttributeKind::DocComment { style, .. }) => Some(*style),
1375 Attribute::Unparsed(attr) if self.has_name(sym::doc) && self.value_str().is_some() => {
1376 Some(attr.style)
1377 }
1378 _ => None,
1379 }
1380 }
1381
1382 fn is_proc_macro_attr(&self) -> bool {
1383 matches!(
1384 self,
1385 Attribute::Parsed(
1386 AttributeKind::ProcMacro(..)
1387 | AttributeKind::ProcMacroAttribute(..)
1388 | AttributeKind::ProcMacroDerive { .. }
1389 )
1390 )
1391 }
1392}
1393
1394impl Attribute {
1396 #[inline]
1397 pub fn id(&self) -> AttrId {
1398 AttributeExt::id(self)
1399 }
1400
1401 #[inline]
1402 pub fn name(&self) -> Option<Symbol> {
1403 AttributeExt::name(self)
1404 }
1405
1406 #[inline]
1407 pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
1408 AttributeExt::meta_item_list(self)
1409 }
1410
1411 #[inline]
1412 pub fn value_str(&self) -> Option<Symbol> {
1413 AttributeExt::value_str(self)
1414 }
1415
1416 #[inline]
1417 pub fn value_span(&self) -> Option<Span> {
1418 AttributeExt::value_span(self)
1419 }
1420
1421 #[inline]
1422 pub fn ident(&self) -> Option<Ident> {
1423 AttributeExt::ident(self)
1424 }
1425
1426 #[inline]
1427 pub fn path_matches(&self, name: &[Symbol]) -> bool {
1428 AttributeExt::path_matches(self, name)
1429 }
1430
1431 #[inline]
1432 pub fn is_doc_comment(&self) -> bool {
1433 AttributeExt::is_doc_comment(self)
1434 }
1435
1436 #[inline]
1437 pub fn has_name(&self, name: Symbol) -> bool {
1438 AttributeExt::has_name(self, name)
1439 }
1440
1441 #[inline]
1442 pub fn has_any_name(&self, names: &[Symbol]) -> bool {
1443 AttributeExt::has_any_name(self, names)
1444 }
1445
1446 #[inline]
1447 pub fn span(&self) -> Span {
1448 AttributeExt::span(self)
1449 }
1450
1451 #[inline]
1452 pub fn is_word(&self) -> bool {
1453 AttributeExt::is_word(self)
1454 }
1455
1456 #[inline]
1457 pub fn path(&self) -> SmallVec<[Symbol; 1]> {
1458 AttributeExt::path(self)
1459 }
1460
1461 #[inline]
1462 pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
1463 AttributeExt::ident_path(self)
1464 }
1465
1466 #[inline]
1467 pub fn doc_str(&self) -> Option<Symbol> {
1468 AttributeExt::doc_str(self)
1469 }
1470
1471 #[inline]
1472 pub fn is_proc_macro_attr(&self) -> bool {
1473 AttributeExt::is_proc_macro_attr(self)
1474 }
1475
1476 #[inline]
1477 pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
1478 AttributeExt::doc_str_and_comment_kind(self)
1479 }
1480}
1481
1482#[derive(Debug)]
1484pub struct AttributeMap<'tcx> {
1485 pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
1486 pub define_opaque: Option<&'tcx [(Span, LocalDefId)]>,
1488 pub opt_hash: Option<Fingerprint>,
1490}
1491
1492impl<'tcx> AttributeMap<'tcx> {
1493 pub const EMPTY: &'static AttributeMap<'static> = &AttributeMap {
1494 map: SortedMap::new(),
1495 opt_hash: Some(Fingerprint::ZERO),
1496 define_opaque: None,
1497 };
1498
1499 #[inline]
1500 pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
1501 self.map.get(&id).copied().unwrap_or(&[])
1502 }
1503}
1504
1505pub struct OwnerNodes<'tcx> {
1509 pub opt_hash_including_bodies: Option<Fingerprint>,
1512 pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
1517 pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
1519}
1520
1521impl<'tcx> OwnerNodes<'tcx> {
1522 pub fn node(&self) -> OwnerNode<'tcx> {
1523 self.nodes[ItemLocalId::ZERO].node.as_owner().unwrap()
1525 }
1526}
1527
1528impl fmt::Debug for OwnerNodes<'_> {
1529 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1530 f.debug_struct("OwnerNodes")
1531 .field("node", &self.nodes[ItemLocalId::ZERO])
1533 .field(
1534 "parents",
1535 &fmt::from_fn(|f| {
1536 f.debug_list()
1537 .entries(self.nodes.iter_enumerated().map(|(id, parented_node)| {
1538 fmt::from_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
1539 }))
1540 .finish()
1541 }),
1542 )
1543 .field("bodies", &self.bodies)
1544 .field("opt_hash_including_bodies", &self.opt_hash_including_bodies)
1545 .finish()
1546 }
1547}
1548
1549#[derive(Debug, HashStable_Generic)]
1551pub struct OwnerInfo<'hir> {
1552 pub nodes: OwnerNodes<'hir>,
1554 pub parenting: LocalDefIdMap<ItemLocalId>,
1556 pub attrs: AttributeMap<'hir>,
1558 pub trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
1561
1562 pub delayed_lints: DelayedLints,
1565}
1566
1567impl<'tcx> OwnerInfo<'tcx> {
1568 #[inline]
1569 pub fn node(&self) -> OwnerNode<'tcx> {
1570 self.nodes.node()
1571 }
1572}
1573
1574#[derive(Copy, Clone, Debug, HashStable_Generic)]
1575pub enum MaybeOwner<'tcx> {
1576 Owner(&'tcx OwnerInfo<'tcx>),
1577 NonOwner(HirId),
1578 Phantom,
1580}
1581
1582impl<'tcx> MaybeOwner<'tcx> {
1583 pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> {
1584 match self {
1585 MaybeOwner::Owner(i) => Some(i),
1586 MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None,
1587 }
1588 }
1589
1590 pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> {
1591 self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner"))
1592 }
1593}
1594
1595#[derive(Debug)]
1602pub struct Crate<'hir> {
1603 pub owners: IndexVec<LocalDefId, MaybeOwner<'hir>>,
1604 pub opt_hir_hash: Option<Fingerprint>,
1606}
1607
1608#[derive(Debug, Clone, Copy, HashStable_Generic)]
1609pub struct Closure<'hir> {
1610 pub def_id: LocalDefId,
1611 pub binder: ClosureBinder,
1612 pub constness: Constness,
1613 pub capture_clause: CaptureBy,
1614 pub bound_generic_params: &'hir [GenericParam<'hir>],
1615 pub fn_decl: &'hir FnDecl<'hir>,
1616 pub body: BodyId,
1617 pub fn_decl_span: Span,
1619 pub fn_arg_span: Option<Span>,
1621 pub kind: ClosureKind,
1622}
1623
1624#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
1625pub enum ClosureKind {
1626 Closure,
1628 Coroutine(CoroutineKind),
1633 CoroutineClosure(CoroutineDesugaring),
1638}
1639
1640#[derive(Debug, Clone, Copy, HashStable_Generic)]
1644pub struct Block<'hir> {
1645 pub stmts: &'hir [Stmt<'hir>],
1647 pub expr: Option<&'hir Expr<'hir>>,
1650 #[stable_hasher(ignore)]
1651 pub hir_id: HirId,
1652 pub rules: BlockCheckMode,
1654 pub span: Span,
1656 pub targeted_by_break: bool,
1660}
1661
1662impl<'hir> Block<'hir> {
1663 pub fn innermost_block(&self) -> &Block<'hir> {
1664 let mut block = self;
1665 while let Some(Expr { kind: ExprKind::Block(inner_block, _), .. }) = block.expr {
1666 block = inner_block;
1667 }
1668 block
1669 }
1670}
1671
1672#[derive(Debug, Clone, Copy, HashStable_Generic)]
1673pub struct TyPat<'hir> {
1674 #[stable_hasher(ignore)]
1675 pub hir_id: HirId,
1676 pub kind: TyPatKind<'hir>,
1677 pub span: Span,
1678}
1679
1680#[derive(Debug, Clone, Copy, HashStable_Generic)]
1681pub struct Pat<'hir> {
1682 #[stable_hasher(ignore)]
1683 pub hir_id: HirId,
1684 pub kind: PatKind<'hir>,
1685 pub span: Span,
1686 pub default_binding_modes: bool,
1689}
1690
1691impl<'hir> Pat<'hir> {
1692 fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
1693 if !it(self) {
1694 return false;
1695 }
1696
1697 use PatKind::*;
1698 match self.kind {
1699 Missing => unreachable!(),
1700 Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
1701 Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
1702 Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
1703 TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
1704 Slice(before, slice, after) => {
1705 before.iter().chain(slice).chain(after.iter()).all(|p| p.walk_short_(it))
1706 }
1707 }
1708 }
1709
1710 pub fn walk_short(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) -> bool {
1717 self.walk_short_(&mut it)
1718 }
1719
1720 fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
1721 if !it(self) {
1722 return;
1723 }
1724
1725 use PatKind::*;
1726 match self.kind {
1727 Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
1728 Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
1729 Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
1730 TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
1731 Slice(before, slice, after) => {
1732 before.iter().chain(slice).chain(after.iter()).for_each(|p| p.walk_(it))
1733 }
1734 }
1735 }
1736
1737 pub fn walk(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) {
1741 self.walk_(&mut it)
1742 }
1743
1744 pub fn walk_always(&self, mut it: impl FnMut(&Pat<'_>)) {
1748 self.walk(|p| {
1749 it(p);
1750 true
1751 })
1752 }
1753
1754 pub fn is_never_pattern(&self) -> bool {
1756 let mut is_never_pattern = false;
1757 self.walk(|pat| match &pat.kind {
1758 PatKind::Never => {
1759 is_never_pattern = true;
1760 false
1761 }
1762 PatKind::Or(s) => {
1763 is_never_pattern = s.iter().all(|p| p.is_never_pattern());
1764 false
1765 }
1766 _ => true,
1767 });
1768 is_never_pattern
1769 }
1770}
1771
1772#[derive(Debug, Clone, Copy, HashStable_Generic)]
1778pub struct PatField<'hir> {
1779 #[stable_hasher(ignore)]
1780 pub hir_id: HirId,
1781 pub ident: Ident,
1783 pub pat: &'hir Pat<'hir>,
1785 pub is_shorthand: bool,
1786 pub span: Span,
1787}
1788
1789#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic, Hash, Eq, Encodable, Decodable)]
1790pub enum RangeEnd {
1791 Included,
1792 Excluded,
1793}
1794
1795impl fmt::Display for RangeEnd {
1796 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1797 f.write_str(match self {
1798 RangeEnd::Included => "..=",
1799 RangeEnd::Excluded => "..",
1800 })
1801 }
1802}
1803
1804#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable_Generic)]
1808pub struct DotDotPos(u32);
1809
1810impl DotDotPos {
1811 pub fn new(n: Option<usize>) -> Self {
1813 match n {
1814 Some(n) => {
1815 assert!(n < u32::MAX as usize);
1816 Self(n as u32)
1817 }
1818 None => Self(u32::MAX),
1819 }
1820 }
1821
1822 pub fn as_opt_usize(&self) -> Option<usize> {
1823 if self.0 == u32::MAX { None } else { Some(self.0 as usize) }
1824 }
1825}
1826
1827impl fmt::Debug for DotDotPos {
1828 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1829 self.as_opt_usize().fmt(f)
1830 }
1831}
1832
1833#[derive(Debug, Clone, Copy, HashStable_Generic)]
1834pub struct PatExpr<'hir> {
1835 #[stable_hasher(ignore)]
1836 pub hir_id: HirId,
1837 pub span: Span,
1838 pub kind: PatExprKind<'hir>,
1839}
1840
1841#[derive(Debug, Clone, Copy, HashStable_Generic)]
1842pub enum PatExprKind<'hir> {
1843 Lit {
1844 lit: Lit,
1845 negated: bool,
1848 },
1849 ConstBlock(ConstBlock),
1850 Path(QPath<'hir>),
1852}
1853
1854#[derive(Debug, Clone, Copy, HashStable_Generic)]
1855pub enum TyPatKind<'hir> {
1856 Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
1858
1859 Or(&'hir [TyPat<'hir>]),
1861
1862 Err(ErrorGuaranteed),
1864}
1865
1866#[derive(Debug, Clone, Copy, HashStable_Generic)]
1867pub enum PatKind<'hir> {
1868 Missing,
1870
1871 Wild,
1873
1874 Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>),
1885
1886 Struct(QPath<'hir>, &'hir [PatField<'hir>], bool),
1889
1890 TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], DotDotPos),
1894
1895 Or(&'hir [Pat<'hir>]),
1898
1899 Never,
1901
1902 Tuple(&'hir [Pat<'hir>], DotDotPos),
1906
1907 Box(&'hir Pat<'hir>),
1909
1910 Deref(&'hir Pat<'hir>),
1912
1913 Ref(&'hir Pat<'hir>, Mutability),
1915
1916 Expr(&'hir PatExpr<'hir>),
1918
1919 Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
1921
1922 Range(Option<&'hir PatExpr<'hir>>, Option<&'hir PatExpr<'hir>>, RangeEnd),
1924
1925 Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
1935
1936 Err(ErrorGuaranteed),
1938}
1939
1940#[derive(Debug, Clone, Copy, HashStable_Generic)]
1942pub struct Stmt<'hir> {
1943 #[stable_hasher(ignore)]
1944 pub hir_id: HirId,
1945 pub kind: StmtKind<'hir>,
1946 pub span: Span,
1947}
1948
1949#[derive(Debug, Clone, Copy, HashStable_Generic)]
1951pub enum StmtKind<'hir> {
1952 Let(&'hir LetStmt<'hir>),
1954
1955 Item(ItemId),
1957
1958 Expr(&'hir Expr<'hir>),
1960
1961 Semi(&'hir Expr<'hir>),
1963}
1964
1965#[derive(Debug, Clone, Copy, HashStable_Generic)]
1967pub struct LetStmt<'hir> {
1968 pub super_: Option<Span>,
1970 pub pat: &'hir Pat<'hir>,
1971 pub ty: Option<&'hir Ty<'hir>>,
1973 pub init: Option<&'hir Expr<'hir>>,
1975 pub els: Option<&'hir Block<'hir>>,
1977 #[stable_hasher(ignore)]
1978 pub hir_id: HirId,
1979 pub span: Span,
1980 pub source: LocalSource,
1984}
1985
1986#[derive(Debug, Clone, Copy, HashStable_Generic)]
1989pub struct Arm<'hir> {
1990 #[stable_hasher(ignore)]
1991 pub hir_id: HirId,
1992 pub span: Span,
1993 pub pat: &'hir Pat<'hir>,
1995 pub guard: Option<&'hir Expr<'hir>>,
1997 pub body: &'hir Expr<'hir>,
1999}
2000
2001#[derive(Debug, Clone, Copy, HashStable_Generic)]
2007pub struct LetExpr<'hir> {
2008 pub span: Span,
2009 pub pat: &'hir Pat<'hir>,
2010 pub ty: Option<&'hir Ty<'hir>>,
2011 pub init: &'hir Expr<'hir>,
2012 pub recovered: ast::Recovered,
2015}
2016
2017#[derive(Debug, Clone, Copy, HashStable_Generic)]
2018pub struct ExprField<'hir> {
2019 #[stable_hasher(ignore)]
2020 pub hir_id: HirId,
2021 pub ident: Ident,
2022 pub expr: &'hir Expr<'hir>,
2023 pub span: Span,
2024 pub is_shorthand: bool,
2025}
2026
2027#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
2028pub enum BlockCheckMode {
2029 DefaultBlock,
2030 UnsafeBlock(UnsafeSource),
2031}
2032
2033#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
2034pub enum UnsafeSource {
2035 CompilerGenerated,
2036 UserProvided,
2037}
2038
2039#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
2040pub struct BodyId {
2041 pub hir_id: HirId,
2042}
2043
2044#[derive(Debug, Clone, Copy, HashStable_Generic)]
2066pub struct Body<'hir> {
2067 pub params: &'hir [Param<'hir>],
2068 pub value: &'hir Expr<'hir>,
2069}
2070
2071impl<'hir> Body<'hir> {
2072 pub fn id(&self) -> BodyId {
2073 BodyId { hir_id: self.value.hir_id }
2074 }
2075}
2076
2077#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
2079pub enum CoroutineKind {
2080 Desugared(CoroutineDesugaring, CoroutineSource),
2082
2083 Coroutine(Movability),
2085}
2086
2087impl CoroutineKind {
2088 pub fn movability(self) -> Movability {
2089 match self {
2090 CoroutineKind::Desugared(CoroutineDesugaring::Async, _)
2091 | CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => Movability::Static,
2092 CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => Movability::Movable,
2093 CoroutineKind::Coroutine(mov) => mov,
2094 }
2095 }
2096
2097 pub fn is_fn_like(self) -> bool {
2098 matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn))
2099 }
2100
2101 pub fn to_plural_string(&self) -> String {
2102 match self {
2103 CoroutineKind::Desugared(d, CoroutineSource::Fn) => format!("{d:#}fn bodies"),
2104 CoroutineKind::Desugared(d, CoroutineSource::Block) => format!("{d:#}blocks"),
2105 CoroutineKind::Desugared(d, CoroutineSource::Closure) => format!("{d:#}closure bodies"),
2106 CoroutineKind::Coroutine(_) => "coroutines".to_string(),
2107 }
2108 }
2109}
2110
2111impl fmt::Display for CoroutineKind {
2112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2113 match self {
2114 CoroutineKind::Desugared(d, k) => {
2115 d.fmt(f)?;
2116 k.fmt(f)
2117 }
2118 CoroutineKind::Coroutine(_) => f.write_str("coroutine"),
2119 }
2120 }
2121}
2122
2123#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy, HashStable_Generic, Encodable, Decodable)]
2129pub enum CoroutineSource {
2130 Block,
2132
2133 Closure,
2135
2136 Fn,
2138}
2139
2140impl fmt::Display for CoroutineSource {
2141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2142 match self {
2143 CoroutineSource::Block => "block",
2144 CoroutineSource::Closure => "closure body",
2145 CoroutineSource::Fn => "fn body",
2146 }
2147 .fmt(f)
2148 }
2149}
2150
2151#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, HashStable_Generic, Encodable, Decodable)]
2152pub enum CoroutineDesugaring {
2153 Async,
2155
2156 Gen,
2158
2159 AsyncGen,
2162}
2163
2164impl fmt::Display for CoroutineDesugaring {
2165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2166 match self {
2167 CoroutineDesugaring::Async => {
2168 if f.alternate() {
2169 f.write_str("`async` ")?;
2170 } else {
2171 f.write_str("async ")?
2172 }
2173 }
2174 CoroutineDesugaring::Gen => {
2175 if f.alternate() {
2176 f.write_str("`gen` ")?;
2177 } else {
2178 f.write_str("gen ")?
2179 }
2180 }
2181 CoroutineDesugaring::AsyncGen => {
2182 if f.alternate() {
2183 f.write_str("`async gen` ")?;
2184 } else {
2185 f.write_str("async gen ")?
2186 }
2187 }
2188 }
2189
2190 Ok(())
2191 }
2192}
2193
2194#[derive(Copy, Clone, Debug)]
2195pub enum BodyOwnerKind {
2196 Fn,
2198
2199 Closure,
2201
2202 Const { inline: bool },
2204
2205 Static(Mutability),
2207
2208 GlobalAsm,
2210}
2211
2212impl BodyOwnerKind {
2213 pub fn is_fn_or_closure(self) -> bool {
2214 match self {
2215 BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
2216 BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::GlobalAsm => {
2217 false
2218 }
2219 }
2220 }
2221}
2222
2223#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2225pub enum ConstContext {
2226 ConstFn,
2228
2229 Static(Mutability),
2231
2232 Const { inline: bool },
2242}
2243
2244impl ConstContext {
2245 pub fn keyword_name(self) -> &'static str {
2249 match self {
2250 Self::Const { .. } => "const",
2251 Self::Static(Mutability::Not) => "static",
2252 Self::Static(Mutability::Mut) => "static mut",
2253 Self::ConstFn => "const fn",
2254 }
2255 }
2256}
2257
2258impl fmt::Display for ConstContext {
2261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2262 match *self {
2263 Self::Const { .. } => write!(f, "constant"),
2264 Self::Static(_) => write!(f, "static"),
2265 Self::ConstFn => write!(f, "constant function"),
2266 }
2267 }
2268}
2269
2270impl IntoDiagArg for ConstContext {
2271 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
2272 DiagArgValue::Str(Cow::Borrowed(match self {
2273 ConstContext::ConstFn => "const_fn",
2274 ConstContext::Static(_) => "static",
2275 ConstContext::Const { .. } => "const",
2276 }))
2277 }
2278}
2279
2280pub type Lit = Spanned<LitKind>;
2282
2283#[derive(Copy, Clone, Debug, HashStable_Generic)]
2292pub struct AnonConst {
2293 #[stable_hasher(ignore)]
2294 pub hir_id: HirId,
2295 pub def_id: LocalDefId,
2296 pub body: BodyId,
2297 pub span: Span,
2298}
2299
2300#[derive(Copy, Clone, Debug, HashStable_Generic)]
2302pub struct ConstBlock {
2303 #[stable_hasher(ignore)]
2304 pub hir_id: HirId,
2305 pub def_id: LocalDefId,
2306 pub body: BodyId,
2307}
2308
2309#[derive(Debug, Clone, Copy, HashStable_Generic)]
2318pub struct Expr<'hir> {
2319 #[stable_hasher(ignore)]
2320 pub hir_id: HirId,
2321 pub kind: ExprKind<'hir>,
2322 pub span: Span,
2323}
2324
2325impl Expr<'_> {
2326 pub fn precedence(&self, has_attr: &dyn Fn(HirId) -> bool) -> ExprPrecedence {
2327 let prefix_attrs_precedence = || -> ExprPrecedence {
2328 if has_attr(self.hir_id) { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous }
2329 };
2330
2331 match &self.kind {
2332 ExprKind::Closure(closure) => {
2333 match closure.fn_decl.output {
2334 FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump,
2335 FnRetTy::Return(_) => prefix_attrs_precedence(),
2336 }
2337 }
2338
2339 ExprKind::Break(..)
2340 | ExprKind::Ret(..)
2341 | ExprKind::Yield(..)
2342 | ExprKind::Become(..) => ExprPrecedence::Jump,
2343
2344 ExprKind::Binary(op, ..) => op.node.precedence(),
2346 ExprKind::Cast(..) => ExprPrecedence::Cast,
2347
2348 ExprKind::Assign(..) |
2349 ExprKind::AssignOp(..) => ExprPrecedence::Assign,
2350
2351 ExprKind::AddrOf(..)
2353 | ExprKind::Let(..)
2358 | ExprKind::Unary(..) => ExprPrecedence::Prefix,
2359
2360 ExprKind::Array(_)
2362 | ExprKind::Block(..)
2363 | ExprKind::Call(..)
2364 | ExprKind::ConstBlock(_)
2365 | ExprKind::Continue(..)
2366 | ExprKind::Field(..)
2367 | ExprKind::If(..)
2368 | ExprKind::Index(..)
2369 | ExprKind::InlineAsm(..)
2370 | ExprKind::Lit(_)
2371 | ExprKind::Loop(..)
2372 | ExprKind::Match(..)
2373 | ExprKind::MethodCall(..)
2374 | ExprKind::OffsetOf(..)
2375 | ExprKind::Path(..)
2376 | ExprKind::Repeat(..)
2377 | ExprKind::Struct(..)
2378 | ExprKind::Tup(_)
2379 | ExprKind::Type(..)
2380 | ExprKind::UnsafeBinderCast(..)
2381 | ExprKind::Use(..)
2382 | ExprKind::Err(_) => prefix_attrs_precedence(),
2383
2384 ExprKind::DropTemps(expr, ..) => expr.precedence(has_attr),
2385 }
2386 }
2387
2388 pub fn is_syntactic_place_expr(&self) -> bool {
2393 self.is_place_expr(|_| true)
2394 }
2395
2396 pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
2401 match self.kind {
2402 ExprKind::Path(QPath::Resolved(_, ref path)) => {
2403 matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static { .. }, _) | Res::Err)
2404 }
2405
2406 ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
2410
2411 ExprKind::UnsafeBinderCast(_, e, _) => e.is_place_expr(allow_projections_from),
2413
2414 ExprKind::Unary(UnOp::Deref, _) => true,
2415
2416 ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _, _) => {
2417 allow_projections_from(base) || base.is_place_expr(allow_projections_from)
2418 }
2419
2420 ExprKind::Path(QPath::LangItem(..)) => false,
2422
2423 ExprKind::Err(_guar)
2425 | ExprKind::Let(&LetExpr { recovered: ast::Recovered::Yes(_guar), .. }) => true,
2426
2427 ExprKind::Path(QPath::TypeRelative(..))
2430 | ExprKind::Call(..)
2431 | ExprKind::MethodCall(..)
2432 | ExprKind::Use(..)
2433 | ExprKind::Struct(..)
2434 | ExprKind::Tup(..)
2435 | ExprKind::If(..)
2436 | ExprKind::Match(..)
2437 | ExprKind::Closure { .. }
2438 | ExprKind::Block(..)
2439 | ExprKind::Repeat(..)
2440 | ExprKind::Array(..)
2441 | ExprKind::Break(..)
2442 | ExprKind::Continue(..)
2443 | ExprKind::Ret(..)
2444 | ExprKind::Become(..)
2445 | ExprKind::Let(..)
2446 | ExprKind::Loop(..)
2447 | ExprKind::Assign(..)
2448 | ExprKind::InlineAsm(..)
2449 | ExprKind::OffsetOf(..)
2450 | ExprKind::AssignOp(..)
2451 | ExprKind::Lit(_)
2452 | ExprKind::ConstBlock(..)
2453 | ExprKind::Unary(..)
2454 | ExprKind::AddrOf(..)
2455 | ExprKind::Binary(..)
2456 | ExprKind::Yield(..)
2457 | ExprKind::Cast(..)
2458 | ExprKind::DropTemps(..) => false,
2459 }
2460 }
2461
2462 pub fn is_size_lit(&self) -> bool {
2465 matches!(
2466 self.kind,
2467 ExprKind::Lit(Lit {
2468 node: LitKind::Int(_, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::Usize)),
2469 ..
2470 })
2471 )
2472 }
2473
2474 pub fn peel_drop_temps(&self) -> &Self {
2480 let mut expr = self;
2481 while let ExprKind::DropTemps(inner) = &expr.kind {
2482 expr = inner;
2483 }
2484 expr
2485 }
2486
2487 pub fn peel_blocks(&self) -> &Self {
2488 let mut expr = self;
2489 while let ExprKind::Block(Block { expr: Some(inner), .. }, _) = &expr.kind {
2490 expr = inner;
2491 }
2492 expr
2493 }
2494
2495 pub fn peel_borrows(&self) -> &Self {
2496 let mut expr = self;
2497 while let ExprKind::AddrOf(.., inner) = &expr.kind {
2498 expr = inner;
2499 }
2500 expr
2501 }
2502
2503 pub fn can_have_side_effects(&self) -> bool {
2504 match self.peel_drop_temps().kind {
2505 ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) | ExprKind::Use(..) => {
2506 false
2507 }
2508 ExprKind::Type(base, _)
2509 | ExprKind::Unary(_, base)
2510 | ExprKind::Field(base, _)
2511 | ExprKind::Index(base, _, _)
2512 | ExprKind::AddrOf(.., base)
2513 | ExprKind::Cast(base, _)
2514 | ExprKind::UnsafeBinderCast(_, base, _) => {
2515 base.can_have_side_effects()
2519 }
2520 ExprKind::Struct(_, fields, init) => {
2521 let init_side_effects = match init {
2522 StructTailExpr::Base(init) => init.can_have_side_effects(),
2523 StructTailExpr::DefaultFields(_) | StructTailExpr::None => false,
2524 };
2525 fields.iter().map(|field| field.expr).any(|e| e.can_have_side_effects())
2526 || init_side_effects
2527 }
2528
2529 ExprKind::Array(args)
2530 | ExprKind::Tup(args)
2531 | ExprKind::Call(
2532 Expr {
2533 kind:
2534 ExprKind::Path(QPath::Resolved(
2535 None,
2536 Path { res: Res::Def(DefKind::Ctor(_, CtorKind::Fn), _), .. },
2537 )),
2538 ..
2539 },
2540 args,
2541 ) => args.iter().any(|arg| arg.can_have_side_effects()),
2542 ExprKind::If(..)
2543 | ExprKind::Match(..)
2544 | ExprKind::MethodCall(..)
2545 | ExprKind::Call(..)
2546 | ExprKind::Closure { .. }
2547 | ExprKind::Block(..)
2548 | ExprKind::Repeat(..)
2549 | ExprKind::Break(..)
2550 | ExprKind::Continue(..)
2551 | ExprKind::Ret(..)
2552 | ExprKind::Become(..)
2553 | ExprKind::Let(..)
2554 | ExprKind::Loop(..)
2555 | ExprKind::Assign(..)
2556 | ExprKind::InlineAsm(..)
2557 | ExprKind::AssignOp(..)
2558 | ExprKind::ConstBlock(..)
2559 | ExprKind::Binary(..)
2560 | ExprKind::Yield(..)
2561 | ExprKind::DropTemps(..)
2562 | ExprKind::Err(_) => true,
2563 }
2564 }
2565
2566 pub fn is_approximately_pattern(&self) -> bool {
2568 match &self.kind {
2569 ExprKind::Array(_)
2570 | ExprKind::Call(..)
2571 | ExprKind::Tup(_)
2572 | ExprKind::Lit(_)
2573 | ExprKind::Path(_)
2574 | ExprKind::Struct(..) => true,
2575 _ => false,
2576 }
2577 }
2578
2579 pub fn equivalent_for_indexing(&self, other: &Expr<'_>) -> bool {
2584 match (self.kind, other.kind) {
2585 (ExprKind::Lit(lit1), ExprKind::Lit(lit2)) => lit1.node == lit2.node,
2586 (
2587 ExprKind::Path(QPath::LangItem(item1, _)),
2588 ExprKind::Path(QPath::LangItem(item2, _)),
2589 ) => item1 == item2,
2590 (
2591 ExprKind::Path(QPath::Resolved(None, path1)),
2592 ExprKind::Path(QPath::Resolved(None, path2)),
2593 ) => path1.res == path2.res,
2594 (
2595 ExprKind::Struct(
2596 QPath::LangItem(LangItem::RangeTo, _),
2597 [val1],
2598 StructTailExpr::None,
2599 ),
2600 ExprKind::Struct(
2601 QPath::LangItem(LangItem::RangeTo, _),
2602 [val2],
2603 StructTailExpr::None,
2604 ),
2605 )
2606 | (
2607 ExprKind::Struct(
2608 QPath::LangItem(LangItem::RangeToInclusive, _),
2609 [val1],
2610 StructTailExpr::None,
2611 ),
2612 ExprKind::Struct(
2613 QPath::LangItem(LangItem::RangeToInclusive, _),
2614 [val2],
2615 StructTailExpr::None,
2616 ),
2617 )
2618 | (
2619 ExprKind::Struct(
2620 QPath::LangItem(LangItem::RangeFrom, _),
2621 [val1],
2622 StructTailExpr::None,
2623 ),
2624 ExprKind::Struct(
2625 QPath::LangItem(LangItem::RangeFrom, _),
2626 [val2],
2627 StructTailExpr::None,
2628 ),
2629 )
2630 | (
2631 ExprKind::Struct(
2632 QPath::LangItem(LangItem::RangeFromCopy, _),
2633 [val1],
2634 StructTailExpr::None,
2635 ),
2636 ExprKind::Struct(
2637 QPath::LangItem(LangItem::RangeFromCopy, _),
2638 [val2],
2639 StructTailExpr::None,
2640 ),
2641 ) => val1.expr.equivalent_for_indexing(val2.expr),
2642 (
2643 ExprKind::Struct(
2644 QPath::LangItem(LangItem::Range, _),
2645 [val1, val3],
2646 StructTailExpr::None,
2647 ),
2648 ExprKind::Struct(
2649 QPath::LangItem(LangItem::Range, _),
2650 [val2, val4],
2651 StructTailExpr::None,
2652 ),
2653 )
2654 | (
2655 ExprKind::Struct(
2656 QPath::LangItem(LangItem::RangeCopy, _),
2657 [val1, val3],
2658 StructTailExpr::None,
2659 ),
2660 ExprKind::Struct(
2661 QPath::LangItem(LangItem::RangeCopy, _),
2662 [val2, val4],
2663 StructTailExpr::None,
2664 ),
2665 )
2666 | (
2667 ExprKind::Struct(
2668 QPath::LangItem(LangItem::RangeInclusiveCopy, _),
2669 [val1, val3],
2670 StructTailExpr::None,
2671 ),
2672 ExprKind::Struct(
2673 QPath::LangItem(LangItem::RangeInclusiveCopy, _),
2674 [val2, val4],
2675 StructTailExpr::None,
2676 ),
2677 ) => {
2678 val1.expr.equivalent_for_indexing(val2.expr)
2679 && val3.expr.equivalent_for_indexing(val4.expr)
2680 }
2681 _ => false,
2682 }
2683 }
2684
2685 pub fn method_ident(&self) -> Option<Ident> {
2686 match self.kind {
2687 ExprKind::MethodCall(receiver_method, ..) => Some(receiver_method.ident),
2688 ExprKind::Unary(_, expr) | ExprKind::AddrOf(.., expr) => expr.method_ident(),
2689 _ => None,
2690 }
2691 }
2692}
2693
2694pub fn is_range_literal(expr: &Expr<'_>) -> bool {
2697 match expr.kind {
2698 ExprKind::Struct(ref qpath, _, _) => matches!(
2700 **qpath,
2701 QPath::LangItem(
2702 LangItem::Range
2703 | LangItem::RangeTo
2704 | LangItem::RangeFrom
2705 | LangItem::RangeFull
2706 | LangItem::RangeToInclusive
2707 | LangItem::RangeCopy
2708 | LangItem::RangeFromCopy
2709 | LangItem::RangeInclusiveCopy,
2710 ..
2711 )
2712 ),
2713
2714 ExprKind::Call(ref func, _) => {
2716 matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)))
2717 }
2718
2719 _ => false,
2720 }
2721}
2722
2723pub fn expr_needs_parens(expr: &Expr<'_>) -> bool {
2730 match expr.kind {
2731 ExprKind::Cast(_, _) | ExprKind::Binary(_, _, _) => true,
2733 _ if is_range_literal(expr) => true,
2735 _ => false,
2736 }
2737}
2738
2739#[derive(Debug, Clone, Copy, HashStable_Generic)]
2740pub enum ExprKind<'hir> {
2741 ConstBlock(ConstBlock),
2743 Array(&'hir [Expr<'hir>]),
2745 Call(&'hir Expr<'hir>, &'hir [Expr<'hir>]),
2752 MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span),
2769 Use(&'hir Expr<'hir>, Span),
2771 Tup(&'hir [Expr<'hir>]),
2773 Binary(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
2775 Unary(UnOp, &'hir Expr<'hir>),
2777 Lit(Lit),
2779 Cast(&'hir Expr<'hir>, &'hir Ty<'hir>),
2781 Type(&'hir Expr<'hir>, &'hir Ty<'hir>),
2783 DropTemps(&'hir Expr<'hir>),
2789 Let(&'hir LetExpr<'hir>),
2794 If(&'hir Expr<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
2803 Loop(&'hir Block<'hir>, Option<Label>, LoopSource, Span),
2809 Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
2812 Closure(&'hir Closure<'hir>),
2819 Block(&'hir Block<'hir>, Option<Label>),
2821
2822 Assign(&'hir Expr<'hir>, &'hir Expr<'hir>, Span),
2824 AssignOp(AssignOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
2828 Field(&'hir Expr<'hir>, Ident),
2830 Index(&'hir Expr<'hir>, &'hir Expr<'hir>, Span),
2834
2835 Path(QPath<'hir>),
2837
2838 AddrOf(BorrowKind, Mutability, &'hir Expr<'hir>),
2840 Break(Destination, Option<&'hir Expr<'hir>>),
2842 Continue(Destination),
2844 Ret(Option<&'hir Expr<'hir>>),
2846 Become(&'hir Expr<'hir>),
2848
2849 InlineAsm(&'hir InlineAsm<'hir>),
2851
2852 OffsetOf(&'hir Ty<'hir>, &'hir [Ident]),
2854
2855 Struct(&'hir QPath<'hir>, &'hir [ExprField<'hir>], StructTailExpr<'hir>),
2860
2861 Repeat(&'hir Expr<'hir>, &'hir ConstArg<'hir>),
2866
2867 Yield(&'hir Expr<'hir>, YieldSource),
2869
2870 UnsafeBinderCast(UnsafeBinderCastKind, &'hir Expr<'hir>, Option<&'hir Ty<'hir>>),
2873
2874 Err(rustc_span::ErrorGuaranteed),
2876}
2877
2878#[derive(Debug, Clone, Copy, HashStable_Generic)]
2879pub enum StructTailExpr<'hir> {
2880 None,
2882 Base(&'hir Expr<'hir>),
2885 DefaultFields(Span),
2889}
2890
2891#[derive(Debug, Clone, Copy, HashStable_Generic)]
2897pub enum QPath<'hir> {
2898 Resolved(Option<&'hir Ty<'hir>>, &'hir Path<'hir>),
2905
2906 TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
2913
2914 LangItem(LangItem, Span),
2916}
2917
2918impl<'hir> QPath<'hir> {
2919 pub fn span(&self) -> Span {
2921 match *self {
2922 QPath::Resolved(_, path) => path.span,
2923 QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span),
2924 QPath::LangItem(_, span) => span,
2925 }
2926 }
2927
2928 pub fn qself_span(&self) -> Span {
2931 match *self {
2932 QPath::Resolved(_, path) => path.span,
2933 QPath::TypeRelative(qself, _) => qself.span,
2934 QPath::LangItem(_, span) => span,
2935 }
2936 }
2937}
2938
2939#[derive(Copy, Clone, Debug, HashStable_Generic)]
2941pub enum LocalSource {
2942 Normal,
2944 AsyncFn,
2955 AwaitDesugar,
2957 AssignDesugar(Span),
2960 Contract,
2962}
2963
2964#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic, Encodable, Decodable)]
2966pub enum MatchSource {
2967 Normal,
2969 Postfix,
2971 ForLoopDesugar,
2973 TryDesugar(HirId),
2975 AwaitDesugar,
2977 FormatArgs,
2979}
2980
2981impl MatchSource {
2982 #[inline]
2983 pub const fn name(self) -> &'static str {
2984 use MatchSource::*;
2985 match self {
2986 Normal => "match",
2987 Postfix => ".match",
2988 ForLoopDesugar => "for",
2989 TryDesugar(_) => "?",
2990 AwaitDesugar => ".await",
2991 FormatArgs => "format_args!()",
2992 }
2993 }
2994}
2995
2996#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
2998pub enum LoopSource {
2999 Loop,
3001 While,
3003 ForLoop,
3005}
3006
3007impl LoopSource {
3008 pub fn name(self) -> &'static str {
3009 match self {
3010 LoopSource::Loop => "loop",
3011 LoopSource::While => "while",
3012 LoopSource::ForLoop => "for",
3013 }
3014 }
3015}
3016
3017#[derive(Copy, Clone, Debug, PartialEq, HashStable_Generic)]
3018pub enum LoopIdError {
3019 OutsideLoopScope,
3020 UnlabeledCfInWhileCondition,
3021 UnresolvedLabel,
3022}
3023
3024impl fmt::Display for LoopIdError {
3025 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3026 f.write_str(match self {
3027 LoopIdError::OutsideLoopScope => "not inside loop scope",
3028 LoopIdError::UnlabeledCfInWhileCondition => {
3029 "unlabeled control flow (break or continue) in while condition"
3030 }
3031 LoopIdError::UnresolvedLabel => "label not found",
3032 })
3033 }
3034}
3035
3036#[derive(Copy, Clone, Debug, PartialEq, HashStable_Generic)]
3037pub struct Destination {
3038 pub label: Option<Label>,
3040
3041 pub target_id: Result<HirId, LoopIdError>,
3044}
3045
3046#[derive(Copy, Clone, Debug, HashStable_Generic)]
3048pub enum YieldSource {
3049 Await { expr: Option<HirId> },
3051 Yield,
3053}
3054
3055impl fmt::Display for YieldSource {
3056 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3057 f.write_str(match self {
3058 YieldSource::Await { .. } => "`await`",
3059 YieldSource::Yield => "`yield`",
3060 })
3061 }
3062}
3063
3064#[derive(Debug, Clone, Copy, HashStable_Generic)]
3067pub struct MutTy<'hir> {
3068 pub ty: &'hir Ty<'hir>,
3069 pub mutbl: Mutability,
3070}
3071
3072#[derive(Debug, Clone, Copy, HashStable_Generic)]
3075pub struct FnSig<'hir> {
3076 pub header: FnHeader,
3077 pub decl: &'hir FnDecl<'hir>,
3078 pub span: Span,
3079}
3080
3081#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
3085pub struct TraitItemId {
3086 pub owner_id: OwnerId,
3087}
3088
3089impl TraitItemId {
3090 #[inline]
3091 pub fn hir_id(&self) -> HirId {
3092 HirId::make_owner(self.owner_id.def_id)
3094 }
3095}
3096
3097#[derive(Debug, Clone, Copy, HashStable_Generic)]
3102pub struct TraitItem<'hir> {
3103 pub ident: Ident,
3104 pub owner_id: OwnerId,
3105 pub generics: &'hir Generics<'hir>,
3106 pub kind: TraitItemKind<'hir>,
3107 pub span: Span,
3108 pub defaultness: Defaultness,
3109 pub has_delayed_lints: bool,
3110}
3111
3112macro_rules! expect_methods_self_kind {
3113 ( $( $name:ident, $ret_ty:ty, $pat:pat, $ret_val:expr; )* ) => {
3114 $(
3115 #[track_caller]
3116 pub fn $name(&self) -> $ret_ty {
3117 let $pat = &self.kind else { expect_failed(stringify!($ident), self) };
3118 $ret_val
3119 }
3120 )*
3121 }
3122}
3123
3124macro_rules! expect_methods_self {
3125 ( $( $name:ident, $ret_ty:ty, $pat:pat, $ret_val:expr; )* ) => {
3126 $(
3127 #[track_caller]
3128 pub fn $name(&self) -> $ret_ty {
3129 let $pat = self else { expect_failed(stringify!($ident), self) };
3130 $ret_val
3131 }
3132 )*
3133 }
3134}
3135
3136#[track_caller]
3137fn expect_failed<T: fmt::Debug>(ident: &'static str, found: T) -> ! {
3138 panic!("{ident}: found {found:?}")
3139}
3140
3141impl<'hir> TraitItem<'hir> {
3142 #[inline]
3143 pub fn hir_id(&self) -> HirId {
3144 HirId::make_owner(self.owner_id.def_id)
3146 }
3147
3148 pub fn trait_item_id(&self) -> TraitItemId {
3149 TraitItemId { owner_id: self.owner_id }
3150 }
3151
3152 expect_methods_self_kind! {
3153 expect_const, (&'hir Ty<'hir>, Option<BodyId>),
3154 TraitItemKind::Const(ty, body), (ty, *body);
3155
3156 expect_fn, (&FnSig<'hir>, &TraitFn<'hir>),
3157 TraitItemKind::Fn(ty, trfn), (ty, trfn);
3158
3159 expect_type, (GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
3160 TraitItemKind::Type(bounds, ty), (bounds, *ty);
3161 }
3162}
3163
3164#[derive(Debug, Clone, Copy, HashStable_Generic)]
3166pub enum TraitFn<'hir> {
3167 Required(&'hir [Option<Ident>]),
3169
3170 Provided(BodyId),
3172}
3173
3174#[derive(Debug, Clone, Copy, HashStable_Generic)]
3176pub enum TraitItemKind<'hir> {
3177 Const(&'hir Ty<'hir>, Option<BodyId>),
3179 Fn(FnSig<'hir>, TraitFn<'hir>),
3181 Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
3184}
3185
3186#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
3190pub struct ImplItemId {
3191 pub owner_id: OwnerId,
3192}
3193
3194impl ImplItemId {
3195 #[inline]
3196 pub fn hir_id(&self) -> HirId {
3197 HirId::make_owner(self.owner_id.def_id)
3199 }
3200}
3201
3202#[derive(Debug, Clone, Copy, HashStable_Generic)]
3206pub struct ImplItem<'hir> {
3207 pub ident: Ident,
3208 pub owner_id: OwnerId,
3209 pub generics: &'hir Generics<'hir>,
3210 pub kind: ImplItemKind<'hir>,
3211 pub defaultness: Defaultness,
3212 pub span: Span,
3213 pub vis_span: Span,
3214 pub has_delayed_lints: bool,
3215 pub trait_item_def_id: Option<DefId>,
3217}
3218
3219impl<'hir> ImplItem<'hir> {
3220 #[inline]
3221 pub fn hir_id(&self) -> HirId {
3222 HirId::make_owner(self.owner_id.def_id)
3224 }
3225
3226 pub fn impl_item_id(&self) -> ImplItemId {
3227 ImplItemId { owner_id: self.owner_id }
3228 }
3229
3230 expect_methods_self_kind! {
3231 expect_const, (&'hir Ty<'hir>, BodyId), ImplItemKind::Const(ty, body), (ty, *body);
3232 expect_fn, (&FnSig<'hir>, BodyId), ImplItemKind::Fn(ty, body), (ty, *body);
3233 expect_type, &'hir Ty<'hir>, ImplItemKind::Type(ty), ty;
3234 }
3235}
3236
3237#[derive(Debug, Clone, Copy, HashStable_Generic)]
3239pub enum ImplItemKind<'hir> {
3240 Const(&'hir Ty<'hir>, BodyId),
3243 Fn(FnSig<'hir>, BodyId),
3245 Type(&'hir Ty<'hir>),
3247}
3248
3249#[derive(Debug, Clone, Copy, HashStable_Generic)]
3260pub struct AssocItemConstraint<'hir> {
3261 #[stable_hasher(ignore)]
3262 pub hir_id: HirId,
3263 pub ident: Ident,
3264 pub gen_args: &'hir GenericArgs<'hir>,
3265 pub kind: AssocItemConstraintKind<'hir>,
3266 pub span: Span,
3267}
3268
3269impl<'hir> AssocItemConstraint<'hir> {
3270 pub fn ty(self) -> Option<&'hir Ty<'hir>> {
3272 match self.kind {
3273 AssocItemConstraintKind::Equality { term: Term::Ty(ty) } => Some(ty),
3274 _ => None,
3275 }
3276 }
3277
3278 pub fn ct(self) -> Option<&'hir ConstArg<'hir>> {
3280 match self.kind {
3281 AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
3282 _ => None,
3283 }
3284 }
3285}
3286
3287#[derive(Debug, Clone, Copy, HashStable_Generic)]
3288pub enum Term<'hir> {
3289 Ty(&'hir Ty<'hir>),
3290 Const(&'hir ConstArg<'hir>),
3291}
3292
3293impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
3294 fn from(ty: &'hir Ty<'hir>) -> Self {
3295 Term::Ty(ty)
3296 }
3297}
3298
3299impl<'hir> From<&'hir ConstArg<'hir>> for Term<'hir> {
3300 fn from(c: &'hir ConstArg<'hir>) -> Self {
3301 Term::Const(c)
3302 }
3303}
3304
3305#[derive(Debug, Clone, Copy, HashStable_Generic)]
3307pub enum AssocItemConstraintKind<'hir> {
3308 Equality { term: Term<'hir> },
3315 Bound { bounds: &'hir [GenericBound<'hir>] },
3317}
3318
3319impl<'hir> AssocItemConstraintKind<'hir> {
3320 pub fn descr(&self) -> &'static str {
3321 match self {
3322 AssocItemConstraintKind::Equality { .. } => "binding",
3323 AssocItemConstraintKind::Bound { .. } => "constraint",
3324 }
3325 }
3326}
3327
3328#[derive(Debug, Clone, Copy, HashStable_Generic)]
3332pub enum AmbigArg {}
3333
3334#[derive(Debug, Clone, Copy, HashStable_Generic)]
3339#[repr(C)]
3340pub struct Ty<'hir, Unambig = ()> {
3341 #[stable_hasher(ignore)]
3342 pub hir_id: HirId,
3343 pub span: Span,
3344 pub kind: TyKind<'hir, Unambig>,
3345}
3346
3347impl<'hir> Ty<'hir, AmbigArg> {
3348 pub fn as_unambig_ty(&self) -> &Ty<'hir> {
3359 let ptr = self as *const Ty<'hir, AmbigArg> as *const Ty<'hir, ()>;
3362 unsafe { &*ptr }
3363 }
3364}
3365
3366impl<'hir> Ty<'hir> {
3367 pub fn try_as_ambig_ty(&self) -> Option<&Ty<'hir, AmbigArg>> {
3373 if let TyKind::Infer(()) = self.kind {
3374 return None;
3375 }
3376
3377 let ptr = self as *const Ty<'hir> as *const Ty<'hir, AmbigArg>;
3381 Some(unsafe { &*ptr })
3382 }
3383}
3384
3385impl<'hir> Ty<'hir, AmbigArg> {
3386 pub fn peel_refs(&self) -> &Ty<'hir> {
3387 let mut final_ty = self.as_unambig_ty();
3388 while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
3389 final_ty = ty;
3390 }
3391 final_ty
3392 }
3393}
3394
3395impl<'hir> Ty<'hir> {
3396 pub fn peel_refs(&self) -> &Self {
3397 let mut final_ty = self;
3398 while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
3399 final_ty = ty;
3400 }
3401 final_ty
3402 }
3403
3404 pub fn as_generic_param(&self) -> Option<(DefId, Ident)> {
3406 let TyKind::Path(QPath::Resolved(None, path)) = self.kind else {
3407 return None;
3408 };
3409 let [segment] = &path.segments else {
3410 return None;
3411 };
3412 match path.res {
3413 Res::Def(DefKind::TyParam, def_id) | Res::SelfTyParam { trait_: def_id } => {
3414 Some((def_id, segment.ident))
3415 }
3416 _ => None,
3417 }
3418 }
3419
3420 pub fn find_self_aliases(&self) -> Vec<Span> {
3421 use crate::intravisit::Visitor;
3422 struct MyVisitor(Vec<Span>);
3423 impl<'v> Visitor<'v> for MyVisitor {
3424 fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) {
3425 if matches!(
3426 &t.kind,
3427 TyKind::Path(QPath::Resolved(
3428 _,
3429 Path { res: crate::def::Res::SelfTyAlias { .. }, .. },
3430 ))
3431 ) {
3432 self.0.push(t.span);
3433 return;
3434 }
3435 crate::intravisit::walk_ty(self, t);
3436 }
3437 }
3438
3439 let mut my_visitor = MyVisitor(vec![]);
3440 my_visitor.visit_ty_unambig(self);
3441 my_visitor.0
3442 }
3443
3444 pub fn is_suggestable_infer_ty(&self) -> bool {
3447 fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool {
3448 generic_args.iter().any(|arg| match arg {
3449 GenericArg::Type(ty) => ty.as_unambig_ty().is_suggestable_infer_ty(),
3450 GenericArg::Infer(_) => true,
3451 _ => false,
3452 })
3453 }
3454 debug!(?self);
3455 match &self.kind {
3456 TyKind::Infer(()) => true,
3457 TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
3458 TyKind::Array(ty, length) => {
3459 ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..))
3460 }
3461 TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
3462 TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
3463 TyKind::Path(QPath::TypeRelative(ty, segment)) => {
3464 ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
3465 }
3466 TyKind::Path(QPath::Resolved(ty_opt, Path { segments, .. })) => {
3467 ty_opt.is_some_and(Self::is_suggestable_infer_ty)
3468 || segments
3469 .iter()
3470 .any(|segment| are_suggestable_generic_args(segment.args().args))
3471 }
3472 _ => false,
3473 }
3474 }
3475}
3476
3477#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
3479pub enum PrimTy {
3480 Int(IntTy),
3481 Uint(UintTy),
3482 Float(FloatTy),
3483 Str,
3484 Bool,
3485 Char,
3486}
3487
3488impl PrimTy {
3489 pub const ALL: [Self; 19] = [
3491 Self::Int(IntTy::I8),
3493 Self::Int(IntTy::I16),
3494 Self::Int(IntTy::I32),
3495 Self::Int(IntTy::I64),
3496 Self::Int(IntTy::I128),
3497 Self::Int(IntTy::Isize),
3498 Self::Uint(UintTy::U8),
3499 Self::Uint(UintTy::U16),
3500 Self::Uint(UintTy::U32),
3501 Self::Uint(UintTy::U64),
3502 Self::Uint(UintTy::U128),
3503 Self::Uint(UintTy::Usize),
3504 Self::Float(FloatTy::F16),
3505 Self::Float(FloatTy::F32),
3506 Self::Float(FloatTy::F64),
3507 Self::Float(FloatTy::F128),
3508 Self::Bool,
3509 Self::Char,
3510 Self::Str,
3511 ];
3512
3513 pub fn name_str(self) -> &'static str {
3517 match self {
3518 PrimTy::Int(i) => i.name_str(),
3519 PrimTy::Uint(u) => u.name_str(),
3520 PrimTy::Float(f) => f.name_str(),
3521 PrimTy::Str => "str",
3522 PrimTy::Bool => "bool",
3523 PrimTy::Char => "char",
3524 }
3525 }
3526
3527 pub fn name(self) -> Symbol {
3528 match self {
3529 PrimTy::Int(i) => i.name(),
3530 PrimTy::Uint(u) => u.name(),
3531 PrimTy::Float(f) => f.name(),
3532 PrimTy::Str => sym::str,
3533 PrimTy::Bool => sym::bool,
3534 PrimTy::Char => sym::char,
3535 }
3536 }
3537
3538 pub fn from_name(name: Symbol) -> Option<Self> {
3541 let ty = match name {
3542 sym::i8 => Self::Int(IntTy::I8),
3544 sym::i16 => Self::Int(IntTy::I16),
3545 sym::i32 => Self::Int(IntTy::I32),
3546 sym::i64 => Self::Int(IntTy::I64),
3547 sym::i128 => Self::Int(IntTy::I128),
3548 sym::isize => Self::Int(IntTy::Isize),
3549 sym::u8 => Self::Uint(UintTy::U8),
3550 sym::u16 => Self::Uint(UintTy::U16),
3551 sym::u32 => Self::Uint(UintTy::U32),
3552 sym::u64 => Self::Uint(UintTy::U64),
3553 sym::u128 => Self::Uint(UintTy::U128),
3554 sym::usize => Self::Uint(UintTy::Usize),
3555 sym::f16 => Self::Float(FloatTy::F16),
3556 sym::f32 => Self::Float(FloatTy::F32),
3557 sym::f64 => Self::Float(FloatTy::F64),
3558 sym::f128 => Self::Float(FloatTy::F128),
3559 sym::bool => Self::Bool,
3560 sym::char => Self::Char,
3561 sym::str => Self::Str,
3562 _ => return None,
3563 };
3564 Some(ty)
3565 }
3566}
3567
3568#[derive(Debug, Clone, Copy, HashStable_Generic)]
3569pub struct FnPtrTy<'hir> {
3570 pub safety: Safety,
3571 pub abi: ExternAbi,
3572 pub generic_params: &'hir [GenericParam<'hir>],
3573 pub decl: &'hir FnDecl<'hir>,
3574 pub param_idents: &'hir [Option<Ident>],
3577}
3578
3579#[derive(Debug, Clone, Copy, HashStable_Generic)]
3580pub struct UnsafeBinderTy<'hir> {
3581 pub generic_params: &'hir [GenericParam<'hir>],
3582 pub inner_ty: &'hir Ty<'hir>,
3583}
3584
3585#[derive(Debug, Clone, Copy, HashStable_Generic)]
3586pub struct OpaqueTy<'hir> {
3587 #[stable_hasher(ignore)]
3588 pub hir_id: HirId,
3589 pub def_id: LocalDefId,
3590 pub bounds: GenericBounds<'hir>,
3591 pub origin: OpaqueTyOrigin<LocalDefId>,
3592 pub span: Span,
3593}
3594
3595#[derive(Debug, Clone, Copy, HashStable_Generic, Encodable, Decodable)]
3596pub enum PreciseCapturingArgKind<T, U> {
3597 Lifetime(T),
3598 Param(U),
3600}
3601
3602pub type PreciseCapturingArg<'hir> =
3603 PreciseCapturingArgKind<&'hir Lifetime, PreciseCapturingNonLifetimeArg>;
3604
3605impl PreciseCapturingArg<'_> {
3606 pub fn hir_id(self) -> HirId {
3607 match self {
3608 PreciseCapturingArg::Lifetime(lt) => lt.hir_id,
3609 PreciseCapturingArg::Param(param) => param.hir_id,
3610 }
3611 }
3612
3613 pub fn name(self) -> Symbol {
3614 match self {
3615 PreciseCapturingArg::Lifetime(lt) => lt.ident.name,
3616 PreciseCapturingArg::Param(param) => param.ident.name,
3617 }
3618 }
3619}
3620
3621#[derive(Debug, Clone, Copy, HashStable_Generic)]
3626pub struct PreciseCapturingNonLifetimeArg {
3627 #[stable_hasher(ignore)]
3628 pub hir_id: HirId,
3629 pub ident: Ident,
3630 pub res: Res,
3631}
3632
3633#[derive(Copy, Clone, PartialEq, Eq, Debug)]
3634#[derive(HashStable_Generic, Encodable, Decodable)]
3635pub enum RpitContext {
3636 Trait,
3637 TraitImpl,
3638}
3639
3640#[derive(Copy, Clone, PartialEq, Eq, Debug)]
3642#[derive(HashStable_Generic, Encodable, Decodable)]
3643pub enum OpaqueTyOrigin<D> {
3644 FnReturn {
3646 parent: D,
3648 in_trait_or_impl: Option<RpitContext>,
3650 },
3651 AsyncFn {
3653 parent: D,
3655 in_trait_or_impl: Option<RpitContext>,
3657 },
3658 TyAlias {
3660 parent: D,
3662 in_assoc_ty: bool,
3664 },
3665}
3666
3667#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
3668pub enum InferDelegationKind {
3669 Input(usize),
3670 Output,
3671}
3672
3673#[repr(u8, C)]
3679#[derive(Debug, Clone, Copy, HashStable_Generic)]
3680pub enum TyKind<'hir, Unambig = ()> {
3681 InferDelegation(DefId, InferDelegationKind),
3683 Slice(&'hir Ty<'hir>),
3685 Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>),
3687 Ptr(MutTy<'hir>),
3689 Ref(&'hir Lifetime, MutTy<'hir>),
3691 FnPtr(&'hir FnPtrTy<'hir>),
3693 UnsafeBinder(&'hir UnsafeBinderTy<'hir>),
3695 Never,
3697 Tup(&'hir [Ty<'hir>]),
3699 Path(QPath<'hir>),
3704 OpaqueDef(&'hir OpaqueTy<'hir>),
3706 TraitAscription(GenericBounds<'hir>),
3708 TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>),
3714 Typeof(&'hir AnonConst),
3716 Err(rustc_span::ErrorGuaranteed),
3718 Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
3720 Infer(Unambig),
3726}
3727
3728#[derive(Debug, Clone, Copy, HashStable_Generic)]
3729pub enum InlineAsmOperand<'hir> {
3730 In {
3731 reg: InlineAsmRegOrRegClass,
3732 expr: &'hir Expr<'hir>,
3733 },
3734 Out {
3735 reg: InlineAsmRegOrRegClass,
3736 late: bool,
3737 expr: Option<&'hir Expr<'hir>>,
3738 },
3739 InOut {
3740 reg: InlineAsmRegOrRegClass,
3741 late: bool,
3742 expr: &'hir Expr<'hir>,
3743 },
3744 SplitInOut {
3745 reg: InlineAsmRegOrRegClass,
3746 late: bool,
3747 in_expr: &'hir Expr<'hir>,
3748 out_expr: Option<&'hir Expr<'hir>>,
3749 },
3750 Const {
3751 anon_const: ConstBlock,
3752 },
3753 SymFn {
3754 expr: &'hir Expr<'hir>,
3755 },
3756 SymStatic {
3757 path: QPath<'hir>,
3758 def_id: DefId,
3759 },
3760 Label {
3761 block: &'hir Block<'hir>,
3762 },
3763}
3764
3765impl<'hir> InlineAsmOperand<'hir> {
3766 pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
3767 match *self {
3768 Self::In { reg, .. }
3769 | Self::Out { reg, .. }
3770 | Self::InOut { reg, .. }
3771 | Self::SplitInOut { reg, .. } => Some(reg),
3772 Self::Const { .. }
3773 | Self::SymFn { .. }
3774 | Self::SymStatic { .. }
3775 | Self::Label { .. } => None,
3776 }
3777 }
3778
3779 pub fn is_clobber(&self) -> bool {
3780 matches!(
3781 self,
3782 InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None }
3783 )
3784 }
3785}
3786
3787#[derive(Debug, Clone, Copy, HashStable_Generic)]
3788pub struct InlineAsm<'hir> {
3789 pub asm_macro: ast::AsmMacro,
3790 pub template: &'hir [InlineAsmTemplatePiece],
3791 pub template_strs: &'hir [(Symbol, Option<Symbol>, Span)],
3792 pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
3793 pub options: InlineAsmOptions,
3794 pub line_spans: &'hir [Span],
3795}
3796
3797impl InlineAsm<'_> {
3798 pub fn contains_label(&self) -> bool {
3799 self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. }))
3800 }
3801}
3802
3803#[derive(Debug, Clone, Copy, HashStable_Generic)]
3805pub struct Param<'hir> {
3806 #[stable_hasher(ignore)]
3807 pub hir_id: HirId,
3808 pub pat: &'hir Pat<'hir>,
3809 pub ty_span: Span,
3810 pub span: Span,
3811}
3812
3813#[derive(Debug, Clone, Copy, HashStable_Generic)]
3815pub struct FnDecl<'hir> {
3816 pub inputs: &'hir [Ty<'hir>],
3820 pub output: FnRetTy<'hir>,
3821 pub c_variadic: bool,
3822 pub implicit_self: ImplicitSelfKind,
3824 pub lifetime_elision_allowed: bool,
3826}
3827
3828impl<'hir> FnDecl<'hir> {
3829 pub fn opt_delegation_sig_id(&self) -> Option<DefId> {
3830 if let FnRetTy::Return(ty) = self.output
3831 && let TyKind::InferDelegation(sig_id, _) = ty.kind
3832 {
3833 return Some(sig_id);
3834 }
3835 None
3836 }
3837}
3838
3839#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
3841pub enum ImplicitSelfKind {
3842 Imm,
3844 Mut,
3846 RefImm,
3848 RefMut,
3850 None,
3853}
3854
3855impl ImplicitSelfKind {
3856 pub fn has_implicit_self(&self) -> bool {
3858 !matches!(*self, ImplicitSelfKind::None)
3859 }
3860}
3861
3862#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
3863pub enum IsAsync {
3864 Async(Span),
3865 NotAsync,
3866}
3867
3868impl IsAsync {
3869 pub fn is_async(self) -> bool {
3870 matches!(self, IsAsync::Async(_))
3871 }
3872}
3873
3874#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
3875pub enum Defaultness {
3876 Default { has_value: bool },
3877 Final,
3878}
3879
3880impl Defaultness {
3881 pub fn has_value(&self) -> bool {
3882 match *self {
3883 Defaultness::Default { has_value } => has_value,
3884 Defaultness::Final => true,
3885 }
3886 }
3887
3888 pub fn is_final(&self) -> bool {
3889 *self == Defaultness::Final
3890 }
3891
3892 pub fn is_default(&self) -> bool {
3893 matches!(*self, Defaultness::Default { .. })
3894 }
3895}
3896
3897#[derive(Debug, Clone, Copy, HashStable_Generic)]
3898pub enum FnRetTy<'hir> {
3899 DefaultReturn(Span),
3905 Return(&'hir Ty<'hir>),
3907}
3908
3909impl<'hir> FnRetTy<'hir> {
3910 #[inline]
3911 pub fn span(&self) -> Span {
3912 match *self {
3913 Self::DefaultReturn(span) => span,
3914 Self::Return(ref ty) => ty.span,
3915 }
3916 }
3917
3918 pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> {
3919 if let Self::Return(ty) = self
3920 && ty.is_suggestable_infer_ty()
3921 {
3922 return Some(*ty);
3923 }
3924 None
3925 }
3926}
3927
3928#[derive(Copy, Clone, Debug, HashStable_Generic)]
3930pub enum ClosureBinder {
3931 Default,
3933 For { span: Span },
3937}
3938
3939#[derive(Debug, Clone, Copy, HashStable_Generic)]
3940pub struct Mod<'hir> {
3941 pub spans: ModSpans,
3942 pub item_ids: &'hir [ItemId],
3943}
3944
3945#[derive(Copy, Clone, Debug, HashStable_Generic)]
3946pub struct ModSpans {
3947 pub inner_span: Span,
3951 pub inject_use_span: Span,
3952}
3953
3954#[derive(Debug, Clone, Copy, HashStable_Generic)]
3955pub struct EnumDef<'hir> {
3956 pub variants: &'hir [Variant<'hir>],
3957}
3958
3959#[derive(Debug, Clone, Copy, HashStable_Generic)]
3960pub struct Variant<'hir> {
3961 pub ident: Ident,
3963 #[stable_hasher(ignore)]
3965 pub hir_id: HirId,
3966 pub def_id: LocalDefId,
3967 pub data: VariantData<'hir>,
3969 pub disr_expr: Option<&'hir AnonConst>,
3971 pub span: Span,
3973}
3974
3975#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
3976pub enum UseKind {
3977 Single(Ident),
3984
3985 Glob,
3987
3988 ListStem,
3992}
3993
3994#[derive(Clone, Debug, Copy, HashStable_Generic)]
4001pub struct TraitRef<'hir> {
4002 pub path: &'hir Path<'hir>,
4003 #[stable_hasher(ignore)]
4005 pub hir_ref_id: HirId,
4006}
4007
4008impl TraitRef<'_> {
4009 pub fn trait_def_id(&self) -> Option<DefId> {
4011 match self.path.res {
4012 Res::Def(DefKind::Trait | DefKind::TraitAlias, did) => Some(did),
4013 Res::Err => None,
4014 res => panic!("{res:?} did not resolve to a trait or trait alias"),
4015 }
4016 }
4017}
4018
4019#[derive(Clone, Debug, Copy, HashStable_Generic)]
4020pub struct PolyTraitRef<'hir> {
4021 pub bound_generic_params: &'hir [GenericParam<'hir>],
4023
4024 pub modifiers: TraitBoundModifiers,
4028
4029 pub trait_ref: TraitRef<'hir>,
4031
4032 pub span: Span,
4033}
4034
4035#[derive(Debug, Clone, Copy, HashStable_Generic)]
4036pub struct FieldDef<'hir> {
4037 pub span: Span,
4038 pub vis_span: Span,
4039 pub ident: Ident,
4040 #[stable_hasher(ignore)]
4041 pub hir_id: HirId,
4042 pub def_id: LocalDefId,
4043 pub ty: &'hir Ty<'hir>,
4044 pub safety: Safety,
4045 pub default: Option<&'hir AnonConst>,
4046}
4047
4048impl FieldDef<'_> {
4049 pub fn is_positional(&self) -> bool {
4051 self.ident.as_str().as_bytes()[0].is_ascii_digit()
4052 }
4053}
4054
4055#[derive(Debug, Clone, Copy, HashStable_Generic)]
4057pub enum VariantData<'hir> {
4058 Struct { fields: &'hir [FieldDef<'hir>], recovered: ast::Recovered },
4062 Tuple(&'hir [FieldDef<'hir>], #[stable_hasher(ignore)] HirId, LocalDefId),
4066 Unit(#[stable_hasher(ignore)] HirId, LocalDefId),
4070}
4071
4072impl<'hir> VariantData<'hir> {
4073 pub fn fields(&self) -> &'hir [FieldDef<'hir>] {
4075 match *self {
4076 VariantData::Struct { fields, .. } | VariantData::Tuple(fields, ..) => fields,
4077 _ => &[],
4078 }
4079 }
4080
4081 pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> {
4082 match *self {
4083 VariantData::Tuple(_, hir_id, def_id) => Some((CtorKind::Fn, hir_id, def_id)),
4084 VariantData::Unit(hir_id, def_id) => Some((CtorKind::Const, hir_id, def_id)),
4085 VariantData::Struct { .. } => None,
4086 }
4087 }
4088
4089 #[inline]
4090 pub fn ctor_kind(&self) -> Option<CtorKind> {
4091 self.ctor().map(|(kind, ..)| kind)
4092 }
4093
4094 #[inline]
4096 pub fn ctor_hir_id(&self) -> Option<HirId> {
4097 self.ctor().map(|(_, hir_id, _)| hir_id)
4098 }
4099
4100 #[inline]
4102 pub fn ctor_def_id(&self) -> Option<LocalDefId> {
4103 self.ctor().map(|(.., def_id)| def_id)
4104 }
4105}
4106
4107#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
4111pub struct ItemId {
4112 pub owner_id: OwnerId,
4113}
4114
4115impl ItemId {
4116 #[inline]
4117 pub fn hir_id(&self) -> HirId {
4118 HirId::make_owner(self.owner_id.def_id)
4120 }
4121}
4122
4123#[derive(Debug, Clone, Copy, HashStable_Generic)]
4132pub struct Item<'hir> {
4133 pub owner_id: OwnerId,
4134 pub kind: ItemKind<'hir>,
4135 pub span: Span,
4136 pub vis_span: Span,
4137 pub has_delayed_lints: bool,
4138}
4139
4140impl<'hir> Item<'hir> {
4141 #[inline]
4142 pub fn hir_id(&self) -> HirId {
4143 HirId::make_owner(self.owner_id.def_id)
4145 }
4146
4147 pub fn item_id(&self) -> ItemId {
4148 ItemId { owner_id: self.owner_id }
4149 }
4150
4151 pub fn is_adt(&self) -> bool {
4154 matches!(self.kind, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..))
4155 }
4156
4157 pub fn is_struct_or_union(&self) -> bool {
4159 matches!(self.kind, ItemKind::Struct(..) | ItemKind::Union(..))
4160 }
4161
4162 expect_methods_self_kind! {
4163 expect_extern_crate, (Option<Symbol>, Ident),
4164 ItemKind::ExternCrate(s, ident), (*s, *ident);
4165
4166 expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk);
4167
4168 expect_static, (Mutability, Ident, &'hir Ty<'hir>, BodyId),
4169 ItemKind::Static(mutbl, ident, ty, body), (*mutbl, *ident, ty, *body);
4170
4171 expect_const, (Ident, &'hir Generics<'hir>, &'hir Ty<'hir>, BodyId),
4172 ItemKind::Const(ident, generics, ty, body), (*ident, generics, ty, *body);
4173
4174 expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId),
4175 ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body);
4176
4177 expect_macro, (Ident, &ast::MacroDef, MacroKinds),
4178 ItemKind::Macro(ident, def, mk), (*ident, def, *mk);
4179
4180 expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m);
4181
4182 expect_foreign_mod, (ExternAbi, &'hir [ForeignItemId]),
4183 ItemKind::ForeignMod { abi, items }, (*abi, items);
4184
4185 expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm;
4186
4187 expect_ty_alias, (Ident, &'hir Generics<'hir>, &'hir Ty<'hir>),
4188 ItemKind::TyAlias(ident, generics, ty), (*ident, generics, ty);
4189
4190 expect_enum, (Ident, &'hir Generics<'hir>, &EnumDef<'hir>),
4191 ItemKind::Enum(ident, generics, def), (*ident, generics, def);
4192
4193 expect_struct, (Ident, &'hir Generics<'hir>, &VariantData<'hir>),
4194 ItemKind::Struct(ident, generics, data), (*ident, generics, data);
4195
4196 expect_union, (Ident, &'hir Generics<'hir>, &VariantData<'hir>),
4197 ItemKind::Union(ident, generics, data), (*ident, generics, data);
4198
4199 expect_trait,
4200 (
4201 Constness,
4202 IsAuto,
4203 Safety,
4204 Ident,
4205 &'hir Generics<'hir>,
4206 GenericBounds<'hir>,
4207 &'hir [TraitItemId]
4208 ),
4209 ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items),
4210 (*constness, *is_auto, *safety, *ident, generics, bounds, items);
4211
4212 expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
4213 ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds);
4214
4215 expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp;
4216 }
4217}
4218
4219#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
4220#[derive(Encodable, Decodable, HashStable_Generic)]
4221pub enum Safety {
4222 Unsafe,
4223 Safe,
4224}
4225
4226impl Safety {
4227 pub fn prefix_str(self) -> &'static str {
4228 match self {
4229 Self::Unsafe => "unsafe ",
4230 Self::Safe => "",
4231 }
4232 }
4233
4234 #[inline]
4235 pub fn is_unsafe(self) -> bool {
4236 !self.is_safe()
4237 }
4238
4239 #[inline]
4240 pub fn is_safe(self) -> bool {
4241 match self {
4242 Self::Unsafe => false,
4243 Self::Safe => true,
4244 }
4245 }
4246}
4247
4248impl fmt::Display for Safety {
4249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4250 f.write_str(match *self {
4251 Self::Unsafe => "unsafe",
4252 Self::Safe => "safe",
4253 })
4254 }
4255}
4256
4257#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
4258pub enum Constness {
4259 Const,
4260 NotConst,
4261}
4262
4263impl fmt::Display for Constness {
4264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4265 f.write_str(match *self {
4266 Self::Const => "const",
4267 Self::NotConst => "non-const",
4268 })
4269 }
4270}
4271
4272#[derive(Copy, Clone, Debug, HashStable_Generic, PartialEq, Eq)]
4277pub enum HeaderSafety {
4278 SafeTargetFeatures,
4284 Normal(Safety),
4285}
4286
4287impl From<Safety> for HeaderSafety {
4288 fn from(v: Safety) -> Self {
4289 Self::Normal(v)
4290 }
4291}
4292
4293#[derive(Copy, Clone, Debug, HashStable_Generic)]
4294pub struct FnHeader {
4295 pub safety: HeaderSafety,
4296 pub constness: Constness,
4297 pub asyncness: IsAsync,
4298 pub abi: ExternAbi,
4299}
4300
4301impl FnHeader {
4302 pub fn is_async(&self) -> bool {
4303 matches!(self.asyncness, IsAsync::Async(_))
4304 }
4305
4306 pub fn is_const(&self) -> bool {
4307 matches!(self.constness, Constness::Const)
4308 }
4309
4310 pub fn is_unsafe(&self) -> bool {
4311 self.safety().is_unsafe()
4312 }
4313
4314 pub fn is_safe(&self) -> bool {
4315 self.safety().is_safe()
4316 }
4317
4318 pub fn safety(&self) -> Safety {
4319 match self.safety {
4320 HeaderSafety::SafeTargetFeatures => Safety::Unsafe,
4321 HeaderSafety::Normal(safety) => safety,
4322 }
4323 }
4324}
4325
4326#[derive(Debug, Clone, Copy, HashStable_Generic)]
4327pub enum ItemKind<'hir> {
4328 ExternCrate(Option<Symbol>, Ident),
4332
4333 Use(&'hir UsePath<'hir>, UseKind),
4339
4340 Static(Mutability, Ident, &'hir Ty<'hir>, BodyId),
4342 Const(Ident, &'hir Generics<'hir>, &'hir Ty<'hir>, BodyId),
4344 Fn {
4346 sig: FnSig<'hir>,
4347 ident: Ident,
4348 generics: &'hir Generics<'hir>,
4349 body: BodyId,
4350 has_body: bool,
4354 },
4355 Macro(Ident, &'hir ast::MacroDef, MacroKinds),
4357 Mod(Ident, &'hir Mod<'hir>),
4359 ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemId] },
4361 GlobalAsm {
4363 asm: &'hir InlineAsm<'hir>,
4364 fake_body: BodyId,
4370 },
4371 TyAlias(Ident, &'hir Generics<'hir>, &'hir Ty<'hir>),
4373 Enum(Ident, &'hir Generics<'hir>, EnumDef<'hir>),
4375 Struct(Ident, &'hir Generics<'hir>, VariantData<'hir>),
4377 Union(Ident, &'hir Generics<'hir>, VariantData<'hir>),
4379 Trait(
4381 Constness,
4382 IsAuto,
4383 Safety,
4384 Ident,
4385 &'hir Generics<'hir>,
4386 GenericBounds<'hir>,
4387 &'hir [TraitItemId],
4388 ),
4389 TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
4391
4392 Impl(Impl<'hir>),
4394}
4395
4396#[derive(Debug, Clone, Copy, HashStable_Generic)]
4401pub struct Impl<'hir> {
4402 pub generics: &'hir Generics<'hir>,
4403 pub of_trait: Option<&'hir TraitImplHeader<'hir>>,
4404 pub self_ty: &'hir Ty<'hir>,
4405 pub items: &'hir [ImplItemId],
4406}
4407
4408#[derive(Debug, Clone, Copy, HashStable_Generic)]
4409pub struct TraitImplHeader<'hir> {
4410 pub constness: Constness,
4411 pub safety: Safety,
4412 pub polarity: ImplPolarity,
4413 pub defaultness: Defaultness,
4414 pub defaultness_span: Option<Span>,
4417 pub trait_ref: TraitRef<'hir>,
4418}
4419
4420impl ItemKind<'_> {
4421 pub fn ident(&self) -> Option<Ident> {
4422 match *self {
4423 ItemKind::ExternCrate(_, ident)
4424 | ItemKind::Use(_, UseKind::Single(ident))
4425 | ItemKind::Static(_, ident, ..)
4426 | ItemKind::Const(ident, ..)
4427 | ItemKind::Fn { ident, .. }
4428 | ItemKind::Macro(ident, ..)
4429 | ItemKind::Mod(ident, ..)
4430 | ItemKind::TyAlias(ident, ..)
4431 | ItemKind::Enum(ident, ..)
4432 | ItemKind::Struct(ident, ..)
4433 | ItemKind::Union(ident, ..)
4434 | ItemKind::Trait(_, _, _, ident, ..)
4435 | ItemKind::TraitAlias(ident, ..) => Some(ident),
4436
4437 ItemKind::Use(_, UseKind::Glob | UseKind::ListStem)
4438 | ItemKind::ForeignMod { .. }
4439 | ItemKind::GlobalAsm { .. }
4440 | ItemKind::Impl(_) => None,
4441 }
4442 }
4443
4444 pub fn generics(&self) -> Option<&Generics<'_>> {
4445 Some(match self {
4446 ItemKind::Fn { generics, .. }
4447 | ItemKind::TyAlias(_, generics, _)
4448 | ItemKind::Const(_, generics, _, _)
4449 | ItemKind::Enum(_, generics, _)
4450 | ItemKind::Struct(_, generics, _)
4451 | ItemKind::Union(_, generics, _)
4452 | ItemKind::Trait(_, _, _, _, generics, _, _)
4453 | ItemKind::TraitAlias(_, generics, _)
4454 | ItemKind::Impl(Impl { generics, .. }) => generics,
4455 _ => return None,
4456 })
4457 }
4458}
4459
4460#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
4464pub struct ForeignItemId {
4465 pub owner_id: OwnerId,
4466}
4467
4468impl ForeignItemId {
4469 #[inline]
4470 pub fn hir_id(&self) -> HirId {
4471 HirId::make_owner(self.owner_id.def_id)
4473 }
4474}
4475
4476#[derive(Debug, Clone, Copy, HashStable_Generic)]
4477pub struct ForeignItem<'hir> {
4478 pub ident: Ident,
4479 pub kind: ForeignItemKind<'hir>,
4480 pub owner_id: OwnerId,
4481 pub span: Span,
4482 pub vis_span: Span,
4483 pub has_delayed_lints: bool,
4484}
4485
4486impl ForeignItem<'_> {
4487 #[inline]
4488 pub fn hir_id(&self) -> HirId {
4489 HirId::make_owner(self.owner_id.def_id)
4491 }
4492
4493 pub fn foreign_item_id(&self) -> ForeignItemId {
4494 ForeignItemId { owner_id: self.owner_id }
4495 }
4496}
4497
4498#[derive(Debug, Clone, Copy, HashStable_Generic)]
4500pub enum ForeignItemKind<'hir> {
4501 Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>),
4508 Static(&'hir Ty<'hir>, Mutability, Safety),
4510 Type,
4512}
4513
4514#[derive(Debug, Copy, Clone, HashStable_Generic)]
4516pub struct Upvar {
4517 pub span: Span,
4519}
4520
4521#[derive(Debug, Clone, HashStable_Generic)]
4525pub struct TraitCandidate {
4526 pub def_id: DefId,
4527 pub import_ids: SmallVec<[LocalDefId; 1]>,
4528}
4529
4530#[derive(Copy, Clone, Debug, HashStable_Generic)]
4531pub enum OwnerNode<'hir> {
4532 Item(&'hir Item<'hir>),
4533 ForeignItem(&'hir ForeignItem<'hir>),
4534 TraitItem(&'hir TraitItem<'hir>),
4535 ImplItem(&'hir ImplItem<'hir>),
4536 Crate(&'hir Mod<'hir>),
4537 Synthetic,
4538}
4539
4540impl<'hir> OwnerNode<'hir> {
4541 pub fn span(&self) -> Span {
4542 match self {
4543 OwnerNode::Item(Item { span, .. })
4544 | OwnerNode::ForeignItem(ForeignItem { span, .. })
4545 | OwnerNode::ImplItem(ImplItem { span, .. })
4546 | OwnerNode::TraitItem(TraitItem { span, .. }) => *span,
4547 OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span,
4548 OwnerNode::Synthetic => unreachable!(),
4549 }
4550 }
4551
4552 pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
4553 match self {
4554 OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4555 | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4556 | OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4557 | OwnerNode::ForeignItem(ForeignItem {
4558 kind: ForeignItemKind::Fn(fn_sig, _, _), ..
4559 }) => Some(fn_sig),
4560 _ => None,
4561 }
4562 }
4563
4564 pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
4565 match self {
4566 OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4567 | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4568 | OwnerNode::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4569 | OwnerNode::ForeignItem(ForeignItem {
4570 kind: ForeignItemKind::Fn(fn_sig, _, _), ..
4571 }) => Some(fn_sig.decl),
4572 _ => None,
4573 }
4574 }
4575
4576 pub fn body_id(&self) -> Option<BodyId> {
4577 match self {
4578 OwnerNode::Item(Item {
4579 kind:
4580 ItemKind::Static(_, _, _, body)
4581 | ItemKind::Const(_, _, _, body)
4582 | ItemKind::Fn { body, .. },
4583 ..
4584 })
4585 | OwnerNode::TraitItem(TraitItem {
4586 kind:
4587 TraitItemKind::Fn(_, TraitFn::Provided(body)) | TraitItemKind::Const(_, Some(body)),
4588 ..
4589 })
4590 | OwnerNode::ImplItem(ImplItem {
4591 kind: ImplItemKind::Fn(_, body) | ImplItemKind::Const(_, body),
4592 ..
4593 }) => Some(*body),
4594 _ => None,
4595 }
4596 }
4597
4598 pub fn generics(self) -> Option<&'hir Generics<'hir>> {
4599 Node::generics(self.into())
4600 }
4601
4602 pub fn def_id(self) -> OwnerId {
4603 match self {
4604 OwnerNode::Item(Item { owner_id, .. })
4605 | OwnerNode::TraitItem(TraitItem { owner_id, .. })
4606 | OwnerNode::ImplItem(ImplItem { owner_id, .. })
4607 | OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id,
4608 OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
4609 OwnerNode::Synthetic => unreachable!(),
4610 }
4611 }
4612
4613 pub fn is_impl_block(&self) -> bool {
4615 matches!(self, OwnerNode::Item(Item { kind: ItemKind::Impl(_), .. }))
4616 }
4617
4618 expect_methods_self! {
4619 expect_item, &'hir Item<'hir>, OwnerNode::Item(n), n;
4620 expect_foreign_item, &'hir ForeignItem<'hir>, OwnerNode::ForeignItem(n), n;
4621 expect_impl_item, &'hir ImplItem<'hir>, OwnerNode::ImplItem(n), n;
4622 expect_trait_item, &'hir TraitItem<'hir>, OwnerNode::TraitItem(n), n;
4623 }
4624}
4625
4626impl<'hir> From<&'hir Item<'hir>> for OwnerNode<'hir> {
4627 fn from(val: &'hir Item<'hir>) -> Self {
4628 OwnerNode::Item(val)
4629 }
4630}
4631
4632impl<'hir> From<&'hir ForeignItem<'hir>> for OwnerNode<'hir> {
4633 fn from(val: &'hir ForeignItem<'hir>) -> Self {
4634 OwnerNode::ForeignItem(val)
4635 }
4636}
4637
4638impl<'hir> From<&'hir ImplItem<'hir>> for OwnerNode<'hir> {
4639 fn from(val: &'hir ImplItem<'hir>) -> Self {
4640 OwnerNode::ImplItem(val)
4641 }
4642}
4643
4644impl<'hir> From<&'hir TraitItem<'hir>> for OwnerNode<'hir> {
4645 fn from(val: &'hir TraitItem<'hir>) -> Self {
4646 OwnerNode::TraitItem(val)
4647 }
4648}
4649
4650impl<'hir> From<OwnerNode<'hir>> for Node<'hir> {
4651 fn from(val: OwnerNode<'hir>) -> Self {
4652 match val {
4653 OwnerNode::Item(n) => Node::Item(n),
4654 OwnerNode::ForeignItem(n) => Node::ForeignItem(n),
4655 OwnerNode::ImplItem(n) => Node::ImplItem(n),
4656 OwnerNode::TraitItem(n) => Node::TraitItem(n),
4657 OwnerNode::Crate(n) => Node::Crate(n),
4658 OwnerNode::Synthetic => Node::Synthetic,
4659 }
4660 }
4661}
4662
4663#[derive(Copy, Clone, Debug, HashStable_Generic)]
4664pub enum Node<'hir> {
4665 Param(&'hir Param<'hir>),
4666 Item(&'hir Item<'hir>),
4667 ForeignItem(&'hir ForeignItem<'hir>),
4668 TraitItem(&'hir TraitItem<'hir>),
4669 ImplItem(&'hir ImplItem<'hir>),
4670 Variant(&'hir Variant<'hir>),
4671 Field(&'hir FieldDef<'hir>),
4672 AnonConst(&'hir AnonConst),
4673 ConstBlock(&'hir ConstBlock),
4674 ConstArg(&'hir ConstArg<'hir>),
4675 Expr(&'hir Expr<'hir>),
4676 ExprField(&'hir ExprField<'hir>),
4677 Stmt(&'hir Stmt<'hir>),
4678 PathSegment(&'hir PathSegment<'hir>),
4679 Ty(&'hir Ty<'hir>),
4680 AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
4681 TraitRef(&'hir TraitRef<'hir>),
4682 OpaqueTy(&'hir OpaqueTy<'hir>),
4683 TyPat(&'hir TyPat<'hir>),
4684 Pat(&'hir Pat<'hir>),
4685 PatField(&'hir PatField<'hir>),
4686 PatExpr(&'hir PatExpr<'hir>),
4690 Arm(&'hir Arm<'hir>),
4691 Block(&'hir Block<'hir>),
4692 LetStmt(&'hir LetStmt<'hir>),
4693 Ctor(&'hir VariantData<'hir>),
4696 Lifetime(&'hir Lifetime),
4697 GenericParam(&'hir GenericParam<'hir>),
4698 Crate(&'hir Mod<'hir>),
4699 Infer(&'hir InferArg),
4700 WherePredicate(&'hir WherePredicate<'hir>),
4701 PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg),
4702 Synthetic,
4704 Err(Span),
4705}
4706
4707impl<'hir> Node<'hir> {
4708 pub fn ident(&self) -> Option<Ident> {
4723 match self {
4724 Node::Item(item) => item.kind.ident(),
4725 Node::TraitItem(TraitItem { ident, .. })
4726 | Node::ImplItem(ImplItem { ident, .. })
4727 | Node::ForeignItem(ForeignItem { ident, .. })
4728 | Node::Field(FieldDef { ident, .. })
4729 | Node::Variant(Variant { ident, .. })
4730 | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
4731 Node::Lifetime(lt) => Some(lt.ident),
4732 Node::GenericParam(p) => Some(p.name.ident()),
4733 Node::AssocItemConstraint(c) => Some(c.ident),
4734 Node::PatField(f) => Some(f.ident),
4735 Node::ExprField(f) => Some(f.ident),
4736 Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident),
4737 Node::Param(..)
4738 | Node::AnonConst(..)
4739 | Node::ConstBlock(..)
4740 | Node::ConstArg(..)
4741 | Node::Expr(..)
4742 | Node::Stmt(..)
4743 | Node::Block(..)
4744 | Node::Ctor(..)
4745 | Node::Pat(..)
4746 | Node::TyPat(..)
4747 | Node::PatExpr(..)
4748 | Node::Arm(..)
4749 | Node::LetStmt(..)
4750 | Node::Crate(..)
4751 | Node::Ty(..)
4752 | Node::TraitRef(..)
4753 | Node::OpaqueTy(..)
4754 | Node::Infer(..)
4755 | Node::WherePredicate(..)
4756 | Node::Synthetic
4757 | Node::Err(..) => None,
4758 }
4759 }
4760
4761 pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> {
4762 match self {
4763 Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4764 | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4765 | Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4766 | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
4767 Some(fn_sig.decl)
4768 }
4769 Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) => {
4770 Some(fn_decl)
4771 }
4772 _ => None,
4773 }
4774 }
4775
4776 pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
4778 if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self
4779 && let Some(of_trait) = impl_block.of_trait
4780 && let Some(trait_id) = of_trait.trait_ref.trait_def_id()
4781 && trait_id == trait_def_id
4782 {
4783 Some(impl_block)
4784 } else {
4785 None
4786 }
4787 }
4788
4789 pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
4790 match self {
4791 Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
4792 | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
4793 | Node::Item(Item { kind: ItemKind::Fn { sig: fn_sig, .. }, .. })
4794 | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
4795 Some(fn_sig)
4796 }
4797 _ => None,
4798 }
4799 }
4800
4801 pub fn ty(self) -> Option<&'hir Ty<'hir>> {
4803 match self {
4804 Node::Item(it) => match it.kind {
4805 ItemKind::TyAlias(_, _, ty)
4806 | ItemKind::Static(_, _, ty, _)
4807 | ItemKind::Const(_, _, ty, _) => Some(ty),
4808 ItemKind::Impl(impl_item) => Some(&impl_item.self_ty),
4809 _ => None,
4810 },
4811 Node::TraitItem(it) => match it.kind {
4812 TraitItemKind::Const(ty, _) => Some(ty),
4813 TraitItemKind::Type(_, ty) => ty,
4814 _ => None,
4815 },
4816 Node::ImplItem(it) => match it.kind {
4817 ImplItemKind::Const(ty, _) => Some(ty),
4818 ImplItemKind::Type(ty) => Some(ty),
4819 _ => None,
4820 },
4821 Node::ForeignItem(it) => match it.kind {
4822 ForeignItemKind::Static(ty, ..) => Some(ty),
4823 _ => None,
4824 },
4825 _ => None,
4826 }
4827 }
4828
4829 pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
4830 match self {
4831 Node::Item(Item { kind: ItemKind::TyAlias(_, _, ty), .. }) => Some(ty),
4832 _ => None,
4833 }
4834 }
4835
4836 #[inline]
4837 pub fn associated_body(&self) -> Option<(LocalDefId, BodyId)> {
4838 match self {
4839 Node::Item(Item {
4840 owner_id,
4841 kind:
4842 ItemKind::Const(_, _, _, body)
4843 | ItemKind::Static(.., body)
4844 | ItemKind::Fn { body, .. },
4845 ..
4846 })
4847 | Node::TraitItem(TraitItem {
4848 owner_id,
4849 kind:
4850 TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
4851 ..
4852 })
4853 | Node::ImplItem(ImplItem {
4854 owner_id,
4855 kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
4856 ..
4857 }) => Some((owner_id.def_id, *body)),
4858
4859 Node::Item(Item {
4860 owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, ..
4861 }) => Some((owner_id.def_id, *fake_body)),
4862
4863 Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
4864 Some((*def_id, *body))
4865 }
4866
4867 Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
4868 Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
4869
4870 _ => None,
4871 }
4872 }
4873
4874 pub fn body_id(&self) -> Option<BodyId> {
4875 Some(self.associated_body()?.1)
4876 }
4877
4878 pub fn generics(self) -> Option<&'hir Generics<'hir>> {
4879 match self {
4880 Node::ForeignItem(ForeignItem {
4881 kind: ForeignItemKind::Fn(_, _, generics), ..
4882 })
4883 | Node::TraitItem(TraitItem { generics, .. })
4884 | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
4885 Node::Item(item) => item.kind.generics(),
4886 _ => None,
4887 }
4888 }
4889
4890 pub fn as_owner(self) -> Option<OwnerNode<'hir>> {
4891 match self {
4892 Node::Item(i) => Some(OwnerNode::Item(i)),
4893 Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)),
4894 Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
4895 Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
4896 Node::Crate(i) => Some(OwnerNode::Crate(i)),
4897 Node::Synthetic => Some(OwnerNode::Synthetic),
4898 _ => None,
4899 }
4900 }
4901
4902 pub fn fn_kind(self) -> Option<FnKind<'hir>> {
4903 match self {
4904 Node::Item(i) => match i.kind {
4905 ItemKind::Fn { ident, sig, generics, .. } => {
4906 Some(FnKind::ItemFn(ident, generics, sig.header))
4907 }
4908 _ => None,
4909 },
4910 Node::TraitItem(ti) => match ti.kind {
4911 TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)),
4912 _ => None,
4913 },
4914 Node::ImplItem(ii) => match ii.kind {
4915 ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig)),
4916 _ => None,
4917 },
4918 Node::Expr(e) => match e.kind {
4919 ExprKind::Closure { .. } => Some(FnKind::Closure),
4920 _ => None,
4921 },
4922 _ => None,
4923 }
4924 }
4925
4926 expect_methods_self! {
4927 expect_param, &'hir Param<'hir>, Node::Param(n), n;
4928 expect_item, &'hir Item<'hir>, Node::Item(n), n;
4929 expect_foreign_item, &'hir ForeignItem<'hir>, Node::ForeignItem(n), n;
4930 expect_trait_item, &'hir TraitItem<'hir>, Node::TraitItem(n), n;
4931 expect_impl_item, &'hir ImplItem<'hir>, Node::ImplItem(n), n;
4932 expect_variant, &'hir Variant<'hir>, Node::Variant(n), n;
4933 expect_field, &'hir FieldDef<'hir>, Node::Field(n), n;
4934 expect_anon_const, &'hir AnonConst, Node::AnonConst(n), n;
4935 expect_inline_const, &'hir ConstBlock, Node::ConstBlock(n), n;
4936 expect_expr, &'hir Expr<'hir>, Node::Expr(n), n;
4937 expect_expr_field, &'hir ExprField<'hir>, Node::ExprField(n), n;
4938 expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n;
4939 expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n;
4940 expect_ty, &'hir Ty<'hir>, Node::Ty(n), n;
4941 expect_assoc_item_constraint, &'hir AssocItemConstraint<'hir>, Node::AssocItemConstraint(n), n;
4942 expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n;
4943 expect_opaque_ty, &'hir OpaqueTy<'hir>, Node::OpaqueTy(n), n;
4944 expect_pat, &'hir Pat<'hir>, Node::Pat(n), n;
4945 expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n;
4946 expect_arm, &'hir Arm<'hir>, Node::Arm(n), n;
4947 expect_block, &'hir Block<'hir>, Node::Block(n), n;
4948 expect_let_stmt, &'hir LetStmt<'hir>, Node::LetStmt(n), n;
4949 expect_ctor, &'hir VariantData<'hir>, Node::Ctor(n), n;
4950 expect_lifetime, &'hir Lifetime, Node::Lifetime(n), n;
4951 expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n;
4952 expect_crate, &'hir Mod<'hir>, Node::Crate(n), n;
4953 expect_infer, &'hir InferArg, Node::Infer(n), n;
4954 expect_closure, &'hir Closure<'hir>, Node::Expr(Expr { kind: ExprKind::Closure(n), .. }), n;
4955 }
4956}
4957
4958#[cfg(target_pointer_width = "64")]
4960mod size_asserts {
4961 use rustc_data_structures::static_assert_size;
4962
4963 use super::*;
4964 static_assert_size!(Block<'_>, 48);
4966 static_assert_size!(Body<'_>, 24);
4967 static_assert_size!(Expr<'_>, 64);
4968 static_assert_size!(ExprKind<'_>, 48);
4969 static_assert_size!(FnDecl<'_>, 40);
4970 static_assert_size!(ForeignItem<'_>, 96);
4971 static_assert_size!(ForeignItemKind<'_>, 56);
4972 static_assert_size!(GenericArg<'_>, 16);
4973 static_assert_size!(GenericBound<'_>, 64);
4974 static_assert_size!(Generics<'_>, 56);
4975 static_assert_size!(Impl<'_>, 40);
4976 static_assert_size!(ImplItem<'_>, 96);
4977 static_assert_size!(ImplItemKind<'_>, 40);
4978 static_assert_size!(Item<'_>, 88);
4979 static_assert_size!(ItemKind<'_>, 64);
4980 static_assert_size!(LetStmt<'_>, 72);
4981 static_assert_size!(Param<'_>, 32);
4982 static_assert_size!(Pat<'_>, 72);
4983 static_assert_size!(PatKind<'_>, 48);
4984 static_assert_size!(Path<'_>, 40);
4985 static_assert_size!(PathSegment<'_>, 48);
4986 static_assert_size!(QPath<'_>, 24);
4987 static_assert_size!(Res, 12);
4988 static_assert_size!(Stmt<'_>, 32);
4989 static_assert_size!(StmtKind<'_>, 16);
4990 static_assert_size!(TraitImplHeader<'_>, 48);
4991 static_assert_size!(TraitItem<'_>, 88);
4992 static_assert_size!(TraitItemKind<'_>, 48);
4993 static_assert_size!(Ty<'_>, 48);
4994 static_assert_size!(TyKind<'_>, 32);
4995 }
4997
4998#[cfg(test)]
4999mod tests;