1use std::assert_matches::debug_assert_matches;
10use std::borrow::Cow;
11use std::collections::BTreeSet;
12use std::collections::hash_map::Entry;
13use std::mem::{replace, swap, take};
14
15use rustc_ast::ptr::P;
16use rustc_ast::visit::{
17 AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list,
18};
19use rustc_ast::*;
20use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
21use rustc_data_structures::unord::{UnordMap, UnordSet};
22use rustc_errors::codes::*;
23use rustc_errors::{
24 Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions,
25};
26use rustc_hir::def::Namespace::{self, *};
27use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
28use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
29use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
30use rustc_middle::middle::resolve_bound_vars::Set1;
31use rustc_middle::ty::DelegationFnSig;
32use rustc_middle::{bug, span_bug};
33use rustc_session::config::{CrateType, ResolveDocLinks};
34use rustc_session::lint::{self, BuiltinLintDiag};
35use rustc_session::parse::feature_err;
36use rustc_span::source_map::{Spanned, respan};
37use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
38use smallvec::{SmallVec, smallvec};
39use tracing::{debug, instrument, trace};
40
41use crate::{
42 BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot,
43 NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError,
44 Used, errors, path_names_to_string, rustdoc,
45};
46
47mod diagnostics;
48
49type Res = def::Res<NodeId>;
50
51use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime};
52
53#[derive(Copy, Clone, Debug)]
54struct BindingInfo {
55 span: Span,
56 annotation: BindingMode,
57}
58
59#[derive(Copy, Clone, PartialEq, Eq, Debug)]
60pub(crate) enum PatternSource {
61 Match,
62 Let,
63 For,
64 FnParam,
65}
66
67#[derive(Copy, Clone, Debug, PartialEq, Eq)]
68enum IsRepeatExpr {
69 No,
70 Yes,
71}
72
73struct IsNeverPattern;
74
75#[derive(Copy, Clone, Debug, PartialEq, Eq)]
78enum AnonConstKind {
79 EnumDiscriminant,
80 FieldDefaultValue,
81 InlineConst,
82 ConstArg(IsRepeatExpr),
83}
84
85impl PatternSource {
86 fn descr(self) -> &'static str {
87 match self {
88 PatternSource::Match => "match binding",
89 PatternSource::Let => "let binding",
90 PatternSource::For => "for binding",
91 PatternSource::FnParam => "function parameter",
92 }
93 }
94}
95
96impl IntoDiagArg for PatternSource {
97 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
98 DiagArgValue::Str(Cow::Borrowed(self.descr()))
99 }
100}
101
102#[derive(PartialEq)]
106enum PatBoundCtx {
107 Product,
109 Or,
111}
112
113#[derive(Copy, Clone, Debug)]
115pub(crate) enum HasGenericParams {
116 Yes(Span),
117 No,
118}
119
120#[derive(Copy, Clone, Debug, Eq, PartialEq)]
122pub(crate) enum ConstantHasGenerics {
123 Yes,
124 No(NoConstantGenericsReason),
125}
126
127impl ConstantHasGenerics {
128 fn force_yes_if(self, b: bool) -> Self {
129 if b { Self::Yes } else { self }
130 }
131}
132
133#[derive(Copy, Clone, Debug, Eq, PartialEq)]
135pub(crate) enum NoConstantGenericsReason {
136 NonTrivialConstArg,
143 IsEnumDiscriminant,
152}
153
154#[derive(Copy, Clone, Debug, Eq, PartialEq)]
155pub(crate) enum ConstantItemKind {
156 Const,
157 Static,
158}
159
160impl ConstantItemKind {
161 pub(crate) fn as_str(&self) -> &'static str {
162 match self {
163 Self::Const => "const",
164 Self::Static => "static",
165 }
166 }
167}
168
169#[derive(Debug, Copy, Clone, PartialEq, Eq)]
170enum RecordPartialRes {
171 Yes,
172 No,
173}
174
175#[derive(Copy, Clone, Debug)]
178pub(crate) enum RibKind<'ra> {
179 Normal,
181
182 AssocItem,
187
188 FnOrCoroutine,
190
191 Item(HasGenericParams, DefKind),
193
194 ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>),
199
200 Module(Module<'ra>),
202
203 MacroDefinition(DefId),
205
206 ForwardGenericParamBan(ForwardGenericParamBanReason),
210
211 ConstParamTy,
214
215 InlineAsmSym,
218}
219
220#[derive(Copy, Clone, PartialEq, Eq, Debug)]
221pub(crate) enum ForwardGenericParamBanReason {
222 Default,
223 ConstParamTy,
224}
225
226impl RibKind<'_> {
227 pub(crate) fn contains_params(&self) -> bool {
230 match self {
231 RibKind::Normal
232 | RibKind::FnOrCoroutine
233 | RibKind::ConstantItem(..)
234 | RibKind::Module(_)
235 | RibKind::MacroDefinition(_)
236 | RibKind::InlineAsmSym => false,
237 RibKind::ConstParamTy
238 | RibKind::AssocItem
239 | RibKind::Item(..)
240 | RibKind::ForwardGenericParamBan(_) => true,
241 }
242 }
243
244 fn is_label_barrier(self) -> bool {
246 match self {
247 RibKind::Normal | RibKind::MacroDefinition(..) => false,
248
249 RibKind::AssocItem
250 | RibKind::FnOrCoroutine
251 | RibKind::Item(..)
252 | RibKind::ConstantItem(..)
253 | RibKind::Module(..)
254 | RibKind::ForwardGenericParamBan(_)
255 | RibKind::ConstParamTy
256 | RibKind::InlineAsmSym => true,
257 }
258 }
259}
260
261#[derive(Debug)]
274pub(crate) struct Rib<'ra, R = Res> {
275 pub bindings: FxHashMap<Ident, R>,
276 pub patterns_with_skipped_bindings: UnordMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>,
277 pub kind: RibKind<'ra>,
278}
279
280impl<'ra, R> Rib<'ra, R> {
281 fn new(kind: RibKind<'ra>) -> Rib<'ra, R> {
282 Rib {
283 bindings: Default::default(),
284 patterns_with_skipped_bindings: Default::default(),
285 kind,
286 }
287 }
288}
289
290#[derive(Clone, Copy, Debug)]
291enum LifetimeUseSet {
292 One { use_span: Span, use_ctxt: visit::LifetimeCtxt },
293 Many,
294}
295
296#[derive(Copy, Clone, Debug)]
297enum LifetimeRibKind {
298 Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
303
304 AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
321
322 Elided(LifetimeRes),
324
325 AnonymousReportError,
331
332 StaticIfNoLifetimeInScope { lint_id: NodeId, emit_lint: bool },
336
337 ElisionFailure,
339
340 ConstParamTy,
345
346 ConcreteAnonConst(NoConstantGenericsReason),
352
353 Item,
355}
356
357#[derive(Copy, Clone, Debug)]
358enum LifetimeBinderKind {
359 BareFnType,
360 PolyTrait,
361 WhereBound,
362 Item,
363 ConstItem,
364 Function,
365 Closure,
366 ImplBlock,
367}
368
369impl LifetimeBinderKind {
370 fn descr(self) -> &'static str {
371 use LifetimeBinderKind::*;
372 match self {
373 BareFnType => "type",
374 PolyTrait => "bound",
375 WhereBound => "bound",
376 Item | ConstItem => "item",
377 ImplBlock => "impl block",
378 Function => "function",
379 Closure => "closure",
380 }
381 }
382}
383
384#[derive(Debug)]
385struct LifetimeRib {
386 kind: LifetimeRibKind,
387 bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
389}
390
391impl LifetimeRib {
392 fn new(kind: LifetimeRibKind) -> LifetimeRib {
393 LifetimeRib { bindings: Default::default(), kind }
394 }
395}
396
397#[derive(Copy, Clone, PartialEq, Eq, Debug)]
398pub(crate) enum AliasPossibility {
399 No,
400 Maybe,
401}
402
403#[derive(Copy, Clone, Debug)]
404pub(crate) enum PathSource<'a> {
405 Type,
407 Trait(AliasPossibility),
409 Expr(Option<&'a Expr>),
411 Pat,
413 Struct,
415 TupleStruct(Span, &'a [Span]),
417 TraitItem(Namespace),
419 Delegation,
421 PreciseCapturingArg(Namespace),
423 ReturnTypeNotation,
425 DefineOpaques,
427}
428
429impl<'a> PathSource<'a> {
430 fn namespace(self) -> Namespace {
431 match self {
432 PathSource::Type
433 | PathSource::Trait(_)
434 | PathSource::Struct
435 | PathSource::DefineOpaques => TypeNS,
436 PathSource::Expr(..)
437 | PathSource::Pat
438 | PathSource::TupleStruct(..)
439 | PathSource::Delegation
440 | PathSource::ReturnTypeNotation => ValueNS,
441 PathSource::TraitItem(ns) => ns,
442 PathSource::PreciseCapturingArg(ns) => ns,
443 }
444 }
445
446 fn defer_to_typeck(self) -> bool {
447 match self {
448 PathSource::Type
449 | PathSource::Expr(..)
450 | PathSource::Pat
451 | PathSource::Struct
452 | PathSource::TupleStruct(..)
453 | PathSource::ReturnTypeNotation => true,
454 PathSource::Trait(_)
455 | PathSource::TraitItem(..)
456 | PathSource::DefineOpaques
457 | PathSource::Delegation
458 | PathSource::PreciseCapturingArg(..) => false,
459 }
460 }
461
462 fn descr_expected(self) -> &'static str {
463 match &self {
464 PathSource::DefineOpaques => "type alias or associated type with opaqaue types",
465 PathSource::Type => "type",
466 PathSource::Trait(_) => "trait",
467 PathSource::Pat => "unit struct, unit variant or constant",
468 PathSource::Struct => "struct, variant or union type",
469 PathSource::TupleStruct(..) => "tuple struct or tuple variant",
470 PathSource::TraitItem(ns) => match ns {
471 TypeNS => "associated type",
472 ValueNS => "method or associated constant",
473 MacroNS => bug!("associated macro"),
474 },
475 PathSource::Expr(parent) => match parent.as_ref().map(|p| &p.kind) {
476 Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind {
479 ExprKind::Path(_, path)
481 if let [segment, _] = path.segments.as_slice()
482 && segment.ident.name == kw::PathRoot =>
483 {
484 "external crate"
485 }
486 ExprKind::Path(_, path)
487 if let Some(segment) = path.segments.last()
488 && let Some(c) = segment.ident.to_string().chars().next()
489 && c.is_uppercase() =>
490 {
491 "function, tuple struct or tuple variant"
492 }
493 _ => "function",
494 },
495 _ => "value",
496 },
497 PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
498 PathSource::PreciseCapturingArg(..) => "type or const parameter",
499 }
500 }
501
502 fn is_call(self) -> bool {
503 matches!(self, PathSource::Expr(Some(&Expr { kind: ExprKind::Call(..), .. })))
504 }
505
506 pub(crate) fn is_expected(self, res: Res) -> bool {
507 match self {
508 PathSource::DefineOpaques => {
509 matches!(
510 res,
511 Res::Def(
512 DefKind::Struct
513 | DefKind::Union
514 | DefKind::Enum
515 | DefKind::TyAlias
516 | DefKind::AssocTy,
517 _
518 ) | Res::SelfTyAlias { .. }
519 )
520 }
521 PathSource::Type => matches!(
522 res,
523 Res::Def(
524 DefKind::Struct
525 | DefKind::Union
526 | DefKind::Enum
527 | DefKind::Trait
528 | DefKind::TraitAlias
529 | DefKind::TyAlias
530 | DefKind::AssocTy
531 | DefKind::TyParam
532 | DefKind::OpaqueTy
533 | DefKind::ForeignTy,
534 _,
535 ) | Res::PrimTy(..)
536 | Res::SelfTyParam { .. }
537 | Res::SelfTyAlias { .. }
538 ),
539 PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
540 PathSource::Trait(AliasPossibility::Maybe) => {
541 matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
542 }
543 PathSource::Expr(..) => matches!(
544 res,
545 Res::Def(
546 DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
547 | DefKind::Const
548 | DefKind::Static { .. }
549 | DefKind::Fn
550 | DefKind::AssocFn
551 | DefKind::AssocConst
552 | DefKind::ConstParam,
553 _,
554 ) | Res::Local(..)
555 | Res::SelfCtor(..)
556 ),
557 PathSource::Pat => {
558 res.expected_in_unit_struct_pat()
559 || matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _))
560 }
561 PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
562 PathSource::Struct => matches!(
563 res,
564 Res::Def(
565 DefKind::Struct
566 | DefKind::Union
567 | DefKind::Variant
568 | DefKind::TyAlias
569 | DefKind::AssocTy,
570 _,
571 ) | Res::SelfTyParam { .. }
572 | Res::SelfTyAlias { .. }
573 ),
574 PathSource::TraitItem(ns) => match res {
575 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
576 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
577 _ => false,
578 },
579 PathSource::ReturnTypeNotation => match res {
580 Res::Def(DefKind::AssocFn, _) => true,
581 _ => false,
582 },
583 PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
584 PathSource::PreciseCapturingArg(ValueNS) => {
585 matches!(res, Res::Def(DefKind::ConstParam, _))
586 }
587 PathSource::PreciseCapturingArg(TypeNS) => matches!(
589 res,
590 Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }
591 ),
592 PathSource::PreciseCapturingArg(MacroNS) => false,
593 }
594 }
595
596 fn error_code(self, has_unexpected_resolution: bool) -> ErrCode {
597 match (self, has_unexpected_resolution) {
598 (PathSource::Trait(_), true) => E0404,
599 (PathSource::Trait(_), false) => E0405,
600 (PathSource::Type | PathSource::DefineOpaques, true) => E0573,
601 (PathSource::Type | PathSource::DefineOpaques, false) => E0412,
602 (PathSource::Struct, true) => E0574,
603 (PathSource::Struct, false) => E0422,
604 (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
605 (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
606 (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
607 (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
608 (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, true) => E0575,
609 (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, false) => E0576,
610 (PathSource::PreciseCapturingArg(..), true) => E0799,
611 (PathSource::PreciseCapturingArg(..), false) => E0800,
612 }
613 }
614}
615
616#[derive(Clone, Copy)]
620enum MaybeExported<'a> {
621 Ok(NodeId),
622 Impl(Option<DefId>),
623 ImplItem(Result<DefId, &'a Visibility>),
624 NestedUse(&'a Visibility),
625}
626
627impl MaybeExported<'_> {
628 fn eval(self, r: &Resolver<'_, '_>) -> bool {
629 let def_id = match self {
630 MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)),
631 MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => {
632 trait_def_id.as_local()
633 }
634 MaybeExported::Impl(None) => return true,
635 MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => {
636 return vis.kind.is_pub();
637 }
638 };
639 def_id.is_none_or(|def_id| r.effective_visibilities.is_exported(def_id))
640 }
641}
642
643#[derive(Debug)]
645pub(crate) struct UnnecessaryQualification<'ra> {
646 pub binding: LexicalScopeBinding<'ra>,
647 pub node_id: NodeId,
648 pub path_span: Span,
649 pub removal_span: Span,
650}
651
652#[derive(Default, Debug)]
653struct DiagMetadata<'ast> {
654 current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,
656
657 current_self_type: Option<Ty>,
659
660 current_self_item: Option<NodeId>,
662
663 current_item: Option<&'ast Item>,
665
666 currently_processing_generic_args: bool,
669
670 current_function: Option<(FnKind<'ast>, Span)>,
672
673 unused_labels: FxHashMap<NodeId, Span>,
676
677 current_block_could_be_bare_struct_literal: Option<Span>,
681
682 current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
684
685 current_pat: Option<&'ast Pat>,
686
687 in_if_condition: Option<&'ast Expr>,
689
690 in_assignment: Option<&'ast Expr>,
692 is_assign_rhs: bool,
693
694 in_non_gat_assoc_type: Option<bool>,
696
697 in_range: Option<(&'ast Expr, &'ast Expr)>,
699
700 current_trait_object: Option<&'ast [ast::GenericBound]>,
703
704 current_where_predicate: Option<&'ast WherePredicate>,
706
707 current_type_path: Option<&'ast Ty>,
708
709 current_impl_items: Option<&'ast [P<AssocItem>]>,
711
712 currently_processing_impl_trait: Option<(TraitRef, Ty)>,
714
715 current_elision_failures: Vec<MissingLifetime>,
718}
719
720struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
721 r: &'a mut Resolver<'ra, 'tcx>,
722
723 parent_scope: ParentScope<'ra>,
725
726 ribs: PerNS<Vec<Rib<'ra>>>,
728
729 last_block_rib: Option<Rib<'ra>>,
731
732 label_ribs: Vec<Rib<'ra, NodeId>>,
734
735 lifetime_ribs: Vec<LifetimeRib>,
737
738 lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>,
744
745 current_trait_ref: Option<(Module<'ra>, TraitRef)>,
747
748 diag_metadata: Box<DiagMetadata<'ast>>,
750
751 in_func_body: bool,
757
758 lifetime_uses: FxHashMap<LocalDefId, LifetimeUseSet>,
760}
761
762impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
764 fn visit_attribute(&mut self, _: &'ast Attribute) {
765 }
768 fn visit_item(&mut self, item: &'ast Item) {
769 let prev = replace(&mut self.diag_metadata.current_item, Some(item));
770 let old_ignore = replace(&mut self.in_func_body, false);
772 self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
773 self.in_func_body = old_ignore;
774 self.diag_metadata.current_item = prev;
775 }
776 fn visit_arm(&mut self, arm: &'ast Arm) {
777 self.resolve_arm(arm);
778 }
779 fn visit_block(&mut self, block: &'ast Block) {
780 let old_macro_rules = self.parent_scope.macro_rules;
781 self.resolve_block(block);
782 self.parent_scope.macro_rules = old_macro_rules;
783 }
784 fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
785 bug!("encountered anon const without a manual call to `resolve_anon_const`: {constant:#?}");
786 }
787 fn visit_expr(&mut self, expr: &'ast Expr) {
788 self.resolve_expr(expr, None);
789 }
790 fn visit_pat(&mut self, p: &'ast Pat) {
791 let prev = self.diag_metadata.current_pat;
792 self.diag_metadata.current_pat = Some(p);
793 visit::walk_pat(self, p);
794 self.diag_metadata.current_pat = prev;
795 }
796 fn visit_local(&mut self, local: &'ast Local) {
797 let local_spans = match local.pat.kind {
798 PatKind::Wild => None,
800 _ => Some((
801 local.pat.span,
802 local.ty.as_ref().map(|ty| ty.span),
803 local.kind.init().map(|init| init.span),
804 )),
805 };
806 let original = replace(&mut self.diag_metadata.current_let_binding, local_spans);
807 self.resolve_local(local);
808 self.diag_metadata.current_let_binding = original;
809 }
810 fn visit_ty(&mut self, ty: &'ast Ty) {
811 let prev = self.diag_metadata.current_trait_object;
812 let prev_ty = self.diag_metadata.current_type_path;
813 match &ty.kind {
814 TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
815 let span = self.r.tcx.sess.source_map().start_point(ty.span);
819 self.resolve_elided_lifetime(ty.id, span);
820 visit::walk_ty(self, ty);
821 }
822 TyKind::Path(qself, path) => {
823 self.diag_metadata.current_type_path = Some(ty);
824
825 let source = if let Some(seg) = path.segments.last()
829 && let Some(args) = &seg.args
830 && matches!(**args, GenericArgs::ParenthesizedElided(..))
831 {
832 PathSource::ReturnTypeNotation
833 } else {
834 PathSource::Type
835 };
836
837 self.smart_resolve_path(ty.id, qself, path, source);
838
839 if qself.is_none()
841 && let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
842 && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) =
843 partial_res.full_res()
844 {
845 let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo());
849 self.with_generic_param_rib(
850 &[],
851 RibKind::Normal,
852 LifetimeRibKind::Generics {
853 binder: ty.id,
854 kind: LifetimeBinderKind::PolyTrait,
855 span,
856 },
857 |this| this.visit_path(path, ty.id),
858 );
859 } else {
860 visit::walk_ty(self, ty)
861 }
862 }
863 TyKind::ImplicitSelf => {
864 let self_ty = Ident::with_dummy_span(kw::SelfUpper);
865 let res = self
866 .resolve_ident_in_lexical_scope(
867 self_ty,
868 TypeNS,
869 Some(Finalize::new(ty.id, ty.span)),
870 None,
871 )
872 .map_or(Res::Err, |d| d.res());
873 self.r.record_partial_res(ty.id, PartialRes::new(res));
874 visit::walk_ty(self, ty)
875 }
876 TyKind::ImplTrait(..) => {
877 let candidates = self.lifetime_elision_candidates.take();
878 visit::walk_ty(self, ty);
879 self.lifetime_elision_candidates = candidates;
880 }
881 TyKind::TraitObject(bounds, ..) => {
882 self.diag_metadata.current_trait_object = Some(&bounds[..]);
883 visit::walk_ty(self, ty)
884 }
885 TyKind::BareFn(bare_fn) => {
886 let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo());
887 self.with_generic_param_rib(
888 &bare_fn.generic_params,
889 RibKind::Normal,
890 LifetimeRibKind::Generics {
891 binder: ty.id,
892 kind: LifetimeBinderKind::BareFnType,
893 span,
894 },
895 |this| {
896 this.visit_generic_params(&bare_fn.generic_params, false);
897 this.with_lifetime_rib(
898 LifetimeRibKind::AnonymousCreateParameter {
899 binder: ty.id,
900 report_in_path: false,
901 },
902 |this| {
903 this.resolve_fn_signature(
904 ty.id,
905 false,
906 bare_fn
909 .decl
910 .inputs
911 .iter()
912 .map(|Param { ty, .. }| (None, &**ty)),
913 &bare_fn.decl.output,
914 )
915 },
916 );
917 },
918 )
919 }
920 TyKind::UnsafeBinder(unsafe_binder) => {
921 let span = ty.span;
923 self.with_generic_param_rib(
924 &unsafe_binder.generic_params,
925 RibKind::Normal,
926 LifetimeRibKind::Generics {
927 binder: ty.id,
928 kind: LifetimeBinderKind::BareFnType,
929 span,
930 },
931 |this| {
932 this.visit_generic_params(&unsafe_binder.generic_params, false);
933 this.with_lifetime_rib(
934 LifetimeRibKind::AnonymousReportError,
937 |this| this.visit_ty(&unsafe_binder.inner_ty),
938 );
939 },
940 )
941 }
942 TyKind::Array(element_ty, length) => {
943 self.visit_ty(element_ty);
944 self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
945 }
946 TyKind::Typeof(ct) => {
947 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
948 }
949 _ => visit::walk_ty(self, ty),
950 }
951 self.diag_metadata.current_trait_object = prev;
952 self.diag_metadata.current_type_path = prev_ty;
953 }
954
955 fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
956 match &t.kind {
957 TyPatKind::Range(start, end, _) => {
958 if let Some(start) = start {
959 self.resolve_anon_const(start, AnonConstKind::ConstArg(IsRepeatExpr::No));
960 }
961 if let Some(end) = end {
962 self.resolve_anon_const(end, AnonConstKind::ConstArg(IsRepeatExpr::No));
963 }
964 }
965 TyPatKind::Err(_) => {}
966 }
967 }
968
969 fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
970 let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
971 self.with_generic_param_rib(
972 &tref.bound_generic_params,
973 RibKind::Normal,
974 LifetimeRibKind::Generics {
975 binder: tref.trait_ref.ref_id,
976 kind: LifetimeBinderKind::PolyTrait,
977 span,
978 },
979 |this| {
980 this.visit_generic_params(&tref.bound_generic_params, false);
981 this.smart_resolve_path(
982 tref.trait_ref.ref_id,
983 &None,
984 &tref.trait_ref.path,
985 PathSource::Trait(AliasPossibility::Maybe),
986 );
987 this.visit_trait_ref(&tref.trait_ref);
988 },
989 );
990 }
991 fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
992 self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
993 let def_kind = self.r.local_def_kind(foreign_item.id);
994 match foreign_item.kind {
995 ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
996 self.with_generic_param_rib(
997 &generics.params,
998 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
999 LifetimeRibKind::Generics {
1000 binder: foreign_item.id,
1001 kind: LifetimeBinderKind::Item,
1002 span: generics.span,
1003 },
1004 |this| visit::walk_item(this, foreign_item),
1005 );
1006 }
1007 ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
1008 self.with_generic_param_rib(
1009 &generics.params,
1010 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
1011 LifetimeRibKind::Generics {
1012 binder: foreign_item.id,
1013 kind: LifetimeBinderKind::Function,
1014 span: generics.span,
1015 },
1016 |this| visit::walk_item(this, foreign_item),
1017 );
1018 }
1019 ForeignItemKind::Static(..) => {
1020 self.with_static_rib(def_kind, |this| visit::walk_item(this, foreign_item))
1021 }
1022 ForeignItemKind::MacCall(..) => {
1023 panic!("unexpanded macro in resolve!")
1024 }
1025 }
1026 }
1027 fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
1028 let previous_value = self.diag_metadata.current_function;
1029 match fn_kind {
1030 FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. })
1033 | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => {
1034 self.visit_fn_header(&sig.header);
1035 self.visit_generics(generics);
1036 self.with_lifetime_rib(
1037 LifetimeRibKind::AnonymousCreateParameter {
1038 binder: fn_id,
1039 report_in_path: false,
1040 },
1041 |this| {
1042 this.resolve_fn_signature(
1043 fn_id,
1044 sig.decl.has_self(),
1045 sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
1046 &sig.decl.output,
1047 );
1048 },
1049 );
1050 return;
1051 }
1052 FnKind::Fn(..) => {
1053 self.diag_metadata.current_function = Some((fn_kind, sp));
1054 }
1055 FnKind::Closure(..) => {}
1057 };
1058 debug!("(resolving function) entering function");
1059
1060 self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
1062 this.with_label_rib(RibKind::FnOrCoroutine, |this| {
1064 match fn_kind {
1065 FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => {
1066 this.visit_generics(generics);
1067
1068 let declaration = &sig.decl;
1069 let coro_node_id = sig
1070 .header
1071 .coroutine_kind
1072 .map(|coroutine_kind| coroutine_kind.return_id());
1073
1074 this.with_lifetime_rib(
1075 LifetimeRibKind::AnonymousCreateParameter {
1076 binder: fn_id,
1077 report_in_path: coro_node_id.is_some(),
1078 },
1079 |this| {
1080 this.resolve_fn_signature(
1081 fn_id,
1082 declaration.has_self(),
1083 declaration
1084 .inputs
1085 .iter()
1086 .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
1087 &declaration.output,
1088 );
1089 },
1090 );
1091
1092 if let Some(contract) = contract {
1093 this.visit_contract(contract);
1094 }
1095
1096 if let Some(body) = body {
1097 let previous_state = replace(&mut this.in_func_body, true);
1100 this.last_block_rib = None;
1102 this.with_lifetime_rib(
1104 LifetimeRibKind::Elided(LifetimeRes::Infer),
1105 |this| this.visit_block(body),
1106 );
1107
1108 debug!("(resolving function) leaving function");
1109 this.in_func_body = previous_state;
1110 }
1111 }
1112 FnKind::Closure(binder, _, declaration, body) => {
1113 this.visit_closure_binder(binder);
1114
1115 this.with_lifetime_rib(
1116 match binder {
1117 ClosureBinder::NotPresent => {
1119 LifetimeRibKind::AnonymousCreateParameter {
1120 binder: fn_id,
1121 report_in_path: false,
1122 }
1123 }
1124 ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
1125 },
1126 |this| this.resolve_params(&declaration.inputs),
1128 );
1129 this.with_lifetime_rib(
1130 match binder {
1131 ClosureBinder::NotPresent => {
1132 LifetimeRibKind::Elided(LifetimeRes::Infer)
1133 }
1134 ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
1135 },
1136 |this| visit::walk_fn_ret_ty(this, &declaration.output),
1137 );
1138
1139 let previous_state = replace(&mut this.in_func_body, true);
1142 this.with_lifetime_rib(
1144 LifetimeRibKind::Elided(LifetimeRes::Infer),
1145 |this| this.visit_expr(body),
1146 );
1147
1148 debug!("(resolving function) leaving function");
1149 this.in_func_body = previous_state;
1150 }
1151 }
1152 })
1153 });
1154 self.diag_metadata.current_function = previous_value;
1155 }
1156
1157 fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
1158 self.resolve_lifetime(lifetime, use_ctxt)
1159 }
1160
1161 fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
1162 match arg {
1163 PreciseCapturingArg::Lifetime(_) => {}
1166
1167 PreciseCapturingArg::Arg(path, id) => {
1168 let mut check_ns = |ns| {
1175 self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
1176 };
1177 if !check_ns(TypeNS) && check_ns(ValueNS) {
1179 self.smart_resolve_path(
1180 *id,
1181 &None,
1182 path,
1183 PathSource::PreciseCapturingArg(ValueNS),
1184 );
1185 } else {
1186 self.smart_resolve_path(
1187 *id,
1188 &None,
1189 path,
1190 PathSource::PreciseCapturingArg(TypeNS),
1191 );
1192 }
1193 }
1194 }
1195
1196 visit::walk_precise_capturing_arg(self, arg)
1197 }
1198
1199 fn visit_generics(&mut self, generics: &'ast Generics) {
1200 self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
1201 for p in &generics.where_clause.predicates {
1202 self.visit_where_predicate(p);
1203 }
1204 }
1205
1206 fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
1207 match b {
1208 ClosureBinder::NotPresent => {}
1209 ClosureBinder::For { generic_params, .. } => {
1210 self.visit_generic_params(
1211 generic_params,
1212 self.diag_metadata.current_self_item.is_some(),
1213 );
1214 }
1215 }
1216 }
1217
1218 fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
1219 debug!("visit_generic_arg({:?})", arg);
1220 let prev = replace(&mut self.diag_metadata.currently_processing_generic_args, true);
1221 match arg {
1222 GenericArg::Type(ty) => {
1223 if let TyKind::Path(None, ref path) = ty.kind
1229 && path.is_potential_trivial_const_arg(false)
1232 {
1233 let mut check_ns = |ns| {
1234 self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
1235 .is_some()
1236 };
1237 if !check_ns(TypeNS) && check_ns(ValueNS) {
1238 self.resolve_anon_const_manual(
1239 true,
1240 AnonConstKind::ConstArg(IsRepeatExpr::No),
1241 |this| {
1242 this.smart_resolve_path(ty.id, &None, path, PathSource::Expr(None));
1243 this.visit_path(path, ty.id);
1244 },
1245 );
1246
1247 self.diag_metadata.currently_processing_generic_args = prev;
1248 return;
1249 }
1250 }
1251
1252 self.visit_ty(ty);
1253 }
1254 GenericArg::Lifetime(lt) => self.visit_lifetime(lt, visit::LifetimeCtxt::GenericArg),
1255 GenericArg::Const(ct) => {
1256 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
1257 }
1258 }
1259 self.diag_metadata.currently_processing_generic_args = prev;
1260 }
1261
1262 fn visit_assoc_item_constraint(&mut self, constraint: &'ast AssocItemConstraint) {
1263 self.visit_ident(&constraint.ident);
1264 if let Some(ref gen_args) = constraint.gen_args {
1265 self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1267 this.visit_generic_args(gen_args)
1268 });
1269 }
1270 match constraint.kind {
1271 AssocItemConstraintKind::Equality { ref term } => match term {
1272 Term::Ty(ty) => self.visit_ty(ty),
1273 Term::Const(c) => {
1274 self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No))
1275 }
1276 },
1277 AssocItemConstraintKind::Bound { ref bounds } => {
1278 walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
1279 }
1280 }
1281 }
1282
1283 fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
1284 let Some(ref args) = path_segment.args else {
1285 return;
1286 };
1287
1288 match &**args {
1289 GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args),
1290 GenericArgs::Parenthesized(p_args) => {
1291 for rib in self.lifetime_ribs.iter().rev() {
1293 match rib.kind {
1294 LifetimeRibKind::Generics {
1297 binder,
1298 kind: LifetimeBinderKind::PolyTrait,
1299 ..
1300 } => {
1301 self.with_lifetime_rib(
1302 LifetimeRibKind::AnonymousCreateParameter {
1303 binder,
1304 report_in_path: false,
1305 },
1306 |this| {
1307 this.resolve_fn_signature(
1308 binder,
1309 false,
1310 p_args.inputs.iter().map(|ty| (None, &**ty)),
1311 &p_args.output,
1312 )
1313 },
1314 );
1315 break;
1316 }
1317 LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => {
1320 visit::walk_generic_args(self, args);
1321 break;
1322 }
1323 LifetimeRibKind::AnonymousCreateParameter { .. }
1324 | LifetimeRibKind::AnonymousReportError
1325 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
1326 | LifetimeRibKind::Elided(_)
1327 | LifetimeRibKind::ElisionFailure
1328 | LifetimeRibKind::ConcreteAnonConst(_)
1329 | LifetimeRibKind::ConstParamTy => {}
1330 }
1331 }
1332 }
1333 GenericArgs::ParenthesizedElided(_) => {}
1334 }
1335 }
1336
1337 fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
1338 debug!("visit_where_predicate {:?}", p);
1339 let previous_value = replace(&mut self.diag_metadata.current_where_predicate, Some(p));
1340 self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1341 if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1342 bounded_ty,
1343 bounds,
1344 bound_generic_params,
1345 ..
1346 }) = &p.kind
1347 {
1348 let span = p.span.shrink_to_lo().to(bounded_ty.span.shrink_to_lo());
1349 this.with_generic_param_rib(
1350 bound_generic_params,
1351 RibKind::Normal,
1352 LifetimeRibKind::Generics {
1353 binder: bounded_ty.id,
1354 kind: LifetimeBinderKind::WhereBound,
1355 span,
1356 },
1357 |this| {
1358 this.visit_generic_params(bound_generic_params, false);
1359 this.visit_ty(bounded_ty);
1360 for bound in bounds {
1361 this.visit_param_bound(bound, BoundKind::Bound)
1362 }
1363 },
1364 );
1365 } else {
1366 visit::walk_where_predicate(this, p);
1367 }
1368 });
1369 self.diag_metadata.current_where_predicate = previous_value;
1370 }
1371
1372 fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
1373 for (op, _) in &asm.operands {
1374 match op {
1375 InlineAsmOperand::In { expr, .. }
1376 | InlineAsmOperand::Out { expr: Some(expr), .. }
1377 | InlineAsmOperand::InOut { expr, .. } => self.visit_expr(expr),
1378 InlineAsmOperand::Out { expr: None, .. } => {}
1379 InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
1380 self.visit_expr(in_expr);
1381 if let Some(out_expr) = out_expr {
1382 self.visit_expr(out_expr);
1383 }
1384 }
1385 InlineAsmOperand::Const { anon_const, .. } => {
1386 self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
1389 }
1390 InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
1391 InlineAsmOperand::Label { block } => self.visit_block(block),
1392 }
1393 }
1394 }
1395
1396 fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
1397 self.with_rib(ValueNS, RibKind::InlineAsmSym, |this| {
1399 this.with_rib(TypeNS, RibKind::InlineAsmSym, |this| {
1400 this.with_label_rib(RibKind::InlineAsmSym, |this| {
1401 this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None));
1402 visit::walk_inline_asm_sym(this, sym);
1403 });
1404 })
1405 });
1406 }
1407
1408 fn visit_variant(&mut self, v: &'ast Variant) {
1409 self.resolve_doc_links(&v.attrs, MaybeExported::Ok(v.id));
1410 visit::walk_variant(self, v)
1411 }
1412
1413 fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
1414 self.resolve_anon_const(discr, AnonConstKind::EnumDiscriminant);
1415 }
1416
1417 fn visit_field_def(&mut self, f: &'ast FieldDef) {
1418 self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
1419 let FieldDef {
1420 attrs,
1421 id: _,
1422 span: _,
1423 vis,
1424 ident,
1425 ty,
1426 is_placeholder: _,
1427 default,
1428 safety: _,
1429 } = f;
1430 walk_list!(self, visit_attribute, attrs);
1431 try_visit!(self.visit_vis(vis));
1432 visit_opt!(self, visit_ident, ident);
1433 try_visit!(self.visit_ty(ty));
1434 if let Some(v) = &default {
1435 self.resolve_anon_const(v, AnonConstKind::FieldDefaultValue);
1436 }
1437 }
1438}
1439
1440impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
1441 fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
1442 let graph_root = resolver.graph_root;
1445 let parent_scope = ParentScope::module(graph_root, resolver);
1446 let start_rib_kind = RibKind::Module(graph_root);
1447 LateResolutionVisitor {
1448 r: resolver,
1449 parent_scope,
1450 ribs: PerNS {
1451 value_ns: vec![Rib::new(start_rib_kind)],
1452 type_ns: vec![Rib::new(start_rib_kind)],
1453 macro_ns: vec![Rib::new(start_rib_kind)],
1454 },
1455 last_block_rib: None,
1456 label_ribs: Vec::new(),
1457 lifetime_ribs: Vec::new(),
1458 lifetime_elision_candidates: None,
1459 current_trait_ref: None,
1460 diag_metadata: Default::default(),
1461 in_func_body: false,
1463 lifetime_uses: Default::default(),
1464 }
1465 }
1466
1467 fn maybe_resolve_ident_in_lexical_scope(
1468 &mut self,
1469 ident: Ident,
1470 ns: Namespace,
1471 ) -> Option<LexicalScopeBinding<'ra>> {
1472 self.r.resolve_ident_in_lexical_scope(
1473 ident,
1474 ns,
1475 &self.parent_scope,
1476 None,
1477 &self.ribs[ns],
1478 None,
1479 )
1480 }
1481
1482 fn resolve_ident_in_lexical_scope(
1483 &mut self,
1484 ident: Ident,
1485 ns: Namespace,
1486 finalize: Option<Finalize>,
1487 ignore_binding: Option<NameBinding<'ra>>,
1488 ) -> Option<LexicalScopeBinding<'ra>> {
1489 self.r.resolve_ident_in_lexical_scope(
1490 ident,
1491 ns,
1492 &self.parent_scope,
1493 finalize,
1494 &self.ribs[ns],
1495 ignore_binding,
1496 )
1497 }
1498
1499 fn resolve_path(
1500 &mut self,
1501 path: &[Segment],
1502 opt_ns: Option<Namespace>, finalize: Option<Finalize>,
1504 ) -> PathResult<'ra> {
1505 self.r.resolve_path_with_ribs(
1506 path,
1507 opt_ns,
1508 &self.parent_scope,
1509 finalize,
1510 Some(&self.ribs),
1511 None,
1512 None,
1513 )
1514 }
1515
1516 fn with_rib<T>(
1536 &mut self,
1537 ns: Namespace,
1538 kind: RibKind<'ra>,
1539 work: impl FnOnce(&mut Self) -> T,
1540 ) -> T {
1541 self.ribs[ns].push(Rib::new(kind));
1542 let ret = work(self);
1543 self.ribs[ns].pop();
1544 ret
1545 }
1546
1547 fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
1548 if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) {
1549 let orig_module = replace(&mut self.parent_scope.module, module);
1551 self.with_rib(ValueNS, RibKind::Module(module), |this| {
1552 this.with_rib(TypeNS, RibKind::Module(module), |this| {
1553 let ret = f(this);
1554 this.parent_scope.module = orig_module;
1555 ret
1556 })
1557 })
1558 } else {
1559 f(self)
1560 }
1561 }
1562
1563 fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) {
1564 let mut forward_ty_ban_rib =
1570 Rib::new(RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::Default));
1571 let mut forward_const_ban_rib =
1572 Rib::new(RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::Default));
1573 for param in params.iter() {
1574 match param.kind {
1575 GenericParamKind::Type { .. } => {
1576 forward_ty_ban_rib
1577 .bindings
1578 .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
1579 }
1580 GenericParamKind::Const { .. } => {
1581 forward_const_ban_rib
1582 .bindings
1583 .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
1584 }
1585 GenericParamKind::Lifetime => {}
1586 }
1587 }
1588
1589 if add_self_upper {
1599 forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
1601 }
1602
1603 let mut forward_ty_ban_rib_const_param_ty = Rib {
1606 bindings: forward_ty_ban_rib.bindings.clone(),
1607 patterns_with_skipped_bindings: Default::default(),
1608 kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
1609 };
1610 let mut forward_const_ban_rib_const_param_ty = Rib {
1611 bindings: forward_const_ban_rib.bindings.clone(),
1612 patterns_with_skipped_bindings: Default::default(),
1613 kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
1614 };
1615 if !self.r.tcx.features().generic_const_parameter_types() {
1618 forward_ty_ban_rib_const_param_ty.bindings.clear();
1619 forward_const_ban_rib_const_param_ty.bindings.clear();
1620 }
1621
1622 self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1623 for param in params {
1624 match param.kind {
1625 GenericParamKind::Lifetime => {
1626 for bound in ¶m.bounds {
1627 this.visit_param_bound(bound, BoundKind::Bound);
1628 }
1629 }
1630 GenericParamKind::Type { ref default } => {
1631 for bound in ¶m.bounds {
1632 this.visit_param_bound(bound, BoundKind::Bound);
1633 }
1634
1635 if let Some(ty) = default {
1636 this.ribs[TypeNS].push(forward_ty_ban_rib);
1637 this.ribs[ValueNS].push(forward_const_ban_rib);
1638 this.visit_ty(ty);
1639 forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
1640 forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
1641 }
1642
1643 let i = &Ident::with_dummy_span(param.ident.name);
1645 forward_ty_ban_rib.bindings.remove(i);
1646 forward_ty_ban_rib_const_param_ty.bindings.remove(i);
1647 }
1648 GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
1649 assert!(param.bounds.is_empty());
1651
1652 this.ribs[TypeNS].push(forward_ty_ban_rib_const_param_ty);
1653 this.ribs[ValueNS].push(forward_const_ban_rib_const_param_ty);
1654 if this.r.tcx.features().generic_const_parameter_types() {
1655 this.visit_ty(ty)
1656 } else {
1657 this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
1658 this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
1659 this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
1660 this.visit_ty(ty)
1661 });
1662 this.ribs[TypeNS].pop().unwrap();
1663 this.ribs[ValueNS].pop().unwrap();
1664 }
1665 forward_const_ban_rib_const_param_ty = this.ribs[ValueNS].pop().unwrap();
1666 forward_ty_ban_rib_const_param_ty = this.ribs[TypeNS].pop().unwrap();
1667
1668 if let Some(expr) = default {
1669 this.ribs[TypeNS].push(forward_ty_ban_rib);
1670 this.ribs[ValueNS].push(forward_const_ban_rib);
1671 this.resolve_anon_const(
1672 expr,
1673 AnonConstKind::ConstArg(IsRepeatExpr::No),
1674 );
1675 forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
1676 forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
1677 }
1678
1679 let i = &Ident::with_dummy_span(param.ident.name);
1681 forward_const_ban_rib.bindings.remove(i);
1682 forward_const_ban_rib_const_param_ty.bindings.remove(i);
1683 }
1684 }
1685 }
1686 })
1687 }
1688
1689 #[instrument(level = "debug", skip(self, work))]
1690 fn with_lifetime_rib<T>(
1691 &mut self,
1692 kind: LifetimeRibKind,
1693 work: impl FnOnce(&mut Self) -> T,
1694 ) -> T {
1695 self.lifetime_ribs.push(LifetimeRib::new(kind));
1696 let outer_elision_candidates = self.lifetime_elision_candidates.take();
1697 let ret = work(self);
1698 self.lifetime_elision_candidates = outer_elision_candidates;
1699 self.lifetime_ribs.pop();
1700 ret
1701 }
1702
1703 #[instrument(level = "debug", skip(self))]
1704 fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
1705 let ident = lifetime.ident;
1706
1707 if ident.name == kw::StaticLifetime {
1708 self.record_lifetime_res(
1709 lifetime.id,
1710 LifetimeRes::Static { suppress_elision_warning: false },
1711 LifetimeElisionCandidate::Named,
1712 );
1713 return;
1714 }
1715
1716 if ident.name == kw::UnderscoreLifetime {
1717 return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false);
1718 }
1719
1720 let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
1721 while let Some(rib) = lifetime_rib_iter.next() {
1722 let normalized_ident = ident.normalize_to_macros_2_0();
1723 if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
1724 self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
1725
1726 if let LifetimeRes::Param { param, binder } = res {
1727 match self.lifetime_uses.entry(param) {
1728 Entry::Vacant(v) => {
1729 debug!("First use of {:?} at {:?}", res, ident.span);
1730 let use_set = self
1731 .lifetime_ribs
1732 .iter()
1733 .rev()
1734 .find_map(|rib| match rib.kind {
1735 LifetimeRibKind::Item
1738 | LifetimeRibKind::AnonymousReportError
1739 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
1740 | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
1741 LifetimeRibKind::AnonymousCreateParameter {
1744 binder: anon_binder,
1745 ..
1746 } => Some(if binder == anon_binder {
1747 LifetimeUseSet::One { use_span: ident.span, use_ctxt }
1748 } else {
1749 LifetimeUseSet::Many
1750 }),
1751 LifetimeRibKind::Elided(r) => Some(if res == r {
1754 LifetimeUseSet::One { use_span: ident.span, use_ctxt }
1755 } else {
1756 LifetimeUseSet::Many
1757 }),
1758 LifetimeRibKind::Generics { .. }
1759 | LifetimeRibKind::ConstParamTy => None,
1760 LifetimeRibKind::ConcreteAnonConst(_) => {
1761 span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
1762 }
1763 })
1764 .unwrap_or(LifetimeUseSet::Many);
1765 debug!(?use_ctxt, ?use_set);
1766 v.insert(use_set);
1767 }
1768 Entry::Occupied(mut o) => {
1769 debug!("Many uses of {:?} at {:?}", res, ident.span);
1770 *o.get_mut() = LifetimeUseSet::Many;
1771 }
1772 }
1773 }
1774 return;
1775 }
1776
1777 match rib.kind {
1778 LifetimeRibKind::Item => break,
1779 LifetimeRibKind::ConstParamTy => {
1780 self.emit_non_static_lt_in_const_param_ty_error(lifetime);
1781 self.record_lifetime_res(
1782 lifetime.id,
1783 LifetimeRes::Error,
1784 LifetimeElisionCandidate::Ignore,
1785 );
1786 return;
1787 }
1788 LifetimeRibKind::ConcreteAnonConst(cause) => {
1789 self.emit_forbidden_non_static_lifetime_error(cause, lifetime);
1790 self.record_lifetime_res(
1791 lifetime.id,
1792 LifetimeRes::Error,
1793 LifetimeElisionCandidate::Ignore,
1794 );
1795 return;
1796 }
1797 LifetimeRibKind::AnonymousCreateParameter { .. }
1798 | LifetimeRibKind::Elided(_)
1799 | LifetimeRibKind::Generics { .. }
1800 | LifetimeRibKind::ElisionFailure
1801 | LifetimeRibKind::AnonymousReportError
1802 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {}
1803 }
1804 }
1805
1806 let normalized_ident = ident.normalize_to_macros_2_0();
1807 let outer_res = lifetime_rib_iter
1808 .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer));
1809
1810 self.emit_undeclared_lifetime_error(lifetime, outer_res);
1811 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
1812 }
1813
1814 #[instrument(level = "debug", skip(self))]
1815 fn resolve_anonymous_lifetime(
1816 &mut self,
1817 lifetime: &Lifetime,
1818 id_for_lint: NodeId,
1819 elided: bool,
1820 ) {
1821 debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
1822
1823 let kind =
1824 if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore };
1825 let missing_lifetime = MissingLifetime {
1826 id: lifetime.id,
1827 span: lifetime.ident.span,
1828 kind,
1829 count: 1,
1830 id_for_lint,
1831 };
1832 let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
1833 for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
1834 debug!(?rib.kind);
1835 match rib.kind {
1836 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
1837 let res = self.create_fresh_lifetime(lifetime.ident, binder, kind);
1838 self.record_lifetime_res(lifetime.id, res, elision_candidate);
1839 return;
1840 }
1841 LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
1842 let mut lifetimes_in_scope = vec![];
1843 for rib in &self.lifetime_ribs[..i] {
1844 lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
1845 if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
1847 && let Some(extra) = self.r.extra_lifetime_params_map.get(&binder)
1848 {
1849 lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
1850 }
1851 }
1852 if lifetimes_in_scope.is_empty() {
1853 self.record_lifetime_res(
1854 lifetime.id,
1855 LifetimeRes::Static { suppress_elision_warning: true },
1857 elision_candidate,
1858 );
1859 return;
1860 } else if emit_lint {
1861 self.r.lint_buffer.buffer_lint(
1862 lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
1863 node_id,
1864 lifetime.ident.span,
1865 lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
1866 elided,
1867 span: lifetime.ident.span,
1868 lifetimes_in_scope: lifetimes_in_scope.into(),
1869 },
1870 );
1871 }
1872 }
1873 LifetimeRibKind::AnonymousReportError => {
1874 if elided {
1875 let suggestion = self.lifetime_ribs[i..].iter().rev().find_map(|rib| {
1876 if let LifetimeRibKind::Generics {
1877 span,
1878 kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound,
1879 ..
1880 } = rib.kind
1881 {
1882 Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion {
1883 lo: span.shrink_to_lo(),
1884 hi: lifetime.ident.span.shrink_to_hi(),
1885 })
1886 } else {
1887 None
1888 }
1889 });
1890 if !self.in_func_body
1893 && let Some((module, _)) = &self.current_trait_ref
1894 && let Some(ty) = &self.diag_metadata.current_self_type
1895 && Some(true) == self.diag_metadata.in_non_gat_assoc_type
1896 && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind
1897 {
1898 if def_id_matches_path(
1899 self.r.tcx,
1900 trait_id,
1901 &["core", "iter", "traits", "iterator", "Iterator"],
1902 ) {
1903 self.r.dcx().emit_err(errors::LendingIteratorReportError {
1904 lifetime: lifetime.ident.span,
1905 ty: ty.span,
1906 });
1907 } else {
1908 self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError {
1909 lifetime: lifetime.ident.span,
1910 });
1911 }
1912 } else {
1913 self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
1914 span: lifetime.ident.span,
1915 suggestion,
1916 });
1917 }
1918 } else {
1919 self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError {
1920 span: lifetime.ident.span,
1921 });
1922 };
1923 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1924 return;
1925 }
1926 LifetimeRibKind::Elided(res) => {
1927 self.record_lifetime_res(lifetime.id, res, elision_candidate);
1928 return;
1929 }
1930 LifetimeRibKind::ElisionFailure => {
1931 self.diag_metadata.current_elision_failures.push(missing_lifetime);
1932 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1933 return;
1934 }
1935 LifetimeRibKind::Item => break,
1936 LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
1937 LifetimeRibKind::ConcreteAnonConst(_) => {
1938 span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
1940 }
1941 }
1942 }
1943 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1944 self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
1945 }
1946
1947 #[instrument(level = "debug", skip(self))]
1948 fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
1949 let id = self.r.next_node_id();
1950 let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
1951
1952 self.record_lifetime_res(
1953 anchor_id,
1954 LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
1955 LifetimeElisionCandidate::Ignore,
1956 );
1957 self.resolve_anonymous_lifetime(<, anchor_id, true);
1958 }
1959
1960 #[instrument(level = "debug", skip(self))]
1961 fn create_fresh_lifetime(
1962 &mut self,
1963 ident: Ident,
1964 binder: NodeId,
1965 kind: MissingLifetimeKind,
1966 ) -> LifetimeRes {
1967 debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1968 debug!(?ident.span);
1969
1970 let param = self.r.next_node_id();
1972 let res = LifetimeRes::Fresh { param, binder, kind };
1973 self.record_lifetime_param(param, res);
1974
1975 self.r
1977 .extra_lifetime_params_map
1978 .entry(binder)
1979 .or_insert_with(Vec::new)
1980 .push((ident, param, res));
1981 res
1982 }
1983
1984 #[instrument(level = "debug", skip(self))]
1985 fn resolve_elided_lifetimes_in_path(
1986 &mut self,
1987 partial_res: PartialRes,
1988 path: &[Segment],
1989 source: PathSource<'_>,
1990 path_span: Span,
1991 ) {
1992 let proj_start = path.len() - partial_res.unresolved_segments();
1993 for (i, segment) in path.iter().enumerate() {
1994 if segment.has_lifetime_args {
1995 continue;
1996 }
1997 let Some(segment_id) = segment.id else {
1998 continue;
1999 };
2000
2001 let type_def_id = match partial_res.base_res() {
2004 Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
2005 self.r.tcx.parent(def_id)
2006 }
2007 Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
2008 self.r.tcx.parent(def_id)
2009 }
2010 Res::Def(DefKind::Struct, def_id)
2011 | Res::Def(DefKind::Union, def_id)
2012 | Res::Def(DefKind::Enum, def_id)
2013 | Res::Def(DefKind::TyAlias, def_id)
2014 | Res::Def(DefKind::Trait, def_id)
2015 if i + 1 == proj_start =>
2016 {
2017 def_id
2018 }
2019 _ => continue,
2020 };
2021
2022 let expected_lifetimes = self.r.item_generics_num_lifetimes(type_def_id);
2023 if expected_lifetimes == 0 {
2024 continue;
2025 }
2026
2027 let node_ids = self.r.next_node_ids(expected_lifetimes);
2028 self.record_lifetime_res(
2029 segment_id,
2030 LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
2031 LifetimeElisionCandidate::Ignore,
2032 );
2033
2034 let inferred = match source {
2035 PathSource::Trait(..)
2036 | PathSource::TraitItem(..)
2037 | PathSource::Type
2038 | PathSource::PreciseCapturingArg(..)
2039 | PathSource::ReturnTypeNotation => false,
2040 PathSource::Expr(..)
2041 | PathSource::Pat
2042 | PathSource::Struct
2043 | PathSource::TupleStruct(..)
2044 | PathSource::DefineOpaques
2045 | PathSource::Delegation => true,
2046 };
2047 if inferred {
2048 for id in node_ids {
2051 self.record_lifetime_res(
2052 id,
2053 LifetimeRes::Infer,
2054 LifetimeElisionCandidate::Named,
2055 );
2056 }
2057 continue;
2058 }
2059
2060 let elided_lifetime_span = if segment.has_generic_args {
2061 segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
2063 } else {
2064 segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
2068 };
2069 let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span);
2070
2071 let kind = if segment.has_generic_args {
2072 MissingLifetimeKind::Comma
2073 } else {
2074 MissingLifetimeKind::Brackets
2075 };
2076 let missing_lifetime = MissingLifetime {
2077 id: node_ids.start,
2078 id_for_lint: segment_id,
2079 span: elided_lifetime_span,
2080 kind,
2081 count: expected_lifetimes,
2082 };
2083 let mut should_lint = true;
2084 for rib in self.lifetime_ribs.iter().rev() {
2085 match rib.kind {
2086 LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
2093 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {
2094 let sess = self.r.tcx.sess;
2095 let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
2096 sess.source_map(),
2097 expected_lifetimes,
2098 path_span,
2099 !segment.has_generic_args,
2100 elided_lifetime_span,
2101 );
2102 self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere {
2103 span: path_span,
2104 subdiag,
2105 });
2106 should_lint = false;
2107
2108 for id in node_ids {
2109 self.record_lifetime_res(
2110 id,
2111 LifetimeRes::Error,
2112 LifetimeElisionCandidate::Named,
2113 );
2114 }
2115 break;
2116 }
2117 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
2119 let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
2121 for id in node_ids {
2122 let res = self.create_fresh_lifetime(ident, binder, kind);
2123 self.record_lifetime_res(
2124 id,
2125 res,
2126 replace(&mut candidate, LifetimeElisionCandidate::Named),
2127 );
2128 }
2129 break;
2130 }
2131 LifetimeRibKind::Elided(res) => {
2132 let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
2133 for id in node_ids {
2134 self.record_lifetime_res(
2135 id,
2136 res,
2137 replace(&mut candidate, LifetimeElisionCandidate::Ignore),
2138 );
2139 }
2140 break;
2141 }
2142 LifetimeRibKind::ElisionFailure => {
2143 self.diag_metadata.current_elision_failures.push(missing_lifetime);
2144 for id in node_ids {
2145 self.record_lifetime_res(
2146 id,
2147 LifetimeRes::Error,
2148 LifetimeElisionCandidate::Ignore,
2149 );
2150 }
2151 break;
2152 }
2153 LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
2158 for id in node_ids {
2159 self.record_lifetime_res(
2160 id,
2161 LifetimeRes::Error,
2162 LifetimeElisionCandidate::Ignore,
2163 );
2164 }
2165 self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
2166 break;
2167 }
2168 LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
2169 LifetimeRibKind::ConcreteAnonConst(_) => {
2170 span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
2172 }
2173 }
2174 }
2175
2176 if should_lint {
2177 self.r.lint_buffer.buffer_lint(
2178 lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
2179 segment_id,
2180 elided_lifetime_span,
2181 lint::BuiltinLintDiag::ElidedLifetimesInPaths(
2182 expected_lifetimes,
2183 path_span,
2184 !segment.has_generic_args,
2185 elided_lifetime_span,
2186 ),
2187 );
2188 }
2189 }
2190 }
2191
2192 #[instrument(level = "debug", skip(self))]
2193 fn record_lifetime_res(
2194 &mut self,
2195 id: NodeId,
2196 res: LifetimeRes,
2197 candidate: LifetimeElisionCandidate,
2198 ) {
2199 if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
2200 panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)")
2201 }
2202
2203 match candidate {
2204 LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => {
2205 debug_assert_eq!(id, missing.id);
2206 match res {
2207 LifetimeRes::Static { suppress_elision_warning } => {
2208 if !suppress_elision_warning {
2209 self.r.lint_buffer.buffer_lint(
2210 lint::builtin::ELIDED_NAMED_LIFETIMES,
2211 missing.id_for_lint,
2212 missing.span,
2213 BuiltinLintDiag::ElidedNamedLifetimes {
2214 elided: (missing.span, missing.kind),
2215 resolution: lint::ElidedLifetimeResolution::Static,
2216 },
2217 );
2218 }
2219 }
2220 LifetimeRes::Param { param, binder: _ } => {
2221 let tcx = self.r.tcx();
2222 self.r.lint_buffer.buffer_lint(
2223 lint::builtin::ELIDED_NAMED_LIFETIMES,
2224 missing.id_for_lint,
2225 missing.span,
2226 BuiltinLintDiag::ElidedNamedLifetimes {
2227 elided: (missing.span, missing.kind),
2228 resolution: lint::ElidedLifetimeResolution::Param(
2229 tcx.item_name(param.into()),
2230 tcx.source_span(param),
2231 ),
2232 },
2233 );
2234 }
2235 LifetimeRes::Fresh { .. }
2236 | LifetimeRes::Infer
2237 | LifetimeRes::Error
2238 | LifetimeRes::ElidedAnchor { .. } => {}
2239 }
2240 }
2241 LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {}
2242 }
2243
2244 match res {
2245 LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => {
2246 if let Some(ref mut candidates) = self.lifetime_elision_candidates {
2247 candidates.push((res, candidate));
2248 }
2249 }
2250 LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
2251 }
2252 }
2253
2254 #[instrument(level = "debug", skip(self))]
2255 fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) {
2256 if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
2257 panic!(
2258 "lifetime parameter {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)"
2259 )
2260 }
2261 }
2262
2263 #[instrument(level = "debug", skip(self, inputs))]
2265 fn resolve_fn_signature(
2266 &mut self,
2267 fn_id: NodeId,
2268 has_self: bool,
2269 inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone,
2270 output_ty: &'ast FnRetTy,
2271 ) {
2272 let elision_lifetime = self.resolve_fn_params(has_self, inputs);
2274 debug!(?elision_lifetime);
2275
2276 let outer_failures = take(&mut self.diag_metadata.current_elision_failures);
2277 let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
2278 self.r.lifetime_elision_allowed.insert(fn_id);
2279 LifetimeRibKind::Elided(*res)
2280 } else {
2281 LifetimeRibKind::ElisionFailure
2282 };
2283 self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty));
2284 let elision_failures =
2285 replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
2286 if !elision_failures.is_empty() {
2287 let Err(failure_info) = elision_lifetime else { bug!() };
2288 self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info));
2289 }
2290 }
2291
2292 fn resolve_fn_params(
2296 &mut self,
2297 has_self: bool,
2298 inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>,
2299 ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> {
2300 enum Elision {
2301 None,
2303 Self_(LifetimeRes),
2305 Param(LifetimeRes),
2307 Err,
2309 }
2310
2311 let outer_candidates = self.lifetime_elision_candidates.take();
2313
2314 let mut elision_lifetime = Elision::None;
2316 let mut parameter_info = Vec::new();
2318 let mut all_candidates = Vec::new();
2319
2320 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
2321 for (index, (pat, ty)) in inputs.enumerate() {
2322 debug!(?pat, ?ty);
2323 self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
2324 if let Some(pat) = pat {
2325 this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
2326 }
2327 });
2328
2329 debug_assert_matches!(self.lifetime_elision_candidates, None);
2331 self.lifetime_elision_candidates = Some(Default::default());
2332 self.visit_ty(ty);
2333 let local_candidates = self.lifetime_elision_candidates.take();
2334
2335 if let Some(candidates) = local_candidates {
2336 let distinct: UnordSet<_> = candidates.iter().map(|(res, _)| *res).collect();
2337 let lifetime_count = distinct.len();
2338 if lifetime_count != 0 {
2339 parameter_info.push(ElisionFnParameter {
2340 index,
2341 ident: if let Some(pat) = pat
2342 && let PatKind::Ident(_, ident, _) = pat.kind
2343 {
2344 Some(ident)
2345 } else {
2346 None
2347 },
2348 lifetime_count,
2349 span: ty.span,
2350 });
2351 all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| {
2352 match candidate {
2353 LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {
2354 None
2355 }
2356 LifetimeElisionCandidate::Missing(missing) => Some(missing),
2357 }
2358 }));
2359 }
2360 if !distinct.is_empty() {
2361 match elision_lifetime {
2362 Elision::None => {
2364 if let Some(res) = distinct.get_only() {
2365 elision_lifetime = Elision::Param(*res)
2367 } else {
2368 elision_lifetime = Elision::Err;
2370 }
2371 }
2372 Elision::Param(_) => elision_lifetime = Elision::Err,
2374 Elision::Self_(_) | Elision::Err => {}
2376 }
2377 }
2378 }
2379
2380 if index == 0 && has_self {
2382 let self_lifetime = self.find_lifetime_for_self(ty);
2383 elision_lifetime = match self_lifetime {
2384 Set1::One(lifetime) => Elision::Self_(lifetime),
2386 Set1::Many => Elision::Err,
2391 Set1::Empty => Elision::None,
2394 }
2395 }
2396 debug!("(resolving function / closure) recorded parameter");
2397 }
2398
2399 debug_assert_matches!(self.lifetime_elision_candidates, None);
2401 self.lifetime_elision_candidates = outer_candidates;
2402
2403 if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime {
2404 return Ok(res);
2405 }
2406
2407 Err((all_candidates, parameter_info))
2409 }
2410
2411 fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
2413 struct FindReferenceVisitor<'a, 'ra, 'tcx> {
2417 r: &'a Resolver<'ra, 'tcx>,
2418 impl_self: Option<Res>,
2419 lifetime: Set1<LifetimeRes>,
2420 }
2421
2422 impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> {
2423 fn visit_ty(&mut self, ty: &'ra Ty) {
2424 trace!("FindReferenceVisitor considering ty={:?}", ty);
2425 if let TyKind::Ref(lt, _) | TyKind::PinnedRef(lt, _) = ty.kind {
2426 let mut visitor =
2428 SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
2429 visitor.visit_ty(ty);
2430 trace!("FindReferenceVisitor: SelfVisitor self_found={:?}", visitor.self_found);
2431 if visitor.self_found {
2432 let lt_id = if let Some(lt) = lt {
2433 lt.id
2434 } else {
2435 let res = self.r.lifetimes_res_map[&ty.id];
2436 let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
2437 start
2438 };
2439 let lt_res = self.r.lifetimes_res_map[<_id];
2440 trace!("FindReferenceVisitor inserting res={:?}", lt_res);
2441 self.lifetime.insert(lt_res);
2442 }
2443 }
2444 visit::walk_ty(self, ty)
2445 }
2446
2447 fn visit_expr(&mut self, _: &'ra Expr) {}
2450 }
2451
2452 struct SelfVisitor<'a, 'ra, 'tcx> {
2455 r: &'a Resolver<'ra, 'tcx>,
2456 impl_self: Option<Res>,
2457 self_found: bool,
2458 }
2459
2460 impl SelfVisitor<'_, '_, '_> {
2461 fn is_self_ty(&self, ty: &Ty) -> bool {
2463 match ty.kind {
2464 TyKind::ImplicitSelf => true,
2465 TyKind::Path(None, _) => {
2466 let path_res = self.r.partial_res_map[&ty.id].full_res();
2467 if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res {
2468 return true;
2469 }
2470 self.impl_self.is_some() && path_res == self.impl_self
2471 }
2472 _ => false,
2473 }
2474 }
2475 }
2476
2477 impl<'ra> Visitor<'ra> for SelfVisitor<'_, '_, '_> {
2478 fn visit_ty(&mut self, ty: &'ra Ty) {
2479 trace!("SelfVisitor considering ty={:?}", ty);
2480 if self.is_self_ty(ty) {
2481 trace!("SelfVisitor found Self");
2482 self.self_found = true;
2483 }
2484 visit::walk_ty(self, ty)
2485 }
2486
2487 fn visit_expr(&mut self, _: &'ra Expr) {}
2490 }
2491
2492 let impl_self = self
2493 .diag_metadata
2494 .current_self_type
2495 .as_ref()
2496 .and_then(|ty| {
2497 if let TyKind::Path(None, _) = ty.kind {
2498 self.r.partial_res_map.get(&ty.id)
2499 } else {
2500 None
2501 }
2502 })
2503 .and_then(|res| res.full_res())
2504 .filter(|res| {
2505 matches!(
2509 res,
2510 Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
2511 )
2512 });
2513 let mut visitor = FindReferenceVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
2514 visitor.visit_ty(ty);
2515 trace!("FindReferenceVisitor found={:?}", visitor.lifetime);
2516 visitor.lifetime
2517 }
2518
2519 fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> {
2522 let mut suggestion = None;
2523
2524 for i in (0..self.label_ribs.len()).rev() {
2525 let rib = &self.label_ribs[i];
2526
2527 if let RibKind::MacroDefinition(def) = rib.kind
2528 && def == self.r.macro_def(label.span.ctxt())
2531 {
2532 label.span.remove_mark();
2533 }
2534
2535 let ident = label.normalize_to_macro_rules();
2536 if let Some((ident, id)) = rib.bindings.get_key_value(&ident) {
2537 let definition_span = ident.span;
2538 return if self.is_label_valid_from_rib(i) {
2539 Ok((*id, definition_span))
2540 } else {
2541 Err(ResolutionError::UnreachableLabel {
2542 name: label.name,
2543 definition_span,
2544 suggestion,
2545 })
2546 };
2547 }
2548
2549 suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
2552 }
2553
2554 Err(ResolutionError::UndeclaredLabel { name: label.name, suggestion })
2555 }
2556
2557 fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
2559 let ribs = &self.label_ribs[rib_index + 1..];
2560 ribs.iter().all(|rib| !rib.kind.is_label_barrier())
2561 }
2562
2563 fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
2564 debug!("resolve_adt");
2565 let kind = self.r.local_def_kind(item.id);
2566 self.with_current_self_item(item, |this| {
2567 this.with_generic_param_rib(
2568 &generics.params,
2569 RibKind::Item(HasGenericParams::Yes(generics.span), kind),
2570 LifetimeRibKind::Generics {
2571 binder: item.id,
2572 kind: LifetimeBinderKind::Item,
2573 span: generics.span,
2574 },
2575 |this| {
2576 let item_def_id = this.r.local_def_id(item.id).to_def_id();
2577 this.with_self_rib(
2578 Res::SelfTyAlias {
2579 alias_to: item_def_id,
2580 forbid_generic: false,
2581 is_trait_impl: false,
2582 },
2583 |this| {
2584 visit::walk_item(this, item);
2585 },
2586 );
2587 },
2588 );
2589 });
2590 }
2591
2592 fn future_proof_import(&mut self, use_tree: &UseTree) {
2593 if let [segment, rest @ ..] = use_tree.prefix.segments.as_slice() {
2594 let ident = segment.ident;
2595 if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
2596 return;
2597 }
2598
2599 let nss = match use_tree.kind {
2600 UseTreeKind::Simple(..) if rest.is_empty() => &[TypeNS, ValueNS][..],
2601 _ => &[TypeNS],
2602 };
2603 let report_error = |this: &Self, ns| {
2604 if this.should_report_errs() {
2605 let what = if ns == TypeNS { "type parameters" } else { "local variables" };
2606 this.r.dcx().emit_err(errors::ImportsCannotReferTo { span: ident.span, what });
2607 }
2608 };
2609
2610 for &ns in nss {
2611 match self.maybe_resolve_ident_in_lexical_scope(ident, ns) {
2612 Some(LexicalScopeBinding::Res(..)) => {
2613 report_error(self, ns);
2614 }
2615 Some(LexicalScopeBinding::Item(binding)) => {
2616 if let Some(LexicalScopeBinding::Res(..)) =
2617 self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding))
2618 {
2619 report_error(self, ns);
2620 }
2621 }
2622 None => {}
2623 }
2624 }
2625 } else if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
2626 for (use_tree, _) in items {
2627 self.future_proof_import(use_tree);
2628 }
2629 }
2630 }
2631
2632 fn resolve_item(&mut self, item: &'ast Item) {
2633 let mod_inner_docs =
2634 matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
2635 if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) {
2636 self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
2637 }
2638
2639 let name = item.ident.name;
2640 debug!("(resolving item) resolving {} ({:?})", name, item.kind);
2641
2642 let def_kind = self.r.local_def_kind(item.id);
2643 match item.kind {
2644 ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
2645 self.with_generic_param_rib(
2646 &generics.params,
2647 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2648 LifetimeRibKind::Generics {
2649 binder: item.id,
2650 kind: LifetimeBinderKind::Item,
2651 span: generics.span,
2652 },
2653 |this| visit::walk_item(this, item),
2654 );
2655 }
2656
2657 ItemKind::Fn(box Fn { ref generics, ref define_opaque, .. }) => {
2658 self.with_generic_param_rib(
2659 &generics.params,
2660 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2661 LifetimeRibKind::Generics {
2662 binder: item.id,
2663 kind: LifetimeBinderKind::Function,
2664 span: generics.span,
2665 },
2666 |this| visit::walk_item(this, item),
2667 );
2668
2669 for (id, path) in define_opaque.iter().flatten() {
2670 self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
2671 }
2672 }
2673
2674 ItemKind::Enum(_, ref generics)
2675 | ItemKind::Struct(_, ref generics)
2676 | ItemKind::Union(_, ref generics) => {
2677 self.resolve_adt(item, generics);
2678 }
2679
2680 ItemKind::Impl(box Impl {
2681 ref generics,
2682 ref of_trait,
2683 ref self_ty,
2684 items: ref impl_items,
2685 ..
2686 }) => {
2687 self.diag_metadata.current_impl_items = Some(impl_items);
2688 self.resolve_implementation(
2689 &item.attrs,
2690 generics,
2691 of_trait,
2692 self_ty,
2693 item.id,
2694 impl_items,
2695 );
2696 self.diag_metadata.current_impl_items = None;
2697 }
2698
2699 ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
2700 self.with_generic_param_rib(
2702 &generics.params,
2703 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2704 LifetimeRibKind::Generics {
2705 binder: item.id,
2706 kind: LifetimeBinderKind::Item,
2707 span: generics.span,
2708 },
2709 |this| {
2710 let local_def_id = this.r.local_def_id(item.id).to_def_id();
2711 this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
2712 this.visit_generics(generics);
2713 walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
2714 this.resolve_trait_items(items);
2715 });
2716 },
2717 );
2718 }
2719
2720 ItemKind::TraitAlias(ref generics, ref bounds) => {
2721 self.with_generic_param_rib(
2723 &generics.params,
2724 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2725 LifetimeRibKind::Generics {
2726 binder: item.id,
2727 kind: LifetimeBinderKind::Item,
2728 span: generics.span,
2729 },
2730 |this| {
2731 let local_def_id = this.r.local_def_id(item.id).to_def_id();
2732 this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
2733 this.visit_generics(generics);
2734 walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
2735 });
2736 },
2737 );
2738 }
2739
2740 ItemKind::Mod(..) => {
2741 self.with_scope(item.id, |this| {
2742 if mod_inner_docs {
2743 this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
2744 }
2745 let old_macro_rules = this.parent_scope.macro_rules;
2746 visit::walk_item(this, item);
2747 if item.attrs.iter().all(|attr| {
2750 !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
2751 }) {
2752 this.parent_scope.macro_rules = old_macro_rules;
2753 }
2754 });
2755 }
2756
2757 ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
2758 self.with_static_rib(def_kind, |this| {
2759 this.with_lifetime_rib(
2760 LifetimeRibKind::Elided(LifetimeRes::Static {
2761 suppress_elision_warning: true,
2762 }),
2763 |this| {
2764 this.visit_ty(ty);
2765 },
2766 );
2767 if let Some(expr) = expr {
2768 this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
2771 }
2772 });
2773 }
2774
2775 ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
2776 self.with_generic_param_rib(
2777 &generics.params,
2778 RibKind::Item(
2779 if self.r.tcx.features().generic_const_items() {
2780 HasGenericParams::Yes(generics.span)
2781 } else {
2782 HasGenericParams::No
2783 },
2784 def_kind,
2785 ),
2786 LifetimeRibKind::Generics {
2787 binder: item.id,
2788 kind: LifetimeBinderKind::ConstItem,
2789 span: generics.span,
2790 },
2791 |this| {
2792 this.visit_generics(generics);
2793
2794 this.with_lifetime_rib(
2795 LifetimeRibKind::Elided(LifetimeRes::Static {
2796 suppress_elision_warning: true,
2797 }),
2798 |this| this.visit_ty(ty),
2799 );
2800
2801 if let Some(expr) = expr {
2802 this.resolve_const_body(
2803 expr,
2804 Some((item.ident, ConstantItemKind::Const)),
2805 );
2806 }
2807 },
2808 );
2809 }
2810
2811 ItemKind::Use(ref use_tree) => {
2812 let maybe_exported = match use_tree.kind {
2813 UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
2814 UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis),
2815 };
2816 self.resolve_doc_links(&item.attrs, maybe_exported);
2817
2818 self.future_proof_import(use_tree);
2819 }
2820
2821 ItemKind::MacroDef(ref macro_def) => {
2822 if macro_def.macro_rules {
2825 let def_id = self.r.local_def_id(item.id);
2826 self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id];
2827 }
2828 }
2829
2830 ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) => {
2831 visit::walk_item(self, item);
2832 }
2833
2834 ItemKind::Delegation(ref delegation) => {
2835 let span = delegation.path.segments.last().unwrap().ident.span;
2836 self.with_generic_param_rib(
2837 &[],
2838 RibKind::Item(HasGenericParams::Yes(span), def_kind),
2839 LifetimeRibKind::Generics {
2840 binder: item.id,
2841 kind: LifetimeBinderKind::Function,
2842 span,
2843 },
2844 |this| this.resolve_delegation(delegation),
2845 );
2846 }
2847
2848 ItemKind::ExternCrate(..) => {}
2849
2850 ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
2851 panic!("unexpanded macro in resolve!")
2852 }
2853 }
2854 }
2855
2856 fn with_generic_param_rib<'c, F>(
2857 &'c mut self,
2858 params: &'c [GenericParam],
2859 kind: RibKind<'ra>,
2860 lifetime_kind: LifetimeRibKind,
2861 f: F,
2862 ) where
2863 F: FnOnce(&mut Self),
2864 {
2865 debug!("with_generic_param_rib");
2866 let LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind, .. } =
2867 lifetime_kind
2868 else {
2869 panic!()
2870 };
2871
2872 let mut function_type_rib = Rib::new(kind);
2873 let mut function_value_rib = Rib::new(kind);
2874 let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
2875
2876 if !params.is_empty() {
2878 let mut seen_bindings = FxHashMap::default();
2879 let mut seen_lifetimes = FxHashSet::default();
2881
2882 for ns in [ValueNS, TypeNS] {
2884 for parent_rib in self.ribs[ns].iter().rev() {
2885 if matches!(parent_rib.kind, RibKind::Module(..)) {
2888 break;
2889 }
2890
2891 #[allow(rustc::potential_query_instability)] seen_bindings
2893 .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
2894 }
2895 }
2896
2897 for rib in self.lifetime_ribs.iter().rev() {
2899 seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
2900 if let LifetimeRibKind::Item = rib.kind {
2901 break;
2902 }
2903 }
2904
2905 for param in params {
2906 let ident = param.ident.normalize_to_macros_2_0();
2907 debug!("with_generic_param_rib: {}", param.id);
2908
2909 if let GenericParamKind::Lifetime = param.kind
2910 && let Some(&original) = seen_lifetimes.get(&ident)
2911 {
2912 diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
2913 self.record_lifetime_param(param.id, LifetimeRes::Error);
2915 continue;
2916 }
2917
2918 match seen_bindings.entry(ident) {
2919 Entry::Occupied(entry) => {
2920 let span = *entry.get();
2921 let err = ResolutionError::NameAlreadyUsedInParameterList(ident, span);
2922 self.report_error(param.ident.span, err);
2923 let rib = match param.kind {
2924 GenericParamKind::Lifetime => {
2925 self.record_lifetime_param(param.id, LifetimeRes::Error);
2927 continue;
2928 }
2929 GenericParamKind::Type { .. } => &mut function_type_rib,
2930 GenericParamKind::Const { .. } => &mut function_value_rib,
2931 };
2932
2933 self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
2935 rib.bindings.insert(ident, Res::Err);
2936 continue;
2937 }
2938 Entry::Vacant(entry) => {
2939 entry.insert(param.ident.span);
2940 }
2941 }
2942
2943 if param.ident.name == kw::UnderscoreLifetime {
2944 self.r
2945 .dcx()
2946 .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
2947 self.record_lifetime_param(param.id, LifetimeRes::Error);
2949 continue;
2950 }
2951
2952 if param.ident.name == kw::StaticLifetime {
2953 self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
2954 span: param.ident.span,
2955 lifetime: param.ident,
2956 });
2957 self.record_lifetime_param(param.id, LifetimeRes::Error);
2959 continue;
2960 }
2961
2962 let def_id = self.r.local_def_id(param.id);
2963
2964 let (rib, def_kind) = match param.kind {
2966 GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
2967 GenericParamKind::Const { .. } => {
2968 (&mut function_value_rib, DefKind::ConstParam)
2969 }
2970 GenericParamKind::Lifetime => {
2971 let res = LifetimeRes::Param { param: def_id, binder };
2972 self.record_lifetime_param(param.id, res);
2973 function_lifetime_rib.bindings.insert(ident, (param.id, res));
2974 continue;
2975 }
2976 };
2977
2978 let res = match kind {
2979 RibKind::Item(..) | RibKind::AssocItem => {
2980 Res::Def(def_kind, def_id.to_def_id())
2981 }
2982 RibKind::Normal => {
2983 if self.r.tcx.features().non_lifetime_binders()
2986 && matches!(param.kind, GenericParamKind::Type { .. })
2987 {
2988 Res::Def(def_kind, def_id.to_def_id())
2989 } else {
2990 Res::Err
2991 }
2992 }
2993 _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
2994 };
2995 self.r.record_partial_res(param.id, PartialRes::new(res));
2996 rib.bindings.insert(ident, res);
2997 }
2998 }
2999
3000 self.lifetime_ribs.push(function_lifetime_rib);
3001 self.ribs[ValueNS].push(function_value_rib);
3002 self.ribs[TypeNS].push(function_type_rib);
3003
3004 f(self);
3005
3006 self.ribs[TypeNS].pop();
3007 self.ribs[ValueNS].pop();
3008 let function_lifetime_rib = self.lifetime_ribs.pop().unwrap();
3009
3010 if let Some(ref mut candidates) = self.lifetime_elision_candidates {
3012 for (_, res) in function_lifetime_rib.bindings.values() {
3013 candidates.retain(|(r, _)| r != res);
3014 }
3015 }
3016
3017 if let LifetimeBinderKind::BareFnType
3018 | LifetimeBinderKind::WhereBound
3019 | LifetimeBinderKind::Function
3020 | LifetimeBinderKind::ImplBlock = generics_kind
3021 {
3022 self.maybe_report_lifetime_uses(generics_span, params)
3023 }
3024 }
3025
3026 fn with_label_rib(&mut self, kind: RibKind<'ra>, f: impl FnOnce(&mut Self)) {
3027 self.label_ribs.push(Rib::new(kind));
3028 f(self);
3029 self.label_ribs.pop();
3030 }
3031
3032 fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) {
3033 let kind = RibKind::Item(HasGenericParams::No, def_kind);
3034 self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
3035 }
3036
3037 #[instrument(level = "debug", skip(self, f))]
3046 fn with_constant_rib(
3047 &mut self,
3048 is_repeat: IsRepeatExpr,
3049 may_use_generics: ConstantHasGenerics,
3050 item: Option<(Ident, ConstantItemKind)>,
3051 f: impl FnOnce(&mut Self),
3052 ) {
3053 let f = |this: &mut Self| {
3054 this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
3055 this.with_rib(
3056 TypeNS,
3057 RibKind::ConstantItem(
3058 may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
3059 item,
3060 ),
3061 |this| {
3062 this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
3063 },
3064 )
3065 })
3066 };
3067
3068 if let ConstantHasGenerics::No(cause) = may_use_generics {
3069 self.with_lifetime_rib(LifetimeRibKind::ConcreteAnonConst(cause), f)
3070 } else {
3071 f(self)
3072 }
3073 }
3074
3075 fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
3076 let previous_value =
3078 replace(&mut self.diag_metadata.current_self_type, Some(self_type.clone()));
3079 let result = f(self);
3080 self.diag_metadata.current_self_type = previous_value;
3081 result
3082 }
3083
3084 fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T {
3085 let previous_value = replace(&mut self.diag_metadata.current_self_item, Some(self_item.id));
3086 let result = f(self);
3087 self.diag_metadata.current_self_item = previous_value;
3088 result
3089 }
3090
3091 fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
3093 let trait_assoc_items =
3094 replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items));
3095
3096 let walk_assoc_item =
3097 |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| {
3098 this.with_generic_param_rib(
3099 &generics.params,
3100 RibKind::AssocItem,
3101 LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind },
3102 |this| visit::walk_assoc_item(this, item, AssocCtxt::Trait),
3103 );
3104 };
3105
3106 for item in trait_items {
3107 self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
3108 match &item.kind {
3109 AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
3110 self.with_generic_param_rib(
3111 &generics.params,
3112 RibKind::AssocItem,
3113 LifetimeRibKind::Generics {
3114 binder: item.id,
3115 span: generics.span,
3116 kind: LifetimeBinderKind::ConstItem,
3117 },
3118 |this| {
3119 this.with_lifetime_rib(
3120 LifetimeRibKind::StaticIfNoLifetimeInScope {
3121 lint_id: item.id,
3122 emit_lint: false,
3123 },
3124 |this| {
3125 this.visit_generics(generics);
3126 this.visit_ty(ty);
3127
3128 if let Some(expr) = expr {
3131 this.resolve_const_body(expr, None);
3137 }
3138 },
3139 )
3140 },
3141 );
3142 }
3143 AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
3144 walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
3145
3146 for (id, path) in define_opaque.iter().flatten() {
3147 self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
3148 }
3149 }
3150 AssocItemKind::Delegation(delegation) => {
3151 self.with_generic_param_rib(
3152 &[],
3153 RibKind::AssocItem,
3154 LifetimeRibKind::Generics {
3155 binder: item.id,
3156 kind: LifetimeBinderKind::Function,
3157 span: delegation.path.segments.last().unwrap().ident.span,
3158 },
3159 |this| this.resolve_delegation(delegation),
3160 );
3161 }
3162 AssocItemKind::Type(box TyAlias { generics, .. }) => self
3163 .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
3164 walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
3165 }),
3166 AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
3167 panic!("unexpanded macro in resolve!")
3168 }
3169 };
3170 }
3171
3172 self.diag_metadata.current_trait_assoc_items = trait_assoc_items;
3173 }
3174
3175 fn with_optional_trait_ref<T>(
3177 &mut self,
3178 opt_trait_ref: Option<&TraitRef>,
3179 self_type: &'ast Ty,
3180 f: impl FnOnce(&mut Self, Option<DefId>) -> T,
3181 ) -> T {
3182 let mut new_val = None;
3183 let mut new_id = None;
3184 if let Some(trait_ref) = opt_trait_ref {
3185 let path: Vec<_> = Segment::from_path(&trait_ref.path);
3186 self.diag_metadata.currently_processing_impl_trait =
3187 Some((trait_ref.clone(), self_type.clone()));
3188 let res = self.smart_resolve_path_fragment(
3189 &None,
3190 &path,
3191 PathSource::Trait(AliasPossibility::No),
3192 Finalize::new(trait_ref.ref_id, trait_ref.path.span),
3193 RecordPartialRes::Yes,
3194 None,
3195 );
3196 self.diag_metadata.currently_processing_impl_trait = None;
3197 if let Some(def_id) = res.expect_full_res().opt_def_id() {
3198 new_id = Some(def_id);
3199 new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
3200 }
3201 }
3202 let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
3203 let result = f(self, new_id);
3204 self.current_trait_ref = original_trait_ref;
3205 result
3206 }
3207
3208 fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) {
3209 let mut self_type_rib = Rib::new(RibKind::Normal);
3210
3211 self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
3213 self.ribs[ns].push(self_type_rib);
3214 f(self);
3215 self.ribs[ns].pop();
3216 }
3217
3218 fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) {
3219 self.with_self_rib_ns(TypeNS, self_res, f)
3220 }
3221
3222 fn resolve_implementation(
3223 &mut self,
3224 attrs: &[ast::Attribute],
3225 generics: &'ast Generics,
3226 opt_trait_reference: &'ast Option<TraitRef>,
3227 self_type: &'ast Ty,
3228 item_id: NodeId,
3229 impl_items: &'ast [P<AssocItem>],
3230 ) {
3231 debug!("resolve_implementation");
3232 self.with_generic_param_rib(
3234 &generics.params,
3235 RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)),
3236 LifetimeRibKind::Generics {
3237 span: generics.span,
3238 binder: item_id,
3239 kind: LifetimeBinderKind::ImplBlock,
3240 },
3241 |this| {
3242 this.with_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| {
3244 this.with_lifetime_rib(
3245 LifetimeRibKind::AnonymousCreateParameter {
3246 binder: item_id,
3247 report_in_path: true
3248 },
3249 |this| {
3250 this.with_optional_trait_ref(
3252 opt_trait_reference.as_ref(),
3253 self_type,
3254 |this, trait_id| {
3255 this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id));
3256
3257 let item_def_id = this.r.local_def_id(item_id);
3258
3259 if let Some(trait_id) = trait_id {
3261 this.r
3262 .trait_impls
3263 .entry(trait_id)
3264 .or_default()
3265 .push(item_def_id);
3266 }
3267
3268 let item_def_id = item_def_id.to_def_id();
3269 let res = Res::SelfTyAlias {
3270 alias_to: item_def_id,
3271 forbid_generic: false,
3272 is_trait_impl: trait_id.is_some()
3273 };
3274 this.with_self_rib(res, |this| {
3275 if let Some(trait_ref) = opt_trait_reference.as_ref() {
3276 visit::walk_trait_ref(this, trait_ref);
3278 }
3279 this.visit_ty(self_type);
3281 this.visit_generics(generics);
3283
3284 this.with_current_self_type(self_type, |this| {
3286 this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
3287 debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
3288 let mut seen_trait_items = Default::default();
3289 for item in impl_items {
3290 this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
3291 }
3292 });
3293 });
3294 });
3295 },
3296 )
3297 },
3298 );
3299 });
3300 },
3301 );
3302 }
3303
3304 fn resolve_impl_item(
3305 &mut self,
3306 item: &'ast AssocItem,
3307 seen_trait_items: &mut FxHashMap<DefId, Span>,
3308 trait_id: Option<DefId>,
3309 ) {
3310 use crate::ResolutionError::*;
3311 self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
3312 match &item.kind {
3313 AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
3314 debug!("resolve_implementation AssocItemKind::Const");
3315 self.with_generic_param_rib(
3316 &generics.params,
3317 RibKind::AssocItem,
3318 LifetimeRibKind::Generics {
3319 binder: item.id,
3320 span: generics.span,
3321 kind: LifetimeBinderKind::ConstItem,
3322 },
3323 |this| {
3324 this.with_lifetime_rib(
3325 LifetimeRibKind::StaticIfNoLifetimeInScope {
3326 lint_id: item.id,
3327 emit_lint: true,
3329 },
3330 |this| {
3331 this.check_trait_item(
3334 item.id,
3335 item.ident,
3336 &item.kind,
3337 ValueNS,
3338 item.span,
3339 seen_trait_items,
3340 |i, s, c| ConstNotMemberOfTrait(i, s, c),
3341 );
3342
3343 this.visit_generics(generics);
3344 this.visit_ty(ty);
3345 if let Some(expr) = expr {
3346 this.resolve_const_body(expr, None);
3352 }
3353 },
3354 );
3355 },
3356 );
3357 }
3358 AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
3359 debug!("resolve_implementation AssocItemKind::Fn");
3360 self.with_generic_param_rib(
3362 &generics.params,
3363 RibKind::AssocItem,
3364 LifetimeRibKind::Generics {
3365 binder: item.id,
3366 span: generics.span,
3367 kind: LifetimeBinderKind::Function,
3368 },
3369 |this| {
3370 this.check_trait_item(
3373 item.id,
3374 item.ident,
3375 &item.kind,
3376 ValueNS,
3377 item.span,
3378 seen_trait_items,
3379 |i, s, c| MethodNotMemberOfTrait(i, s, c),
3380 );
3381
3382 visit::walk_assoc_item(this, item, AssocCtxt::Impl)
3383 },
3384 );
3385
3386 for (id, path) in define_opaque.iter().flatten() {
3387 self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
3388 }
3389 }
3390 AssocItemKind::Type(box TyAlias { generics, .. }) => {
3391 self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
3392 debug!("resolve_implementation AssocItemKind::Type");
3393 self.with_generic_param_rib(
3395 &generics.params,
3396 RibKind::AssocItem,
3397 LifetimeRibKind::Generics {
3398 binder: item.id,
3399 span: generics.span,
3400 kind: LifetimeBinderKind::Item,
3401 },
3402 |this| {
3403 this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
3404 this.check_trait_item(
3407 item.id,
3408 item.ident,
3409 &item.kind,
3410 TypeNS,
3411 item.span,
3412 seen_trait_items,
3413 |i, s, c| TypeNotMemberOfTrait(i, s, c),
3414 );
3415
3416 visit::walk_assoc_item(this, item, AssocCtxt::Impl)
3417 });
3418 },
3419 );
3420 self.diag_metadata.in_non_gat_assoc_type = None;
3421 }
3422 AssocItemKind::Delegation(box delegation) => {
3423 debug!("resolve_implementation AssocItemKind::Delegation");
3424 self.with_generic_param_rib(
3425 &[],
3426 RibKind::AssocItem,
3427 LifetimeRibKind::Generics {
3428 binder: item.id,
3429 kind: LifetimeBinderKind::Function,
3430 span: delegation.path.segments.last().unwrap().ident.span,
3431 },
3432 |this| {
3433 this.check_trait_item(
3434 item.id,
3435 item.ident,
3436 &item.kind,
3437 ValueNS,
3438 item.span,
3439 seen_trait_items,
3440 |i, s, c| MethodNotMemberOfTrait(i, s, c),
3441 );
3442
3443 this.resolve_delegation(delegation)
3444 },
3445 );
3446 }
3447 AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
3448 panic!("unexpanded macro in resolve!")
3449 }
3450 }
3451 }
3452
3453 fn check_trait_item<F>(
3454 &mut self,
3455 id: NodeId,
3456 mut ident: Ident,
3457 kind: &AssocItemKind,
3458 ns: Namespace,
3459 span: Span,
3460 seen_trait_items: &mut FxHashMap<DefId, Span>,
3461 err: F,
3462 ) where
3463 F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'ra>,
3464 {
3465 let Some((module, _)) = self.current_trait_ref else {
3467 return;
3468 };
3469 ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
3470 let key = BindingKey::new(ident, ns);
3471 let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
3472 debug!(?binding);
3473 if binding.is_none() {
3474 let ns = match ns {
3477 ValueNS => TypeNS,
3478 TypeNS => ValueNS,
3479 _ => ns,
3480 };
3481 let key = BindingKey::new(ident, ns);
3482 binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
3483 debug!(?binding);
3484 }
3485
3486 let feed_visibility = |this: &mut Self, def_id| {
3487 let vis = this.r.tcx.visibility(def_id);
3488 let vis = if vis.is_visible_locally() {
3489 vis.expect_local()
3490 } else {
3491 this.r.dcx().span_delayed_bug(
3492 span,
3493 "error should be emitted when an unexpected trait item is used",
3494 );
3495 rustc_middle::ty::Visibility::Public
3496 };
3497 this.r.feed_visibility(this.r.feed(id), vis);
3498 };
3499
3500 let Some(binding) = binding else {
3501 let candidate = self.find_similarly_named_assoc_item(ident.name, kind);
3503 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
3504 let path_names = path_names_to_string(path);
3505 self.report_error(span, err(ident, path_names, candidate));
3506 feed_visibility(self, module.def_id());
3507 return;
3508 };
3509
3510 let res = binding.res();
3511 let Res::Def(def_kind, id_in_trait) = res else { bug!() };
3512 feed_visibility(self, id_in_trait);
3513
3514 match seen_trait_items.entry(id_in_trait) {
3515 Entry::Occupied(entry) => {
3516 self.report_error(
3517 span,
3518 ResolutionError::TraitImplDuplicate {
3519 name: ident,
3520 old_span: *entry.get(),
3521 trait_item_span: binding.span,
3522 },
3523 );
3524 return;
3525 }
3526 Entry::Vacant(entry) => {
3527 entry.insert(span);
3528 }
3529 };
3530
3531 match (def_kind, kind) {
3532 (DefKind::AssocTy, AssocItemKind::Type(..))
3533 | (DefKind::AssocFn, AssocItemKind::Fn(..))
3534 | (DefKind::AssocConst, AssocItemKind::Const(..))
3535 | (DefKind::AssocFn, AssocItemKind::Delegation(..)) => {
3536 self.r.record_partial_res(id, PartialRes::new(res));
3537 return;
3538 }
3539 _ => {}
3540 }
3541
3542 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
3544 let (code, kind) = match kind {
3545 AssocItemKind::Const(..) => (E0323, "const"),
3546 AssocItemKind::Fn(..) => (E0324, "method"),
3547 AssocItemKind::Type(..) => (E0325, "type"),
3548 AssocItemKind::Delegation(..) => (E0324, "method"),
3549 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
3550 span_bug!(span, "unexpanded macro")
3551 }
3552 };
3553 let trait_path = path_names_to_string(path);
3554 self.report_error(
3555 span,
3556 ResolutionError::TraitImplMismatch {
3557 name: ident,
3558 kind,
3559 code,
3560 trait_path,
3561 trait_item_span: binding.span,
3562 },
3563 );
3564 }
3565
3566 fn resolve_const_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) {
3567 self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
3568 this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
3569 this.visit_expr(expr)
3570 });
3571 })
3572 }
3573
3574 fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
3575 self.smart_resolve_path(
3576 delegation.id,
3577 &delegation.qself,
3578 &delegation.path,
3579 PathSource::Delegation,
3580 );
3581 if let Some(qself) = &delegation.qself {
3582 self.visit_ty(&qself.ty);
3583 }
3584 self.visit_path(&delegation.path, delegation.id);
3585 let Some(body) = &delegation.body else { return };
3586 self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
3587 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3589
3590 let span = delegation.path.segments.last().unwrap().ident.span;
3591 this.fresh_binding(
3592 Ident::new(kw::SelfLower, span),
3593 delegation.id,
3594 PatternSource::FnParam,
3595 &mut bindings,
3596 );
3597 this.visit_block(body);
3598 });
3599 }
3600
3601 fn resolve_params(&mut self, params: &'ast [Param]) {
3602 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3603 self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
3604 for Param { pat, .. } in params {
3605 this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
3606 }
3607 });
3608 for Param { ty, .. } in params {
3609 self.visit_ty(ty);
3610 }
3611 }
3612
3613 fn resolve_local(&mut self, local: &'ast Local) {
3614 debug!("resolving local ({:?})", local);
3615 visit_opt!(self, visit_ty, &local.ty);
3617
3618 if let Some((init, els)) = local.kind.init_else_opt() {
3620 self.visit_expr(init);
3621
3622 if let Some(els) = els {
3624 self.visit_block(els);
3625 }
3626 }
3627
3628 self.resolve_pattern_top(&local.pat, PatternSource::Let);
3630 }
3631
3632 fn compute_and_check_binding_map(
3652 &mut self,
3653 pat: &Pat,
3654 ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
3655 let mut binding_map = FxIndexMap::default();
3656 let mut is_never_pat = false;
3657
3658 pat.walk(&mut |pat| {
3659 match pat.kind {
3660 PatKind::Ident(annotation, ident, ref sub_pat)
3661 if sub_pat.is_some() || self.is_base_res_local(pat.id) =>
3662 {
3663 binding_map.insert(ident, BindingInfo { span: ident.span, annotation });
3664 }
3665 PatKind::Or(ref ps) => {
3666 match self.compute_and_check_or_pat_binding_map(ps) {
3669 Ok(bm) => binding_map.extend(bm),
3670 Err(IsNeverPattern) => is_never_pat = true,
3671 }
3672 return false;
3673 }
3674 PatKind::Never => is_never_pat = true,
3675 _ => {}
3676 }
3677
3678 true
3679 });
3680
3681 if is_never_pat {
3682 for (_, binding) in binding_map {
3683 self.report_error(binding.span, ResolutionError::BindingInNeverPattern);
3684 }
3685 Err(IsNeverPattern)
3686 } else {
3687 Ok(binding_map)
3688 }
3689 }
3690
3691 fn is_base_res_local(&self, nid: NodeId) -> bool {
3692 matches!(
3693 self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()),
3694 Some(Res::Local(..))
3695 )
3696 }
3697
3698 fn compute_and_check_or_pat_binding_map(
3718 &mut self,
3719 pats: &[P<Pat>],
3720 ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
3721 let mut missing_vars = FxIndexMap::default();
3722 let mut inconsistent_vars = FxIndexMap::default();
3723
3724 let not_never_pats = pats
3726 .iter()
3727 .filter_map(|pat| {
3728 let binding_map = self.compute_and_check_binding_map(pat).ok()?;
3729 Some((binding_map, pat))
3730 })
3731 .collect::<Vec<_>>();
3732
3733 for (map_outer, pat_outer) in not_never_pats.iter() {
3735 let inners = not_never_pats
3737 .iter()
3738 .filter(|(_, pat)| pat.id != pat_outer.id)
3739 .flat_map(|(map, _)| map);
3740
3741 for (&name, binding_inner) in inners {
3742 match map_outer.get(&name) {
3743 None => {
3744 let binding_error =
3746 missing_vars.entry(name).or_insert_with(|| BindingError {
3747 name,
3748 origin: BTreeSet::new(),
3749 target: BTreeSet::new(),
3750 could_be_path: name.as_str().starts_with(char::is_uppercase),
3751 });
3752 binding_error.origin.insert(binding_inner.span);
3753 binding_error.target.insert(pat_outer.span);
3754 }
3755 Some(binding_outer) => {
3756 if binding_outer.annotation != binding_inner.annotation {
3757 inconsistent_vars
3759 .entry(name)
3760 .or_insert((binding_inner.span, binding_outer.span));
3761 }
3762 }
3763 }
3764 }
3765 }
3766
3767 for (name, mut v) in missing_vars {
3769 if inconsistent_vars.contains_key(&name) {
3770 v.could_be_path = false;
3771 }
3772 self.report_error(
3773 *v.origin.iter().next().unwrap(),
3774 ResolutionError::VariableNotBoundInPattern(v, self.parent_scope),
3775 );
3776 }
3777
3778 for (name, v) in inconsistent_vars {
3780 self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
3781 }
3782
3783 if not_never_pats.is_empty() {
3785 Err(IsNeverPattern)
3787 } else {
3788 let mut binding_map = FxIndexMap::default();
3789 for (bm, _) in not_never_pats {
3790 binding_map.extend(bm);
3791 }
3792 Ok(binding_map)
3793 }
3794 }
3795
3796 fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
3798 let mut is_or_or_never = false;
3799 pat.walk(&mut |pat| match pat.kind {
3800 PatKind::Or(..) | PatKind::Never => {
3801 is_or_or_never = true;
3802 false
3803 }
3804 _ => true,
3805 });
3806 if is_or_or_never {
3807 let _ = self.compute_and_check_binding_map(pat);
3808 }
3809 }
3810
3811 fn resolve_arm(&mut self, arm: &'ast Arm) {
3812 self.with_rib(ValueNS, RibKind::Normal, |this| {
3813 this.resolve_pattern_top(&arm.pat, PatternSource::Match);
3814 visit_opt!(this, visit_expr, &arm.guard);
3815 visit_opt!(this, visit_expr, &arm.body);
3816 });
3817 }
3818
3819 fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
3821 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3822 self.resolve_pattern(pat, pat_src, &mut bindings);
3823 }
3824
3825 fn resolve_pattern(
3826 &mut self,
3827 pat: &'ast Pat,
3828 pat_src: PatternSource,
3829 bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
3830 ) {
3831 visit::walk_pat(self, pat);
3835 self.resolve_pattern_inner(pat, pat_src, bindings);
3836 self.check_consistent_bindings(pat);
3838 }
3839
3840 #[tracing::instrument(skip(self, bindings), level = "debug")]
3860 fn resolve_pattern_inner(
3861 &mut self,
3862 pat: &Pat,
3863 pat_src: PatternSource,
3864 bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
3865 ) {
3866 pat.walk(&mut |pat| {
3868 match pat.kind {
3869 PatKind::Ident(bmode, ident, ref sub) => {
3870 let has_sub = sub.is_some();
3873 let res = self
3874 .try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
3875 .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3876 self.r.record_partial_res(pat.id, PartialRes::new(res));
3877 self.r.record_pat_span(pat.id, pat.span);
3878 }
3879 PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
3880 self.smart_resolve_path(
3881 pat.id,
3882 qself,
3883 path,
3884 PathSource::TupleStruct(
3885 pat.span,
3886 self.r.arenas.alloc_pattern_spans(sub_patterns.iter().map(|p| p.span)),
3887 ),
3888 );
3889 }
3890 PatKind::Path(ref qself, ref path) => {
3891 self.smart_resolve_path(pat.id, qself, path, PathSource::Pat);
3892 }
3893 PatKind::Struct(ref qself, ref path, ref _fields, ref rest) => {
3894 self.smart_resolve_path(pat.id, qself, path, PathSource::Struct);
3895 self.record_patterns_with_skipped_bindings(pat, rest);
3896 }
3897 PatKind::Or(ref ps) => {
3898 bindings.push((PatBoundCtx::Or, Default::default()));
3902 for p in ps {
3903 bindings.push((PatBoundCtx::Product, Default::default()));
3907 self.resolve_pattern_inner(p, pat_src, bindings);
3908 let collected = bindings.pop().unwrap().1;
3911 bindings.last_mut().unwrap().1.extend(collected);
3912 }
3913 let collected = bindings.pop().unwrap().1;
3917 bindings.last_mut().unwrap().1.extend(collected);
3918
3919 return false;
3921 }
3922 _ => {}
3923 }
3924 true
3925 });
3926 }
3927
3928 fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) {
3929 match rest {
3930 ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) => {
3931 if let Some(partial_res) = self.r.partial_res_map.get(&pat.id)
3933 && let Some(res) = partial_res.full_res()
3934 && let Some(def_id) = res.opt_def_id()
3935 {
3936 self.ribs[ValueNS]
3937 .last_mut()
3938 .unwrap()
3939 .patterns_with_skipped_bindings
3940 .entry(def_id)
3941 .or_default()
3942 .push((
3943 pat.span,
3944 match rest {
3945 ast::PatFieldsRest::Recovered(guar) => Err(*guar),
3946 _ => Ok(()),
3947 },
3948 ));
3949 }
3950 }
3951 ast::PatFieldsRest::None => {}
3952 }
3953 }
3954
3955 fn fresh_binding(
3956 &mut self,
3957 ident: Ident,
3958 pat_id: NodeId,
3959 pat_src: PatternSource,
3960 bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
3961 ) -> Res {
3962 let ident = ident.normalize_to_macro_rules();
3966
3967 let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
3968 let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product);
3970 let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or);
3973
3974 if already_bound_and {
3975 use ResolutionError::*;
3977 let error = match pat_src {
3978 PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList,
3980 _ => IdentifierBoundMoreThanOnceInSamePattern,
3982 };
3983 self.report_error(ident.span, error(ident));
3984 }
3985
3986 let ident_valid = ident.name != kw::Empty;
3988 if ident_valid {
3989 bindings.last_mut().unwrap().1.insert(ident);
3990 }
3991
3992 if already_bound_or {
3993 self.innermost_rib_bindings(ValueNS)[&ident]
3996 } else {
3997 let res = Res::Local(pat_id);
3998 if ident_valid {
3999 self.innermost_rib_bindings(ValueNS).insert(ident, res);
4001 }
4002 res
4003 }
4004 }
4005
4006 fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap<Ident, Res> {
4007 &mut self.ribs[ns].last_mut().unwrap().bindings
4008 }
4009
4010 fn try_resolve_as_non_binding(
4011 &mut self,
4012 pat_src: PatternSource,
4013 ann: BindingMode,
4014 ident: Ident,
4015 has_sub: bool,
4016 ) -> Option<Res> {
4017 let is_syntactic_ambiguity = !has_sub && ann == BindingMode::NONE;
4021
4022 let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
4023 let (res, binding) = match ls_binding {
4024 LexicalScopeBinding::Item(binding)
4025 if is_syntactic_ambiguity && binding.is_ambiguity_recursive() =>
4026 {
4027 self.r.record_use(ident, binding, Used::Other);
4032 return None;
4033 }
4034 LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
4035 LexicalScopeBinding::Res(res) => (res, None),
4036 };
4037
4038 match res {
4039 Res::SelfCtor(_) | Res::Def(
4041 DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst | DefKind::ConstParam,
4042 _,
4043 ) if is_syntactic_ambiguity => {
4044 if let Some(binding) = binding {
4046 self.r.record_use(ident, binding, Used::Other);
4047 }
4048 Some(res)
4049 }
4050 Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::AssocConst | DefKind::Static { .. }, _) => {
4051 let binding = binding.expect("no binding for a ctor or static");
4057 self.report_error(
4058 ident.span,
4059 ResolutionError::BindingShadowsSomethingUnacceptable {
4060 shadowing_binding: pat_src,
4061 name: ident.name,
4062 participle: if binding.is_import() { "imported" } else { "defined" },
4063 article: binding.res().article(),
4064 shadowed_binding: binding.res(),
4065 shadowed_binding_span: binding.span,
4066 },
4067 );
4068 None
4069 }
4070 Res::Def(DefKind::ConstParam, def_id) => {
4071 self.report_error(
4074 ident.span,
4075 ResolutionError::BindingShadowsSomethingUnacceptable {
4076 shadowing_binding: pat_src,
4077 name: ident.name,
4078 participle: "defined",
4079 article: res.article(),
4080 shadowed_binding: res,
4081 shadowed_binding_span: self.r.def_span(def_id),
4082 }
4083 );
4084 None
4085 }
4086 Res::Def(DefKind::Fn | DefKind::AssocFn, _) | Res::Local(..) | Res::Err => {
4087 None
4089 }
4090 Res::SelfCtor(_) => {
4091 self.r.dcx().span_delayed_bug(
4094 ident.span,
4095 "unexpected `SelfCtor` in pattern, expected identifier"
4096 );
4097 None
4098 }
4099 _ => span_bug!(
4100 ident.span,
4101 "unexpected resolution for an identifier in pattern: {:?}",
4102 res,
4103 ),
4104 }
4105 }
4106
4107 fn smart_resolve_path(
4113 &mut self,
4114 id: NodeId,
4115 qself: &Option<P<QSelf>>,
4116 path: &Path,
4117 source: PathSource<'ast>,
4118 ) {
4119 self.smart_resolve_path_fragment(
4120 qself,
4121 &Segment::from_path(path),
4122 source,
4123 Finalize::new(id, path.span),
4124 RecordPartialRes::Yes,
4125 None,
4126 );
4127 }
4128
4129 #[instrument(level = "debug", skip(self))]
4130 fn smart_resolve_path_fragment(
4131 &mut self,
4132 qself: &Option<P<QSelf>>,
4133 path: &[Segment],
4134 source: PathSource<'ast>,
4135 finalize: Finalize,
4136 record_partial_res: RecordPartialRes,
4137 parent_qself: Option<&QSelf>,
4138 ) -> PartialRes {
4139 let ns = source.namespace();
4140
4141 let Finalize { node_id, path_span, .. } = finalize;
4142 let report_errors = |this: &mut Self, res: Option<Res>| {
4143 if this.should_report_errs() {
4144 let (err, candidates) = this.smart_resolve_report_errors(
4145 path,
4146 None,
4147 path_span,
4148 source,
4149 res,
4150 parent_qself,
4151 );
4152
4153 let def_id = this.parent_scope.module.nearest_parent_mod();
4154 let instead = res.is_some();
4155 let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
4156 && path[0].ident.span.lo() == end.span.lo()
4157 && !matches!(start.kind, ExprKind::Lit(_))
4158 {
4159 let mut sugg = ".";
4160 let mut span = start.span.between(end.span);
4161 if span.lo() + BytePos(2) == span.hi() {
4162 span = span.with_lo(span.lo() + BytePos(1));
4165 sugg = "";
4166 }
4167 Some((
4168 span,
4169 "you might have meant to write `.` instead of `..`",
4170 sugg.to_string(),
4171 Applicability::MaybeIncorrect,
4172 ))
4173 } else if res.is_none()
4174 && let PathSource::Type
4175 | PathSource::Expr(_)
4176 | PathSource::PreciseCapturingArg(..) = source
4177 {
4178 this.suggest_adding_generic_parameter(path, source)
4179 } else {
4180 None
4181 };
4182
4183 let ue = UseError {
4184 err,
4185 candidates,
4186 def_id,
4187 instead,
4188 suggestion,
4189 path: path.into(),
4190 is_call: source.is_call(),
4191 };
4192
4193 this.r.use_injections.push(ue);
4194 }
4195
4196 PartialRes::new(Res::Err)
4197 };
4198
4199 let report_errors_for_call =
4205 |this: &mut Self, parent_err: Spanned<ResolutionError<'ra>>| {
4206 let (following_seg, prefix_path) = match path.split_last() {
4210 Some((last, path)) if !path.is_empty() => (Some(last), path),
4211 _ => return Some(parent_err),
4212 };
4213
4214 let (mut err, candidates) = this.smart_resolve_report_errors(
4215 prefix_path,
4216 following_seg,
4217 path_span,
4218 PathSource::Type,
4219 None,
4220 parent_qself,
4221 );
4222
4223 let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node);
4238
4239 err.messages = take(&mut parent_err.messages);
4241 err.code = take(&mut parent_err.code);
4242 swap(&mut err.span, &mut parent_err.span);
4243 err.children = take(&mut parent_err.children);
4244 err.sort_span = parent_err.sort_span;
4245 err.is_lint = parent_err.is_lint.clone();
4246
4247 match &mut err.suggestions {
4249 Suggestions::Enabled(typo_suggestions) => match &mut parent_err.suggestions {
4250 Suggestions::Enabled(parent_suggestions) => {
4251 typo_suggestions.append(parent_suggestions)
4253 }
4254 Suggestions::Sealed(_) | Suggestions::Disabled => {
4255 err.suggestions = std::mem::take(&mut parent_err.suggestions);
4260 }
4261 },
4262 Suggestions::Sealed(_) | Suggestions::Disabled => (),
4263 }
4264
4265 parent_err.cancel();
4266
4267 let def_id = this.parent_scope.module.nearest_parent_mod();
4268
4269 if this.should_report_errs() {
4270 if candidates.is_empty() {
4271 if path.len() == 2
4272 && let [segment] = prefix_path
4273 {
4274 err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod);
4280 } else {
4281 err.emit();
4286 }
4287 } else {
4288 this.r.use_injections.push(UseError {
4290 err,
4291 candidates,
4292 def_id,
4293 instead: false,
4294 suggestion: None,
4295 path: prefix_path.into(),
4296 is_call: source.is_call(),
4297 });
4298 }
4299 } else {
4300 err.cancel();
4301 }
4302
4303 None
4306 };
4307
4308 let partial_res = match self.resolve_qpath_anywhere(
4309 qself,
4310 path,
4311 ns,
4312 path_span,
4313 source.defer_to_typeck(),
4314 finalize,
4315 ) {
4316 Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
4317 if let Some(items) = self.diag_metadata.current_trait_assoc_items
4319 && let [Segment { ident, .. }] = path
4320 && items.iter().any(|item| {
4321 item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
4322 })
4323 {
4324 let mut diag = self.r.tcx.dcx().struct_allow("");
4325 diag.span_suggestion_verbose(
4326 path_span.shrink_to_lo(),
4327 "there is an associated type with the same name",
4328 "Self::",
4329 Applicability::MaybeIncorrect,
4330 );
4331 diag.stash(path_span, StashKey::AssociatedTypeSuggestion);
4332 }
4333
4334 if source.is_expected(res) || res == Res::Err {
4335 partial_res
4336 } else {
4337 report_errors(self, Some(res))
4338 }
4339 }
4340
4341 Ok(Some(partial_res)) if source.defer_to_typeck() => {
4342 if ns == ValueNS {
4346 let item_name = path.last().unwrap().ident;
4347 let traits = self.traits_in_scope(item_name, ns);
4348 self.r.trait_map.insert(node_id, traits);
4349 }
4350
4351 if PrimTy::from_name(path[0].ident.name).is_some() {
4352 let mut std_path = Vec::with_capacity(1 + path.len());
4353
4354 std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std)));
4355 std_path.extend(path);
4356 if let PathResult::Module(_) | PathResult::NonModule(_) =
4357 self.resolve_path(&std_path, Some(ns), None)
4358 {
4359 let item_span =
4361 path.iter().last().map_or(path_span, |segment| segment.ident.span);
4362
4363 self.r.confused_type_with_std_module.insert(item_span, path_span);
4364 self.r.confused_type_with_std_module.insert(path_span, path_span);
4365 }
4366 }
4367
4368 partial_res
4369 }
4370
4371 Err(err) => {
4372 if let Some(err) = report_errors_for_call(self, err) {
4373 self.report_error(err.span, err.node);
4374 }
4375
4376 PartialRes::new(Res::Err)
4377 }
4378
4379 _ => report_errors(self, None),
4380 };
4381
4382 if record_partial_res == RecordPartialRes::Yes {
4383 self.r.record_partial_res(node_id, partial_res);
4385 self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span);
4386 self.lint_unused_qualifications(path, ns, finalize);
4387 }
4388
4389 partial_res
4390 }
4391
4392 fn self_type_is_available(&mut self) -> bool {
4393 let binding = self
4394 .maybe_resolve_ident_in_lexical_scope(Ident::with_dummy_span(kw::SelfUpper), TypeNS);
4395 if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
4396 }
4397
4398 fn self_value_is_available(&mut self, self_span: Span) -> bool {
4399 let ident = Ident::new(kw::SelfLower, self_span);
4400 let binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS);
4401 if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
4402 }
4403
4404 fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'ra>) {
4408 if self.should_report_errs() {
4409 self.r.report_error(span, resolution_error);
4410 }
4411 }
4412
4413 #[inline]
4414 fn should_report_errs(&self) -> bool {
4418 !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body)
4419 && !self.r.glob_error.is_some()
4420 }
4421
4422 fn resolve_qpath_anywhere(
4424 &mut self,
4425 qself: &Option<P<QSelf>>,
4426 path: &[Segment],
4427 primary_ns: Namespace,
4428 span: Span,
4429 defer_to_typeck: bool,
4430 finalize: Finalize,
4431 ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
4432 let mut fin_res = None;
4433
4434 for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() {
4435 if i == 0 || ns != primary_ns {
4436 match self.resolve_qpath(qself, path, ns, finalize)? {
4437 Some(partial_res)
4438 if partial_res.unresolved_segments() == 0 || defer_to_typeck =>
4439 {
4440 return Ok(Some(partial_res));
4441 }
4442 partial_res => {
4443 if fin_res.is_none() {
4444 fin_res = partial_res;
4445 }
4446 }
4447 }
4448 }
4449 }
4450
4451 assert!(primary_ns != MacroNS);
4452
4453 if qself.is_none() {
4454 let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
4455 let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
4456 if let Ok((_, res)) =
4457 self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None)
4458 {
4459 return Ok(Some(PartialRes::new(res)));
4460 }
4461 }
4462
4463 Ok(fin_res)
4464 }
4465
4466 fn resolve_qpath(
4468 &mut self,
4469 qself: &Option<P<QSelf>>,
4470 path: &[Segment],
4471 ns: Namespace,
4472 finalize: Finalize,
4473 ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
4474 debug!(
4475 "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})",
4476 qself, path, ns, finalize,
4477 );
4478
4479 if let Some(qself) = qself {
4480 if qself.position == 0 {
4481 return Ok(Some(PartialRes::with_unresolved_segments(
4485 Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()),
4486 path.len(),
4487 )));
4488 }
4489
4490 let num_privacy_errors = self.r.privacy_errors.len();
4491 let trait_res = self.smart_resolve_path_fragment(
4493 &None,
4494 &path[..qself.position],
4495 PathSource::Trait(AliasPossibility::No),
4496 Finalize::new(finalize.node_id, qself.path_span),
4497 RecordPartialRes::No,
4498 Some(&qself),
4499 );
4500
4501 if trait_res.expect_full_res() == Res::Err {
4502 return Ok(Some(trait_res));
4503 }
4504
4505 self.r.privacy_errors.truncate(num_privacy_errors);
4508
4509 let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
4517 let partial_res = self.smart_resolve_path_fragment(
4518 &None,
4519 &path[..=qself.position],
4520 PathSource::TraitItem(ns),
4521 Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
4522 RecordPartialRes::No,
4523 Some(&qself),
4524 );
4525
4526 return Ok(Some(PartialRes::with_unresolved_segments(
4530 partial_res.base_res(),
4531 partial_res.unresolved_segments() + path.len() - qself.position - 1,
4532 )));
4533 }
4534
4535 let result = match self.resolve_path(path, Some(ns), Some(finalize)) {
4536 PathResult::NonModule(path_res) => path_res,
4537 PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
4538 PartialRes::new(module.res().unwrap())
4539 }
4540 PathResult::Failed { error_implied_by_parse_error: true, .. } => {
4544 PartialRes::new(Res::Err)
4545 }
4546 PathResult::Module(ModuleOrUniformRoot::Module(_)) | PathResult::Failed { .. }
4559 if (ns == TypeNS || path.len() > 1)
4560 && PrimTy::from_name(path[0].ident.name).is_some() =>
4561 {
4562 let prim = PrimTy::from_name(path[0].ident.name).unwrap();
4563 let tcx = self.r.tcx();
4564
4565 let gate_err_sym_msg = match prim {
4566 PrimTy::Float(FloatTy::F16) if !tcx.features().f16() => {
4567 Some((sym::f16, "the type `f16` is unstable"))
4568 }
4569 PrimTy::Float(FloatTy::F128) if !tcx.features().f128() => {
4570 Some((sym::f128, "the type `f128` is unstable"))
4571 }
4572 _ => None,
4573 };
4574
4575 if let Some((sym, msg)) = gate_err_sym_msg {
4576 let span = path[0].ident.span;
4577 if !span.allows_unstable(sym) {
4578 feature_err(tcx.sess, sym, span, msg).emit();
4579 }
4580 };
4581
4582 PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
4583 }
4584 PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
4585 PartialRes::new(module.res().unwrap())
4586 }
4587 PathResult::Failed {
4588 is_error_from_last_segment: false,
4589 span,
4590 label,
4591 suggestion,
4592 module,
4593 segment_name,
4594 error_implied_by_parse_error: _,
4595 } => {
4596 return Err(respan(
4597 span,
4598 ResolutionError::FailedToResolve {
4599 segment: Some(segment_name),
4600 label,
4601 suggestion,
4602 module,
4603 },
4604 ));
4605 }
4606 PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None),
4607 PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"),
4608 };
4609
4610 Ok(Some(result))
4611 }
4612
4613 fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) {
4614 if let Some(label) = label {
4615 if label.ident.as_str().as_bytes()[1] != b'_' {
4616 self.diag_metadata.unused_labels.insert(id, label.ident.span);
4617 }
4618
4619 if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
4620 diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident)
4621 }
4622
4623 self.with_label_rib(RibKind::Normal, |this| {
4624 let ident = label.ident.normalize_to_macro_rules();
4625 this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
4626 f(this);
4627 });
4628 } else {
4629 f(self);
4630 }
4631 }
4632
4633 fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &'ast Block) {
4634 self.with_resolved_label(label, id, |this| this.visit_block(block));
4635 }
4636
4637 fn resolve_block(&mut self, block: &'ast Block) {
4638 debug!("(resolving block) entering block");
4639 let orig_module = self.parent_scope.module;
4641 let anonymous_module = self.r.block_map.get(&block.id).cloned(); let mut num_macro_definition_ribs = 0;
4644 if let Some(anonymous_module) = anonymous_module {
4645 debug!("(resolving block) found anonymous module, moving down");
4646 self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module)));
4647 self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module)));
4648 self.parent_scope.module = anonymous_module;
4649 } else {
4650 self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
4651 }
4652
4653 let prev = self.diag_metadata.current_block_could_be_bare_struct_literal.take();
4654 if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
4655 (block.could_be_bare_literal, &block.stmts[..])
4656 && let ExprKind::Type(..) = expr.kind
4657 {
4658 self.diag_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
4659 }
4660 for stmt in &block.stmts {
4662 if let StmtKind::Item(ref item) = stmt.kind
4663 && let ItemKind::MacroDef(..) = item.kind
4664 {
4665 num_macro_definition_ribs += 1;
4666 let res = self.r.local_def_id(item.id).to_def_id();
4667 self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res)));
4668 self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res)));
4669 }
4670
4671 self.visit_stmt(stmt);
4672 }
4673 self.diag_metadata.current_block_could_be_bare_struct_literal = prev;
4674
4675 self.parent_scope.module = orig_module;
4677 for _ in 0..num_macro_definition_ribs {
4678 self.ribs[ValueNS].pop();
4679 self.label_ribs.pop();
4680 }
4681 self.last_block_rib = self.ribs[ValueNS].pop();
4682 if anonymous_module.is_some() {
4683 self.ribs[TypeNS].pop();
4684 }
4685 debug!("(resolving block) leaving block");
4686 }
4687
4688 fn resolve_anon_const(&mut self, constant: &'ast AnonConst, anon_const_kind: AnonConstKind) {
4689 debug!(
4690 "resolve_anon_const(constant: {:?}, anon_const_kind: {:?})",
4691 constant, anon_const_kind
4692 );
4693
4694 let is_trivial_const_arg = constant
4695 .value
4696 .is_potential_trivial_const_arg(self.r.tcx.features().min_generic_const_args());
4697 self.resolve_anon_const_manual(is_trivial_const_arg, anon_const_kind, |this| {
4698 this.resolve_expr(&constant.value, None)
4699 })
4700 }
4701
4702 fn resolve_anon_const_manual(
4709 &mut self,
4710 is_trivial_const_arg: bool,
4711 anon_const_kind: AnonConstKind,
4712 resolve_expr: impl FnOnce(&mut Self),
4713 ) {
4714 let is_repeat_expr = match anon_const_kind {
4715 AnonConstKind::ConstArg(is_repeat_expr) => is_repeat_expr,
4716 _ => IsRepeatExpr::No,
4717 };
4718
4719 let may_use_generics = match anon_const_kind {
4720 AnonConstKind::EnumDiscriminant => {
4721 ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
4722 }
4723 AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes,
4724 AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
4725 AnonConstKind::ConstArg(_) => {
4726 if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg {
4727 ConstantHasGenerics::Yes
4728 } else {
4729 ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
4730 }
4731 }
4732 };
4733
4734 self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| {
4735 this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
4736 resolve_expr(this);
4737 });
4738 });
4739 }
4740
4741 fn resolve_expr_field(&mut self, f: &'ast ExprField, e: &'ast Expr) {
4742 self.resolve_expr(&f.expr, Some(e));
4743 self.visit_ident(&f.ident);
4744 walk_list!(self, visit_attribute, f.attrs.iter());
4745 }
4746
4747 fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
4748 self.record_candidate_traits_for_expr_if_necessary(expr);
4752
4753 match expr.kind {
4755 ExprKind::Path(ref qself, ref path) => {
4756 self.smart_resolve_path(expr.id, qself, path, PathSource::Expr(parent));
4757 visit::walk_expr(self, expr);
4758 }
4759
4760 ExprKind::Struct(ref se) => {
4761 self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct);
4762 if let Some(qself) = &se.qself {
4766 self.visit_ty(&qself.ty);
4767 }
4768 self.visit_path(&se.path, expr.id);
4769 walk_list!(self, resolve_expr_field, &se.fields, expr);
4770 match &se.rest {
4771 StructRest::Base(expr) => self.visit_expr(expr),
4772 StructRest::Rest(_span) => {}
4773 StructRest::None => {}
4774 }
4775 }
4776
4777 ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
4778 match self.resolve_label(label.ident) {
4779 Ok((node_id, _)) => {
4780 self.r.label_res_map.insert(expr.id, node_id);
4782 self.diag_metadata.unused_labels.remove(&node_id);
4783 }
4784 Err(error) => {
4785 self.report_error(label.ident.span, error);
4786 }
4787 }
4788
4789 visit::walk_expr(self, expr);
4791 }
4792
4793 ExprKind::Break(None, Some(ref e)) => {
4794 self.resolve_expr(e, Some(expr));
4797 }
4798
4799 ExprKind::Let(ref pat, ref scrutinee, _, _) => {
4800 self.visit_expr(scrutinee);
4801 self.resolve_pattern_top(pat, PatternSource::Let);
4802 }
4803
4804 ExprKind::If(ref cond, ref then, ref opt_else) => {
4805 self.with_rib(ValueNS, RibKind::Normal, |this| {
4806 let old = this.diag_metadata.in_if_condition.replace(cond);
4807 this.visit_expr(cond);
4808 this.diag_metadata.in_if_condition = old;
4809 this.visit_block(then);
4810 });
4811 if let Some(expr) = opt_else {
4812 self.visit_expr(expr);
4813 }
4814 }
4815
4816 ExprKind::Loop(ref block, label, _) => {
4817 self.resolve_labeled_block(label, expr.id, block)
4818 }
4819
4820 ExprKind::While(ref cond, ref block, label) => {
4821 self.with_resolved_label(label, expr.id, |this| {
4822 this.with_rib(ValueNS, RibKind::Normal, |this| {
4823 let old = this.diag_metadata.in_if_condition.replace(cond);
4824 this.visit_expr(cond);
4825 this.diag_metadata.in_if_condition = old;
4826 this.visit_block(block);
4827 })
4828 });
4829 }
4830
4831 ExprKind::ForLoop { ref pat, ref iter, ref body, label, kind: _ } => {
4832 self.visit_expr(iter);
4833 self.with_rib(ValueNS, RibKind::Normal, |this| {
4834 this.resolve_pattern_top(pat, PatternSource::For);
4835 this.resolve_labeled_block(label, expr.id, body);
4836 });
4837 }
4838
4839 ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block),
4840
4841 ExprKind::Field(ref subexpression, _) => {
4843 self.resolve_expr(subexpression, Some(expr));
4844 }
4845 ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => {
4846 self.resolve_expr(receiver, Some(expr));
4847 for arg in args {
4848 self.resolve_expr(arg, None);
4849 }
4850 self.visit_path_segment(seg);
4851 }
4852
4853 ExprKind::Call(ref callee, ref arguments) => {
4854 self.resolve_expr(callee, Some(expr));
4855 let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default();
4856 for (idx, argument) in arguments.iter().enumerate() {
4857 if const_args.contains(&idx) {
4860 let is_trivial_const_arg = argument.is_potential_trivial_const_arg(
4861 self.r.tcx.features().min_generic_const_args(),
4862 );
4863 self.resolve_anon_const_manual(
4864 is_trivial_const_arg,
4865 AnonConstKind::ConstArg(IsRepeatExpr::No),
4866 |this| this.resolve_expr(argument, None),
4867 );
4868 } else {
4869 self.resolve_expr(argument, None);
4870 }
4871 }
4872 }
4873 ExprKind::Type(ref _type_expr, ref _ty) => {
4874 visit::walk_expr(self, expr);
4875 }
4876 ExprKind::Closure(box ast::Closure {
4878 binder: ClosureBinder::For { ref generic_params, span },
4879 ..
4880 }) => {
4881 self.with_generic_param_rib(
4882 generic_params,
4883 RibKind::Normal,
4884 LifetimeRibKind::Generics {
4885 binder: expr.id,
4886 kind: LifetimeBinderKind::Closure,
4887 span,
4888 },
4889 |this| visit::walk_expr(this, expr),
4890 );
4891 }
4892 ExprKind::Closure(..) => visit::walk_expr(self, expr),
4893 ExprKind::Gen(..) => {
4894 self.with_label_rib(RibKind::FnOrCoroutine, |this| visit::walk_expr(this, expr));
4895 }
4896 ExprKind::Repeat(ref elem, ref ct) => {
4897 self.visit_expr(elem);
4898 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
4899 }
4900 ExprKind::ConstBlock(ref ct) => {
4901 self.resolve_anon_const(ct, AnonConstKind::InlineConst);
4902 }
4903 ExprKind::Index(ref elem, ref idx, _) => {
4904 self.resolve_expr(elem, Some(expr));
4905 self.visit_expr(idx);
4906 }
4907 ExprKind::Assign(ref lhs, ref rhs, _) => {
4908 if !self.diag_metadata.is_assign_rhs {
4909 self.diag_metadata.in_assignment = Some(expr);
4910 }
4911 self.visit_expr(lhs);
4912 self.diag_metadata.is_assign_rhs = true;
4913 self.diag_metadata.in_assignment = None;
4914 self.visit_expr(rhs);
4915 self.diag_metadata.is_assign_rhs = false;
4916 }
4917 ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
4918 self.diag_metadata.in_range = Some((start, end));
4919 self.resolve_expr(start, Some(expr));
4920 self.resolve_expr(end, Some(expr));
4921 self.diag_metadata.in_range = None;
4922 }
4923 _ => {
4924 visit::walk_expr(self, expr);
4925 }
4926 }
4927 }
4928
4929 fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
4930 match expr.kind {
4931 ExprKind::Field(_, ident) => {
4932 let traits = self.traits_in_scope(ident, ValueNS);
4937 self.r.trait_map.insert(expr.id, traits);
4938 }
4939 ExprKind::MethodCall(ref call) => {
4940 debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
4941 let traits = self.traits_in_scope(call.seg.ident, ValueNS);
4942 self.r.trait_map.insert(expr.id, traits);
4943 }
4944 _ => {
4945 }
4947 }
4948 }
4949
4950 fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> {
4951 self.r.traits_in_scope(
4952 self.current_trait_ref.as_ref().map(|(module, _)| *module),
4953 &self.parent_scope,
4954 ident.span.ctxt(),
4955 Some((ident.name, ns)),
4956 )
4957 }
4958
4959 fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
4960 let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
4964 let res = *doc_link_resolutions
4965 .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
4966 .or_default()
4967 .entry((Symbol::intern(path_str), ns))
4968 .or_insert_with_key(|(path, ns)| {
4969 let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope);
4970 if let Some(res) = res
4971 && let Some(def_id) = res.opt_def_id()
4972 && self.is_invalid_proc_macro_item_for_doc(def_id)
4973 {
4974 return None;
4977 }
4978 res
4979 });
4980 self.r.doc_link_resolutions = doc_link_resolutions;
4981 res
4982 }
4983
4984 fn is_invalid_proc_macro_item_for_doc(&self, did: DefId) -> bool {
4985 if !matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata)
4986 || !self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
4987 {
4988 return false;
4989 }
4990 let Some(local_did) = did.as_local() else { return true };
4991 let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true };
4992 !self.r.proc_macros.contains(node_id)
4993 }
4994
4995 fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
4996 match self.r.tcx.sess.opts.resolve_doc_links {
4997 ResolveDocLinks::None => return,
4998 ResolveDocLinks::ExportedMetadata
4999 if !self.r.tcx.crate_types().iter().copied().any(CrateType::has_metadata)
5000 || !maybe_exported.eval(self.r) =>
5001 {
5002 return;
5003 }
5004 ResolveDocLinks::Exported
5005 if !maybe_exported.eval(self.r)
5006 && !rustdoc::has_primitive_or_keyword_docs(attrs) =>
5007 {
5008 return;
5009 }
5010 ResolveDocLinks::ExportedMetadata
5011 | ResolveDocLinks::Exported
5012 | ResolveDocLinks::All => {}
5013 }
5014
5015 if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
5016 return;
5017 }
5018
5019 let mut need_traits_in_scope = false;
5020 for path_str in rustdoc::attrs_to_preprocessed_links(attrs) {
5021 let mut any_resolved = false;
5023 let mut need_assoc = false;
5024 for ns in [TypeNS, ValueNS, MacroNS] {
5025 if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) {
5026 any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool));
5029 } else if ns != MacroNS {
5030 need_assoc = true;
5031 }
5032 }
5033
5034 if need_assoc || !any_resolved {
5036 let mut path = &path_str[..];
5037 while let Some(idx) = path.rfind("::") {
5038 path = &path[..idx];
5039 need_traits_in_scope = true;
5040 for ns in [TypeNS, ValueNS, MacroNS] {
5041 self.resolve_and_cache_rustdoc_path(path, ns);
5042 }
5043 }
5044 }
5045 }
5046
5047 if need_traits_in_scope {
5048 let mut doc_link_traits_in_scope = std::mem::take(&mut self.r.doc_link_traits_in_scope);
5050 doc_link_traits_in_scope
5051 .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
5052 .or_insert_with(|| {
5053 self.r
5054 .traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None)
5055 .into_iter()
5056 .filter_map(|tr| {
5057 if self.is_invalid_proc_macro_item_for_doc(tr.def_id) {
5058 return None;
5061 }
5062 Some(tr.def_id)
5063 })
5064 .collect()
5065 });
5066 self.r.doc_link_traits_in_scope = doc_link_traits_in_scope;
5067 }
5068 }
5069
5070 fn lint_unused_qualifications(&mut self, path: &[Segment], ns: Namespace, finalize: Finalize) {
5071 if let Some(seg) = path.first()
5073 && seg.ident.name == kw::PathRoot
5074 {
5075 return;
5076 }
5077
5078 if finalize.path_span.from_expansion()
5079 || path.iter().any(|seg| seg.ident.span.from_expansion())
5080 {
5081 return;
5082 }
5083
5084 let end_pos =
5085 path.iter().position(|seg| seg.has_generic_args).map_or(path.len(), |pos| pos + 1);
5086 let unqualified = path[..end_pos].iter().enumerate().skip(1).rev().find_map(|(i, seg)| {
5087 let ns = if i + 1 == path.len() { ns } else { TypeNS };
5096 let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
5097 let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
5098 (res == binding.res()).then_some((seg, binding))
5099 });
5100
5101 if let Some((seg, binding)) = unqualified {
5102 self.r.potentially_unnecessary_qualifications.push(UnnecessaryQualification {
5103 binding,
5104 node_id: finalize.node_id,
5105 path_span: finalize.path_span,
5106 removal_span: path[0].ident.span.until(seg.ident.span),
5107 });
5108 }
5109 }
5110}
5111
5112struct ItemInfoCollector<'a, 'ra, 'tcx> {
5115 r: &'a mut Resolver<'ra, 'tcx>,
5116}
5117
5118impl ItemInfoCollector<'_, '_, '_> {
5119 fn collect_fn_info(
5120 &mut self,
5121 header: FnHeader,
5122 decl: &FnDecl,
5123 id: NodeId,
5124 attrs: &[Attribute],
5125 ) {
5126 let sig = DelegationFnSig {
5127 header,
5128 param_count: decl.inputs.len(),
5129 has_self: decl.has_self(),
5130 c_variadic: decl.c_variadic(),
5131 target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
5132 };
5133 self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
5134 }
5135}
5136
5137impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
5138 fn visit_item(&mut self, item: &'ast Item) {
5139 match &item.kind {
5140 ItemKind::TyAlias(box TyAlias { generics, .. })
5141 | ItemKind::Const(box ConstItem { generics, .. })
5142 | ItemKind::Fn(box Fn { generics, .. })
5143 | ItemKind::Enum(_, generics)
5144 | ItemKind::Struct(_, generics)
5145 | ItemKind::Union(_, generics)
5146 | ItemKind::Impl(box Impl { generics, .. })
5147 | ItemKind::Trait(box Trait { generics, .. })
5148 | ItemKind::TraitAlias(generics, _) => {
5149 if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind {
5150 self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
5151 }
5152
5153 let def_id = self.r.local_def_id(item.id);
5154 let count = generics
5155 .params
5156 .iter()
5157 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
5158 .count();
5159 self.r.item_generics_num_lifetimes.insert(def_id, count);
5160 }
5161
5162 ItemKind::ForeignMod(ForeignMod { extern_span, safety: _, abi, items }) => {
5163 for foreign_item in items {
5164 if let ForeignItemKind::Fn(box Fn { sig, .. }) = &foreign_item.kind {
5165 let new_header =
5166 FnHeader { ext: Extern::from_abi(*abi, *extern_span), ..sig.header };
5167 self.collect_fn_info(new_header, &sig.decl, foreign_item.id, &item.attrs);
5168 }
5169 }
5170 }
5171
5172 ItemKind::Mod(..)
5173 | ItemKind::Static(..)
5174 | ItemKind::Use(..)
5175 | ItemKind::ExternCrate(..)
5176 | ItemKind::MacroDef(..)
5177 | ItemKind::GlobalAsm(..)
5178 | ItemKind::MacCall(..)
5179 | ItemKind::DelegationMac(..) => {}
5180 ItemKind::Delegation(..) => {
5181 }
5186 }
5187 visit::walk_item(self, item)
5188 }
5189
5190 fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
5191 if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
5192 self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs);
5193 }
5194 visit::walk_assoc_item(self, item, ctxt);
5195 }
5196}
5197
5198impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
5199 pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
5200 visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
5201 let mut late_resolution_visitor = LateResolutionVisitor::new(self);
5202 late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
5203 visit::walk_crate(&mut late_resolution_visitor, krate);
5204 #[allow(rustc::potential_query_instability)] for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
5206 self.lint_buffer.buffer_lint(
5207 lint::builtin::UNUSED_LABELS,
5208 *id,
5209 *span,
5210 BuiltinLintDiag::UnusedLabel,
5211 );
5212 }
5213 }
5214}
5215
5216fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool {
5218 let mut path = expected_path.iter().rev();
5219 while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) {
5220 if !tcx.opt_item_name(def_id).is_some_and(|n| n.as_str() == *next_step) {
5221 return false;
5222 }
5223 def_id = parent;
5224 }
5225 true
5226}