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_errors::codes::*;
22use rustc_errors::{
23 Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions,
24};
25use rustc_hir::def::Namespace::{self, *};
26use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
27use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
28use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
29use rustc_middle::middle::resolve_bound_vars::Set1;
30use rustc_middle::ty::DelegationFnSig;
31use rustc_middle::{bug, span_bug};
32use rustc_session::config::{CrateType, ResolveDocLinks};
33use rustc_session::lint::{self, BuiltinLintDiag};
34use rustc_session::parse::feature_err;
35use rustc_span::source_map::{Spanned, respan};
36use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym};
37use smallvec::{SmallVec, smallvec};
38use tracing::{debug, instrument, trace};
39
40use crate::{
41 BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot,
42 NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError,
43 Used, errors, path_names_to_string, rustdoc,
44};
45
46mod diagnostics;
47
48type Res = def::Res<NodeId>;
49
50type IdentMap<T> = FxHashMap<Ident, T>;
51
52use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime};
53
54#[derive(Copy, Clone, Debug)]
55struct BindingInfo {
56 span: Span,
57 annotation: BindingMode,
58}
59
60#[derive(Copy, Clone, PartialEq, Eq, Debug)]
61pub(crate) enum PatternSource {
62 Match,
63 Let,
64 For,
65 FnParam,
66}
67
68#[derive(Copy, Clone, Debug, PartialEq, Eq)]
69enum IsRepeatExpr {
70 No,
71 Yes,
72}
73
74struct IsNeverPattern;
75
76#[derive(Copy, Clone, Debug, PartialEq, Eq)]
79enum AnonConstKind {
80 EnumDiscriminant,
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) -> 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,
210
211 ConstParamTy,
214
215 InlineAsmSym,
218}
219
220impl RibKind<'_> {
221 pub(crate) fn contains_params(&self) -> bool {
224 match self {
225 RibKind::Normal
226 | RibKind::FnOrCoroutine
227 | RibKind::ConstantItem(..)
228 | RibKind::Module(_)
229 | RibKind::MacroDefinition(_)
230 | RibKind::ConstParamTy
231 | RibKind::InlineAsmSym => false,
232 RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true,
233 }
234 }
235
236 fn is_label_barrier(self) -> bool {
238 match self {
239 RibKind::Normal | RibKind::MacroDefinition(..) => false,
240
241 RibKind::AssocItem
242 | RibKind::FnOrCoroutine
243 | RibKind::Item(..)
244 | RibKind::ConstantItem(..)
245 | RibKind::Module(..)
246 | RibKind::ForwardGenericParamBan
247 | RibKind::ConstParamTy
248 | RibKind::InlineAsmSym => true,
249 }
250 }
251}
252
253#[derive(Debug)]
266pub(crate) struct Rib<'ra, R = Res> {
267 pub bindings: IdentMap<R>,
268 pub patterns_with_skipped_bindings: FxHashMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>,
269 pub kind: RibKind<'ra>,
270}
271
272impl<'ra, R> Rib<'ra, R> {
273 fn new(kind: RibKind<'ra>) -> Rib<'ra, R> {
274 Rib {
275 bindings: Default::default(),
276 patterns_with_skipped_bindings: Default::default(),
277 kind,
278 }
279 }
280}
281
282#[derive(Clone, Copy, Debug)]
283enum LifetimeUseSet {
284 One { use_span: Span, use_ctxt: visit::LifetimeCtxt },
285 Many,
286}
287
288#[derive(Copy, Clone, Debug)]
289enum LifetimeRibKind {
290 Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
295
296 AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
313
314 Elided(LifetimeRes),
316
317 AnonymousReportError,
323
324 StaticIfNoLifetimeInScope { lint_id: NodeId, emit_lint: bool },
328
329 ElisionFailure,
331
332 ConstParamTy,
337
338 ConcreteAnonConst(NoConstantGenericsReason),
344
345 Item,
347}
348
349#[derive(Copy, Clone, Debug)]
350enum LifetimeBinderKind {
351 BareFnType,
352 PolyTrait,
353 WhereBound,
354 Item,
355 ConstItem,
356 Function,
357 Closure,
358 ImplBlock,
359}
360
361impl LifetimeBinderKind {
362 fn descr(self) -> &'static str {
363 use LifetimeBinderKind::*;
364 match self {
365 BareFnType => "type",
366 PolyTrait => "bound",
367 WhereBound => "bound",
368 Item | ConstItem => "item",
369 ImplBlock => "impl block",
370 Function => "function",
371 Closure => "closure",
372 }
373 }
374}
375
376#[derive(Debug)]
377struct LifetimeRib {
378 kind: LifetimeRibKind,
379 bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
381}
382
383impl LifetimeRib {
384 fn new(kind: LifetimeRibKind) -> LifetimeRib {
385 LifetimeRib { bindings: Default::default(), kind }
386 }
387}
388
389#[derive(Copy, Clone, PartialEq, Eq, Debug)]
390pub(crate) enum AliasPossibility {
391 No,
392 Maybe,
393}
394
395#[derive(Copy, Clone, Debug)]
396pub(crate) enum PathSource<'a> {
397 Type,
399 Trait(AliasPossibility),
401 Expr(Option<&'a Expr>),
403 Pat,
405 Struct,
407 TupleStruct(Span, &'a [Span]),
409 TraitItem(Namespace),
411 Delegation,
413 PreciseCapturingArg(Namespace),
415 ReturnTypeNotation,
417}
418
419impl<'a> PathSource<'a> {
420 fn namespace(self) -> Namespace {
421 match self {
422 PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
423 PathSource::Expr(..)
424 | PathSource::Pat
425 | PathSource::TupleStruct(..)
426 | PathSource::Delegation
427 | PathSource::ReturnTypeNotation => ValueNS,
428 PathSource::TraitItem(ns) => ns,
429 PathSource::PreciseCapturingArg(ns) => ns,
430 }
431 }
432
433 fn defer_to_typeck(self) -> bool {
434 match self {
435 PathSource::Type
436 | PathSource::Expr(..)
437 | PathSource::Pat
438 | PathSource::Struct
439 | PathSource::TupleStruct(..)
440 | PathSource::ReturnTypeNotation => true,
441 PathSource::Trait(_)
442 | PathSource::TraitItem(..)
443 | PathSource::Delegation
444 | PathSource::PreciseCapturingArg(..) => false,
445 }
446 }
447
448 fn descr_expected(self) -> &'static str {
449 match &self {
450 PathSource::Type => "type",
451 PathSource::Trait(_) => "trait",
452 PathSource::Pat => "unit struct, unit variant or constant",
453 PathSource::Struct => "struct, variant or union type",
454 PathSource::TupleStruct(..) => "tuple struct or tuple variant",
455 PathSource::TraitItem(ns) => match ns {
456 TypeNS => "associated type",
457 ValueNS => "method or associated constant",
458 MacroNS => bug!("associated macro"),
459 },
460 PathSource::Expr(parent) => match parent.as_ref().map(|p| &p.kind) {
461 Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind {
464 ExprKind::Path(_, path)
466 if let [segment, _] = path.segments.as_slice()
467 && segment.ident.name == kw::PathRoot =>
468 {
469 "external crate"
470 }
471 ExprKind::Path(_, path)
472 if let Some(segment) = path.segments.last()
473 && let Some(c) = segment.ident.to_string().chars().next()
474 && c.is_uppercase() =>
475 {
476 "function, tuple struct or tuple variant"
477 }
478 _ => "function",
479 },
480 _ => "value",
481 },
482 PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
483 PathSource::PreciseCapturingArg(..) => "type or const parameter",
484 }
485 }
486
487 fn is_call(self) -> bool {
488 matches!(self, PathSource::Expr(Some(&Expr { kind: ExprKind::Call(..), .. })))
489 }
490
491 pub(crate) fn is_expected(self, res: Res) -> bool {
492 match self {
493 PathSource::Type => matches!(
494 res,
495 Res::Def(
496 DefKind::Struct
497 | DefKind::Union
498 | DefKind::Enum
499 | DefKind::Trait
500 | DefKind::TraitAlias
501 | DefKind::TyAlias
502 | DefKind::AssocTy
503 | DefKind::TyParam
504 | DefKind::OpaqueTy
505 | DefKind::ForeignTy,
506 _,
507 ) | Res::PrimTy(..)
508 | Res::SelfTyParam { .. }
509 | Res::SelfTyAlias { .. }
510 ),
511 PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
512 PathSource::Trait(AliasPossibility::Maybe) => {
513 matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
514 }
515 PathSource::Expr(..) => matches!(
516 res,
517 Res::Def(
518 DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
519 | DefKind::Const
520 | DefKind::Static { .. }
521 | DefKind::Fn
522 | DefKind::AssocFn
523 | DefKind::AssocConst
524 | DefKind::ConstParam,
525 _,
526 ) | Res::Local(..)
527 | Res::SelfCtor(..)
528 ),
529 PathSource::Pat => {
530 res.expected_in_unit_struct_pat()
531 || matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _))
532 }
533 PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
534 PathSource::Struct => matches!(
535 res,
536 Res::Def(
537 DefKind::Struct
538 | DefKind::Union
539 | DefKind::Variant
540 | DefKind::TyAlias
541 | DefKind::AssocTy,
542 _,
543 ) | Res::SelfTyParam { .. }
544 | Res::SelfTyAlias { .. }
545 ),
546 PathSource::TraitItem(ns) => match res {
547 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
548 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
549 _ => false,
550 },
551 PathSource::ReturnTypeNotation => match res {
552 Res::Def(DefKind::AssocFn, _) => true,
553 _ => false,
554 },
555 PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
556 PathSource::PreciseCapturingArg(ValueNS) => {
557 matches!(res, Res::Def(DefKind::ConstParam, _))
558 }
559 PathSource::PreciseCapturingArg(TypeNS) => matches!(
561 res,
562 Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }
563 ),
564 PathSource::PreciseCapturingArg(MacroNS) => false,
565 }
566 }
567
568 fn error_code(self, has_unexpected_resolution: bool) -> ErrCode {
569 match (self, has_unexpected_resolution) {
570 (PathSource::Trait(_), true) => E0404,
571 (PathSource::Trait(_), false) => E0405,
572 (PathSource::Type, true) => E0573,
573 (PathSource::Type, false) => E0412,
574 (PathSource::Struct, true) => E0574,
575 (PathSource::Struct, false) => E0422,
576 (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
577 (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
578 (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
579 (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
580 (PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
581 (PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
582 (PathSource::PreciseCapturingArg(..), true) => E0799,
583 (PathSource::PreciseCapturingArg(..), false) => E0800,
584 }
585 }
586}
587
588#[derive(Clone, Copy)]
592enum MaybeExported<'a> {
593 Ok(NodeId),
594 Impl(Option<DefId>),
595 ImplItem(Result<DefId, &'a Visibility>),
596 NestedUse(&'a Visibility),
597}
598
599impl MaybeExported<'_> {
600 fn eval(self, r: &Resolver<'_, '_>) -> bool {
601 let def_id = match self {
602 MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)),
603 MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => {
604 trait_def_id.as_local()
605 }
606 MaybeExported::Impl(None) => return true,
607 MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => {
608 return vis.kind.is_pub();
609 }
610 };
611 def_id.is_none_or(|def_id| r.effective_visibilities.is_exported(def_id))
612 }
613}
614
615#[derive(Debug)]
617pub(crate) struct UnnecessaryQualification<'ra> {
618 pub binding: LexicalScopeBinding<'ra>,
619 pub node_id: NodeId,
620 pub path_span: Span,
621 pub removal_span: Span,
622}
623
624#[derive(Default)]
625struct DiagMetadata<'ast> {
626 current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,
628
629 current_self_type: Option<Ty>,
631
632 current_self_item: Option<NodeId>,
634
635 current_item: Option<&'ast Item>,
637
638 currently_processing_generic_args: bool,
641
642 current_function: Option<(FnKind<'ast>, Span)>,
644
645 unused_labels: FxHashMap<NodeId, Span>,
648
649 current_block_could_be_bare_struct_literal: Option<Span>,
653
654 current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
656
657 current_pat: Option<&'ast Pat>,
658
659 in_if_condition: Option<&'ast Expr>,
661
662 in_assignment: Option<&'ast Expr>,
664 is_assign_rhs: bool,
665
666 in_non_gat_assoc_type: Option<bool>,
668
669 in_range: Option<(&'ast Expr, &'ast Expr)>,
671
672 current_trait_object: Option<&'ast [ast::GenericBound]>,
675
676 current_where_predicate: Option<&'ast WherePredicate>,
678
679 current_type_path: Option<&'ast Ty>,
680
681 current_impl_items: Option<&'ast [P<AssocItem>]>,
683
684 currently_processing_impl_trait: Option<(TraitRef, Ty)>,
686
687 current_elision_failures: Vec<MissingLifetime>,
690}
691
692struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
693 r: &'a mut Resolver<'ra, 'tcx>,
694
695 parent_scope: ParentScope<'ra>,
697
698 ribs: PerNS<Vec<Rib<'ra>>>,
700
701 last_block_rib: Option<Rib<'ra>>,
703
704 label_ribs: Vec<Rib<'ra, NodeId>>,
706
707 lifetime_ribs: Vec<LifetimeRib>,
709
710 lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>,
716
717 current_trait_ref: Option<(Module<'ra>, TraitRef)>,
719
720 diag_metadata: Box<DiagMetadata<'ast>>,
722
723 in_func_body: bool,
729
730 lifetime_uses: FxHashMap<LocalDefId, LifetimeUseSet>,
732}
733
734impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
736 fn visit_attribute(&mut self, _: &'ast Attribute) {
737 }
740 fn visit_item(&mut self, item: &'ast Item) {
741 let prev = replace(&mut self.diag_metadata.current_item, Some(item));
742 let old_ignore = replace(&mut self.in_func_body, false);
744 self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
745 self.in_func_body = old_ignore;
746 self.diag_metadata.current_item = prev;
747 }
748 fn visit_arm(&mut self, arm: &'ast Arm) {
749 self.resolve_arm(arm);
750 }
751 fn visit_block(&mut self, block: &'ast Block) {
752 let old_macro_rules = self.parent_scope.macro_rules;
753 self.resolve_block(block);
754 self.parent_scope.macro_rules = old_macro_rules;
755 }
756 fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
757 bug!("encountered anon const without a manual call to `resolve_anon_const`: {constant:#?}");
758 }
759 fn visit_expr(&mut self, expr: &'ast Expr) {
760 self.resolve_expr(expr, None);
761 }
762 fn visit_pat(&mut self, p: &'ast Pat) {
763 let prev = self.diag_metadata.current_pat;
764 self.diag_metadata.current_pat = Some(p);
765 visit::walk_pat(self, p);
766 self.diag_metadata.current_pat = prev;
767 }
768 fn visit_local(&mut self, local: &'ast Local) {
769 let local_spans = match local.pat.kind {
770 PatKind::Wild => None,
772 _ => Some((
773 local.pat.span,
774 local.ty.as_ref().map(|ty| ty.span),
775 local.kind.init().map(|init| init.span),
776 )),
777 };
778 let original = replace(&mut self.diag_metadata.current_let_binding, local_spans);
779 self.resolve_local(local);
780 self.diag_metadata.current_let_binding = original;
781 }
782 fn visit_ty(&mut self, ty: &'ast Ty) {
783 let prev = self.diag_metadata.current_trait_object;
784 let prev_ty = self.diag_metadata.current_type_path;
785 match &ty.kind {
786 TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
787 let span = self.r.tcx.sess.source_map().start_point(ty.span);
791 self.resolve_elided_lifetime(ty.id, span);
792 visit::walk_ty(self, ty);
793 }
794 TyKind::Path(qself, path) => {
795 self.diag_metadata.current_type_path = Some(ty);
796
797 let source = if let Some(seg) = path.segments.last()
801 && let Some(args) = &seg.args
802 && matches!(**args, GenericArgs::ParenthesizedElided(..))
803 {
804 PathSource::ReturnTypeNotation
805 } else {
806 PathSource::Type
807 };
808
809 self.smart_resolve_path(ty.id, qself, path, source);
810
811 if qself.is_none()
813 && let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
814 && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) =
815 partial_res.full_res()
816 {
817 let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo());
821 self.with_generic_param_rib(
822 &[],
823 RibKind::Normal,
824 LifetimeRibKind::Generics {
825 binder: ty.id,
826 kind: LifetimeBinderKind::PolyTrait,
827 span,
828 },
829 |this| this.visit_path(path, ty.id),
830 );
831 } else {
832 visit::walk_ty(self, ty)
833 }
834 }
835 TyKind::ImplicitSelf => {
836 let self_ty = Ident::with_dummy_span(kw::SelfUpper);
837 let res = self
838 .resolve_ident_in_lexical_scope(
839 self_ty,
840 TypeNS,
841 Some(Finalize::new(ty.id, ty.span)),
842 None,
843 )
844 .map_or(Res::Err, |d| d.res());
845 self.r.record_partial_res(ty.id, PartialRes::new(res));
846 visit::walk_ty(self, ty)
847 }
848 TyKind::ImplTrait(..) => {
849 let candidates = self.lifetime_elision_candidates.take();
850 visit::walk_ty(self, ty);
851 self.lifetime_elision_candidates = candidates;
852 }
853 TyKind::TraitObject(bounds, ..) => {
854 self.diag_metadata.current_trait_object = Some(&bounds[..]);
855 visit::walk_ty(self, ty)
856 }
857 TyKind::BareFn(bare_fn) => {
858 let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo());
859 self.with_generic_param_rib(
860 &bare_fn.generic_params,
861 RibKind::Normal,
862 LifetimeRibKind::Generics {
863 binder: ty.id,
864 kind: LifetimeBinderKind::BareFnType,
865 span,
866 },
867 |this| {
868 this.visit_generic_params(&bare_fn.generic_params, false);
869 this.with_lifetime_rib(
870 LifetimeRibKind::AnonymousCreateParameter {
871 binder: ty.id,
872 report_in_path: false,
873 },
874 |this| {
875 this.resolve_fn_signature(
876 ty.id,
877 false,
878 bare_fn
881 .decl
882 .inputs
883 .iter()
884 .map(|Param { ty, .. }| (None, &**ty)),
885 &bare_fn.decl.output,
886 )
887 },
888 );
889 },
890 )
891 }
892 TyKind::UnsafeBinder(unsafe_binder) => {
893 let span = ty.span;
895 self.with_generic_param_rib(
896 &unsafe_binder.generic_params,
897 RibKind::Normal,
898 LifetimeRibKind::Generics {
899 binder: ty.id,
900 kind: LifetimeBinderKind::BareFnType,
901 span,
902 },
903 |this| {
904 this.visit_generic_params(&unsafe_binder.generic_params, false);
905 this.with_lifetime_rib(
906 LifetimeRibKind::AnonymousReportError,
909 |this| this.visit_ty(&unsafe_binder.inner_ty),
910 );
911 },
912 )
913 }
914 TyKind::Array(element_ty, length) => {
915 self.visit_ty(element_ty);
916 self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
917 }
918 TyKind::Typeof(ct) => {
919 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
920 }
921 _ => visit::walk_ty(self, ty),
922 }
923 self.diag_metadata.current_trait_object = prev;
924 self.diag_metadata.current_type_path = prev_ty;
925 }
926
927 fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
928 match &t.kind {
929 TyPatKind::Range(start, end, _) => {
930 if let Some(start) = start {
931 self.resolve_anon_const(start, AnonConstKind::ConstArg(IsRepeatExpr::No));
932 }
933 if let Some(end) = end {
934 self.resolve_anon_const(end, AnonConstKind::ConstArg(IsRepeatExpr::No));
935 }
936 }
937 TyPatKind::Err(_) => {}
938 }
939 }
940
941 fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
942 let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
943 self.with_generic_param_rib(
944 &tref.bound_generic_params,
945 RibKind::Normal,
946 LifetimeRibKind::Generics {
947 binder: tref.trait_ref.ref_id,
948 kind: LifetimeBinderKind::PolyTrait,
949 span,
950 },
951 |this| {
952 this.visit_generic_params(&tref.bound_generic_params, false);
953 this.smart_resolve_path(
954 tref.trait_ref.ref_id,
955 &None,
956 &tref.trait_ref.path,
957 PathSource::Trait(AliasPossibility::Maybe),
958 );
959 this.visit_trait_ref(&tref.trait_ref);
960 },
961 );
962 }
963 fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
964 self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
965 let def_kind = self.r.local_def_kind(foreign_item.id);
966 match foreign_item.kind {
967 ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
968 self.with_generic_param_rib(
969 &generics.params,
970 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
971 LifetimeRibKind::Generics {
972 binder: foreign_item.id,
973 kind: LifetimeBinderKind::Item,
974 span: generics.span,
975 },
976 |this| visit::walk_item(this, foreign_item),
977 );
978 }
979 ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
980 self.with_generic_param_rib(
981 &generics.params,
982 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
983 LifetimeRibKind::Generics {
984 binder: foreign_item.id,
985 kind: LifetimeBinderKind::Function,
986 span: generics.span,
987 },
988 |this| visit::walk_item(this, foreign_item),
989 );
990 }
991 ForeignItemKind::Static(..) => {
992 self.with_static_rib(def_kind, |this| visit::walk_item(this, foreign_item))
993 }
994 ForeignItemKind::MacCall(..) => {
995 panic!("unexpanded macro in resolve!")
996 }
997 }
998 }
999 fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
1000 let previous_value = self.diag_metadata.current_function;
1001 match fn_kind {
1002 FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. })
1005 | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => {
1006 self.visit_fn_header(&sig.header);
1007 self.visit_generics(generics);
1008 self.with_lifetime_rib(
1009 LifetimeRibKind::AnonymousCreateParameter {
1010 binder: fn_id,
1011 report_in_path: false,
1012 },
1013 |this| {
1014 this.resolve_fn_signature(
1015 fn_id,
1016 sig.decl.has_self(),
1017 sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
1018 &sig.decl.output,
1019 );
1020 },
1021 );
1022 return;
1023 }
1024 FnKind::Fn(..) => {
1025 self.diag_metadata.current_function = Some((fn_kind, sp));
1026 }
1027 FnKind::Closure(..) => {}
1029 };
1030 debug!("(resolving function) entering function");
1031
1032 self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
1034 this.with_label_rib(RibKind::FnOrCoroutine, |this| {
1036 match fn_kind {
1037 FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => {
1038 this.visit_generics(generics);
1039
1040 let declaration = &sig.decl;
1041 let coro_node_id = sig
1042 .header
1043 .coroutine_kind
1044 .map(|coroutine_kind| coroutine_kind.return_id());
1045
1046 this.with_lifetime_rib(
1047 LifetimeRibKind::AnonymousCreateParameter {
1048 binder: fn_id,
1049 report_in_path: coro_node_id.is_some(),
1050 },
1051 |this| {
1052 this.resolve_fn_signature(
1053 fn_id,
1054 declaration.has_self(),
1055 declaration
1056 .inputs
1057 .iter()
1058 .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
1059 &declaration.output,
1060 );
1061 },
1062 );
1063
1064 if let Some(contract) = contract {
1065 this.visit_contract(contract);
1066 }
1067
1068 if let Some(body) = body {
1069 let previous_state = replace(&mut this.in_func_body, true);
1072 this.last_block_rib = None;
1074 this.with_lifetime_rib(
1076 LifetimeRibKind::Elided(LifetimeRes::Infer),
1077 |this| this.visit_block(body),
1078 );
1079
1080 debug!("(resolving function) leaving function");
1081 this.in_func_body = previous_state;
1082 }
1083 }
1084 FnKind::Closure(binder, _, declaration, body) => {
1085 this.visit_closure_binder(binder);
1086
1087 this.with_lifetime_rib(
1088 match binder {
1089 ClosureBinder::NotPresent => {
1091 LifetimeRibKind::AnonymousCreateParameter {
1092 binder: fn_id,
1093 report_in_path: false,
1094 }
1095 }
1096 ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
1097 },
1098 |this| this.resolve_params(&declaration.inputs),
1100 );
1101 this.with_lifetime_rib(
1102 match binder {
1103 ClosureBinder::NotPresent => {
1104 LifetimeRibKind::Elided(LifetimeRes::Infer)
1105 }
1106 ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
1107 },
1108 |this| visit::walk_fn_ret_ty(this, &declaration.output),
1109 );
1110
1111 let previous_state = replace(&mut this.in_func_body, true);
1114 this.with_lifetime_rib(
1116 LifetimeRibKind::Elided(LifetimeRes::Infer),
1117 |this| this.visit_expr(body),
1118 );
1119
1120 debug!("(resolving function) leaving function");
1121 this.in_func_body = previous_state;
1122 }
1123 }
1124 })
1125 });
1126 self.diag_metadata.current_function = previous_value;
1127 }
1128
1129 fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
1130 self.resolve_lifetime(lifetime, use_ctxt)
1131 }
1132
1133 fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
1134 match arg {
1135 PreciseCapturingArg::Lifetime(_) => {}
1138
1139 PreciseCapturingArg::Arg(path, id) => {
1140 let mut check_ns = |ns| {
1147 self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
1148 };
1149 if !check_ns(TypeNS) && check_ns(ValueNS) {
1151 self.smart_resolve_path(
1152 *id,
1153 &None,
1154 path,
1155 PathSource::PreciseCapturingArg(ValueNS),
1156 );
1157 } else {
1158 self.smart_resolve_path(
1159 *id,
1160 &None,
1161 path,
1162 PathSource::PreciseCapturingArg(TypeNS),
1163 );
1164 }
1165 }
1166 }
1167
1168 visit::walk_precise_capturing_arg(self, arg)
1169 }
1170
1171 fn visit_generics(&mut self, generics: &'ast Generics) {
1172 self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
1173 for p in &generics.where_clause.predicates {
1174 self.visit_where_predicate(p);
1175 }
1176 }
1177
1178 fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
1179 match b {
1180 ClosureBinder::NotPresent => {}
1181 ClosureBinder::For { generic_params, .. } => {
1182 self.visit_generic_params(
1183 generic_params,
1184 self.diag_metadata.current_self_item.is_some(),
1185 );
1186 }
1187 }
1188 }
1189
1190 fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
1191 debug!("visit_generic_arg({:?})", arg);
1192 let prev = replace(&mut self.diag_metadata.currently_processing_generic_args, true);
1193 match arg {
1194 GenericArg::Type(ref ty) => {
1195 if let TyKind::Path(None, ref path) = ty.kind
1201 && path.is_potential_trivial_const_arg()
1204 {
1205 let mut check_ns = |ns| {
1206 self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
1207 .is_some()
1208 };
1209 if !check_ns(TypeNS) && check_ns(ValueNS) {
1210 self.resolve_anon_const_manual(
1211 true,
1212 AnonConstKind::ConstArg(IsRepeatExpr::No),
1213 |this| {
1214 this.smart_resolve_path(ty.id, &None, path, PathSource::Expr(None));
1215 this.visit_path(path, ty.id);
1216 },
1217 );
1218
1219 self.diag_metadata.currently_processing_generic_args = prev;
1220 return;
1221 }
1222 }
1223
1224 self.visit_ty(ty);
1225 }
1226 GenericArg::Lifetime(lt) => self.visit_lifetime(lt, visit::LifetimeCtxt::GenericArg),
1227 GenericArg::Const(ct) => {
1228 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
1229 }
1230 }
1231 self.diag_metadata.currently_processing_generic_args = prev;
1232 }
1233
1234 fn visit_assoc_item_constraint(&mut self, constraint: &'ast AssocItemConstraint) {
1235 self.visit_ident(&constraint.ident);
1236 if let Some(ref gen_args) = constraint.gen_args {
1237 self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1239 this.visit_generic_args(gen_args)
1240 });
1241 }
1242 match constraint.kind {
1243 AssocItemConstraintKind::Equality { ref term } => match term {
1244 Term::Ty(ty) => self.visit_ty(ty),
1245 Term::Const(c) => {
1246 self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No))
1247 }
1248 },
1249 AssocItemConstraintKind::Bound { ref bounds } => {
1250 walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
1251 }
1252 }
1253 }
1254
1255 fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
1256 let Some(ref args) = path_segment.args else {
1257 return;
1258 };
1259
1260 match &**args {
1261 GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args),
1262 GenericArgs::Parenthesized(p_args) => {
1263 for rib in self.lifetime_ribs.iter().rev() {
1265 match rib.kind {
1266 LifetimeRibKind::Generics {
1269 binder,
1270 kind: LifetimeBinderKind::PolyTrait,
1271 ..
1272 } => {
1273 self.with_lifetime_rib(
1274 LifetimeRibKind::AnonymousCreateParameter {
1275 binder,
1276 report_in_path: false,
1277 },
1278 |this| {
1279 this.resolve_fn_signature(
1280 binder,
1281 false,
1282 p_args.inputs.iter().map(|ty| (None, &**ty)),
1283 &p_args.output,
1284 )
1285 },
1286 );
1287 break;
1288 }
1289 LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => {
1292 visit::walk_generic_args(self, args);
1293 break;
1294 }
1295 LifetimeRibKind::AnonymousCreateParameter { .. }
1296 | LifetimeRibKind::AnonymousReportError
1297 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
1298 | LifetimeRibKind::Elided(_)
1299 | LifetimeRibKind::ElisionFailure
1300 | LifetimeRibKind::ConcreteAnonConst(_)
1301 | LifetimeRibKind::ConstParamTy => {}
1302 }
1303 }
1304 }
1305 GenericArgs::ParenthesizedElided(_) => {}
1306 }
1307 }
1308
1309 fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
1310 debug!("visit_where_predicate {:?}", p);
1311 let previous_value = replace(&mut self.diag_metadata.current_where_predicate, Some(p));
1312 self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1313 if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1314 bounded_ty,
1315 bounds,
1316 bound_generic_params,
1317 ..
1318 }) = &p.kind
1319 {
1320 let span = p.span.shrink_to_lo().to(bounded_ty.span.shrink_to_lo());
1321 this.with_generic_param_rib(
1322 bound_generic_params,
1323 RibKind::Normal,
1324 LifetimeRibKind::Generics {
1325 binder: bounded_ty.id,
1326 kind: LifetimeBinderKind::WhereBound,
1327 span,
1328 },
1329 |this| {
1330 this.visit_generic_params(bound_generic_params, false);
1331 this.visit_ty(bounded_ty);
1332 for bound in bounds {
1333 this.visit_param_bound(bound, BoundKind::Bound)
1334 }
1335 },
1336 );
1337 } else {
1338 visit::walk_where_predicate(this, p);
1339 }
1340 });
1341 self.diag_metadata.current_where_predicate = previous_value;
1342 }
1343
1344 fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
1345 for (op, _) in &asm.operands {
1346 match op {
1347 InlineAsmOperand::In { expr, .. }
1348 | InlineAsmOperand::Out { expr: Some(expr), .. }
1349 | InlineAsmOperand::InOut { expr, .. } => self.visit_expr(expr),
1350 InlineAsmOperand::Out { expr: None, .. } => {}
1351 InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
1352 self.visit_expr(in_expr);
1353 if let Some(out_expr) = out_expr {
1354 self.visit_expr(out_expr);
1355 }
1356 }
1357 InlineAsmOperand::Const { anon_const, .. } => {
1358 self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
1361 }
1362 InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
1363 InlineAsmOperand::Label { block } => self.visit_block(block),
1364 }
1365 }
1366 }
1367
1368 fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
1369 self.with_rib(ValueNS, RibKind::InlineAsmSym, |this| {
1371 this.with_rib(TypeNS, RibKind::InlineAsmSym, |this| {
1372 this.with_label_rib(RibKind::InlineAsmSym, |this| {
1373 this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None));
1374 visit::walk_inline_asm_sym(this, sym);
1375 });
1376 })
1377 });
1378 }
1379
1380 fn visit_variant(&mut self, v: &'ast Variant) {
1381 self.resolve_doc_links(&v.attrs, MaybeExported::Ok(v.id));
1382 visit::walk_variant(self, v)
1383 }
1384
1385 fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
1386 self.resolve_anon_const(discr, AnonConstKind::EnumDiscriminant);
1387 }
1388
1389 fn visit_field_def(&mut self, f: &'ast FieldDef) {
1390 self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
1391 let FieldDef {
1392 attrs,
1393 id: _,
1394 span: _,
1395 vis,
1396 ident,
1397 ty,
1398 is_placeholder: _,
1399 default,
1400 safety: _,
1401 } = f;
1402 walk_list!(self, visit_attribute, attrs);
1403 try_visit!(self.visit_vis(vis));
1404 visit_opt!(self, visit_ident, ident);
1405 try_visit!(self.visit_ty(ty));
1406 if let Some(v) = &default {
1407 self.resolve_anon_const(v, AnonConstKind::ConstArg(IsRepeatExpr::No));
1408 }
1409 }
1410}
1411
1412impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
1413 fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
1414 let graph_root = resolver.graph_root;
1417 let parent_scope = ParentScope::module(graph_root, resolver);
1418 let start_rib_kind = RibKind::Module(graph_root);
1419 LateResolutionVisitor {
1420 r: resolver,
1421 parent_scope,
1422 ribs: PerNS {
1423 value_ns: vec![Rib::new(start_rib_kind)],
1424 type_ns: vec![Rib::new(start_rib_kind)],
1425 macro_ns: vec![Rib::new(start_rib_kind)],
1426 },
1427 last_block_rib: None,
1428 label_ribs: Vec::new(),
1429 lifetime_ribs: Vec::new(),
1430 lifetime_elision_candidates: None,
1431 current_trait_ref: None,
1432 diag_metadata: Default::default(),
1433 in_func_body: false,
1435 lifetime_uses: Default::default(),
1436 }
1437 }
1438
1439 fn maybe_resolve_ident_in_lexical_scope(
1440 &mut self,
1441 ident: Ident,
1442 ns: Namespace,
1443 ) -> Option<LexicalScopeBinding<'ra>> {
1444 self.r.resolve_ident_in_lexical_scope(
1445 ident,
1446 ns,
1447 &self.parent_scope,
1448 None,
1449 &self.ribs[ns],
1450 None,
1451 )
1452 }
1453
1454 fn resolve_ident_in_lexical_scope(
1455 &mut self,
1456 ident: Ident,
1457 ns: Namespace,
1458 finalize: Option<Finalize>,
1459 ignore_binding: Option<NameBinding<'ra>>,
1460 ) -> Option<LexicalScopeBinding<'ra>> {
1461 self.r.resolve_ident_in_lexical_scope(
1462 ident,
1463 ns,
1464 &self.parent_scope,
1465 finalize,
1466 &self.ribs[ns],
1467 ignore_binding,
1468 )
1469 }
1470
1471 fn resolve_path(
1472 &mut self,
1473 path: &[Segment],
1474 opt_ns: Option<Namespace>, finalize: Option<Finalize>,
1476 ) -> PathResult<'ra> {
1477 self.r.resolve_path_with_ribs(
1478 path,
1479 opt_ns,
1480 &self.parent_scope,
1481 finalize,
1482 Some(&self.ribs),
1483 None,
1484 None,
1485 )
1486 }
1487
1488 fn with_rib<T>(
1508 &mut self,
1509 ns: Namespace,
1510 kind: RibKind<'ra>,
1511 work: impl FnOnce(&mut Self) -> T,
1512 ) -> T {
1513 self.ribs[ns].push(Rib::new(kind));
1514 let ret = work(self);
1515 self.ribs[ns].pop();
1516 ret
1517 }
1518
1519 fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
1520 if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) {
1521 let orig_module = replace(&mut self.parent_scope.module, module);
1523 self.with_rib(ValueNS, RibKind::Module(module), |this| {
1524 this.with_rib(TypeNS, RibKind::Module(module), |this| {
1525 let ret = f(this);
1526 this.parent_scope.module = orig_module;
1527 ret
1528 })
1529 })
1530 } else {
1531 f(self)
1532 }
1533 }
1534
1535 fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) {
1536 let mut forward_ty_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
1542 let mut forward_const_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
1543 for param in params.iter() {
1544 match param.kind {
1545 GenericParamKind::Type { .. } => {
1546 forward_ty_ban_rib
1547 .bindings
1548 .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
1549 }
1550 GenericParamKind::Const { .. } => {
1551 forward_const_ban_rib
1552 .bindings
1553 .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
1554 }
1555 GenericParamKind::Lifetime => {}
1556 }
1557 }
1558
1559 if add_self_upper {
1569 forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
1571 }
1572
1573 self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1574 for param in params {
1575 match param.kind {
1576 GenericParamKind::Lifetime => {
1577 for bound in ¶m.bounds {
1578 this.visit_param_bound(bound, BoundKind::Bound);
1579 }
1580 }
1581 GenericParamKind::Type { ref default } => {
1582 for bound in ¶m.bounds {
1583 this.visit_param_bound(bound, BoundKind::Bound);
1584 }
1585
1586 if let Some(ref ty) = default {
1587 this.ribs[TypeNS].push(forward_ty_ban_rib);
1588 this.ribs[ValueNS].push(forward_const_ban_rib);
1589 this.visit_ty(ty);
1590 forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
1591 forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
1592 }
1593
1594 forward_ty_ban_rib
1596 .bindings
1597 .remove(&Ident::with_dummy_span(param.ident.name));
1598 }
1599 GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
1600 assert!(param.bounds.is_empty());
1602
1603 this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
1604 this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
1605 this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
1606 this.visit_ty(ty)
1607 });
1608 this.ribs[TypeNS].pop().unwrap();
1609 this.ribs[ValueNS].pop().unwrap();
1610
1611 if let Some(ref expr) = default {
1612 this.ribs[TypeNS].push(forward_ty_ban_rib);
1613 this.ribs[ValueNS].push(forward_const_ban_rib);
1614 this.resolve_anon_const(
1615 expr,
1616 AnonConstKind::ConstArg(IsRepeatExpr::No),
1617 );
1618 forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
1619 forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
1620 }
1621
1622 forward_const_ban_rib
1624 .bindings
1625 .remove(&Ident::with_dummy_span(param.ident.name));
1626 }
1627 }
1628 }
1629 })
1630 }
1631
1632 #[instrument(level = "debug", skip(self, work))]
1633 fn with_lifetime_rib<T>(
1634 &mut self,
1635 kind: LifetimeRibKind,
1636 work: impl FnOnce(&mut Self) -> T,
1637 ) -> T {
1638 self.lifetime_ribs.push(LifetimeRib::new(kind));
1639 let outer_elision_candidates = self.lifetime_elision_candidates.take();
1640 let ret = work(self);
1641 self.lifetime_elision_candidates = outer_elision_candidates;
1642 self.lifetime_ribs.pop();
1643 ret
1644 }
1645
1646 #[instrument(level = "debug", skip(self))]
1647 fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
1648 let ident = lifetime.ident;
1649
1650 if ident.name == kw::StaticLifetime {
1651 self.record_lifetime_res(
1652 lifetime.id,
1653 LifetimeRes::Static { suppress_elision_warning: false },
1654 LifetimeElisionCandidate::Named,
1655 );
1656 return;
1657 }
1658
1659 if ident.name == kw::UnderscoreLifetime {
1660 return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false);
1661 }
1662
1663 let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
1664 while let Some(rib) = lifetime_rib_iter.next() {
1665 let normalized_ident = ident.normalize_to_macros_2_0();
1666 if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
1667 self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
1668
1669 if let LifetimeRes::Param { param, binder } = res {
1670 match self.lifetime_uses.entry(param) {
1671 Entry::Vacant(v) => {
1672 debug!("First use of {:?} at {:?}", res, ident.span);
1673 let use_set = self
1674 .lifetime_ribs
1675 .iter()
1676 .rev()
1677 .find_map(|rib| match rib.kind {
1678 LifetimeRibKind::Item
1681 | LifetimeRibKind::AnonymousReportError
1682 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
1683 | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
1684 LifetimeRibKind::AnonymousCreateParameter {
1687 binder: anon_binder,
1688 ..
1689 } => Some(if binder == anon_binder {
1690 LifetimeUseSet::One { use_span: ident.span, use_ctxt }
1691 } else {
1692 LifetimeUseSet::Many
1693 }),
1694 LifetimeRibKind::Elided(r) => Some(if res == r {
1697 LifetimeUseSet::One { use_span: ident.span, use_ctxt }
1698 } else {
1699 LifetimeUseSet::Many
1700 }),
1701 LifetimeRibKind::Generics { .. }
1702 | LifetimeRibKind::ConstParamTy => None,
1703 LifetimeRibKind::ConcreteAnonConst(_) => {
1704 span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
1705 }
1706 })
1707 .unwrap_or(LifetimeUseSet::Many);
1708 debug!(?use_ctxt, ?use_set);
1709 v.insert(use_set);
1710 }
1711 Entry::Occupied(mut o) => {
1712 debug!("Many uses of {:?} at {:?}", res, ident.span);
1713 *o.get_mut() = LifetimeUseSet::Many;
1714 }
1715 }
1716 }
1717 return;
1718 }
1719
1720 match rib.kind {
1721 LifetimeRibKind::Item => break,
1722 LifetimeRibKind::ConstParamTy => {
1723 self.emit_non_static_lt_in_const_param_ty_error(lifetime);
1724 self.record_lifetime_res(
1725 lifetime.id,
1726 LifetimeRes::Error,
1727 LifetimeElisionCandidate::Ignore,
1728 );
1729 return;
1730 }
1731 LifetimeRibKind::ConcreteAnonConst(cause) => {
1732 self.emit_forbidden_non_static_lifetime_error(cause, lifetime);
1733 self.record_lifetime_res(
1734 lifetime.id,
1735 LifetimeRes::Error,
1736 LifetimeElisionCandidate::Ignore,
1737 );
1738 return;
1739 }
1740 LifetimeRibKind::AnonymousCreateParameter { .. }
1741 | LifetimeRibKind::Elided(_)
1742 | LifetimeRibKind::Generics { .. }
1743 | LifetimeRibKind::ElisionFailure
1744 | LifetimeRibKind::AnonymousReportError
1745 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {}
1746 }
1747 }
1748
1749 let normalized_ident = ident.normalize_to_macros_2_0();
1750 let outer_res = lifetime_rib_iter
1751 .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer));
1752
1753 self.emit_undeclared_lifetime_error(lifetime, outer_res);
1754 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
1755 }
1756
1757 #[instrument(level = "debug", skip(self))]
1758 fn resolve_anonymous_lifetime(
1759 &mut self,
1760 lifetime: &Lifetime,
1761 id_for_lint: NodeId,
1762 elided: bool,
1763 ) {
1764 debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
1765
1766 let kind =
1767 if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore };
1768 let missing_lifetime = MissingLifetime {
1769 id: lifetime.id,
1770 span: lifetime.ident.span,
1771 kind,
1772 count: 1,
1773 id_for_lint,
1774 };
1775 let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
1776 for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
1777 debug!(?rib.kind);
1778 match rib.kind {
1779 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
1780 let res = self.create_fresh_lifetime(lifetime.ident, binder, kind);
1781 self.record_lifetime_res(lifetime.id, res, elision_candidate);
1782 return;
1783 }
1784 LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
1785 let mut lifetimes_in_scope = vec![];
1786 for rib in &self.lifetime_ribs[..i] {
1787 lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
1788 if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
1790 && let Some(extra) = self.r.extra_lifetime_params_map.get(&binder)
1791 {
1792 lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
1793 }
1794 }
1795 if lifetimes_in_scope.is_empty() {
1796 self.record_lifetime_res(
1797 lifetime.id,
1798 LifetimeRes::Static { suppress_elision_warning: true },
1800 elision_candidate,
1801 );
1802 return;
1803 } else if emit_lint {
1804 self.r.lint_buffer.buffer_lint(
1805 lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
1806 node_id,
1807 lifetime.ident.span,
1808 lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
1809 elided,
1810 span: lifetime.ident.span,
1811 lifetimes_in_scope: lifetimes_in_scope.into(),
1812 },
1813 );
1814 }
1815 }
1816 LifetimeRibKind::AnonymousReportError => {
1817 if elided {
1818 let suggestion = self.lifetime_ribs[i..].iter().rev().find_map(|rib| {
1819 if let LifetimeRibKind::Generics {
1820 span,
1821 kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound,
1822 ..
1823 } = rib.kind
1824 {
1825 Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion {
1826 lo: span.shrink_to_lo(),
1827 hi: lifetime.ident.span.shrink_to_hi(),
1828 })
1829 } else {
1830 None
1831 }
1832 });
1833 if !self.in_func_body
1836 && let Some((module, _)) = &self.current_trait_ref
1837 && let Some(ty) = &self.diag_metadata.current_self_type
1838 && Some(true) == self.diag_metadata.in_non_gat_assoc_type
1839 && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind
1840 {
1841 if def_id_matches_path(
1842 self.r.tcx,
1843 trait_id,
1844 &["core", "iter", "traits", "iterator", "Iterator"],
1845 ) {
1846 self.r.dcx().emit_err(errors::LendingIteratorReportError {
1847 lifetime: lifetime.ident.span,
1848 ty: ty.span,
1849 });
1850 } else {
1851 self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError {
1852 lifetime: lifetime.ident.span,
1853 });
1854 }
1855 } else {
1856 self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
1857 span: lifetime.ident.span,
1858 suggestion,
1859 });
1860 }
1861 } else {
1862 self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError {
1863 span: lifetime.ident.span,
1864 });
1865 };
1866 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1867 return;
1868 }
1869 LifetimeRibKind::Elided(res) => {
1870 self.record_lifetime_res(lifetime.id, res, elision_candidate);
1871 return;
1872 }
1873 LifetimeRibKind::ElisionFailure => {
1874 self.diag_metadata.current_elision_failures.push(missing_lifetime);
1875 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1876 return;
1877 }
1878 LifetimeRibKind::Item => break,
1879 LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
1880 LifetimeRibKind::ConcreteAnonConst(_) => {
1881 span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
1883 }
1884 }
1885 }
1886 self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1887 self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
1888 }
1889
1890 #[instrument(level = "debug", skip(self))]
1891 fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
1892 let id = self.r.next_node_id();
1893 let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };
1894
1895 self.record_lifetime_res(
1896 anchor_id,
1897 LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
1898 LifetimeElisionCandidate::Ignore,
1899 );
1900 self.resolve_anonymous_lifetime(<, anchor_id, true);
1901 }
1902
1903 #[instrument(level = "debug", skip(self))]
1904 fn create_fresh_lifetime(
1905 &mut self,
1906 ident: Ident,
1907 binder: NodeId,
1908 kind: MissingLifetimeKind,
1909 ) -> LifetimeRes {
1910 debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
1911 debug!(?ident.span);
1912
1913 let param = self.r.next_node_id();
1915 let res = LifetimeRes::Fresh { param, binder, kind };
1916 self.record_lifetime_param(param, res);
1917
1918 self.r
1920 .extra_lifetime_params_map
1921 .entry(binder)
1922 .or_insert_with(Vec::new)
1923 .push((ident, param, res));
1924 res
1925 }
1926
1927 #[instrument(level = "debug", skip(self))]
1928 fn resolve_elided_lifetimes_in_path(
1929 &mut self,
1930 partial_res: PartialRes,
1931 path: &[Segment],
1932 source: PathSource<'_>,
1933 path_span: Span,
1934 ) {
1935 let proj_start = path.len() - partial_res.unresolved_segments();
1936 for (i, segment) in path.iter().enumerate() {
1937 if segment.has_lifetime_args {
1938 continue;
1939 }
1940 let Some(segment_id) = segment.id else {
1941 continue;
1942 };
1943
1944 let type_def_id = match partial_res.base_res() {
1947 Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
1948 self.r.tcx.parent(def_id)
1949 }
1950 Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
1951 self.r.tcx.parent(def_id)
1952 }
1953 Res::Def(DefKind::Struct, def_id)
1954 | Res::Def(DefKind::Union, def_id)
1955 | Res::Def(DefKind::Enum, def_id)
1956 | Res::Def(DefKind::TyAlias, def_id)
1957 | Res::Def(DefKind::Trait, def_id)
1958 if i + 1 == proj_start =>
1959 {
1960 def_id
1961 }
1962 _ => continue,
1963 };
1964
1965 let expected_lifetimes = self.r.item_generics_num_lifetimes(type_def_id);
1966 if expected_lifetimes == 0 {
1967 continue;
1968 }
1969
1970 let node_ids = self.r.next_node_ids(expected_lifetimes);
1971 self.record_lifetime_res(
1972 segment_id,
1973 LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
1974 LifetimeElisionCandidate::Ignore,
1975 );
1976
1977 let inferred = match source {
1978 PathSource::Trait(..)
1979 | PathSource::TraitItem(..)
1980 | PathSource::Type
1981 | PathSource::PreciseCapturingArg(..)
1982 | PathSource::ReturnTypeNotation => false,
1983 PathSource::Expr(..)
1984 | PathSource::Pat
1985 | PathSource::Struct
1986 | PathSource::TupleStruct(..)
1987 | PathSource::Delegation => true,
1988 };
1989 if inferred {
1990 for id in node_ids {
1993 self.record_lifetime_res(
1994 id,
1995 LifetimeRes::Infer,
1996 LifetimeElisionCandidate::Named,
1997 );
1998 }
1999 continue;
2000 }
2001
2002 let elided_lifetime_span = if segment.has_generic_args {
2003 segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
2005 } else {
2006 segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
2010 };
2011 let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span);
2012
2013 let kind = if segment.has_generic_args {
2014 MissingLifetimeKind::Comma
2015 } else {
2016 MissingLifetimeKind::Brackets
2017 };
2018 let missing_lifetime = MissingLifetime {
2019 id: node_ids.start,
2020 id_for_lint: segment_id,
2021 span: elided_lifetime_span,
2022 kind,
2023 count: expected_lifetimes,
2024 };
2025 let mut should_lint = true;
2026 for rib in self.lifetime_ribs.iter().rev() {
2027 match rib.kind {
2028 LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
2035 | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {
2036 let sess = self.r.tcx.sess;
2037 let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
2038 sess.source_map(),
2039 expected_lifetimes,
2040 path_span,
2041 !segment.has_generic_args,
2042 elided_lifetime_span,
2043 );
2044 self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere {
2045 span: path_span,
2046 subdiag,
2047 });
2048 should_lint = false;
2049
2050 for id in node_ids {
2051 self.record_lifetime_res(
2052 id,
2053 LifetimeRes::Error,
2054 LifetimeElisionCandidate::Named,
2055 );
2056 }
2057 break;
2058 }
2059 LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
2061 let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
2063 for id in node_ids {
2064 let res = self.create_fresh_lifetime(ident, binder, kind);
2065 self.record_lifetime_res(
2066 id,
2067 res,
2068 replace(&mut candidate, LifetimeElisionCandidate::Named),
2069 );
2070 }
2071 break;
2072 }
2073 LifetimeRibKind::Elided(res) => {
2074 let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
2075 for id in node_ids {
2076 self.record_lifetime_res(
2077 id,
2078 res,
2079 replace(&mut candidate, LifetimeElisionCandidate::Ignore),
2080 );
2081 }
2082 break;
2083 }
2084 LifetimeRibKind::ElisionFailure => {
2085 self.diag_metadata.current_elision_failures.push(missing_lifetime);
2086 for id in node_ids {
2087 self.record_lifetime_res(
2088 id,
2089 LifetimeRes::Error,
2090 LifetimeElisionCandidate::Ignore,
2091 );
2092 }
2093 break;
2094 }
2095 LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
2100 for id in node_ids {
2101 self.record_lifetime_res(
2102 id,
2103 LifetimeRes::Error,
2104 LifetimeElisionCandidate::Ignore,
2105 );
2106 }
2107 self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
2108 break;
2109 }
2110 LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
2111 LifetimeRibKind::ConcreteAnonConst(_) => {
2112 span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
2114 }
2115 }
2116 }
2117
2118 if should_lint {
2119 self.r.lint_buffer.buffer_lint(
2120 lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
2121 segment_id,
2122 elided_lifetime_span,
2123 lint::BuiltinLintDiag::ElidedLifetimesInPaths(
2124 expected_lifetimes,
2125 path_span,
2126 !segment.has_generic_args,
2127 elided_lifetime_span,
2128 ),
2129 );
2130 }
2131 }
2132 }
2133
2134 #[instrument(level = "debug", skip(self))]
2135 fn record_lifetime_res(
2136 &mut self,
2137 id: NodeId,
2138 res: LifetimeRes,
2139 candidate: LifetimeElisionCandidate,
2140 ) {
2141 if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
2142 panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)")
2143 }
2144
2145 match candidate {
2146 LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => {
2147 debug_assert_eq!(id, missing.id);
2148 match res {
2149 LifetimeRes::Static { suppress_elision_warning } => {
2150 if !suppress_elision_warning {
2151 self.r.lint_buffer.buffer_lint(
2152 lint::builtin::ELIDED_NAMED_LIFETIMES,
2153 missing.id_for_lint,
2154 missing.span,
2155 BuiltinLintDiag::ElidedNamedLifetimes {
2156 elided: (missing.span, missing.kind),
2157 resolution: lint::ElidedLifetimeResolution::Static,
2158 },
2159 );
2160 }
2161 }
2162 LifetimeRes::Param { param, binder: _ } => {
2163 let tcx = self.r.tcx();
2164 self.r.lint_buffer.buffer_lint(
2165 lint::builtin::ELIDED_NAMED_LIFETIMES,
2166 missing.id_for_lint,
2167 missing.span,
2168 BuiltinLintDiag::ElidedNamedLifetimes {
2169 elided: (missing.span, missing.kind),
2170 resolution: lint::ElidedLifetimeResolution::Param(
2171 tcx.item_name(param.into()),
2172 tcx.source_span(param),
2173 ),
2174 },
2175 );
2176 }
2177 LifetimeRes::Fresh { .. }
2178 | LifetimeRes::Infer
2179 | LifetimeRes::Error
2180 | LifetimeRes::ElidedAnchor { .. } => {}
2181 }
2182 }
2183 LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {}
2184 }
2185
2186 match res {
2187 LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => {
2188 if let Some(ref mut candidates) = self.lifetime_elision_candidates {
2189 candidates.push((res, candidate));
2190 }
2191 }
2192 LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
2193 }
2194 }
2195
2196 #[instrument(level = "debug", skip(self))]
2197 fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) {
2198 if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
2199 panic!(
2200 "lifetime parameter {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)"
2201 )
2202 }
2203 }
2204
2205 #[instrument(level = "debug", skip(self, inputs))]
2207 fn resolve_fn_signature(
2208 &mut self,
2209 fn_id: NodeId,
2210 has_self: bool,
2211 inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone,
2212 output_ty: &'ast FnRetTy,
2213 ) {
2214 let elision_lifetime = self.resolve_fn_params(has_self, inputs);
2216 debug!(?elision_lifetime);
2217
2218 let outer_failures = take(&mut self.diag_metadata.current_elision_failures);
2219 let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
2220 self.r.lifetime_elision_allowed.insert(fn_id);
2221 LifetimeRibKind::Elided(*res)
2222 } else {
2223 LifetimeRibKind::ElisionFailure
2224 };
2225 self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty));
2226 let elision_failures =
2227 replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
2228 if !elision_failures.is_empty() {
2229 let Err(failure_info) = elision_lifetime else { bug!() };
2230 self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info));
2231 }
2232 }
2233
2234 fn resolve_fn_params(
2238 &mut self,
2239 has_self: bool,
2240 inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>,
2241 ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> {
2242 enum Elision {
2243 None,
2245 Self_(LifetimeRes),
2247 Param(LifetimeRes),
2249 Err,
2251 }
2252
2253 let outer_candidates = self.lifetime_elision_candidates.take();
2255
2256 let mut elision_lifetime = Elision::None;
2258 let mut parameter_info = Vec::new();
2260 let mut all_candidates = Vec::new();
2261
2262 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
2263 for (index, (pat, ty)) in inputs.enumerate() {
2264 debug!(?pat, ?ty);
2265 self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
2266 if let Some(pat) = pat {
2267 this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
2268 }
2269 });
2270
2271 debug_assert_matches!(self.lifetime_elision_candidates, None);
2273 self.lifetime_elision_candidates = Some(Default::default());
2274 self.visit_ty(ty);
2275 let local_candidates = self.lifetime_elision_candidates.take();
2276
2277 if let Some(candidates) = local_candidates {
2278 let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect();
2279 let lifetime_count = distinct.len();
2280 if lifetime_count != 0 {
2281 parameter_info.push(ElisionFnParameter {
2282 index,
2283 ident: if let Some(pat) = pat
2284 && let PatKind::Ident(_, ident, _) = pat.kind
2285 {
2286 Some(ident)
2287 } else {
2288 None
2289 },
2290 lifetime_count,
2291 span: ty.span,
2292 });
2293 all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| {
2294 match candidate {
2295 LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {
2296 None
2297 }
2298 LifetimeElisionCandidate::Missing(missing) => Some(missing),
2299 }
2300 }));
2301 }
2302 let mut distinct_iter = distinct.into_iter();
2303 if let Some(res) = distinct_iter.next() {
2304 match elision_lifetime {
2305 Elision::None => {
2307 if distinct_iter.next().is_none() {
2308 elision_lifetime = Elision::Param(res)
2310 } else {
2311 elision_lifetime = Elision::Err;
2313 }
2314 }
2315 Elision::Param(_) => elision_lifetime = Elision::Err,
2317 Elision::Self_(_) | Elision::Err => {}
2319 }
2320 }
2321 }
2322
2323 if index == 0 && has_self {
2325 let self_lifetime = self.find_lifetime_for_self(ty);
2326 elision_lifetime = match self_lifetime {
2327 Set1::One(lifetime) => Elision::Self_(lifetime),
2329 Set1::Many => Elision::Err,
2334 Set1::Empty => Elision::None,
2337 }
2338 }
2339 debug!("(resolving function / closure) recorded parameter");
2340 }
2341
2342 debug_assert_matches!(self.lifetime_elision_candidates, None);
2344 self.lifetime_elision_candidates = outer_candidates;
2345
2346 if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime {
2347 return Ok(res);
2348 }
2349
2350 Err((all_candidates, parameter_info))
2352 }
2353
2354 fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
2356 struct FindReferenceVisitor<'a, 'ra, 'tcx> {
2360 r: &'a Resolver<'ra, 'tcx>,
2361 impl_self: Option<Res>,
2362 lifetime: Set1<LifetimeRes>,
2363 }
2364
2365 impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> {
2366 fn visit_ty(&mut self, ty: &'ra Ty) {
2367 trace!("FindReferenceVisitor considering ty={:?}", ty);
2368 if let TyKind::Ref(lt, _) | TyKind::PinnedRef(lt, _) = ty.kind {
2369 let mut visitor =
2371 SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
2372 visitor.visit_ty(ty);
2373 trace!("FindReferenceVisitor: SelfVisitor self_found={:?}", visitor.self_found);
2374 if visitor.self_found {
2375 let lt_id = if let Some(lt) = lt {
2376 lt.id
2377 } else {
2378 let res = self.r.lifetimes_res_map[&ty.id];
2379 let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
2380 start
2381 };
2382 let lt_res = self.r.lifetimes_res_map[<_id];
2383 trace!("FindReferenceVisitor inserting res={:?}", lt_res);
2384 self.lifetime.insert(lt_res);
2385 }
2386 }
2387 visit::walk_ty(self, ty)
2388 }
2389
2390 fn visit_expr(&mut self, _: &'ra Expr) {}
2393 }
2394
2395 struct SelfVisitor<'a, 'ra, 'tcx> {
2398 r: &'a Resolver<'ra, 'tcx>,
2399 impl_self: Option<Res>,
2400 self_found: bool,
2401 }
2402
2403 impl SelfVisitor<'_, '_, '_> {
2404 fn is_self_ty(&self, ty: &Ty) -> bool {
2406 match ty.kind {
2407 TyKind::ImplicitSelf => true,
2408 TyKind::Path(None, _) => {
2409 let path_res = self.r.partial_res_map[&ty.id].full_res();
2410 if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res {
2411 return true;
2412 }
2413 self.impl_self.is_some() && path_res == self.impl_self
2414 }
2415 _ => false,
2416 }
2417 }
2418 }
2419
2420 impl<'ra> Visitor<'ra> for SelfVisitor<'_, '_, '_> {
2421 fn visit_ty(&mut self, ty: &'ra Ty) {
2422 trace!("SelfVisitor considering ty={:?}", ty);
2423 if self.is_self_ty(ty) {
2424 trace!("SelfVisitor found Self");
2425 self.self_found = true;
2426 }
2427 visit::walk_ty(self, ty)
2428 }
2429
2430 fn visit_expr(&mut self, _: &'ra Expr) {}
2433 }
2434
2435 let impl_self = self
2436 .diag_metadata
2437 .current_self_type
2438 .as_ref()
2439 .and_then(|ty| {
2440 if let TyKind::Path(None, _) = ty.kind {
2441 self.r.partial_res_map.get(&ty.id)
2442 } else {
2443 None
2444 }
2445 })
2446 .and_then(|res| res.full_res())
2447 .filter(|res| {
2448 matches!(
2452 res,
2453 Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
2454 )
2455 });
2456 let mut visitor = FindReferenceVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
2457 visitor.visit_ty(ty);
2458 trace!("FindReferenceVisitor found={:?}", visitor.lifetime);
2459 visitor.lifetime
2460 }
2461
2462 fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> {
2465 let mut suggestion = None;
2466
2467 for i in (0..self.label_ribs.len()).rev() {
2468 let rib = &self.label_ribs[i];
2469
2470 if let RibKind::MacroDefinition(def) = rib.kind
2471 && def == self.r.macro_def(label.span.ctxt())
2474 {
2475 label.span.remove_mark();
2476 }
2477
2478 let ident = label.normalize_to_macro_rules();
2479 if let Some((ident, id)) = rib.bindings.get_key_value(&ident) {
2480 let definition_span = ident.span;
2481 return if self.is_label_valid_from_rib(i) {
2482 Ok((*id, definition_span))
2483 } else {
2484 Err(ResolutionError::UnreachableLabel {
2485 name: label.name,
2486 definition_span,
2487 suggestion,
2488 })
2489 };
2490 }
2491
2492 suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
2495 }
2496
2497 Err(ResolutionError::UndeclaredLabel { name: label.name, suggestion })
2498 }
2499
2500 fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
2502 let ribs = &self.label_ribs[rib_index + 1..];
2503 ribs.iter().all(|rib| !rib.kind.is_label_barrier())
2504 }
2505
2506 fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
2507 debug!("resolve_adt");
2508 let kind = self.r.local_def_kind(item.id);
2509 self.with_current_self_item(item, |this| {
2510 this.with_generic_param_rib(
2511 &generics.params,
2512 RibKind::Item(HasGenericParams::Yes(generics.span), kind),
2513 LifetimeRibKind::Generics {
2514 binder: item.id,
2515 kind: LifetimeBinderKind::Item,
2516 span: generics.span,
2517 },
2518 |this| {
2519 let item_def_id = this.r.local_def_id(item.id).to_def_id();
2520 this.with_self_rib(
2521 Res::SelfTyAlias {
2522 alias_to: item_def_id,
2523 forbid_generic: false,
2524 is_trait_impl: false,
2525 },
2526 |this| {
2527 visit::walk_item(this, item);
2528 },
2529 );
2530 },
2531 );
2532 });
2533 }
2534
2535 fn future_proof_import(&mut self, use_tree: &UseTree) {
2536 if let [segment, rest @ ..] = use_tree.prefix.segments.as_slice() {
2537 let ident = segment.ident;
2538 if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
2539 return;
2540 }
2541
2542 let nss = match use_tree.kind {
2543 UseTreeKind::Simple(..) if rest.is_empty() => &[TypeNS, ValueNS][..],
2544 _ => &[TypeNS],
2545 };
2546 let report_error = |this: &Self, ns| {
2547 if this.should_report_errs() {
2548 let what = if ns == TypeNS { "type parameters" } else { "local variables" };
2549 this.r.dcx().emit_err(errors::ImportsCannotReferTo { span: ident.span, what });
2550 }
2551 };
2552
2553 for &ns in nss {
2554 match self.maybe_resolve_ident_in_lexical_scope(ident, ns) {
2555 Some(LexicalScopeBinding::Res(..)) => {
2556 report_error(self, ns);
2557 }
2558 Some(LexicalScopeBinding::Item(binding)) => {
2559 if let Some(LexicalScopeBinding::Res(..)) =
2560 self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding))
2561 {
2562 report_error(self, ns);
2563 }
2564 }
2565 None => {}
2566 }
2567 }
2568 } else if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
2569 for (use_tree, _) in items {
2570 self.future_proof_import(use_tree);
2571 }
2572 }
2573 }
2574
2575 fn resolve_item(&mut self, item: &'ast Item) {
2576 let mod_inner_docs =
2577 matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
2578 if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) {
2579 self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
2580 }
2581
2582 let name = item.ident.name;
2583 debug!("(resolving item) resolving {} ({:?})", name, item.kind);
2584
2585 let def_kind = self.r.local_def_kind(item.id);
2586 match item.kind {
2587 ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
2588 self.with_generic_param_rib(
2589 &generics.params,
2590 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2591 LifetimeRibKind::Generics {
2592 binder: item.id,
2593 kind: LifetimeBinderKind::Item,
2594 span: generics.span,
2595 },
2596 |this| visit::walk_item(this, item),
2597 );
2598 }
2599
2600 ItemKind::Fn(box Fn { ref generics, .. }) => {
2601 self.with_generic_param_rib(
2602 &generics.params,
2603 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2604 LifetimeRibKind::Generics {
2605 binder: item.id,
2606 kind: LifetimeBinderKind::Function,
2607 span: generics.span,
2608 },
2609 |this| visit::walk_item(this, item),
2610 );
2611 }
2612
2613 ItemKind::Enum(_, ref generics)
2614 | ItemKind::Struct(_, ref generics)
2615 | ItemKind::Union(_, ref generics) => {
2616 self.resolve_adt(item, generics);
2617 }
2618
2619 ItemKind::Impl(box Impl {
2620 ref generics,
2621 ref of_trait,
2622 ref self_ty,
2623 items: ref impl_items,
2624 ..
2625 }) => {
2626 self.diag_metadata.current_impl_items = Some(impl_items);
2627 self.resolve_implementation(
2628 &item.attrs,
2629 generics,
2630 of_trait,
2631 self_ty,
2632 item.id,
2633 impl_items,
2634 );
2635 self.diag_metadata.current_impl_items = None;
2636 }
2637
2638 ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
2639 self.with_generic_param_rib(
2641 &generics.params,
2642 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2643 LifetimeRibKind::Generics {
2644 binder: item.id,
2645 kind: LifetimeBinderKind::Item,
2646 span: generics.span,
2647 },
2648 |this| {
2649 let local_def_id = this.r.local_def_id(item.id).to_def_id();
2650 this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
2651 this.visit_generics(generics);
2652 walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
2653 this.resolve_trait_items(items);
2654 });
2655 },
2656 );
2657 }
2658
2659 ItemKind::TraitAlias(ref generics, ref bounds) => {
2660 self.with_generic_param_rib(
2662 &generics.params,
2663 RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
2664 LifetimeRibKind::Generics {
2665 binder: item.id,
2666 kind: LifetimeBinderKind::Item,
2667 span: generics.span,
2668 },
2669 |this| {
2670 let local_def_id = this.r.local_def_id(item.id).to_def_id();
2671 this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
2672 this.visit_generics(generics);
2673 walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
2674 });
2675 },
2676 );
2677 }
2678
2679 ItemKind::Mod(..) => {
2680 self.with_scope(item.id, |this| {
2681 if mod_inner_docs {
2682 this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
2683 }
2684 let old_macro_rules = this.parent_scope.macro_rules;
2685 visit::walk_item(this, item);
2686 if item.attrs.iter().all(|attr| {
2689 !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
2690 }) {
2691 this.parent_scope.macro_rules = old_macro_rules;
2692 }
2693 });
2694 }
2695
2696 ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
2697 self.with_static_rib(def_kind, |this| {
2698 this.with_lifetime_rib(
2699 LifetimeRibKind::Elided(LifetimeRes::Static {
2700 suppress_elision_warning: true,
2701 }),
2702 |this| {
2703 this.visit_ty(ty);
2704 },
2705 );
2706 if let Some(expr) = expr {
2707 this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
2710 }
2711 });
2712 }
2713
2714 ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
2715 self.with_generic_param_rib(
2716 &generics.params,
2717 RibKind::Item(
2718 if self.r.tcx.features().generic_const_items() {
2719 HasGenericParams::Yes(generics.span)
2720 } else {
2721 HasGenericParams::No
2722 },
2723 def_kind,
2724 ),
2725 LifetimeRibKind::Generics {
2726 binder: item.id,
2727 kind: LifetimeBinderKind::ConstItem,
2728 span: generics.span,
2729 },
2730 |this| {
2731 this.visit_generics(generics);
2732
2733 this.with_lifetime_rib(
2734 LifetimeRibKind::Elided(LifetimeRes::Static {
2735 suppress_elision_warning: true,
2736 }),
2737 |this| this.visit_ty(ty),
2738 );
2739
2740 if let Some(expr) = expr {
2741 this.resolve_const_body(
2742 expr,
2743 Some((item.ident, ConstantItemKind::Const)),
2744 );
2745 }
2746 },
2747 );
2748 }
2749
2750 ItemKind::Use(ref use_tree) => {
2751 let maybe_exported = match use_tree.kind {
2752 UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
2753 UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis),
2754 };
2755 self.resolve_doc_links(&item.attrs, maybe_exported);
2756
2757 self.future_proof_import(use_tree);
2758 }
2759
2760 ItemKind::MacroDef(ref macro_def) => {
2761 if macro_def.macro_rules {
2764 let def_id = self.r.local_def_id(item.id);
2765 self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id];
2766 }
2767 }
2768
2769 ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) => {
2770 visit::walk_item(self, item);
2771 }
2772
2773 ItemKind::Delegation(ref delegation) => {
2774 let span = delegation.path.segments.last().unwrap().ident.span;
2775 self.with_generic_param_rib(
2776 &[],
2777 RibKind::Item(HasGenericParams::Yes(span), def_kind),
2778 LifetimeRibKind::Generics {
2779 binder: item.id,
2780 kind: LifetimeBinderKind::Function,
2781 span,
2782 },
2783 |this| this.resolve_delegation(delegation),
2784 );
2785 }
2786
2787 ItemKind::ExternCrate(..) => {}
2788
2789 ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
2790 panic!("unexpanded macro in resolve!")
2791 }
2792 }
2793 }
2794
2795 fn with_generic_param_rib<'c, F>(
2796 &'c mut self,
2797 params: &'c [GenericParam],
2798 kind: RibKind<'ra>,
2799 lifetime_kind: LifetimeRibKind,
2800 f: F,
2801 ) where
2802 F: FnOnce(&mut Self),
2803 {
2804 debug!("with_generic_param_rib");
2805 let LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind, .. } =
2806 lifetime_kind
2807 else {
2808 panic!()
2809 };
2810
2811 let mut function_type_rib = Rib::new(kind);
2812 let mut function_value_rib = Rib::new(kind);
2813 let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
2814
2815 if !params.is_empty() {
2817 let mut seen_bindings = FxHashMap::default();
2818 let mut seen_lifetimes = FxHashSet::default();
2820
2821 for ns in [ValueNS, TypeNS] {
2823 for parent_rib in self.ribs[ns].iter().rev() {
2824 if matches!(parent_rib.kind, RibKind::Module(..)) {
2827 break;
2828 }
2829
2830 seen_bindings
2831 .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
2832 }
2833 }
2834
2835 for rib in self.lifetime_ribs.iter().rev() {
2837 seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
2838 if let LifetimeRibKind::Item = rib.kind {
2839 break;
2840 }
2841 }
2842
2843 for param in params {
2844 let ident = param.ident.normalize_to_macros_2_0();
2845 debug!("with_generic_param_rib: {}", param.id);
2846
2847 if let GenericParamKind::Lifetime = param.kind
2848 && let Some(&original) = seen_lifetimes.get(&ident)
2849 {
2850 diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
2851 self.record_lifetime_param(param.id, LifetimeRes::Error);
2853 continue;
2854 }
2855
2856 match seen_bindings.entry(ident) {
2857 Entry::Occupied(entry) => {
2858 let span = *entry.get();
2859 let err = ResolutionError::NameAlreadyUsedInParameterList(ident, span);
2860 self.report_error(param.ident.span, err);
2861 let rib = match param.kind {
2862 GenericParamKind::Lifetime => {
2863 self.record_lifetime_param(param.id, LifetimeRes::Error);
2865 continue;
2866 }
2867 GenericParamKind::Type { .. } => &mut function_type_rib,
2868 GenericParamKind::Const { .. } => &mut function_value_rib,
2869 };
2870
2871 self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
2873 rib.bindings.insert(ident, Res::Err);
2874 continue;
2875 }
2876 Entry::Vacant(entry) => {
2877 entry.insert(param.ident.span);
2878 }
2879 }
2880
2881 if param.ident.name == kw::UnderscoreLifetime {
2882 self.r
2883 .dcx()
2884 .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
2885 self.record_lifetime_param(param.id, LifetimeRes::Error);
2887 continue;
2888 }
2889
2890 if param.ident.name == kw::StaticLifetime {
2891 self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
2892 span: param.ident.span,
2893 lifetime: param.ident,
2894 });
2895 self.record_lifetime_param(param.id, LifetimeRes::Error);
2897 continue;
2898 }
2899
2900 let def_id = self.r.local_def_id(param.id);
2901
2902 let (rib, def_kind) = match param.kind {
2904 GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
2905 GenericParamKind::Const { .. } => {
2906 (&mut function_value_rib, DefKind::ConstParam)
2907 }
2908 GenericParamKind::Lifetime => {
2909 let res = LifetimeRes::Param { param: def_id, binder };
2910 self.record_lifetime_param(param.id, res);
2911 function_lifetime_rib.bindings.insert(ident, (param.id, res));
2912 continue;
2913 }
2914 };
2915
2916 let res = match kind {
2917 RibKind::Item(..) | RibKind::AssocItem => {
2918 Res::Def(def_kind, def_id.to_def_id())
2919 }
2920 RibKind::Normal => {
2921 if self.r.tcx.features().non_lifetime_binders()
2924 && matches!(param.kind, GenericParamKind::Type { .. })
2925 {
2926 Res::Def(def_kind, def_id.to_def_id())
2927 } else {
2928 Res::Err
2929 }
2930 }
2931 _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
2932 };
2933 self.r.record_partial_res(param.id, PartialRes::new(res));
2934 rib.bindings.insert(ident, res);
2935 }
2936 }
2937
2938 self.lifetime_ribs.push(function_lifetime_rib);
2939 self.ribs[ValueNS].push(function_value_rib);
2940 self.ribs[TypeNS].push(function_type_rib);
2941
2942 f(self);
2943
2944 self.ribs[TypeNS].pop();
2945 self.ribs[ValueNS].pop();
2946 let function_lifetime_rib = self.lifetime_ribs.pop().unwrap();
2947
2948 if let Some(ref mut candidates) = self.lifetime_elision_candidates {
2950 for (_, res) in function_lifetime_rib.bindings.values() {
2951 candidates.retain(|(r, _)| r != res);
2952 }
2953 }
2954
2955 if let LifetimeBinderKind::BareFnType
2956 | LifetimeBinderKind::WhereBound
2957 | LifetimeBinderKind::Function
2958 | LifetimeBinderKind::ImplBlock = generics_kind
2959 {
2960 self.maybe_report_lifetime_uses(generics_span, params)
2961 }
2962 }
2963
2964 fn with_label_rib(&mut self, kind: RibKind<'ra>, f: impl FnOnce(&mut Self)) {
2965 self.label_ribs.push(Rib::new(kind));
2966 f(self);
2967 self.label_ribs.pop();
2968 }
2969
2970 fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) {
2971 let kind = RibKind::Item(HasGenericParams::No, def_kind);
2972 self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
2973 }
2974
2975 #[instrument(level = "debug", skip(self, f))]
2984 fn with_constant_rib(
2985 &mut self,
2986 is_repeat: IsRepeatExpr,
2987 may_use_generics: ConstantHasGenerics,
2988 item: Option<(Ident, ConstantItemKind)>,
2989 f: impl FnOnce(&mut Self),
2990 ) {
2991 let f = |this: &mut Self| {
2992 this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
2993 this.with_rib(
2994 TypeNS,
2995 RibKind::ConstantItem(
2996 may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
2997 item,
2998 ),
2999 |this| {
3000 this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
3001 },
3002 )
3003 })
3004 };
3005
3006 if let ConstantHasGenerics::No(cause) = may_use_generics {
3007 self.with_lifetime_rib(LifetimeRibKind::ConcreteAnonConst(cause), f)
3008 } else {
3009 f(self)
3010 }
3011 }
3012
3013 fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
3014 let previous_value =
3016 replace(&mut self.diag_metadata.current_self_type, Some(self_type.clone()));
3017 let result = f(self);
3018 self.diag_metadata.current_self_type = previous_value;
3019 result
3020 }
3021
3022 fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T {
3023 let previous_value = replace(&mut self.diag_metadata.current_self_item, Some(self_item.id));
3024 let result = f(self);
3025 self.diag_metadata.current_self_item = previous_value;
3026 result
3027 }
3028
3029 fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
3031 let trait_assoc_items =
3032 replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items));
3033
3034 let walk_assoc_item =
3035 |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| {
3036 this.with_generic_param_rib(
3037 &generics.params,
3038 RibKind::AssocItem,
3039 LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind },
3040 |this| visit::walk_assoc_item(this, item, AssocCtxt::Trait),
3041 );
3042 };
3043
3044 for item in trait_items {
3045 self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
3046 match &item.kind {
3047 AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
3048 self.with_generic_param_rib(
3049 &generics.params,
3050 RibKind::AssocItem,
3051 LifetimeRibKind::Generics {
3052 binder: item.id,
3053 span: generics.span,
3054 kind: LifetimeBinderKind::ConstItem,
3055 },
3056 |this| {
3057 this.with_lifetime_rib(
3058 LifetimeRibKind::StaticIfNoLifetimeInScope {
3059 lint_id: item.id,
3060 emit_lint: false,
3061 },
3062 |this| {
3063 this.visit_generics(generics);
3064 this.visit_ty(ty);
3065
3066 if let Some(expr) = expr {
3069 this.resolve_const_body(expr, None);
3075 }
3076 },
3077 )
3078 },
3079 );
3080 }
3081 AssocItemKind::Fn(box Fn { generics, .. }) => {
3082 walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
3083 }
3084 AssocItemKind::Delegation(delegation) => {
3085 self.with_generic_param_rib(
3086 &[],
3087 RibKind::AssocItem,
3088 LifetimeRibKind::Generics {
3089 binder: item.id,
3090 kind: LifetimeBinderKind::Function,
3091 span: delegation.path.segments.last().unwrap().ident.span,
3092 },
3093 |this| this.resolve_delegation(delegation),
3094 );
3095 }
3096 AssocItemKind::Type(box TyAlias { generics, .. }) => self
3097 .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
3098 walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
3099 }),
3100 AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
3101 panic!("unexpanded macro in resolve!")
3102 }
3103 };
3104 }
3105
3106 self.diag_metadata.current_trait_assoc_items = trait_assoc_items;
3107 }
3108
3109 fn with_optional_trait_ref<T>(
3111 &mut self,
3112 opt_trait_ref: Option<&TraitRef>,
3113 self_type: &'ast Ty,
3114 f: impl FnOnce(&mut Self, Option<DefId>) -> T,
3115 ) -> T {
3116 let mut new_val = None;
3117 let mut new_id = None;
3118 if let Some(trait_ref) = opt_trait_ref {
3119 let path: Vec<_> = Segment::from_path(&trait_ref.path);
3120 self.diag_metadata.currently_processing_impl_trait =
3121 Some((trait_ref.clone(), self_type.clone()));
3122 let res = self.smart_resolve_path_fragment(
3123 &None,
3124 &path,
3125 PathSource::Trait(AliasPossibility::No),
3126 Finalize::new(trait_ref.ref_id, trait_ref.path.span),
3127 RecordPartialRes::Yes,
3128 );
3129 self.diag_metadata.currently_processing_impl_trait = None;
3130 if let Some(def_id) = res.expect_full_res().opt_def_id() {
3131 new_id = Some(def_id);
3132 new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
3133 }
3134 }
3135 let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
3136 let result = f(self, new_id);
3137 self.current_trait_ref = original_trait_ref;
3138 result
3139 }
3140
3141 fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) {
3142 let mut self_type_rib = Rib::new(RibKind::Normal);
3143
3144 self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
3146 self.ribs[ns].push(self_type_rib);
3147 f(self);
3148 self.ribs[ns].pop();
3149 }
3150
3151 fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) {
3152 self.with_self_rib_ns(TypeNS, self_res, f)
3153 }
3154
3155 fn resolve_implementation(
3156 &mut self,
3157 attrs: &[ast::Attribute],
3158 generics: &'ast Generics,
3159 opt_trait_reference: &'ast Option<TraitRef>,
3160 self_type: &'ast Ty,
3161 item_id: NodeId,
3162 impl_items: &'ast [P<AssocItem>],
3163 ) {
3164 debug!("resolve_implementation");
3165 self.with_generic_param_rib(
3167 &generics.params,
3168 RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)),
3169 LifetimeRibKind::Generics {
3170 span: generics.span,
3171 binder: item_id,
3172 kind: LifetimeBinderKind::ImplBlock,
3173 },
3174 |this| {
3175 this.with_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| {
3177 this.with_lifetime_rib(
3178 LifetimeRibKind::AnonymousCreateParameter {
3179 binder: item_id,
3180 report_in_path: true
3181 },
3182 |this| {
3183 this.with_optional_trait_ref(
3185 opt_trait_reference.as_ref(),
3186 self_type,
3187 |this, trait_id| {
3188 this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id));
3189
3190 let item_def_id = this.r.local_def_id(item_id);
3191
3192 if let Some(trait_id) = trait_id {
3194 this.r
3195 .trait_impls
3196 .entry(trait_id)
3197 .or_default()
3198 .push(item_def_id);
3199 }
3200
3201 let item_def_id = item_def_id.to_def_id();
3202 let res = Res::SelfTyAlias {
3203 alias_to: item_def_id,
3204 forbid_generic: false,
3205 is_trait_impl: trait_id.is_some()
3206 };
3207 this.with_self_rib(res, |this| {
3208 if let Some(trait_ref) = opt_trait_reference.as_ref() {
3209 visit::walk_trait_ref(this, trait_ref);
3211 }
3212 this.visit_ty(self_type);
3214 this.visit_generics(generics);
3216
3217 this.with_current_self_type(self_type, |this| {
3219 this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
3220 debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
3221 let mut seen_trait_items = Default::default();
3222 for item in impl_items {
3223 this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
3224 }
3225 });
3226 });
3227 });
3228 },
3229 )
3230 },
3231 );
3232 });
3233 },
3234 );
3235 }
3236
3237 fn resolve_impl_item(
3238 &mut self,
3239 item: &'ast AssocItem,
3240 seen_trait_items: &mut FxHashMap<DefId, Span>,
3241 trait_id: Option<DefId>,
3242 ) {
3243 use crate::ResolutionError::*;
3244 self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
3245 match &item.kind {
3246 AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
3247 debug!("resolve_implementation AssocItemKind::Const");
3248 self.with_generic_param_rib(
3249 &generics.params,
3250 RibKind::AssocItem,
3251 LifetimeRibKind::Generics {
3252 binder: item.id,
3253 span: generics.span,
3254 kind: LifetimeBinderKind::ConstItem,
3255 },
3256 |this| {
3257 this.with_lifetime_rib(
3258 LifetimeRibKind::StaticIfNoLifetimeInScope {
3259 lint_id: item.id,
3260 emit_lint: true,
3262 },
3263 |this| {
3264 this.check_trait_item(
3267 item.id,
3268 item.ident,
3269 &item.kind,
3270 ValueNS,
3271 item.span,
3272 seen_trait_items,
3273 |i, s, c| ConstNotMemberOfTrait(i, s, c),
3274 );
3275
3276 this.visit_generics(generics);
3277 this.visit_ty(ty);
3278 if let Some(expr) = expr {
3279 this.resolve_const_body(expr, None);
3285 }
3286 },
3287 );
3288 },
3289 );
3290 }
3291 AssocItemKind::Fn(box Fn { generics, .. }) => {
3292 debug!("resolve_implementation AssocItemKind::Fn");
3293 self.with_generic_param_rib(
3295 &generics.params,
3296 RibKind::AssocItem,
3297 LifetimeRibKind::Generics {
3298 binder: item.id,
3299 span: generics.span,
3300 kind: LifetimeBinderKind::Function,
3301 },
3302 |this| {
3303 this.check_trait_item(
3306 item.id,
3307 item.ident,
3308 &item.kind,
3309 ValueNS,
3310 item.span,
3311 seen_trait_items,
3312 |i, s, c| MethodNotMemberOfTrait(i, s, c),
3313 );
3314
3315 visit::walk_assoc_item(this, item, AssocCtxt::Impl)
3316 },
3317 );
3318 }
3319 AssocItemKind::Type(box TyAlias { generics, .. }) => {
3320 self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
3321 debug!("resolve_implementation AssocItemKind::Type");
3322 self.with_generic_param_rib(
3324 &generics.params,
3325 RibKind::AssocItem,
3326 LifetimeRibKind::Generics {
3327 binder: item.id,
3328 span: generics.span,
3329 kind: LifetimeBinderKind::Item,
3330 },
3331 |this| {
3332 this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
3333 this.check_trait_item(
3336 item.id,
3337 item.ident,
3338 &item.kind,
3339 TypeNS,
3340 item.span,
3341 seen_trait_items,
3342 |i, s, c| TypeNotMemberOfTrait(i, s, c),
3343 );
3344
3345 visit::walk_assoc_item(this, item, AssocCtxt::Impl)
3346 });
3347 },
3348 );
3349 self.diag_metadata.in_non_gat_assoc_type = None;
3350 }
3351 AssocItemKind::Delegation(box delegation) => {
3352 debug!("resolve_implementation AssocItemKind::Delegation");
3353 self.with_generic_param_rib(
3354 &[],
3355 RibKind::AssocItem,
3356 LifetimeRibKind::Generics {
3357 binder: item.id,
3358 kind: LifetimeBinderKind::Function,
3359 span: delegation.path.segments.last().unwrap().ident.span,
3360 },
3361 |this| {
3362 this.check_trait_item(
3363 item.id,
3364 item.ident,
3365 &item.kind,
3366 ValueNS,
3367 item.span,
3368 seen_trait_items,
3369 |i, s, c| MethodNotMemberOfTrait(i, s, c),
3370 );
3371
3372 this.resolve_delegation(delegation)
3373 },
3374 );
3375 }
3376 AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
3377 panic!("unexpanded macro in resolve!")
3378 }
3379 }
3380 }
3381
3382 fn check_trait_item<F>(
3383 &mut self,
3384 id: NodeId,
3385 mut ident: Ident,
3386 kind: &AssocItemKind,
3387 ns: Namespace,
3388 span: Span,
3389 seen_trait_items: &mut FxHashMap<DefId, Span>,
3390 err: F,
3391 ) where
3392 F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'ra>,
3393 {
3394 let Some((module, _)) = self.current_trait_ref else {
3396 return;
3397 };
3398 ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
3399 let key = BindingKey::new(ident, ns);
3400 let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
3401 debug!(?binding);
3402 if binding.is_none() {
3403 let ns = match ns {
3406 ValueNS => TypeNS,
3407 TypeNS => ValueNS,
3408 _ => ns,
3409 };
3410 let key = BindingKey::new(ident, ns);
3411 binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
3412 debug!(?binding);
3413 }
3414
3415 let feed_visibility = |this: &mut Self, def_id| {
3416 let vis = this.r.tcx.visibility(def_id);
3417 let vis = if vis.is_visible_locally() {
3418 vis.expect_local()
3419 } else {
3420 this.r.dcx().span_delayed_bug(
3421 span,
3422 "error should be emitted when an unexpected trait item is used",
3423 );
3424 rustc_middle::ty::Visibility::Public
3425 };
3426 this.r.feed_visibility(this.r.feed(id), vis);
3427 };
3428
3429 let Some(binding) = binding else {
3430 let candidate = self.find_similarly_named_assoc_item(ident.name, kind);
3432 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
3433 let path_names = path_names_to_string(path);
3434 self.report_error(span, err(ident, path_names, candidate));
3435 feed_visibility(self, module.def_id());
3436 return;
3437 };
3438
3439 let res = binding.res();
3440 let Res::Def(def_kind, id_in_trait) = res else { bug!() };
3441 feed_visibility(self, id_in_trait);
3442
3443 match seen_trait_items.entry(id_in_trait) {
3444 Entry::Occupied(entry) => {
3445 self.report_error(
3446 span,
3447 ResolutionError::TraitImplDuplicate {
3448 name: ident,
3449 old_span: *entry.get(),
3450 trait_item_span: binding.span,
3451 },
3452 );
3453 return;
3454 }
3455 Entry::Vacant(entry) => {
3456 entry.insert(span);
3457 }
3458 };
3459
3460 match (def_kind, kind) {
3461 (DefKind::AssocTy, AssocItemKind::Type(..))
3462 | (DefKind::AssocFn, AssocItemKind::Fn(..))
3463 | (DefKind::AssocConst, AssocItemKind::Const(..))
3464 | (DefKind::AssocFn, AssocItemKind::Delegation(..)) => {
3465 self.r.record_partial_res(id, PartialRes::new(res));
3466 return;
3467 }
3468 _ => {}
3469 }
3470
3471 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
3473 let (code, kind) = match kind {
3474 AssocItemKind::Const(..) => (E0323, "const"),
3475 AssocItemKind::Fn(..) => (E0324, "method"),
3476 AssocItemKind::Type(..) => (E0325, "type"),
3477 AssocItemKind::Delegation(..) => (E0324, "method"),
3478 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
3479 span_bug!(span, "unexpanded macro")
3480 }
3481 };
3482 let trait_path = path_names_to_string(path);
3483 self.report_error(
3484 span,
3485 ResolutionError::TraitImplMismatch {
3486 name: ident,
3487 kind,
3488 code,
3489 trait_path,
3490 trait_item_span: binding.span,
3491 },
3492 );
3493 }
3494
3495 fn resolve_const_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) {
3496 self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
3497 this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
3498 this.visit_expr(expr)
3499 });
3500 })
3501 }
3502
3503 fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
3504 self.smart_resolve_path(
3505 delegation.id,
3506 &delegation.qself,
3507 &delegation.path,
3508 PathSource::Delegation,
3509 );
3510 if let Some(qself) = &delegation.qself {
3511 self.visit_ty(&qself.ty);
3512 }
3513 self.visit_path(&delegation.path, delegation.id);
3514 let Some(body) = &delegation.body else { return };
3515 self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
3516 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3518
3519 let span = delegation.path.segments.last().unwrap().ident.span;
3520 this.fresh_binding(
3521 Ident::new(kw::SelfLower, span),
3522 delegation.id,
3523 PatternSource::FnParam,
3524 &mut bindings,
3525 );
3526 this.visit_block(body);
3527 });
3528 }
3529
3530 fn resolve_params(&mut self, params: &'ast [Param]) {
3531 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3532 self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
3533 for Param { pat, .. } in params {
3534 this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
3535 }
3536 });
3537 for Param { ty, .. } in params {
3538 self.visit_ty(ty);
3539 }
3540 }
3541
3542 fn resolve_local(&mut self, local: &'ast Local) {
3543 debug!("resolving local ({:?})", local);
3544 visit_opt!(self, visit_ty, &local.ty);
3546
3547 if let Some((init, els)) = local.kind.init_else_opt() {
3549 self.visit_expr(init);
3550
3551 if let Some(els) = els {
3553 self.visit_block(els);
3554 }
3555 }
3556
3557 self.resolve_pattern_top(&local.pat, PatternSource::Let);
3559 }
3560
3561 fn compute_and_check_binding_map(
3581 &mut self,
3582 pat: &Pat,
3583 ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
3584 let mut binding_map = FxIndexMap::default();
3585 let mut is_never_pat = false;
3586
3587 pat.walk(&mut |pat| {
3588 match pat.kind {
3589 PatKind::Ident(annotation, ident, ref sub_pat)
3590 if sub_pat.is_some() || self.is_base_res_local(pat.id) =>
3591 {
3592 binding_map.insert(ident, BindingInfo { span: ident.span, annotation });
3593 }
3594 PatKind::Or(ref ps) => {
3595 match self.compute_and_check_or_pat_binding_map(ps) {
3598 Ok(bm) => binding_map.extend(bm),
3599 Err(IsNeverPattern) => is_never_pat = true,
3600 }
3601 return false;
3602 }
3603 PatKind::Never => is_never_pat = true,
3604 _ => {}
3605 }
3606
3607 true
3608 });
3609
3610 if is_never_pat {
3611 for (_, binding) in binding_map {
3612 self.report_error(binding.span, ResolutionError::BindingInNeverPattern);
3613 }
3614 Err(IsNeverPattern)
3615 } else {
3616 Ok(binding_map)
3617 }
3618 }
3619
3620 fn is_base_res_local(&self, nid: NodeId) -> bool {
3621 matches!(
3622 self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()),
3623 Some(Res::Local(..))
3624 )
3625 }
3626
3627 fn compute_and_check_or_pat_binding_map(
3647 &mut self,
3648 pats: &[P<Pat>],
3649 ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
3650 let mut missing_vars = FxIndexMap::default();
3651 let mut inconsistent_vars = FxIndexMap::default();
3652
3653 let not_never_pats = pats
3655 .iter()
3656 .filter_map(|pat| {
3657 let binding_map = self.compute_and_check_binding_map(pat).ok()?;
3658 Some((binding_map, pat))
3659 })
3660 .collect::<Vec<_>>();
3661
3662 for (map_outer, pat_outer) in not_never_pats.iter() {
3664 let inners = not_never_pats
3666 .iter()
3667 .filter(|(_, pat)| pat.id != pat_outer.id)
3668 .flat_map(|(map, _)| map);
3669
3670 for (&name, binding_inner) in inners {
3671 match map_outer.get(&name) {
3672 None => {
3673 let binding_error =
3675 missing_vars.entry(name).or_insert_with(|| BindingError {
3676 name,
3677 origin: BTreeSet::new(),
3678 target: BTreeSet::new(),
3679 could_be_path: name.as_str().starts_with(char::is_uppercase),
3680 });
3681 binding_error.origin.insert(binding_inner.span);
3682 binding_error.target.insert(pat_outer.span);
3683 }
3684 Some(binding_outer) => {
3685 if binding_outer.annotation != binding_inner.annotation {
3686 inconsistent_vars
3688 .entry(name)
3689 .or_insert((binding_inner.span, binding_outer.span));
3690 }
3691 }
3692 }
3693 }
3694 }
3695
3696 for (name, mut v) in missing_vars {
3698 if inconsistent_vars.contains_key(&name) {
3699 v.could_be_path = false;
3700 }
3701 self.report_error(
3702 *v.origin.iter().next().unwrap(),
3703 ResolutionError::VariableNotBoundInPattern(v, self.parent_scope),
3704 );
3705 }
3706
3707 for (name, v) in inconsistent_vars {
3709 self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
3710 }
3711
3712 if not_never_pats.is_empty() {
3714 Err(IsNeverPattern)
3716 } else {
3717 let mut binding_map = FxIndexMap::default();
3718 for (bm, _) in not_never_pats {
3719 binding_map.extend(bm);
3720 }
3721 Ok(binding_map)
3722 }
3723 }
3724
3725 fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
3727 let mut is_or_or_never = false;
3728 pat.walk(&mut |pat| match pat.kind {
3729 PatKind::Or(..) | PatKind::Never => {
3730 is_or_or_never = true;
3731 false
3732 }
3733 _ => true,
3734 });
3735 if is_or_or_never {
3736 let _ = self.compute_and_check_binding_map(pat);
3737 }
3738 }
3739
3740 fn resolve_arm(&mut self, arm: &'ast Arm) {
3741 self.with_rib(ValueNS, RibKind::Normal, |this| {
3742 this.resolve_pattern_top(&arm.pat, PatternSource::Match);
3743 visit_opt!(this, visit_expr, &arm.guard);
3744 visit_opt!(this, visit_expr, &arm.body);
3745 });
3746 }
3747
3748 fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
3750 let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
3751 self.resolve_pattern(pat, pat_src, &mut bindings);
3752 }
3753
3754 fn resolve_pattern(
3755 &mut self,
3756 pat: &'ast Pat,
3757 pat_src: PatternSource,
3758 bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
3759 ) {
3760 visit::walk_pat(self, pat);
3764 self.resolve_pattern_inner(pat, pat_src, bindings);
3765 self.check_consistent_bindings(pat);
3767 }
3768
3769 #[tracing::instrument(skip(self, bindings), level = "debug")]
3789 fn resolve_pattern_inner(
3790 &mut self,
3791 pat: &Pat,
3792 pat_src: PatternSource,
3793 bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
3794 ) {
3795 pat.walk(&mut |pat| {
3797 match pat.kind {
3798 PatKind::Ident(bmode, ident, ref sub) => {
3799 let has_sub = sub.is_some();
3802 let res = self
3803 .try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
3804 .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3805 self.r.record_partial_res(pat.id, PartialRes::new(res));
3806 self.r.record_pat_span(pat.id, pat.span);
3807 }
3808 PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
3809 self.smart_resolve_path(
3810 pat.id,
3811 qself,
3812 path,
3813 PathSource::TupleStruct(
3814 pat.span,
3815 self.r.arenas.alloc_pattern_spans(sub_patterns.iter().map(|p| p.span)),
3816 ),
3817 );
3818 }
3819 PatKind::Path(ref qself, ref path) => {
3820 self.smart_resolve_path(pat.id, qself, path, PathSource::Pat);
3821 }
3822 PatKind::Struct(ref qself, ref path, ref _fields, ref rest) => {
3823 self.smart_resolve_path(pat.id, qself, path, PathSource::Struct);
3824 self.record_patterns_with_skipped_bindings(pat, rest);
3825 }
3826 PatKind::Or(ref ps) => {
3827 bindings.push((PatBoundCtx::Or, Default::default()));
3831 for p in ps {
3832 bindings.push((PatBoundCtx::Product, Default::default()));
3836 self.resolve_pattern_inner(p, pat_src, bindings);
3837 let collected = bindings.pop().unwrap().1;
3840 bindings.last_mut().unwrap().1.extend(collected);
3841 }
3842 let collected = bindings.pop().unwrap().1;
3846 bindings.last_mut().unwrap().1.extend(collected);
3847
3848 return false;
3850 }
3851 _ => {}
3852 }
3853 true
3854 });
3855 }
3856
3857 fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) {
3858 match rest {
3859 ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) => {
3860 if let Some(partial_res) = self.r.partial_res_map.get(&pat.id)
3862 && let Some(res) = partial_res.full_res()
3863 && let Some(def_id) = res.opt_def_id()
3864 {
3865 self.ribs[ValueNS]
3866 .last_mut()
3867 .unwrap()
3868 .patterns_with_skipped_bindings
3869 .entry(def_id)
3870 .or_default()
3871 .push((
3872 pat.span,
3873 match rest {
3874 ast::PatFieldsRest::Recovered(guar) => Err(*guar),
3875 _ => Ok(()),
3876 },
3877 ));
3878 }
3879 }
3880 ast::PatFieldsRest::None => {}
3881 }
3882 }
3883
3884 fn fresh_binding(
3885 &mut self,
3886 ident: Ident,
3887 pat_id: NodeId,
3888 pat_src: PatternSource,
3889 bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
3890 ) -> Res {
3891 let ident = ident.normalize_to_macro_rules();
3895
3896 let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
3897 let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product);
3899 let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or);
3902
3903 if already_bound_and {
3904 use ResolutionError::*;
3906 let error = match pat_src {
3907 PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList,
3909 _ => IdentifierBoundMoreThanOnceInSamePattern,
3911 };
3912 self.report_error(ident.span, error(ident));
3913 }
3914
3915 let ident_valid = ident.name != kw::Empty;
3917 if ident_valid {
3918 bindings.last_mut().unwrap().1.insert(ident);
3919 }
3920
3921 if already_bound_or {
3922 self.innermost_rib_bindings(ValueNS)[&ident]
3925 } else {
3926 let res = Res::Local(pat_id);
3927 if ident_valid {
3928 self.innermost_rib_bindings(ValueNS).insert(ident, res);
3930 }
3931 res
3932 }
3933 }
3934
3935 fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {
3936 &mut self.ribs[ns].last_mut().unwrap().bindings
3937 }
3938
3939 fn try_resolve_as_non_binding(
3940 &mut self,
3941 pat_src: PatternSource,
3942 ann: BindingMode,
3943 ident: Ident,
3944 has_sub: bool,
3945 ) -> Option<Res> {
3946 let is_syntactic_ambiguity = !has_sub && ann == BindingMode::NONE;
3950
3951 let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
3952 let (res, binding) = match ls_binding {
3953 LexicalScopeBinding::Item(binding)
3954 if is_syntactic_ambiguity && binding.is_ambiguity_recursive() =>
3955 {
3956 self.r.record_use(ident, binding, Used::Other);
3961 return None;
3962 }
3963 LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
3964 LexicalScopeBinding::Res(res) => (res, None),
3965 };
3966
3967 match res {
3968 Res::SelfCtor(_) | Res::Def(
3970 DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst | DefKind::ConstParam,
3971 _,
3972 ) if is_syntactic_ambiguity => {
3973 if let Some(binding) = binding {
3975 self.r.record_use(ident, binding, Used::Other);
3976 }
3977 Some(res)
3978 }
3979 Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::AssocConst | DefKind::Static { .. }, _) => {
3980 let binding = binding.expect("no binding for a ctor or static");
3986 self.report_error(
3987 ident.span,
3988 ResolutionError::BindingShadowsSomethingUnacceptable {
3989 shadowing_binding: pat_src,
3990 name: ident.name,
3991 participle: if binding.is_import() { "imported" } else { "defined" },
3992 article: binding.res().article(),
3993 shadowed_binding: binding.res(),
3994 shadowed_binding_span: binding.span,
3995 },
3996 );
3997 None
3998 }
3999 Res::Def(DefKind::ConstParam, def_id) => {
4000 self.report_error(
4003 ident.span,
4004 ResolutionError::BindingShadowsSomethingUnacceptable {
4005 shadowing_binding: pat_src,
4006 name: ident.name,
4007 participle: "defined",
4008 article: res.article(),
4009 shadowed_binding: res,
4010 shadowed_binding_span: self.r.def_span(def_id),
4011 }
4012 );
4013 None
4014 }
4015 Res::Def(DefKind::Fn | DefKind::AssocFn, _) | Res::Local(..) | Res::Err => {
4016 None
4018 }
4019 Res::SelfCtor(_) => {
4020 self.r.dcx().span_delayed_bug(
4023 ident.span,
4024 "unexpected `SelfCtor` in pattern, expected identifier"
4025 );
4026 None
4027 }
4028 _ => span_bug!(
4029 ident.span,
4030 "unexpected resolution for an identifier in pattern: {:?}",
4031 res,
4032 ),
4033 }
4034 }
4035
4036 fn smart_resolve_path(
4042 &mut self,
4043 id: NodeId,
4044 qself: &Option<P<QSelf>>,
4045 path: &Path,
4046 source: PathSource<'ast>,
4047 ) {
4048 self.smart_resolve_path_fragment(
4049 qself,
4050 &Segment::from_path(path),
4051 source,
4052 Finalize::new(id, path.span),
4053 RecordPartialRes::Yes,
4054 );
4055 }
4056
4057 #[instrument(level = "debug", skip(self))]
4058 fn smart_resolve_path_fragment(
4059 &mut self,
4060 qself: &Option<P<QSelf>>,
4061 path: &[Segment],
4062 source: PathSource<'ast>,
4063 finalize: Finalize,
4064 record_partial_res: RecordPartialRes,
4065 ) -> PartialRes {
4066 let ns = source.namespace();
4067
4068 let Finalize { node_id, path_span, .. } = finalize;
4069 let report_errors = |this: &mut Self, res: Option<Res>| {
4070 if this.should_report_errs() {
4071 let (err, candidates) =
4072 this.smart_resolve_report_errors(path, None, path_span, source, res);
4073
4074 let def_id = this.parent_scope.module.nearest_parent_mod();
4075 let instead = res.is_some();
4076 let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
4077 && path[0].ident.span.lo() == end.span.lo()
4078 && !matches!(start.kind, ExprKind::Lit(_))
4079 {
4080 let mut sugg = ".";
4081 let mut span = start.span.between(end.span);
4082 if span.lo() + BytePos(2) == span.hi() {
4083 span = span.with_lo(span.lo() + BytePos(1));
4086 sugg = "";
4087 }
4088 Some((
4089 span,
4090 "you might have meant to write `.` instead of `..`",
4091 sugg.to_string(),
4092 Applicability::MaybeIncorrect,
4093 ))
4094 } else if res.is_none()
4095 && let PathSource::Type
4096 | PathSource::Expr(_)
4097 | PathSource::PreciseCapturingArg(..) = source
4098 {
4099 this.suggest_adding_generic_parameter(path, source)
4100 } else {
4101 None
4102 };
4103
4104 let ue = UseError {
4105 err,
4106 candidates,
4107 def_id,
4108 instead,
4109 suggestion,
4110 path: path.into(),
4111 is_call: source.is_call(),
4112 };
4113
4114 this.r.use_injections.push(ue);
4115 }
4116
4117 PartialRes::new(Res::Err)
4118 };
4119
4120 let report_errors_for_call =
4126 |this: &mut Self, parent_err: Spanned<ResolutionError<'ra>>| {
4127 let (following_seg, prefix_path) = match path.split_last() {
4131 Some((last, path)) if !path.is_empty() => (Some(last), path),
4132 _ => return Some(parent_err),
4133 };
4134
4135 let (mut err, candidates) = this.smart_resolve_report_errors(
4136 prefix_path,
4137 following_seg,
4138 path_span,
4139 PathSource::Type,
4140 None,
4141 );
4142
4143 let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node);
4158
4159 err.messages = take(&mut parent_err.messages);
4161 err.code = take(&mut parent_err.code);
4162 swap(&mut err.span, &mut parent_err.span);
4163 err.children = take(&mut parent_err.children);
4164 err.sort_span = parent_err.sort_span;
4165 err.is_lint = parent_err.is_lint.clone();
4166
4167 match &mut err.suggestions {
4169 Suggestions::Enabled(typo_suggestions) => match &mut parent_err.suggestions {
4170 Suggestions::Enabled(parent_suggestions) => {
4171 typo_suggestions.append(parent_suggestions)
4173 }
4174 Suggestions::Sealed(_) | Suggestions::Disabled => {
4175 err.suggestions = std::mem::take(&mut parent_err.suggestions);
4180 }
4181 },
4182 Suggestions::Sealed(_) | Suggestions::Disabled => (),
4183 }
4184
4185 parent_err.cancel();
4186
4187 let def_id = this.parent_scope.module.nearest_parent_mod();
4188
4189 if this.should_report_errs() {
4190 if candidates.is_empty() {
4191 if path.len() == 2
4192 && let [segment] = prefix_path
4193 {
4194 err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod);
4200 } else {
4201 err.emit();
4206 }
4207 } else {
4208 this.r.use_injections.push(UseError {
4210 err,
4211 candidates,
4212 def_id,
4213 instead: false,
4214 suggestion: None,
4215 path: prefix_path.into(),
4216 is_call: source.is_call(),
4217 });
4218 }
4219 } else {
4220 err.cancel();
4221 }
4222
4223 None
4226 };
4227
4228 let partial_res = match self.resolve_qpath_anywhere(
4229 qself,
4230 path,
4231 ns,
4232 path_span,
4233 source.defer_to_typeck(),
4234 finalize,
4235 ) {
4236 Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
4237 if let Some(items) = self.diag_metadata.current_trait_assoc_items
4239 && let [Segment { ident, .. }] = path
4240 && items.iter().any(|item| {
4241 item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
4242 })
4243 {
4244 let mut diag = self.r.tcx.dcx().struct_allow("");
4245 diag.span_suggestion_verbose(
4246 path_span.shrink_to_lo(),
4247 "there is an associated type with the same name",
4248 "Self::",
4249 Applicability::MaybeIncorrect,
4250 );
4251 diag.stash(path_span, StashKey::AssociatedTypeSuggestion);
4252 }
4253
4254 if source.is_expected(res) || res == Res::Err {
4255 partial_res
4256 } else {
4257 report_errors(self, Some(res))
4258 }
4259 }
4260
4261 Ok(Some(partial_res)) if source.defer_to_typeck() => {
4262 if ns == ValueNS {
4266 let item_name = path.last().unwrap().ident;
4267 let traits = self.traits_in_scope(item_name, ns);
4268 self.r.trait_map.insert(node_id, traits);
4269 }
4270
4271 if PrimTy::from_name(path[0].ident.name).is_some() {
4272 let mut std_path = Vec::with_capacity(1 + path.len());
4273
4274 std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std)));
4275 std_path.extend(path);
4276 if let PathResult::Module(_) | PathResult::NonModule(_) =
4277 self.resolve_path(&std_path, Some(ns), None)
4278 {
4279 let item_span =
4281 path.iter().last().map_or(path_span, |segment| segment.ident.span);
4282
4283 self.r.confused_type_with_std_module.insert(item_span, path_span);
4284 self.r.confused_type_with_std_module.insert(path_span, path_span);
4285 }
4286 }
4287
4288 partial_res
4289 }
4290
4291 Err(err) => {
4292 if let Some(err) = report_errors_for_call(self, err) {
4293 self.report_error(err.span, err.node);
4294 }
4295
4296 PartialRes::new(Res::Err)
4297 }
4298
4299 _ => report_errors(self, None),
4300 };
4301
4302 if record_partial_res == RecordPartialRes::Yes {
4303 self.r.record_partial_res(node_id, partial_res);
4305 self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span);
4306 self.lint_unused_qualifications(path, ns, finalize);
4307 }
4308
4309 partial_res
4310 }
4311
4312 fn self_type_is_available(&mut self) -> bool {
4313 let binding = self
4314 .maybe_resolve_ident_in_lexical_scope(Ident::with_dummy_span(kw::SelfUpper), TypeNS);
4315 if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
4316 }
4317
4318 fn self_value_is_available(&mut self, self_span: Span) -> bool {
4319 let ident = Ident::new(kw::SelfLower, self_span);
4320 let binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS);
4321 if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
4322 }
4323
4324 fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'ra>) {
4328 if self.should_report_errs() {
4329 self.r.report_error(span, resolution_error);
4330 }
4331 }
4332
4333 #[inline]
4334 fn should_report_errs(&self) -> bool {
4338 !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body)
4339 && !self.r.glob_error.is_some()
4340 }
4341
4342 fn resolve_qpath_anywhere(
4344 &mut self,
4345 qself: &Option<P<QSelf>>,
4346 path: &[Segment],
4347 primary_ns: Namespace,
4348 span: Span,
4349 defer_to_typeck: bool,
4350 finalize: Finalize,
4351 ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
4352 let mut fin_res = None;
4353
4354 for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() {
4355 if i == 0 || ns != primary_ns {
4356 match self.resolve_qpath(qself, path, ns, finalize)? {
4357 Some(partial_res)
4358 if partial_res.unresolved_segments() == 0 || defer_to_typeck =>
4359 {
4360 return Ok(Some(partial_res));
4361 }
4362 partial_res => {
4363 if fin_res.is_none() {
4364 fin_res = partial_res;
4365 }
4366 }
4367 }
4368 }
4369 }
4370
4371 assert!(primary_ns != MacroNS);
4372
4373 if qself.is_none() {
4374 let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
4375 let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
4376 if let Ok((_, res)) =
4377 self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None)
4378 {
4379 return Ok(Some(PartialRes::new(res)));
4380 }
4381 }
4382
4383 Ok(fin_res)
4384 }
4385
4386 fn resolve_qpath(
4388 &mut self,
4389 qself: &Option<P<QSelf>>,
4390 path: &[Segment],
4391 ns: Namespace,
4392 finalize: Finalize,
4393 ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
4394 debug!(
4395 "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})",
4396 qself, path, ns, finalize,
4397 );
4398
4399 if let Some(qself) = qself {
4400 if qself.position == 0 {
4401 return Ok(Some(PartialRes::with_unresolved_segments(
4405 Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()),
4406 path.len(),
4407 )));
4408 }
4409
4410 let num_privacy_errors = self.r.privacy_errors.len();
4411 let trait_res = self.smart_resolve_path_fragment(
4413 &None,
4414 &path[..qself.position],
4415 PathSource::Trait(AliasPossibility::No),
4416 Finalize::new(finalize.node_id, qself.path_span),
4417 RecordPartialRes::No,
4418 );
4419
4420 if trait_res.expect_full_res() == Res::Err {
4421 return Ok(Some(trait_res));
4422 }
4423
4424 self.r.privacy_errors.truncate(num_privacy_errors);
4427
4428 let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
4436 let partial_res = self.smart_resolve_path_fragment(
4437 &None,
4438 &path[..=qself.position],
4439 PathSource::TraitItem(ns),
4440 Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
4441 RecordPartialRes::No,
4442 );
4443
4444 return Ok(Some(PartialRes::with_unresolved_segments(
4448 partial_res.base_res(),
4449 partial_res.unresolved_segments() + path.len() - qself.position - 1,
4450 )));
4451 }
4452
4453 let result = match self.resolve_path(path, Some(ns), Some(finalize)) {
4454 PathResult::NonModule(path_res) => path_res,
4455 PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
4456 PartialRes::new(module.res().unwrap())
4457 }
4458 PathResult::Failed { error_implied_by_parse_error: true, .. } => {
4462 PartialRes::new(Res::Err)
4463 }
4464 PathResult::Module(ModuleOrUniformRoot::Module(_)) | PathResult::Failed { .. }
4477 if (ns == TypeNS || path.len() > 1)
4478 && PrimTy::from_name(path[0].ident.name).is_some() =>
4479 {
4480 let prim = PrimTy::from_name(path[0].ident.name).unwrap();
4481 let tcx = self.r.tcx();
4482
4483 let gate_err_sym_msg = match prim {
4484 PrimTy::Float(FloatTy::F16) if !tcx.features().f16() => {
4485 Some((sym::f16, "the type `f16` is unstable"))
4486 }
4487 PrimTy::Float(FloatTy::F128) if !tcx.features().f128() => {
4488 Some((sym::f128, "the type `f128` is unstable"))
4489 }
4490 _ => None,
4491 };
4492
4493 if let Some((sym, msg)) = gate_err_sym_msg {
4494 let span = path[0].ident.span;
4495 if !span.allows_unstable(sym) {
4496 feature_err(tcx.sess, sym, span, msg).emit();
4497 }
4498 };
4499
4500 PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
4501 }
4502 PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
4503 PartialRes::new(module.res().unwrap())
4504 }
4505 PathResult::Failed {
4506 is_error_from_last_segment: false,
4507 span,
4508 label,
4509 suggestion,
4510 module,
4511 segment_name,
4512 error_implied_by_parse_error: _,
4513 } => {
4514 return Err(respan(
4515 span,
4516 ResolutionError::FailedToResolve {
4517 segment: Some(segment_name),
4518 label,
4519 suggestion,
4520 module,
4521 },
4522 ));
4523 }
4524 PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None),
4525 PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"),
4526 };
4527
4528 Ok(Some(result))
4529 }
4530
4531 fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) {
4532 if let Some(label) = label {
4533 if label.ident.as_str().as_bytes()[1] != b'_' {
4534 self.diag_metadata.unused_labels.insert(id, label.ident.span);
4535 }
4536
4537 if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
4538 diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident)
4539 }
4540
4541 self.with_label_rib(RibKind::Normal, |this| {
4542 let ident = label.ident.normalize_to_macro_rules();
4543 this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
4544 f(this);
4545 });
4546 } else {
4547 f(self);
4548 }
4549 }
4550
4551 fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &'ast Block) {
4552 self.with_resolved_label(label, id, |this| this.visit_block(block));
4553 }
4554
4555 fn resolve_block(&mut self, block: &'ast Block) {
4556 debug!("(resolving block) entering block");
4557 let orig_module = self.parent_scope.module;
4559 let anonymous_module = self.r.block_map.get(&block.id).cloned(); let mut num_macro_definition_ribs = 0;
4562 if let Some(anonymous_module) = anonymous_module {
4563 debug!("(resolving block) found anonymous module, moving down");
4564 self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module)));
4565 self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module)));
4566 self.parent_scope.module = anonymous_module;
4567 } else {
4568 self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
4569 }
4570
4571 let prev = self.diag_metadata.current_block_could_be_bare_struct_literal.take();
4572 if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
4573 (block.could_be_bare_literal, &block.stmts[..])
4574 && let ExprKind::Type(..) = expr.kind
4575 {
4576 self.diag_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
4577 }
4578 for stmt in &block.stmts {
4580 if let StmtKind::Item(ref item) = stmt.kind
4581 && let ItemKind::MacroDef(..) = item.kind
4582 {
4583 num_macro_definition_ribs += 1;
4584 let res = self.r.local_def_id(item.id).to_def_id();
4585 self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res)));
4586 self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res)));
4587 }
4588
4589 self.visit_stmt(stmt);
4590 }
4591 self.diag_metadata.current_block_could_be_bare_struct_literal = prev;
4592
4593 self.parent_scope.module = orig_module;
4595 for _ in 0..num_macro_definition_ribs {
4596 self.ribs[ValueNS].pop();
4597 self.label_ribs.pop();
4598 }
4599 self.last_block_rib = self.ribs[ValueNS].pop();
4600 if anonymous_module.is_some() {
4601 self.ribs[TypeNS].pop();
4602 }
4603 debug!("(resolving block) leaving block");
4604 }
4605
4606 fn resolve_anon_const(&mut self, constant: &'ast AnonConst, anon_const_kind: AnonConstKind) {
4607 debug!(
4608 "resolve_anon_const(constant: {:?}, anon_const_kind: {:?})",
4609 constant, anon_const_kind
4610 );
4611
4612 self.resolve_anon_const_manual(
4613 constant.value.is_potential_trivial_const_arg(),
4614 anon_const_kind,
4615 |this| this.resolve_expr(&constant.value, None),
4616 )
4617 }
4618
4619 fn resolve_anon_const_manual(
4626 &mut self,
4627 is_trivial_const_arg: bool,
4628 anon_const_kind: AnonConstKind,
4629 resolve_expr: impl FnOnce(&mut Self),
4630 ) {
4631 let is_repeat_expr = match anon_const_kind {
4632 AnonConstKind::ConstArg(is_repeat_expr) => is_repeat_expr,
4633 _ => IsRepeatExpr::No,
4634 };
4635
4636 let may_use_generics = match anon_const_kind {
4637 AnonConstKind::EnumDiscriminant => {
4638 ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
4639 }
4640 AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
4641 AnonConstKind::ConstArg(_) => {
4642 if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg {
4643 ConstantHasGenerics::Yes
4644 } else {
4645 ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
4646 }
4647 }
4648 };
4649
4650 self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| {
4651 this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
4652 resolve_expr(this);
4653 });
4654 });
4655 }
4656
4657 fn resolve_expr_field(&mut self, f: &'ast ExprField, e: &'ast Expr) {
4658 self.resolve_expr(&f.expr, Some(e));
4659 self.visit_ident(&f.ident);
4660 walk_list!(self, visit_attribute, f.attrs.iter());
4661 }
4662
4663 fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
4664 self.record_candidate_traits_for_expr_if_necessary(expr);
4668
4669 match expr.kind {
4671 ExprKind::Path(ref qself, ref path) => {
4672 self.smart_resolve_path(expr.id, qself, path, PathSource::Expr(parent));
4673 visit::walk_expr(self, expr);
4674 }
4675
4676 ExprKind::Struct(ref se) => {
4677 self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct);
4678 if let Some(qself) = &se.qself {
4682 self.visit_ty(&qself.ty);
4683 }
4684 self.visit_path(&se.path, expr.id);
4685 walk_list!(self, resolve_expr_field, &se.fields, expr);
4686 match &se.rest {
4687 StructRest::Base(expr) => self.visit_expr(expr),
4688 StructRest::Rest(_span) => {}
4689 StructRest::None => {}
4690 }
4691 }
4692
4693 ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
4694 match self.resolve_label(label.ident) {
4695 Ok((node_id, _)) => {
4696 self.r.label_res_map.insert(expr.id, node_id);
4698 self.diag_metadata.unused_labels.remove(&node_id);
4699 }
4700 Err(error) => {
4701 self.report_error(label.ident.span, error);
4702 }
4703 }
4704
4705 visit::walk_expr(self, expr);
4707 }
4708
4709 ExprKind::Break(None, Some(ref e)) => {
4710 self.resolve_expr(e, Some(expr));
4713 }
4714
4715 ExprKind::Let(ref pat, ref scrutinee, _, _) => {
4716 self.visit_expr(scrutinee);
4717 self.resolve_pattern_top(pat, PatternSource::Let);
4718 }
4719
4720 ExprKind::If(ref cond, ref then, ref opt_else) => {
4721 self.with_rib(ValueNS, RibKind::Normal, |this| {
4722 let old = this.diag_metadata.in_if_condition.replace(cond);
4723 this.visit_expr(cond);
4724 this.diag_metadata.in_if_condition = old;
4725 this.visit_block(then);
4726 });
4727 if let Some(expr) = opt_else {
4728 self.visit_expr(expr);
4729 }
4730 }
4731
4732 ExprKind::Loop(ref block, label, _) => {
4733 self.resolve_labeled_block(label, expr.id, block)
4734 }
4735
4736 ExprKind::While(ref cond, ref block, label) => {
4737 self.with_resolved_label(label, expr.id, |this| {
4738 this.with_rib(ValueNS, RibKind::Normal, |this| {
4739 let old = this.diag_metadata.in_if_condition.replace(cond);
4740 this.visit_expr(cond);
4741 this.diag_metadata.in_if_condition = old;
4742 this.visit_block(block);
4743 })
4744 });
4745 }
4746
4747 ExprKind::ForLoop { ref pat, ref iter, ref body, label, kind: _ } => {
4748 self.visit_expr(iter);
4749 self.with_rib(ValueNS, RibKind::Normal, |this| {
4750 this.resolve_pattern_top(pat, PatternSource::For);
4751 this.resolve_labeled_block(label, expr.id, body);
4752 });
4753 }
4754
4755 ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block),
4756
4757 ExprKind::Field(ref subexpression, _) => {
4759 self.resolve_expr(subexpression, Some(expr));
4760 }
4761 ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => {
4762 self.resolve_expr(receiver, Some(expr));
4763 for arg in args {
4764 self.resolve_expr(arg, None);
4765 }
4766 self.visit_path_segment(seg);
4767 }
4768
4769 ExprKind::Call(ref callee, ref arguments) => {
4770 self.resolve_expr(callee, Some(expr));
4771 let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default();
4772 for (idx, argument) in arguments.iter().enumerate() {
4773 if const_args.contains(&idx) {
4776 self.resolve_anon_const_manual(
4777 argument.is_potential_trivial_const_arg(),
4778 AnonConstKind::ConstArg(IsRepeatExpr::No),
4779 |this| this.resolve_expr(argument, None),
4780 );
4781 } else {
4782 self.resolve_expr(argument, None);
4783 }
4784 }
4785 }
4786 ExprKind::Type(ref _type_expr, ref _ty) => {
4787 visit::walk_expr(self, expr);
4788 }
4789 ExprKind::Closure(box ast::Closure {
4791 binder: ClosureBinder::For { ref generic_params, span },
4792 ..
4793 }) => {
4794 self.with_generic_param_rib(
4795 generic_params,
4796 RibKind::Normal,
4797 LifetimeRibKind::Generics {
4798 binder: expr.id,
4799 kind: LifetimeBinderKind::Closure,
4800 span,
4801 },
4802 |this| visit::walk_expr(this, expr),
4803 );
4804 }
4805 ExprKind::Closure(..) => visit::walk_expr(self, expr),
4806 ExprKind::Gen(..) => {
4807 self.with_label_rib(RibKind::FnOrCoroutine, |this| visit::walk_expr(this, expr));
4808 }
4809 ExprKind::Repeat(ref elem, ref ct) => {
4810 self.visit_expr(elem);
4811 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
4812 }
4813 ExprKind::ConstBlock(ref ct) => {
4814 self.resolve_anon_const(ct, AnonConstKind::InlineConst);
4815 }
4816 ExprKind::Index(ref elem, ref idx, _) => {
4817 self.resolve_expr(elem, Some(expr));
4818 self.visit_expr(idx);
4819 }
4820 ExprKind::Assign(ref lhs, ref rhs, _) => {
4821 if !self.diag_metadata.is_assign_rhs {
4822 self.diag_metadata.in_assignment = Some(expr);
4823 }
4824 self.visit_expr(lhs);
4825 self.diag_metadata.is_assign_rhs = true;
4826 self.diag_metadata.in_assignment = None;
4827 self.visit_expr(rhs);
4828 self.diag_metadata.is_assign_rhs = false;
4829 }
4830 ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
4831 self.diag_metadata.in_range = Some((start, end));
4832 self.resolve_expr(start, Some(expr));
4833 self.resolve_expr(end, Some(expr));
4834 self.diag_metadata.in_range = None;
4835 }
4836 _ => {
4837 visit::walk_expr(self, expr);
4838 }
4839 }
4840 }
4841
4842 fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
4843 match expr.kind {
4844 ExprKind::Field(_, ident) => {
4845 let traits = self.traits_in_scope(ident, ValueNS);
4850 self.r.trait_map.insert(expr.id, traits);
4851 }
4852 ExprKind::MethodCall(ref call) => {
4853 debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
4854 let traits = self.traits_in_scope(call.seg.ident, ValueNS);
4855 self.r.trait_map.insert(expr.id, traits);
4856 }
4857 _ => {
4858 }
4860 }
4861 }
4862
4863 fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> {
4864 self.r.traits_in_scope(
4865 self.current_trait_ref.as_ref().map(|(module, _)| *module),
4866 &self.parent_scope,
4867 ident.span.ctxt(),
4868 Some((ident.name, ns)),
4869 )
4870 }
4871
4872 fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
4873 let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
4877 let res = *doc_link_resolutions
4878 .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
4879 .or_default()
4880 .entry((Symbol::intern(path_str), ns))
4881 .or_insert_with_key(|(path, ns)| {
4882 let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope);
4883 if let Some(res) = res
4884 && let Some(def_id) = res.opt_def_id()
4885 && self.is_invalid_proc_macro_item_for_doc(def_id)
4886 {
4887 return None;
4890 }
4891 res
4892 });
4893 self.r.doc_link_resolutions = doc_link_resolutions;
4894 res
4895 }
4896
4897 fn is_invalid_proc_macro_item_for_doc(&self, did: DefId) -> bool {
4898 if !matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata)
4899 || !self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
4900 {
4901 return false;
4902 }
4903 let Some(local_did) = did.as_local() else { return true };
4904 let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true };
4905 !self.r.proc_macros.contains(node_id)
4906 }
4907
4908 fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
4909 match self.r.tcx.sess.opts.resolve_doc_links {
4910 ResolveDocLinks::None => return,
4911 ResolveDocLinks::ExportedMetadata
4912 if !self.r.tcx.crate_types().iter().copied().any(CrateType::has_metadata)
4913 || !maybe_exported.eval(self.r) =>
4914 {
4915 return;
4916 }
4917 ResolveDocLinks::Exported
4918 if !maybe_exported.eval(self.r)
4919 && !rustdoc::has_primitive_or_keyword_docs(attrs) =>
4920 {
4921 return;
4922 }
4923 ResolveDocLinks::ExportedMetadata
4924 | ResolveDocLinks::Exported
4925 | ResolveDocLinks::All => {}
4926 }
4927
4928 if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
4929 return;
4930 }
4931
4932 let mut need_traits_in_scope = false;
4933 for path_str in rustdoc::attrs_to_preprocessed_links(attrs) {
4934 let mut any_resolved = false;
4936 let mut need_assoc = false;
4937 for ns in [TypeNS, ValueNS, MacroNS] {
4938 if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) {
4939 any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool));
4942 } else if ns != MacroNS {
4943 need_assoc = true;
4944 }
4945 }
4946
4947 if need_assoc || !any_resolved {
4949 let mut path = &path_str[..];
4950 while let Some(idx) = path.rfind("::") {
4951 path = &path[..idx];
4952 need_traits_in_scope = true;
4953 for ns in [TypeNS, ValueNS, MacroNS] {
4954 self.resolve_and_cache_rustdoc_path(path, ns);
4955 }
4956 }
4957 }
4958 }
4959
4960 if need_traits_in_scope {
4961 let mut doc_link_traits_in_scope = std::mem::take(&mut self.r.doc_link_traits_in_scope);
4963 doc_link_traits_in_scope
4964 .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
4965 .or_insert_with(|| {
4966 self.r
4967 .traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None)
4968 .into_iter()
4969 .filter_map(|tr| {
4970 if self.is_invalid_proc_macro_item_for_doc(tr.def_id) {
4971 return None;
4974 }
4975 Some(tr.def_id)
4976 })
4977 .collect()
4978 });
4979 self.r.doc_link_traits_in_scope = doc_link_traits_in_scope;
4980 }
4981 }
4982
4983 fn lint_unused_qualifications(&mut self, path: &[Segment], ns: Namespace, finalize: Finalize) {
4984 if let Some(seg) = path.first()
4986 && seg.ident.name == kw::PathRoot
4987 {
4988 return;
4989 }
4990
4991 if finalize.path_span.from_expansion()
4992 || path.iter().any(|seg| seg.ident.span.from_expansion())
4993 {
4994 return;
4995 }
4996
4997 let end_pos =
4998 path.iter().position(|seg| seg.has_generic_args).map_or(path.len(), |pos| pos + 1);
4999 let unqualified = path[..end_pos].iter().enumerate().skip(1).rev().find_map(|(i, seg)| {
5000 let ns = if i + 1 == path.len() { ns } else { TypeNS };
5009 let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
5010 let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
5011 (res == binding.res()).then_some((seg, binding))
5012 });
5013
5014 if let Some((seg, binding)) = unqualified {
5015 self.r.potentially_unnecessary_qualifications.push(UnnecessaryQualification {
5016 binding,
5017 node_id: finalize.node_id,
5018 path_span: finalize.path_span,
5019 removal_span: path[0].ident.span.until(seg.ident.span),
5020 });
5021 }
5022 }
5023}
5024
5025struct ItemInfoCollector<'a, 'ra, 'tcx> {
5028 r: &'a mut Resolver<'ra, 'tcx>,
5029}
5030
5031impl ItemInfoCollector<'_, '_, '_> {
5032 fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) {
5033 let sig = DelegationFnSig {
5034 header: sig.header,
5035 param_count: sig.decl.inputs.len(),
5036 has_self: sig.decl.has_self(),
5037 c_variadic: sig.decl.c_variadic(),
5038 target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
5039 };
5040 self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
5041 }
5042}
5043
5044impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
5045 fn visit_item(&mut self, item: &'ast Item) {
5046 match &item.kind {
5047 ItemKind::TyAlias(box TyAlias { ref generics, .. })
5048 | ItemKind::Const(box ConstItem { ref generics, .. })
5049 | ItemKind::Fn(box Fn { ref generics, .. })
5050 | ItemKind::Enum(_, ref generics)
5051 | ItemKind::Struct(_, ref generics)
5052 | ItemKind::Union(_, ref generics)
5053 | ItemKind::Impl(box Impl { ref generics, .. })
5054 | ItemKind::Trait(box Trait { ref generics, .. })
5055 | ItemKind::TraitAlias(ref generics, _) => {
5056 if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
5057 self.collect_fn_info(sig, item.id, &item.attrs);
5058 }
5059
5060 let def_id = self.r.local_def_id(item.id);
5061 let count = generics
5062 .params
5063 .iter()
5064 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
5065 .count();
5066 self.r.item_generics_num_lifetimes.insert(def_id, count);
5067 }
5068
5069 ItemKind::Mod(..)
5070 | ItemKind::ForeignMod(..)
5071 | ItemKind::Static(..)
5072 | ItemKind::Use(..)
5073 | ItemKind::ExternCrate(..)
5074 | ItemKind::MacroDef(..)
5075 | ItemKind::GlobalAsm(..)
5076 | ItemKind::MacCall(..)
5077 | ItemKind::DelegationMac(..) => {}
5078 ItemKind::Delegation(..) => {
5079 }
5084 }
5085 visit::walk_item(self, item)
5086 }
5087
5088 fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
5089 if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
5090 self.collect_fn_info(sig, item.id, &item.attrs);
5091 }
5092 visit::walk_assoc_item(self, item, ctxt);
5093 }
5094}
5095
5096impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
5097 pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
5098 visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
5099 let mut late_resolution_visitor = LateResolutionVisitor::new(self);
5100 late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
5101 visit::walk_crate(&mut late_resolution_visitor, krate);
5102 for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
5103 self.lint_buffer.buffer_lint(
5104 lint::builtin::UNUSED_LABELS,
5105 *id,
5106 *span,
5107 BuiltinLintDiag::UnusedLabel,
5108 );
5109 }
5110 }
5111}
5112
5113fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool {
5115 let mut path = expected_path.iter().rev();
5116 while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) {
5117 if !tcx.opt_item_name(def_id).is_some_and(|n| n.as_str() == *next_step) {
5118 return false;
5119 }
5120 def_id = parent;
5121 }
5122 true
5123}