]>
Commit | Line | Data |
---|---|---|
923072b8 | 1 | // ignore-tidy-filelength |
e1599b0c XL |
2 | //! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros. |
3 | //! It runs when the crate is fully expanded and its module structure is fully built. | |
4 | //! So it just walks through the crate and resolves all the expressions, types, etc. | |
5 | //! | |
6 | //! If you wonder why there's no `early.rs`, that's because it's split into three files - | |
dfeec247 | 7 | //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`. |
e1599b0c | 8 | |
49aad941 | 9 | use crate::BindingKey; |
9ffffee4 | 10 | use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding}; |
04454e1e | 11 | use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; |
416331ca XL |
12 | use crate::{ResolutionError, Resolver, Segment, UseError}; |
13 | ||
74b04a01 | 14 | use rustc_ast::ptr::P; |
04454e1e | 15 | use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; |
3dfed10e | 16 | use rustc_ast::*; |
04454e1e | 17 | use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; |
9c376795 | 18 | use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; |
dfeec247 | 19 | use rustc_hir::def::Namespace::{self, *}; |
49aad941 | 20 | use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; |
2b03887a | 21 | use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; |
f2b60f7d | 22 | use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; |
9ffffee4 | 23 | use rustc_middle::middle::resolve_bound_vars::Set1; |
ba9703b0 | 24 | use rustc_middle::{bug, span_bug}; |
9ffffee4 | 25 | use rustc_session::config::{CrateType, ResolveDocLinks}; |
ba9703b0 | 26 | use rustc_session::lint; |
9ffffee4 | 27 | use rustc_span::source_map::{respan, Spanned}; |
f9f354fc | 28 | use rustc_span::symbol::{kw, sym, Ident, Symbol}; |
9ffffee4 | 29 | use rustc_span::{BytePos, Span, SyntaxContext}; |
416331ca | 30 | use smallvec::{smallvec, SmallVec}; |
416331ca | 31 | |
f2b60f7d | 32 | use std::assert_matches::debug_assert_matches; |
487cf647 | 33 | use std::borrow::Cow; |
fc512014 | 34 | use std::collections::{hash_map::Entry, BTreeSet}; |
487cf647 | 35 | use std::mem::{replace, swap, take}; |
416331ca XL |
36 | |
37 | mod diagnostics; | |
38 | ||
39 | type Res = def::Res<NodeId>; | |
40 | ||
e1599b0c XL |
41 | type IdentMap<T> = FxHashMap<Ident, T>; |
42 | ||
416331ca | 43 | /// Map from the name in a pattern to its binding mode. |
e1599b0c | 44 | type BindingMap = IdentMap<BindingInfo>; |
416331ca | 45 | |
064997fb FG |
46 | use diagnostics::{ |
47 | ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind, | |
48 | }; | |
49 | ||
416331ca XL |
50 | #[derive(Copy, Clone, Debug)] |
51 | struct BindingInfo { | |
52 | span: Span, | |
f2b60f7d | 53 | annotation: BindingAnnotation, |
416331ca XL |
54 | } |
55 | ||
416331ca | 56 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
9ffffee4 | 57 | pub(crate) enum PatternSource { |
416331ca XL |
58 | Match, |
59 | Let, | |
60 | For, | |
61 | FnParam, | |
62 | } | |
63 | ||
29967ef6 XL |
64 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
65 | enum IsRepeatExpr { | |
66 | No, | |
67 | Yes, | |
68 | } | |
69 | ||
49aad941 FG |
70 | /// Describes whether an `AnonConst` is a type level const arg or |
71 | /// some other form of anon const (i.e. inline consts or enum discriminants) | |
72 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | |
73 | enum AnonConstKind { | |
74 | EnumDiscriminant, | |
75 | InlineConst, | |
76 | ConstArg(IsRepeatExpr), | |
77 | } | |
78 | ||
416331ca | 79 | impl PatternSource { |
9ffffee4 | 80 | fn descr(self) -> &'static str { |
416331ca XL |
81 | match self { |
82 | PatternSource::Match => "match binding", | |
83 | PatternSource::Let => "let binding", | |
84 | PatternSource::For => "for binding", | |
85 | PatternSource::FnParam => "function parameter", | |
86 | } | |
87 | } | |
88 | } | |
89 | ||
487cf647 FG |
90 | impl IntoDiagnosticArg for PatternSource { |
91 | fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { | |
92 | DiagnosticArgValue::Str(Cow::Borrowed(self.descr())) | |
93 | } | |
94 | } | |
95 | ||
e1599b0c XL |
96 | /// Denotes whether the context for the set of already bound bindings is a `Product` |
97 | /// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`. | |
98 | /// See those functions for more information. | |
60c5eb7d | 99 | #[derive(PartialEq)] |
e1599b0c XL |
100 | enum PatBoundCtx { |
101 | /// A product pattern context, e.g., `Variant(a, b)`. | |
102 | Product, | |
103 | /// An or-pattern context, e.g., `p_0 | ... | p_n`. | |
104 | Or, | |
105 | } | |
106 | ||
e74abb32 | 107 | /// Does this the item (from the item rib scope) allow generic parameters? |
f2b60f7d | 108 | #[derive(Copy, Clone, Debug)] |
923072b8 | 109 | pub(crate) enum HasGenericParams { |
f2b60f7d FG |
110 | Yes(Span), |
111 | No, | |
112 | } | |
113 | ||
114 | /// May this constant have generics? | |
115 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
116 | pub(crate) enum ConstantHasGenerics { | |
dfeec247 | 117 | Yes, |
49aad941 | 118 | No(NoConstantGenericsReason), |
dfeec247 | 119 | } |
e74abb32 | 120 | |
f2b60f7d | 121 | impl ConstantHasGenerics { |
04454e1e FG |
122 | fn force_yes_if(self, b: bool) -> Self { |
123 | if b { Self::Yes } else { self } | |
124 | } | |
125 | } | |
126 | ||
49aad941 FG |
127 | /// Reason for why an anon const is not allowed to reference generic parameters |
128 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
129 | pub(crate) enum NoConstantGenericsReason { | |
130 | /// Const arguments are only allowed to use generic parameters when: | |
131 | /// - `feature(generic_const_exprs)` is enabled | |
132 | /// or | |
133 | /// - the const argument is a sole const generic paramater, i.e. `foo::<{ N }>()` | |
134 | /// | |
135 | /// If neither of the above are true then this is used as the cause. | |
136 | NonTrivialConstArg, | |
137 | /// Enum discriminants are not allowed to reference generic parameters ever, this | |
138 | /// is used when an anon const is in the following position: | |
139 | /// | |
140 | /// ```rust,compile_fail | |
141 | /// enum Foo<const N: isize> { | |
142 | /// Variant = { N }, // this anon const is not allowed to use generics | |
143 | /// } | |
144 | /// ``` | |
145 | IsEnumDiscriminant, | |
146 | } | |
147 | ||
5869c6ff | 148 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
923072b8 | 149 | pub(crate) enum ConstantItemKind { |
5869c6ff XL |
150 | Const, |
151 | Static, | |
152 | } | |
153 | ||
49aad941 FG |
154 | impl ConstantItemKind { |
155 | pub(crate) fn as_str(&self) -> &'static str { | |
156 | match self { | |
157 | Self::Const => "const", | |
158 | Self::Static => "static", | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
353b0b11 FG |
163 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
164 | enum RecordPartialRes { | |
165 | Yes, | |
166 | No, | |
167 | } | |
168 | ||
416331ca XL |
169 | /// The rib kind restricts certain accesses, |
170 | /// e.g. to a `Res::Local` of an outer item. | |
171 | #[derive(Copy, Clone, Debug)] | |
923072b8 | 172 | pub(crate) enum RibKind<'a> { |
416331ca | 173 | /// No restriction needs to be applied. |
49aad941 | 174 | Normal, |
416331ca XL |
175 | |
176 | /// We passed through an impl or trait and are now in one of its | |
177 | /// methods or associated types. Allow references to ty params that impl or trait | |
178 | /// binds. Disallow any other upvars (including other ty params that are | |
179 | /// upvars). | |
49aad941 | 180 | AssocItem, |
416331ca | 181 | |
f035d41b | 182 | /// We passed through a closure. Disallow labels. |
49aad941 | 183 | ClosureOrAsync, |
f035d41b | 184 | |
416331ca | 185 | /// We passed through an item scope. Disallow upvars. |
49aad941 | 186 | Item(HasGenericParams), |
416331ca XL |
187 | |
188 | /// We're in a constant item. Can't refer to dynamic stuff. | |
1b1a35ee | 189 | /// |
04454e1e FG |
190 | /// The item may reference generic parameters in trivial constant expressions. |
191 | /// All other constants aren't allowed to use generic params at all. | |
49aad941 | 192 | ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), |
416331ca XL |
193 | |
194 | /// We passed through a module. | |
49aad941 | 195 | Module(Module<'a>), |
416331ca XL |
196 | |
197 | /// We passed through a `macro_rules!` statement | |
198 | MacroDefinition(DefId), | |
199 | ||
cdc7bbd5 XL |
200 | /// All bindings in this rib are generic parameters that can't be used |
201 | /// from the default of a generic parameter because they're not declared | |
202 | /// before said generic parameter. Also see the `visit_generics` override. | |
49aad941 | 203 | ForwardGenericParamBan, |
3dfed10e XL |
204 | |
205 | /// We are inside of the type of a const parameter. Can't refer to any | |
206 | /// parameters. | |
49aad941 | 207 | ConstParamTy, |
04454e1e FG |
208 | |
209 | /// We are inside a `sym` inline assembly operand. Can only refer to | |
210 | /// globals. | |
49aad941 | 211 | InlineAsmSym, |
416331ca XL |
212 | } |
213 | ||
e1599b0c | 214 | impl RibKind<'_> { |
f035d41b XL |
215 | /// Whether this rib kind contains generic parameters, as opposed to local |
216 | /// variables. | |
923072b8 | 217 | pub(crate) fn contains_params(&self) -> bool { |
e1599b0c | 218 | match self { |
49aad941 FG |
219 | RibKind::Normal |
220 | | RibKind::ClosureOrAsync | |
221 | | RibKind::ConstantItem(..) | |
222 | | RibKind::Module(_) | |
223 | | RibKind::MacroDefinition(_) | |
224 | | RibKind::ConstParamTy | |
225 | | RibKind::InlineAsmSym => false, | |
226 | RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true, | |
e1599b0c XL |
227 | } |
228 | } | |
923072b8 FG |
229 | |
230 | /// This rib forbids referring to labels defined in upwards ribs. | |
231 | fn is_label_barrier(self) -> bool { | |
232 | match self { | |
49aad941 FG |
233 | RibKind::Normal | RibKind::MacroDefinition(..) => false, |
234 | ||
235 | RibKind::AssocItem | |
236 | | RibKind::ClosureOrAsync | |
237 | | RibKind::Item(..) | |
238 | | RibKind::ConstantItem(..) | |
239 | | RibKind::Module(..) | |
240 | | RibKind::ForwardGenericParamBan | |
241 | | RibKind::ConstParamTy | |
242 | | RibKind::InlineAsmSym => true, | |
923072b8 FG |
243 | } |
244 | } | |
e1599b0c XL |
245 | } |
246 | ||
416331ca XL |
247 | /// A single local scope. |
248 | /// | |
249 | /// A rib represents a scope names can live in. Note that these appear in many places, not just | |
250 | /// around braces. At any place where the list of accessible names (of the given namespace) | |
251 | /// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a | |
252 | /// stack. This may be, for example, a `let` statement (because it introduces variables), a macro, | |
253 | /// etc. | |
254 | /// | |
923072b8 | 255 | /// Different [rib kinds](enum@RibKind) are transparent for different names. |
416331ca XL |
256 | /// |
257 | /// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When | |
258 | /// resolving, the name is looked up from inside out. | |
259 | #[derive(Debug)] | |
923072b8 | 260 | pub(crate) struct Rib<'a, R = Res> { |
e1599b0c | 261 | pub bindings: IdentMap<R>, |
416331ca XL |
262 | pub kind: RibKind<'a>, |
263 | } | |
264 | ||
265 | impl<'a, R> Rib<'a, R> { | |
266 | fn new(kind: RibKind<'a>) -> Rib<'a, R> { | |
dfeec247 | 267 | Rib { bindings: Default::default(), kind } |
416331ca XL |
268 | } |
269 | } | |
270 | ||
923072b8 FG |
271 | #[derive(Clone, Copy, Debug)] |
272 | enum LifetimeUseSet { | |
273 | One { use_span: Span, use_ctxt: visit::LifetimeCtxt }, | |
274 | Many, | |
275 | } | |
276 | ||
04454e1e FG |
277 | #[derive(Copy, Clone, Debug)] |
278 | enum LifetimeRibKind { | |
2b03887a FG |
279 | // -- Ribs introducing named lifetimes |
280 | // | |
04454e1e | 281 | /// This rib declares generic parameters. |
2b03887a | 282 | /// Only for this kind the `LifetimeRib::bindings` field can be non-empty. |
923072b8 | 283 | Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind }, |
04454e1e | 284 | |
2b03887a FG |
285 | // -- Ribs introducing unnamed lifetimes |
286 | // | |
923072b8 | 287 | /// Create a new anonymous lifetime parameter and reference it. |
04454e1e | 288 | /// |
923072b8 FG |
289 | /// If `report_in_path`, report an error when encountering lifetime elision in a path: |
290 | /// ```compile_fail | |
291 | /// struct Foo<'a> { x: &'a () } | |
292 | /// async fn foo(x: Foo) {} | |
293 | /// ``` | |
04454e1e | 294 | /// |
923072b8 FG |
295 | /// Note: the error should not trigger when the elided lifetime is in a pattern or |
296 | /// expression-position path: | |
297 | /// ``` | |
298 | /// struct Foo<'a> { x: &'a () } | |
299 | /// async fn foo(Foo { x: _ }: Foo<'_>) {} | |
300 | /// ``` | |
301 | AnonymousCreateParameter { binder: NodeId, report_in_path: bool }, | |
04454e1e | 302 | |
2b03887a FG |
303 | /// Replace all anonymous lifetimes by provided lifetime. |
304 | Elided(LifetimeRes), | |
305 | ||
306 | // -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later. | |
307 | // | |
04454e1e FG |
308 | /// Give a hard error when either `&` or `'_` is written. Used to |
309 | /// rule out things like `where T: Foo<'_>`. Does not imply an | |
310 | /// error on default object bounds (e.g., `Box<dyn Foo>`). | |
311 | AnonymousReportError, | |
312 | ||
064997fb FG |
313 | /// Signal we cannot find which should be the anonymous lifetime. |
314 | ElisionFailure, | |
2b03887a | 315 | |
49aad941 FG |
316 | /// This rib forbids usage of generic parameters inside of const parameter types. |
317 | /// | |
318 | /// While this is desirable to support eventually, it is difficult to do and so is | |
319 | /// currently forbidden. See rust-lang/project-const-generics#28 for more info. | |
320 | ConstParamTy, | |
2b03887a | 321 | |
49aad941 FG |
322 | /// Usage of generic parameters is forbidden in various positions for anon consts: |
323 | /// - const arguments when `generic_const_exprs` is not enabled | |
324 | /// - enum discriminant values | |
325 | /// | |
326 | /// This rib emits an error when a lifetime would resolve to a lifetime parameter. | |
327 | ConcreteAnonConst(NoConstantGenericsReason), | |
2b03887a FG |
328 | |
329 | /// This rib acts as a barrier to forbid reference to lifetimes of a parent item. | |
330 | Item, | |
04454e1e FG |
331 | } |
332 | ||
333 | #[derive(Copy, Clone, Debug)] | |
334 | enum LifetimeBinderKind { | |
335 | BareFnType, | |
336 | PolyTrait, | |
337 | WhereBound, | |
338 | Item, | |
339 | Function, | |
064997fb | 340 | Closure, |
04454e1e FG |
341 | ImplBlock, |
342 | } | |
343 | ||
344 | impl LifetimeBinderKind { | |
345 | fn descr(self) -> &'static str { | |
346 | use LifetimeBinderKind::*; | |
347 | match self { | |
348 | BareFnType => "type", | |
349 | PolyTrait => "bound", | |
350 | WhereBound => "bound", | |
351 | Item => "item", | |
352 | ImplBlock => "impl block", | |
353 | Function => "function", | |
064997fb | 354 | Closure => "closure", |
04454e1e FG |
355 | } |
356 | } | |
357 | } | |
358 | ||
359 | #[derive(Debug)] | |
360 | struct LifetimeRib { | |
361 | kind: LifetimeRibKind, | |
362 | // We need to preserve insertion order for async fns. | |
363 | bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>, | |
364 | } | |
365 | ||
366 | impl LifetimeRib { | |
367 | fn new(kind: LifetimeRibKind) -> LifetimeRib { | |
368 | LifetimeRib { bindings: Default::default(), kind } | |
369 | } | |
370 | } | |
371 | ||
416331ca | 372 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
923072b8 | 373 | pub(crate) enum AliasPossibility { |
416331ca XL |
374 | No, |
375 | Maybe, | |
376 | } | |
377 | ||
378 | #[derive(Copy, Clone, Debug)] | |
923072b8 | 379 | pub(crate) enum PathSource<'a> { |
416331ca XL |
380 | // Type paths `Path`. |
381 | Type, | |
382 | // Trait paths in bounds or impls. | |
383 | Trait(AliasPossibility), | |
384 | // Expression paths `path`, with optional parent context. | |
385 | Expr(Option<&'a Expr>), | |
386 | // Paths in path patterns `Path`. | |
387 | Pat, | |
388 | // Paths in struct expressions and patterns `Path { .. }`. | |
389 | Struct, | |
390 | // Paths in tuple struct patterns `Path(..)`. | |
1b1a35ee | 391 | TupleStruct(Span, &'a [Span]), |
416331ca XL |
392 | // `m::A::B` in `<T as m::A>::B::C`. |
393 | TraitItem(Namespace), | |
394 | } | |
395 | ||
396 | impl<'a> PathSource<'a> { | |
397 | fn namespace(self) -> Namespace { | |
398 | match self { | |
399 | PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS, | |
1b1a35ee | 400 | PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) => ValueNS, |
416331ca XL |
401 | PathSource::TraitItem(ns) => ns, |
402 | } | |
403 | } | |
404 | ||
405 | fn defer_to_typeck(self) -> bool { | |
406 | match self { | |
dfeec247 XL |
407 | PathSource::Type |
408 | | PathSource::Expr(..) | |
409 | | PathSource::Pat | |
410 | | PathSource::Struct | |
1b1a35ee | 411 | | PathSource::TupleStruct(..) => true, |
416331ca XL |
412 | PathSource::Trait(_) | PathSource::TraitItem(..) => false, |
413 | } | |
414 | } | |
415 | ||
416 | fn descr_expected(self) -> &'static str { | |
e74abb32 | 417 | match &self { |
416331ca XL |
418 | PathSource::Type => "type", |
419 | PathSource::Trait(_) => "trait", | |
e74abb32 | 420 | PathSource::Pat => "unit struct, unit variant or constant", |
416331ca | 421 | PathSource::Struct => "struct, variant or union type", |
1b1a35ee | 422 | PathSource::TupleStruct(..) => "tuple struct or tuple variant", |
416331ca XL |
423 | PathSource::TraitItem(ns) => match ns { |
424 | TypeNS => "associated type", | |
425 | ValueNS => "method or associated constant", | |
426 | MacroNS => bug!("associated macro"), | |
427 | }, | |
3dfed10e | 428 | PathSource::Expr(parent) => match parent.as_ref().map(|p| &p.kind) { |
416331ca XL |
429 | // "function" here means "anything callable" rather than `DefKind::Fn`, |
430 | // this is not precise but usually more helpful than just "value". | |
dfeec247 | 431 | Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind { |
5869c6ff XL |
432 | // the case of `::some_crate()` |
433 | ExprKind::Path(_, path) | |
434 | if path.segments.len() == 2 | |
435 | && path.segments[0].ident.name == kw::PathRoot => | |
436 | { | |
437 | "external crate" | |
438 | } | |
dfeec247 XL |
439 | ExprKind::Path(_, path) => { |
440 | let mut msg = "function"; | |
441 | if let Some(segment) = path.segments.iter().last() { | |
442 | if let Some(c) = segment.ident.to_string().chars().next() { | |
443 | if c.is_uppercase() { | |
444 | msg = "function, tuple struct or tuple variant"; | |
e74abb32 XL |
445 | } |
446 | } | |
e74abb32 | 447 | } |
dfeec247 | 448 | msg |
e74abb32 | 449 | } |
dfeec247 XL |
450 | _ => "function", |
451 | }, | |
416331ca XL |
452 | _ => "value", |
453 | }, | |
454 | } | |
455 | } | |
456 | ||
f035d41b | 457 | fn is_call(self) -> bool { |
29967ef6 | 458 | matches!(self, PathSource::Expr(Some(&Expr { kind: ExprKind::Call(..), .. }))) |
f035d41b XL |
459 | } |
460 | ||
923072b8 | 461 | pub(crate) fn is_expected(self, res: Res) -> bool { |
416331ca | 462 | match self { |
5869c6ff XL |
463 | PathSource::Type => matches!( |
464 | res, | |
465 | Res::Def( | |
ba9703b0 | 466 | DefKind::Struct |
5869c6ff XL |
467 | | DefKind::Union |
468 | | DefKind::Enum | |
469 | | DefKind::Trait | |
470 | | DefKind::TraitAlias | |
471 | | DefKind::TyAlias | |
472 | | DefKind::AssocTy | |
473 | | DefKind::TyParam | |
474 | | DefKind::OpaqueTy | |
475 | | DefKind::ForeignTy, | |
ba9703b0 | 476 | _, |
5869c6ff | 477 | ) | Res::PrimTy(..) |
2b03887a FG |
478 | | Res::SelfTyParam { .. } |
479 | | Res::SelfTyAlias { .. } | |
5869c6ff | 480 | ), |
29967ef6 XL |
481 | PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)), |
482 | PathSource::Trait(AliasPossibility::Maybe) => { | |
483 | matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) | |
484 | } | |
5869c6ff XL |
485 | PathSource::Expr(..) => matches!( |
486 | res, | |
487 | Res::Def( | |
ba9703b0 | 488 | DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn) |
5869c6ff | 489 | | DefKind::Const |
5e7ed085 | 490 | | DefKind::Static(_) |
5869c6ff XL |
491 | | DefKind::Fn |
492 | | DefKind::AssocFn | |
493 | | DefKind::AssocConst | |
494 | | DefKind::ConstParam, | |
ba9703b0 | 495 | _, |
5869c6ff XL |
496 | ) | Res::Local(..) |
497 | | Res::SelfCtor(..) | |
498 | ), | |
04454e1e FG |
499 | PathSource::Pat => { |
500 | res.expected_in_unit_struct_pat() | |
501 | || matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _)) | |
502 | } | |
29967ef6 | 503 | PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(), |
5869c6ff XL |
504 | PathSource::Struct => matches!( |
505 | res, | |
506 | Res::Def( | |
ba9703b0 | 507 | DefKind::Struct |
5869c6ff XL |
508 | | DefKind::Union |
509 | | DefKind::Variant | |
510 | | DefKind::TyAlias | |
511 | | DefKind::AssocTy, | |
ba9703b0 | 512 | _, |
2b03887a FG |
513 | ) | Res::SelfTyParam { .. } |
514 | | Res::SelfTyAlias { .. } | |
5869c6ff | 515 | ), |
416331ca | 516 | PathSource::TraitItem(ns) => match res { |
ba9703b0 | 517 | Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true, |
416331ca XL |
518 | Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, |
519 | _ => false, | |
520 | }, | |
521 | } | |
522 | } | |
523 | ||
dfeec247 XL |
524 | fn error_code(self, has_unexpected_resolution: bool) -> DiagnosticId { |
525 | use rustc_errors::error_code; | |
416331ca | 526 | match (self, has_unexpected_resolution) { |
dfeec247 XL |
527 | (PathSource::Trait(_), true) => error_code!(E0404), |
528 | (PathSource::Trait(_), false) => error_code!(E0405), | |
529 | (PathSource::Type, true) => error_code!(E0573), | |
530 | (PathSource::Type, false) => error_code!(E0412), | |
531 | (PathSource::Struct, true) => error_code!(E0574), | |
532 | (PathSource::Struct, false) => error_code!(E0422), | |
533 | (PathSource::Expr(..), true) => error_code!(E0423), | |
534 | (PathSource::Expr(..), false) => error_code!(E0425), | |
1b1a35ee XL |
535 | (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532), |
536 | (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531), | |
dfeec247 XL |
537 | (PathSource::TraitItem(..), true) => error_code!(E0575), |
538 | (PathSource::TraitItem(..), false) => error_code!(E0576), | |
416331ca XL |
539 | } |
540 | } | |
541 | } | |
542 | ||
9ffffee4 FG |
543 | /// At this point for most items we can answer whether that item is exported or not, |
544 | /// but some items like impls require type information to determine exported-ness, so we make a | |
545 | /// conservative estimate for them (e.g. based on nominal visibility). | |
546 | #[derive(Clone, Copy)] | |
547 | enum MaybeExported<'a> { | |
548 | Ok(NodeId), | |
549 | Impl(Option<DefId>), | |
550 | ImplItem(Result<DefId, &'a Visibility>), | |
551 | } | |
552 | ||
553 | impl MaybeExported<'_> { | |
554 | fn eval(self, r: &Resolver<'_, '_>) -> bool { | |
555 | let def_id = match self { | |
556 | MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)), | |
557 | MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => { | |
558 | trait_def_id.as_local() | |
559 | } | |
560 | MaybeExported::Impl(None) => return true, | |
561 | MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(), | |
562 | }; | |
563 | def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id)) | |
564 | } | |
565 | } | |
566 | ||
e74abb32 | 567 | #[derive(Default)] |
dfeec247 | 568 | struct DiagnosticMetadata<'ast> { |
29967ef6 XL |
569 | /// The current trait's associated items' ident, used for diagnostic suggestions. |
570 | current_trait_assoc_items: Option<&'ast [P<AssocItem>]>, | |
e74abb32 XL |
571 | |
572 | /// The current self type if inside an impl (used for better errors). | |
573 | current_self_type: Option<Ty>, | |
574 | ||
575 | /// The current self item if inside an ADT (used for better errors). | |
576 | current_self_item: Option<NodeId>, | |
577 | ||
dfeec247 XL |
578 | /// The current trait (used to suggest). |
579 | current_item: Option<&'ast Item>, | |
580 | ||
581 | /// When processing generics and encountering a type not found, suggest introducing a type | |
582 | /// param. | |
583 | currently_processing_generics: bool, | |
584 | ||
29967ef6 | 585 | /// The current enclosing (non-closure) function (used for better errors). |
f9f354fc | 586 | current_function: Option<(FnKind<'ast>, Span)>, |
e74abb32 XL |
587 | |
588 | /// A list of labels as of yet unused. Labels will be removed from this map when | |
589 | /// they are used (in a `break` or `continue` statement) | |
590 | unused_labels: FxHashMap<NodeId, Span>, | |
591 | ||
94222f64 XL |
592 | /// Only used for better errors on `let x = { foo: bar };`. |
593 | /// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only | |
594 | /// needed for cases where this parses as a correct type ascription. | |
595 | current_block_could_be_bare_struct_literal: Option<Span>, | |
596 | ||
e74abb32 XL |
597 | /// Only used for better errors on `let <pat>: <expr, not type>;`. |
598 | current_let_binding: Option<(Span, Option<Span>, Option<Span>)>, | |
1b1a35ee XL |
599 | |
600 | /// Used to detect possible `if let` written without `let` and to provide structured suggestion. | |
601 | in_if_condition: Option<&'ast Expr>, | |
29967ef6 | 602 | |
2b03887a FG |
603 | /// Used to detect possible new binding written without `let` and to provide structured suggestion. |
604 | in_assignment: Option<&'ast Expr>, | |
487cf647 | 605 | is_assign_rhs: bool, |
2b03887a | 606 | |
9c376795 FG |
607 | /// Used to detect possible `.` -> `..` typo when calling methods. |
608 | in_range: Option<(&'ast Expr, &'ast Expr)>, | |
609 | ||
29967ef6 XL |
610 | /// If we are currently in a trait object definition. Used to point at the bounds when |
611 | /// encountering a struct or enum. | |
612 | current_trait_object: Option<&'ast [ast::GenericBound]>, | |
613 | ||
614 | /// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`. | |
615 | current_where_predicate: Option<&'ast WherePredicate>, | |
5099ac24 FG |
616 | |
617 | current_type_path: Option<&'ast Ty>, | |
04454e1e FG |
618 | |
619 | /// The current impl items (used to suggest). | |
620 | current_impl_items: Option<&'ast [P<AssocItem>]>, | |
923072b8 FG |
621 | |
622 | /// When processing impl trait | |
623 | currently_processing_impl_trait: Option<(TraitRef, Ty)>, | |
064997fb FG |
624 | |
625 | /// Accumulate the errors due to missed lifetime elision, | |
626 | /// and report them all at once for each function. | |
627 | current_elision_failures: Vec<MissingLifetime>, | |
e74abb32 XL |
628 | } |
629 | ||
9ffffee4 FG |
630 | struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { |
631 | r: &'b mut Resolver<'a, 'tcx>, | |
416331ca XL |
632 | |
633 | /// The module that represents the current item scope. | |
634 | parent_scope: ParentScope<'a>, | |
635 | ||
636 | /// The current set of local scopes for types and values. | |
416331ca XL |
637 | ribs: PerNS<Vec<Rib<'a>>>, |
638 | ||
353b0b11 | 639 | /// Previous popped `rib`, only used for diagnostic. |
9c376795 FG |
640 | last_block_rib: Option<Rib<'a>>, |
641 | ||
416331ca XL |
642 | /// The current set of local scopes, for labels. |
643 | label_ribs: Vec<Rib<'a, NodeId>>, | |
644 | ||
04454e1e FG |
645 | /// The current set of local scopes for lifetimes. |
646 | lifetime_ribs: Vec<LifetimeRib>, | |
647 | ||
064997fb FG |
648 | /// We are looking for lifetimes in an elision context. |
649 | /// The set contains all the resolutions that we encountered so far. | |
650 | /// They will be used to determine the correct lifetime for the fn return type. | |
651 | /// The `LifetimeElisionCandidate` is used for diagnostics, to suggest introducing named | |
652 | /// lifetimes. | |
f2b60f7d | 653 | lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>, |
064997fb | 654 | |
416331ca XL |
655 | /// The trait that the current context can refer to. |
656 | current_trait_ref: Option<(Module<'a>, TraitRef)>, | |
657 | ||
e74abb32 | 658 | /// Fields used to add information to diagnostic errors. |
064997fb | 659 | diagnostic_metadata: Box<DiagnosticMetadata<'ast>>, |
3dfed10e XL |
660 | |
661 | /// State used to know whether to ignore resolution errors for function bodies. | |
662 | /// | |
663 | /// In particular, rustdoc uses this to avoid giving errors for `cfg()` items. | |
664 | /// In most cases this will be `None`, in which case errors will always be reported. | |
1b1a35ee | 665 | /// If it is `true`, then it will be updated when entering a nested function or trait body. |
3dfed10e | 666 | in_func_body: bool, |
923072b8 FG |
667 | |
668 | /// Count the number of places a lifetime is used. | |
669 | lifetime_uses: FxHashMap<LocalDefId, LifetimeUseSet>, | |
416331ca XL |
670 | } |
671 | ||
672 | /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. | |
9ffffee4 | 673 | impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, 'tcx> { |
3c0e092e XL |
674 | fn visit_attribute(&mut self, _: &'ast Attribute) { |
675 | // We do not want to resolve expressions that appear in attributes, | |
676 | // as they do not correspond to actual code. | |
677 | } | |
dfeec247 XL |
678 | fn visit_item(&mut self, item: &'ast Item) { |
679 | let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item)); | |
3dfed10e XL |
680 | // Always report errors in items we just entered. |
681 | let old_ignore = replace(&mut self.in_func_body, false); | |
04454e1e | 682 | self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item)); |
3dfed10e | 683 | self.in_func_body = old_ignore; |
dfeec247 | 684 | self.diagnostic_metadata.current_item = prev; |
416331ca | 685 | } |
dfeec247 | 686 | fn visit_arm(&mut self, arm: &'ast Arm) { |
416331ca XL |
687 | self.resolve_arm(arm); |
688 | } | |
dfeec247 | 689 | fn visit_block(&mut self, block: &'ast Block) { |
9ffffee4 | 690 | let old_macro_rules = self.parent_scope.macro_rules; |
416331ca | 691 | self.resolve_block(block); |
9ffffee4 | 692 | self.parent_scope.macro_rules = old_macro_rules; |
416331ca | 693 | } |
49aad941 FG |
694 | fn visit_anon_const(&mut self, _constant: &'ast AnonConst) { |
695 | bug!("encountered anon const without a manual call to `resolve_anon_const`"); | |
416331ca | 696 | } |
dfeec247 | 697 | fn visit_expr(&mut self, expr: &'ast Expr) { |
416331ca XL |
698 | self.resolve_expr(expr, None); |
699 | } | |
dfeec247 | 700 | fn visit_local(&mut self, local: &'ast Local) { |
e74abb32 XL |
701 | let local_spans = match local.pat.kind { |
702 | // We check for this to avoid tuple struct fields. | |
703 | PatKind::Wild => None, | |
704 | _ => Some(( | |
705 | local.pat.span, | |
706 | local.ty.as_ref().map(|ty| ty.span), | |
94222f64 | 707 | local.kind.init().map(|init| init.span), |
e74abb32 XL |
708 | )), |
709 | }; | |
710 | let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans); | |
416331ca | 711 | self.resolve_local(local); |
e74abb32 | 712 | self.diagnostic_metadata.current_let_binding = original; |
416331ca | 713 | } |
dfeec247 | 714 | fn visit_ty(&mut self, ty: &'ast Ty) { |
29967ef6 | 715 | let prev = self.diagnostic_metadata.current_trait_object; |
5099ac24 | 716 | let prev_ty = self.diagnostic_metadata.current_type_path; |
49aad941 | 717 | match &ty.kind { |
9c376795 | 718 | TyKind::Ref(None, _) => { |
04454e1e FG |
719 | // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with |
720 | // NodeId `ty.id`. | |
064997fb | 721 | // This span will be used in case of elision failure. |
9ffffee4 | 722 | let span = self.r.tcx.sess.source_map().start_point(ty.span); |
04454e1e | 723 | self.resolve_elided_lifetime(ty.id, span); |
064997fb | 724 | visit::walk_ty(self, ty); |
04454e1e | 725 | } |
49aad941 | 726 | TyKind::Path(qself, path) => { |
5099ac24 | 727 | self.diagnostic_metadata.current_type_path = Some(ty); |
487cf647 | 728 | self.smart_resolve_path(ty.id, &qself, path, PathSource::Type); |
923072b8 FG |
729 | |
730 | // Check whether we should interpret this as a bare trait object. | |
731 | if qself.is_none() | |
732 | && let Some(partial_res) = self.r.partial_res_map.get(&ty.id) | |
2b03887a | 733 | && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res() |
923072b8 | 734 | { |
9c376795 | 735 | // This path is actually a bare trait object. In case of a bare `Fn`-trait |
923072b8 FG |
736 | // object with anonymous lifetimes, we need this rib to correctly place the |
737 | // synthetic lifetimes. | |
738 | let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo()); | |
739 | self.with_generic_param_rib( | |
740 | &[], | |
49aad941 | 741 | RibKind::Normal, |
923072b8 FG |
742 | LifetimeRibKind::Generics { |
743 | binder: ty.id, | |
744 | kind: LifetimeBinderKind::PolyTrait, | |
745 | span, | |
746 | }, | |
747 | |this| this.visit_path(&path, ty.id), | |
748 | ); | |
064997fb FG |
749 | } else { |
750 | visit::walk_ty(self, ty) | |
923072b8 | 751 | } |
416331ca XL |
752 | } |
753 | TyKind::ImplicitSelf => { | |
e1599b0c | 754 | let self_ty = Ident::with_dummy_span(kw::SelfUpper); |
dfeec247 | 755 | let res = self |
5e7ed085 FG |
756 | .resolve_ident_in_lexical_scope( |
757 | self_ty, | |
758 | TypeNS, | |
04454e1e FG |
759 | Some(Finalize::new(ty.id, ty.span)), |
760 | None, | |
5e7ed085 | 761 | ) |
dfeec247 | 762 | .map_or(Res::Err, |d| d.res()); |
416331ca | 763 | self.r.record_partial_res(ty.id, PartialRes::new(res)); |
064997fb FG |
764 | visit::walk_ty(self, ty) |
765 | } | |
766 | TyKind::ImplTrait(..) => { | |
767 | let candidates = self.lifetime_elision_candidates.take(); | |
768 | visit::walk_ty(self, ty); | |
769 | self.lifetime_elision_candidates = candidates; | |
416331ca | 770 | } |
49aad941 | 771 | TyKind::TraitObject(bounds, ..) => { |
29967ef6 | 772 | self.diagnostic_metadata.current_trait_object = Some(&bounds[..]); |
064997fb | 773 | visit::walk_ty(self, ty) |
29967ef6 | 774 | } |
49aad941 | 775 | TyKind::BareFn(bare_fn) => { |
923072b8 | 776 | let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo()); |
04454e1e FG |
777 | self.with_generic_param_rib( |
778 | &bare_fn.generic_params, | |
49aad941 | 779 | RibKind::Normal, |
04454e1e | 780 | LifetimeRibKind::Generics { |
923072b8 | 781 | binder: ty.id, |
04454e1e FG |
782 | kind: LifetimeBinderKind::BareFnType, |
783 | span, | |
784 | }, | |
785 | |this| { | |
923072b8 | 786 | this.visit_generic_params(&bare_fn.generic_params, false); |
04454e1e | 787 | this.with_lifetime_rib( |
923072b8 FG |
788 | LifetimeRibKind::AnonymousCreateParameter { |
789 | binder: ty.id, | |
790 | report_in_path: false, | |
04454e1e | 791 | }, |
064997fb FG |
792 | |this| { |
793 | this.resolve_fn_signature( | |
794 | ty.id, | |
795 | false, | |
796 | // We don't need to deal with patterns in parameters, because | |
797 | // they are not possible for foreign or bodiless functions. | |
798 | bare_fn | |
799 | .decl | |
800 | .inputs | |
801 | .iter() | |
802 | .map(|Param { ty, .. }| (None, &**ty)), | |
803 | &bare_fn.decl.output, | |
804 | ) | |
805 | }, | |
04454e1e FG |
806 | ); |
807 | }, | |
064997fb | 808 | ) |
04454e1e | 809 | } |
49aad941 FG |
810 | TyKind::Array(element_ty, length) => { |
811 | self.visit_ty(element_ty); | |
812 | self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No)); | |
813 | } | |
814 | TyKind::Typeof(ct) => { | |
815 | self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No)) | |
816 | } | |
064997fb | 817 | _ => visit::walk_ty(self, ty), |
416331ca | 818 | } |
29967ef6 | 819 | self.diagnostic_metadata.current_trait_object = prev; |
5099ac24 | 820 | self.diagnostic_metadata.current_type_path = prev_ty; |
416331ca | 821 | } |
f2b60f7d | 822 | fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) { |
923072b8 | 823 | let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo()); |
04454e1e FG |
824 | self.with_generic_param_rib( |
825 | &tref.bound_generic_params, | |
49aad941 | 826 | RibKind::Normal, |
04454e1e | 827 | LifetimeRibKind::Generics { |
923072b8 | 828 | binder: tref.trait_ref.ref_id, |
04454e1e FG |
829 | kind: LifetimeBinderKind::PolyTrait, |
830 | span, | |
831 | }, | |
832 | |this| { | |
923072b8 | 833 | this.visit_generic_params(&tref.bound_generic_params, false); |
04454e1e FG |
834 | this.smart_resolve_path( |
835 | tref.trait_ref.ref_id, | |
487cf647 | 836 | &None, |
04454e1e FG |
837 | &tref.trait_ref.path, |
838 | PathSource::Trait(AliasPossibility::Maybe), | |
839 | ); | |
840 | this.visit_trait_ref(&tref.trait_ref); | |
841 | }, | |
dfeec247 | 842 | ); |
416331ca | 843 | } |
dfeec247 | 844 | fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { |
9ffffee4 | 845 | self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); |
e74abb32 | 846 | match foreign_item.kind { |
04454e1e | 847 | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { |
2b03887a FG |
848 | self.with_generic_param_rib( |
849 | &generics.params, | |
49aad941 | 850 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
2b03887a FG |
851 | LifetimeRibKind::Generics { |
852 | binder: foreign_item.id, | |
853 | kind: LifetimeBinderKind::Item, | |
854 | span: generics.span, | |
855 | }, | |
856 | |this| visit::walk_foreign_item(this, foreign_item), | |
857 | ); | |
04454e1e FG |
858 | } |
859 | ForeignItemKind::Fn(box Fn { ref generics, .. }) => { | |
2b03887a FG |
860 | self.with_generic_param_rib( |
861 | &generics.params, | |
49aad941 | 862 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
2b03887a FG |
863 | LifetimeRibKind::Generics { |
864 | binder: foreign_item.id, | |
865 | kind: LifetimeBinderKind::Function, | |
866 | span: generics.span, | |
867 | }, | |
868 | |this| visit::walk_foreign_item(this, foreign_item), | |
869 | ); | |
416331ca | 870 | } |
e74abb32 | 871 | ForeignItemKind::Static(..) => { |
2b03887a | 872 | self.with_static_rib(|this| { |
e74abb32 XL |
873 | visit::walk_foreign_item(this, foreign_item); |
874 | }); | |
875 | } | |
ba9703b0 | 876 | ForeignItemKind::MacCall(..) => { |
04454e1e | 877 | panic!("unexpanded macro in resolve!") |
e74abb32 XL |
878 | } |
879 | } | |
416331ca | 880 | } |
04454e1e | 881 | fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { |
f2b60f7d FG |
882 | let previous_value = self.diagnostic_metadata.current_function; |
883 | match fn_kind { | |
5099ac24 FG |
884 | // Bail if the function is foreign, and thus cannot validly have |
885 | // a body, or if there's no body for some other reason. | |
04454e1e FG |
886 | FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) |
887 | | FnKind::Fn(_, _, sig, _, generics, None) => { | |
923072b8 FG |
888 | self.visit_fn_header(&sig.header); |
889 | self.visit_generics(generics); | |
923072b8 | 890 | self.with_lifetime_rib( |
064997fb FG |
891 | LifetimeRibKind::AnonymousCreateParameter { |
892 | binder: fn_id, | |
893 | report_in_path: false, | |
894 | }, | |
895 | |this| { | |
896 | this.resolve_fn_signature( | |
897 | fn_id, | |
898 | sig.decl.has_self(), | |
899 | sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)), | |
900 | &sig.decl.output, | |
2b03887a | 901 | ); |
064997fb | 902 | }, |
923072b8 | 903 | ); |
49aad941 | 904 | self.record_lifetime_params_for_async(fn_id, sig.header.asyncness.opt_return_id()); |
5099ac24 FG |
905 | return; |
906 | } | |
f2b60f7d FG |
907 | FnKind::Fn(..) => { |
908 | self.diagnostic_metadata.current_function = Some((fn_kind, sp)); | |
909 | } | |
910 | // Do not update `current_function` for closures: it suggests `self` parameters. | |
911 | FnKind::Closure(..) => {} | |
416331ca | 912 | }; |
74b04a01 | 913 | debug!("(resolving function) entering function"); |
416331ca XL |
914 | |
915 | // Create a value rib for the function. | |
49aad941 | 916 | self.with_rib(ValueNS, RibKind::ClosureOrAsync, |this| { |
e1599b0c | 917 | // Create a label rib for the function. |
49aad941 | 918 | this.with_label_rib(RibKind::ClosureOrAsync, |this| { |
923072b8 FG |
919 | match fn_kind { |
920 | FnKind::Fn(_, _, sig, _, generics, body) => { | |
921 | this.visit_generics(generics); | |
922 | ||
923 | let declaration = &sig.decl; | |
924 | let async_node_id = sig.header.asyncness.opt_return_id(); | |
925 | ||
064997fb | 926 | this.with_lifetime_rib( |
923072b8 FG |
927 | LifetimeRibKind::AnonymousCreateParameter { |
928 | binder: fn_id, | |
064997fb FG |
929 | report_in_path: async_node_id.is_some(), |
930 | }, | |
931 | |this| { | |
932 | this.resolve_fn_signature( | |
933 | fn_id, | |
934 | declaration.has_self(), | |
935 | declaration | |
936 | .inputs | |
937 | .iter() | |
938 | .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)), | |
939 | &declaration.output, | |
940 | ) | |
941 | }, | |
04454e1e | 942 | ); |
923072b8 | 943 | |
2b03887a | 944 | this.record_lifetime_params_for_async(fn_id, async_node_id); |
04454e1e | 945 | |
923072b8 FG |
946 | if let Some(body) = body { |
947 | // Ignore errors in function bodies if this is rustdoc | |
948 | // Be sure not to set this until the function signature has been resolved. | |
949 | let previous_state = replace(&mut this.in_func_body, true); | |
9c376795 FG |
950 | // We only care block in the same function |
951 | this.last_block_rib = None; | |
923072b8 FG |
952 | // Resolve the function body, potentially inside the body of an async closure |
953 | this.with_lifetime_rib( | |
064997fb | 954 | LifetimeRibKind::Elided(LifetimeRes::Infer), |
923072b8 FG |
955 | |this| this.visit_block(body), |
956 | ); | |
e1599b0c | 957 | |
923072b8 FG |
958 | debug!("(resolving function) leaving function"); |
959 | this.in_func_body = previous_state; | |
960 | } | |
04454e1e | 961 | } |
064997fb FG |
962 | FnKind::Closure(binder, declaration, body) => { |
963 | this.visit_closure_binder(binder); | |
964 | ||
923072b8 | 965 | this.with_lifetime_rib( |
064997fb FG |
966 | match binder { |
967 | // We do not have any explicit generic lifetime parameter. | |
968 | ClosureBinder::NotPresent => { | |
969 | LifetimeRibKind::AnonymousCreateParameter { | |
970 | binder: fn_id, | |
971 | report_in_path: false, | |
972 | } | |
973 | } | |
974 | ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError, | |
923072b8 FG |
975 | }, |
976 | // Add each argument to the rib. | |
977 | |this| this.resolve_params(&declaration.inputs), | |
978 | ); | |
979 | this.with_lifetime_rib( | |
064997fb FG |
980 | match binder { |
981 | ClosureBinder::NotPresent => { | |
982 | LifetimeRibKind::Elided(LifetimeRes::Infer) | |
983 | } | |
984 | ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError, | |
985 | }, | |
923072b8 FG |
986 | |this| visit::walk_fn_ret_ty(this, &declaration.output), |
987 | ); | |
988 | ||
989 | // Ignore errors in function bodies if this is rustdoc | |
990 | // Be sure not to set this until the function signature has been resolved. | |
991 | let previous_state = replace(&mut this.in_func_body, true); | |
992 | // Resolve the function body, potentially inside the body of an async closure | |
993 | this.with_lifetime_rib( | |
064997fb | 994 | LifetimeRibKind::Elided(LifetimeRes::Infer), |
923072b8 FG |
995 | |this| this.visit_expr(body), |
996 | ); | |
e1599b0c | 997 | |
923072b8 FG |
998 | debug!("(resolving function) leaving function"); |
999 | this.in_func_body = previous_state; | |
1000 | } | |
1001 | } | |
e1599b0c XL |
1002 | }) |
1003 | }); | |
e74abb32 | 1004 | self.diagnostic_metadata.current_function = previous_value; |
416331ca | 1005 | } |
923072b8 FG |
1006 | fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) { |
1007 | self.resolve_lifetime(lifetime, use_ctxt) | |
04454e1e | 1008 | } |
416331ca | 1009 | |
dfeec247 | 1010 | fn visit_generics(&mut self, generics: &'ast Generics) { |
923072b8 | 1011 | self.visit_generic_params( |
04454e1e FG |
1012 | &generics.params, |
1013 | self.diagnostic_metadata.current_self_item.is_some(), | |
1014 | ); | |
416331ca XL |
1015 | for p in &generics.where_clause.predicates { |
1016 | self.visit_where_predicate(p); | |
1017 | } | |
1018 | } | |
60c5eb7d | 1019 | |
064997fb FG |
1020 | fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) { |
1021 | match b { | |
1022 | ClosureBinder::NotPresent => {} | |
1023 | ClosureBinder::For { generic_params, .. } => { | |
1024 | self.visit_generic_params( | |
1025 | &generic_params, | |
1026 | self.diagnostic_metadata.current_self_item.is_some(), | |
1027 | ); | |
1028 | } | |
1029 | } | |
1030 | } | |
1031 | ||
dfeec247 | 1032 | fn visit_generic_arg(&mut self, arg: &'ast GenericArg) { |
60c5eb7d | 1033 | debug!("visit_generic_arg({:?})", arg); |
dfeec247 | 1034 | let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true); |
60c5eb7d XL |
1035 | match arg { |
1036 | GenericArg::Type(ref ty) => { | |
74b04a01 | 1037 | // We parse const arguments as path types as we cannot distinguish them during |
60c5eb7d XL |
1038 | // parsing. We try to resolve that ambiguity by attempting resolution the type |
1039 | // namespace first, and if that fails we try again in the value namespace. If | |
1040 | // resolution in the value namespace succeeds, we have an generic const argument on | |
1041 | // our hands. | |
49aad941 | 1042 | if let TyKind::Path(None, ref path) = ty.kind { |
60c5eb7d XL |
1043 | // We cannot disambiguate multi-segment paths right now as that requires type |
1044 | // checking. | |
49aad941 | 1045 | if path.is_potential_trivial_const_arg() { |
dfeec247 | 1046 | let mut check_ns = |ns| { |
04454e1e FG |
1047 | self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns) |
1048 | .is_some() | |
dfeec247 | 1049 | }; |
60c5eb7d | 1050 | if !check_ns(TypeNS) && check_ns(ValueNS) { |
49aad941 FG |
1051 | self.resolve_anon_const_manual( |
1052 | true, | |
1053 | AnonConstKind::ConstArg(IsRepeatExpr::No), | |
04454e1e FG |
1054 | |this| { |
1055 | this.smart_resolve_path( | |
1056 | ty.id, | |
49aad941 | 1057 | &None, |
04454e1e FG |
1058 | path, |
1059 | PathSource::Expr(None), | |
1060 | ); | |
04454e1e FG |
1061 | this.visit_path(path, ty.id); |
1062 | }, | |
1063 | ); | |
60c5eb7d | 1064 | |
dfeec247 | 1065 | self.diagnostic_metadata.currently_processing_generics = prev; |
60c5eb7d XL |
1066 | return; |
1067 | } | |
1068 | } | |
1069 | } | |
1070 | ||
1071 | self.visit_ty(ty); | |
1072 | } | |
923072b8 | 1073 | GenericArg::Lifetime(lt) => self.visit_lifetime(lt, visit::LifetimeCtxt::GenericArg), |
49aad941 FG |
1074 | GenericArg::Const(ct) => { |
1075 | self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No)) | |
1076 | } | |
60c5eb7d | 1077 | } |
dfeec247 | 1078 | self.diagnostic_metadata.currently_processing_generics = prev; |
60c5eb7d | 1079 | } |
29967ef6 | 1080 | |
923072b8 FG |
1081 | fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { |
1082 | self.visit_ident(constraint.ident); | |
1083 | if let Some(ref gen_args) = constraint.gen_args { | |
1084 | // Forbid anonymous lifetimes in GAT parameters until proper semantics are decided. | |
1085 | self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { | |
f2b60f7d | 1086 | this.visit_generic_args(gen_args) |
923072b8 FG |
1087 | }); |
1088 | } | |
1089 | match constraint.kind { | |
1090 | AssocConstraintKind::Equality { ref term } => match term { | |
1091 | Term::Ty(ty) => self.visit_ty(ty), | |
49aad941 FG |
1092 | Term::Const(c) => { |
1093 | self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No)) | |
1094 | } | |
923072b8 FG |
1095 | }, |
1096 | AssocConstraintKind::Bound { ref bounds } => { | |
1097 | walk_list!(self, visit_param_bound, bounds, BoundKind::Bound); | |
1098 | } | |
1099 | } | |
1100 | } | |
1101 | ||
f2b60f7d | 1102 | fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) { |
04454e1e FG |
1103 | if let Some(ref args) = path_segment.args { |
1104 | match &**args { | |
f2b60f7d | 1105 | GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args), |
923072b8 FG |
1106 | GenericArgs::Parenthesized(p_args) => { |
1107 | // Probe the lifetime ribs to know how to behave. | |
1108 | for rib in self.lifetime_ribs.iter().rev() { | |
1109 | match rib.kind { | |
9c376795 | 1110 | // We are inside a `PolyTraitRef`. The lifetimes are |
49aad941 | 1111 | // to be introduced in that (maybe implicit) `for<>` binder. |
923072b8 FG |
1112 | LifetimeRibKind::Generics { |
1113 | binder, | |
1114 | kind: LifetimeBinderKind::PolyTrait, | |
1115 | .. | |
1116 | } => { | |
1117 | self.with_lifetime_rib( | |
1118 | LifetimeRibKind::AnonymousCreateParameter { | |
1119 | binder, | |
1120 | report_in_path: false, | |
1121 | }, | |
064997fb FG |
1122 | |this| { |
1123 | this.resolve_fn_signature( | |
1124 | binder, | |
1125 | false, | |
1126 | p_args.inputs.iter().map(|ty| (None, &**ty)), | |
1127 | &p_args.output, | |
1128 | ) | |
1129 | }, | |
923072b8 FG |
1130 | ); |
1131 | break; | |
1132 | } | |
9c376795 | 1133 | // We have nowhere to introduce generics. Code is malformed, |
923072b8 FG |
1134 | // so use regular lifetime resolution to avoid spurious errors. |
1135 | LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => { | |
f2b60f7d | 1136 | visit::walk_generic_args(self, args); |
923072b8 FG |
1137 | break; |
1138 | } | |
064997fb | 1139 | LifetimeRibKind::AnonymousCreateParameter { .. } |
923072b8 | 1140 | | LifetimeRibKind::AnonymousReportError |
064997fb FG |
1141 | | LifetimeRibKind::Elided(_) |
1142 | | LifetimeRibKind::ElisionFailure | |
49aad941 FG |
1143 | | LifetimeRibKind::ConcreteAnonConst(_) |
1144 | | LifetimeRibKind::ConstParamTy => {} | |
923072b8 FG |
1145 | } |
1146 | } | |
1147 | } | |
04454e1e FG |
1148 | } |
1149 | } | |
1150 | } | |
1151 | ||
29967ef6 XL |
1152 | fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { |
1153 | debug!("visit_where_predicate {:?}", p); | |
1154 | let previous_value = | |
1155 | replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p)); | |
04454e1e FG |
1156 | self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { |
1157 | if let WherePredicate::BoundPredicate(WhereBoundPredicate { | |
1158 | ref bounded_ty, | |
1159 | ref bounds, | |
1160 | ref bound_generic_params, | |
1161 | span: predicate_span, | |
1162 | .. | |
1163 | }) = p | |
1164 | { | |
923072b8 | 1165 | let span = predicate_span.shrink_to_lo().to(bounded_ty.span.shrink_to_lo()); |
04454e1e FG |
1166 | this.with_generic_param_rib( |
1167 | &bound_generic_params, | |
49aad941 | 1168 | RibKind::Normal, |
04454e1e | 1169 | LifetimeRibKind::Generics { |
923072b8 | 1170 | binder: bounded_ty.id, |
04454e1e FG |
1171 | kind: LifetimeBinderKind::WhereBound, |
1172 | span, | |
1173 | }, | |
1174 | |this| { | |
923072b8 | 1175 | this.visit_generic_params(&bound_generic_params, false); |
04454e1e FG |
1176 | this.visit_ty(bounded_ty); |
1177 | for bound in bounds { | |
1178 | this.visit_param_bound(bound, BoundKind::Bound) | |
1179 | } | |
1180 | }, | |
1181 | ); | |
1182 | } else { | |
1183 | visit::walk_where_predicate(this, p); | |
1184 | } | |
1185 | }); | |
29967ef6 XL |
1186 | self.diagnostic_metadata.current_where_predicate = previous_value; |
1187 | } | |
04454e1e | 1188 | |
923072b8 FG |
1189 | fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) { |
1190 | for (op, _) in &asm.operands { | |
1191 | match op { | |
1192 | InlineAsmOperand::In { expr, .. } | |
1193 | | InlineAsmOperand::Out { expr: Some(expr), .. } | |
1194 | | InlineAsmOperand::InOut { expr, .. } => self.visit_expr(expr), | |
1195 | InlineAsmOperand::Out { expr: None, .. } => {} | |
1196 | InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { | |
1197 | self.visit_expr(in_expr); | |
1198 | if let Some(out_expr) = out_expr { | |
1199 | self.visit_expr(out_expr); | |
1200 | } | |
1201 | } | |
1202 | InlineAsmOperand::Const { anon_const, .. } => { | |
1203 | // Although this is `DefKind::AnonConst`, it is allowed to reference outer | |
1204 | // generic parameters like an inline const. | |
49aad941 | 1205 | self.resolve_anon_const(anon_const, AnonConstKind::InlineConst); |
923072b8 FG |
1206 | } |
1207 | InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym), | |
1208 | } | |
1209 | } | |
1210 | } | |
1211 | ||
04454e1e FG |
1212 | fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) { |
1213 | // This is similar to the code for AnonConst. | |
49aad941 FG |
1214 | self.with_rib(ValueNS, RibKind::InlineAsmSym, |this| { |
1215 | this.with_rib(TypeNS, RibKind::InlineAsmSym, |this| { | |
1216 | this.with_label_rib(RibKind::InlineAsmSym, |this| { | |
487cf647 | 1217 | this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None)); |
04454e1e FG |
1218 | visit::walk_inline_asm_sym(this, sym); |
1219 | }); | |
1220 | }) | |
1221 | }); | |
1222 | } | |
9ffffee4 FG |
1223 | |
1224 | fn visit_variant(&mut self, v: &'ast Variant) { | |
1225 | self.resolve_doc_links(&v.attrs, MaybeExported::Ok(v.id)); | |
1226 | visit::walk_variant(self, v) | |
1227 | } | |
1228 | ||
49aad941 FG |
1229 | fn visit_variant_discr(&mut self, discr: &'ast AnonConst) { |
1230 | self.resolve_anon_const(discr, AnonConstKind::EnumDiscriminant); | |
1231 | } | |
1232 | ||
9ffffee4 FG |
1233 | fn visit_field_def(&mut self, f: &'ast FieldDef) { |
1234 | self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id)); | |
1235 | visit::walk_field_def(self, f) | |
1236 | } | |
416331ca XL |
1237 | } |
1238 | ||
9ffffee4 FG |
1239 | impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { |
1240 | fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { | |
416331ca XL |
1241 | // During late resolution we only track the module component of the parent scope, |
1242 | // although it may be useful to track other components as well for diagnostics. | |
416331ca | 1243 | let graph_root = resolver.graph_root; |
29967ef6 | 1244 | let parent_scope = ParentScope::module(graph_root, resolver); |
49aad941 | 1245 | let start_rib_kind = RibKind::Module(graph_root); |
416331ca XL |
1246 | LateResolutionVisitor { |
1247 | r: resolver, | |
1248 | parent_scope, | |
1249 | ribs: PerNS { | |
e1599b0c XL |
1250 | value_ns: vec![Rib::new(start_rib_kind)], |
1251 | type_ns: vec![Rib::new(start_rib_kind)], | |
1252 | macro_ns: vec![Rib::new(start_rib_kind)], | |
416331ca | 1253 | }, |
9c376795 | 1254 | last_block_rib: None, |
416331ca | 1255 | label_ribs: Vec::new(), |
04454e1e | 1256 | lifetime_ribs: Vec::new(), |
064997fb | 1257 | lifetime_elision_candidates: None, |
416331ca | 1258 | current_trait_ref: None, |
353b0b11 | 1259 | diagnostic_metadata: Default::default(), |
3dfed10e XL |
1260 | // errors at module scope should always be reported |
1261 | in_func_body: false, | |
923072b8 | 1262 | lifetime_uses: Default::default(), |
416331ca XL |
1263 | } |
1264 | } | |
1265 | ||
04454e1e FG |
1266 | fn maybe_resolve_ident_in_lexical_scope( |
1267 | &mut self, | |
1268 | ident: Ident, | |
1269 | ns: Namespace, | |
1270 | ) -> Option<LexicalScopeBinding<'a>> { | |
1271 | self.r.resolve_ident_in_lexical_scope( | |
1272 | ident, | |
1273 | ns, | |
1274 | &self.parent_scope, | |
1275 | None, | |
1276 | &self.ribs[ns], | |
1277 | None, | |
1278 | ) | |
1279 | } | |
1280 | ||
dfeec247 XL |
1281 | fn resolve_ident_in_lexical_scope( |
1282 | &mut self, | |
1283 | ident: Ident, | |
1284 | ns: Namespace, | |
04454e1e FG |
1285 | finalize: Option<Finalize>, |
1286 | ignore_binding: Option<&'a NameBinding<'a>>, | |
dfeec247 | 1287 | ) -> Option<LexicalScopeBinding<'a>> { |
416331ca | 1288 | self.r.resolve_ident_in_lexical_scope( |
dfeec247 XL |
1289 | ident, |
1290 | ns, | |
1291 | &self.parent_scope, | |
5e7ed085 | 1292 | finalize, |
dfeec247 | 1293 | &self.ribs[ns], |
04454e1e | 1294 | ignore_binding, |
416331ca XL |
1295 | ) |
1296 | } | |
1297 | ||
1298 | fn resolve_path( | |
1299 | &mut self, | |
1300 | path: &[Segment], | |
1301 | opt_ns: Option<Namespace>, // `None` indicates a module path in import | |
04454e1e | 1302 | finalize: Option<Finalize>, |
416331ca | 1303 | ) -> PathResult<'a> { |
04454e1e FG |
1304 | self.r.resolve_path_with_ribs( |
1305 | path, | |
1306 | opt_ns, | |
1307 | &self.parent_scope, | |
1308 | finalize, | |
1309 | Some(&self.ribs), | |
1310 | None, | |
1311 | ) | |
416331ca XL |
1312 | } |
1313 | ||
1314 | // AST resolution | |
1315 | // | |
1316 | // We maintain a list of value ribs and type ribs. | |
1317 | // | |
1318 | // Simultaneously, we keep track of the current position in the module | |
1319 | // graph in the `parent_scope.module` pointer. When we go to resolve a name in | |
1320 | // the value or type namespaces, we first look through all the ribs and | |
1321 | // then query the module graph. When we resolve a name in the module | |
1322 | // namespace, we can skip all the ribs (since nested modules are not | |
1323 | // allowed within blocks in Rust) and jump straight to the current module | |
1324 | // graph node. | |
1325 | // | |
1326 | // Named implementations are handled separately. When we find a method | |
1327 | // call, we consult the module node to find all of the implementations in | |
1328 | // scope. This information is lazily cached in the module node. We then | |
1329 | // generate a fake "implementation scope" containing all the | |
1330 | // implementations thus found, for compatibility with old resolve pass. | |
1331 | ||
e1599b0c XL |
1332 | /// Do some `work` within a new innermost rib of the given `kind` in the given namespace (`ns`). |
1333 | fn with_rib<T>( | |
1334 | &mut self, | |
1335 | ns: Namespace, | |
1336 | kind: RibKind<'a>, | |
1337 | work: impl FnOnce(&mut Self) -> T, | |
1338 | ) -> T { | |
1339 | self.ribs[ns].push(Rib::new(kind)); | |
1340 | let ret = work(self); | |
1341 | self.ribs[ns].pop(); | |
1342 | ret | |
1343 | } | |
1344 | ||
1345 | fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { | |
c295e0f8 | 1346 | if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) { |
416331ca XL |
1347 | // Move down in the graph. |
1348 | let orig_module = replace(&mut self.parent_scope.module, module); | |
49aad941 FG |
1349 | self.with_rib(ValueNS, RibKind::Module(module), |this| { |
1350 | this.with_rib(TypeNS, RibKind::Module(module), |this| { | |
e1599b0c XL |
1351 | let ret = f(this); |
1352 | this.parent_scope.module = orig_module; | |
1353 | ret | |
1354 | }) | |
1355 | }) | |
416331ca XL |
1356 | } else { |
1357 | f(self) | |
1358 | } | |
1359 | } | |
1360 | ||
923072b8 | 1361 | fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) { |
04454e1e FG |
1362 | // For type parameter defaults, we have to ban access |
1363 | // to following type parameters, as the InternalSubsts can only | |
1364 | // provide previous type parameters as they're built. We | |
1365 | // put all the parameters on the ban list and then remove | |
1366 | // them one by one as they are processed and become available. | |
49aad941 FG |
1367 | let mut forward_ty_ban_rib = Rib::new(RibKind::ForwardGenericParamBan); |
1368 | let mut forward_const_ban_rib = Rib::new(RibKind::ForwardGenericParamBan); | |
04454e1e FG |
1369 | for param in params.iter() { |
1370 | match param.kind { | |
1371 | GenericParamKind::Type { .. } => { | |
1372 | forward_ty_ban_rib | |
1373 | .bindings | |
1374 | .insert(Ident::with_dummy_span(param.ident.name), Res::Err); | |
1375 | } | |
1376 | GenericParamKind::Const { .. } => { | |
1377 | forward_const_ban_rib | |
1378 | .bindings | |
1379 | .insert(Ident::with_dummy_span(param.ident.name), Res::Err); | |
1380 | } | |
1381 | GenericParamKind::Lifetime => {} | |
1382 | } | |
1383 | } | |
1384 | ||
1385 | // rust-lang/rust#61631: The type `Self` is essentially | |
1386 | // another type parameter. For ADTs, we consider it | |
1387 | // well-defined only after all of the ADT type parameters have | |
1388 | // been provided. Therefore, we do not allow use of `Self` | |
1389 | // anywhere in ADT type parameter defaults. | |
1390 | // | |
1391 | // (We however cannot ban `Self` for defaults on *all* generic | |
1392 | // lists; e.g. trait generics can usefully refer to `Self`, | |
1393 | // such as in the case of `trait Add<Rhs = Self>`.) | |
1394 | if add_self_upper { | |
1395 | // (`Some` if + only if we are in ADT's generics.) | |
1396 | forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); | |
1397 | } | |
1398 | ||
1399 | self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { | |
1400 | for param in params { | |
1401 | match param.kind { | |
1402 | GenericParamKind::Lifetime => { | |
1403 | for bound in ¶m.bounds { | |
1404 | this.visit_param_bound(bound, BoundKind::Bound); | |
1405 | } | |
1406 | } | |
1407 | GenericParamKind::Type { ref default } => { | |
1408 | for bound in ¶m.bounds { | |
1409 | this.visit_param_bound(bound, BoundKind::Bound); | |
1410 | } | |
1411 | ||
1412 | if let Some(ref ty) = default { | |
1413 | this.ribs[TypeNS].push(forward_ty_ban_rib); | |
1414 | this.ribs[ValueNS].push(forward_const_ban_rib); | |
1415 | this.visit_ty(ty); | |
1416 | forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); | |
1417 | forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); | |
1418 | } | |
1419 | ||
1420 | // Allow all following defaults to refer to this type parameter. | |
1421 | forward_ty_ban_rib | |
1422 | .bindings | |
1423 | .remove(&Ident::with_dummy_span(param.ident.name)); | |
1424 | } | |
1425 | GenericParamKind::Const { ref ty, kw_span: _, ref default } => { | |
1426 | // Const parameters can't have param bounds. | |
1427 | assert!(param.bounds.is_empty()); | |
1428 | ||
49aad941 FG |
1429 | this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy)); |
1430 | this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy)); | |
1431 | this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| { | |
04454e1e FG |
1432 | this.visit_ty(ty) |
1433 | }); | |
1434 | this.ribs[TypeNS].pop().unwrap(); | |
1435 | this.ribs[ValueNS].pop().unwrap(); | |
1436 | ||
1437 | if let Some(ref expr) = default { | |
1438 | this.ribs[TypeNS].push(forward_ty_ban_rib); | |
1439 | this.ribs[ValueNS].push(forward_const_ban_rib); | |
49aad941 FG |
1440 | this.resolve_anon_const( |
1441 | expr, | |
1442 | AnonConstKind::ConstArg(IsRepeatExpr::No), | |
1443 | ); | |
04454e1e FG |
1444 | forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); |
1445 | forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); | |
1446 | } | |
1447 | ||
1448 | // Allow all following defaults to refer to this const parameter. | |
1449 | forward_const_ban_rib | |
1450 | .bindings | |
1451 | .remove(&Ident::with_dummy_span(param.ident.name)); | |
1452 | } | |
1453 | } | |
1454 | } | |
1455 | }) | |
1456 | } | |
1457 | ||
f2b60f7d | 1458 | #[instrument(level = "debug", skip(self, work))] |
04454e1e FG |
1459 | fn with_lifetime_rib<T>( |
1460 | &mut self, | |
1461 | kind: LifetimeRibKind, | |
1462 | work: impl FnOnce(&mut Self) -> T, | |
1463 | ) -> T { | |
1464 | self.lifetime_ribs.push(LifetimeRib::new(kind)); | |
064997fb | 1465 | let outer_elision_candidates = self.lifetime_elision_candidates.take(); |
04454e1e | 1466 | let ret = work(self); |
064997fb | 1467 | self.lifetime_elision_candidates = outer_elision_candidates; |
04454e1e FG |
1468 | self.lifetime_ribs.pop(); |
1469 | ret | |
1470 | } | |
1471 | ||
f2b60f7d | 1472 | #[instrument(level = "debug", skip(self))] |
923072b8 | 1473 | fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) { |
04454e1e FG |
1474 | let ident = lifetime.ident; |
1475 | ||
1476 | if ident.name == kw::StaticLifetime { | |
064997fb FG |
1477 | self.record_lifetime_res( |
1478 | lifetime.id, | |
1479 | LifetimeRes::Static, | |
1480 | LifetimeElisionCandidate::Named, | |
1481 | ); | |
04454e1e FG |
1482 | return; |
1483 | } | |
1484 | ||
1485 | if ident.name == kw::UnderscoreLifetime { | |
1486 | return self.resolve_anonymous_lifetime(lifetime, false); | |
1487 | } | |
1488 | ||
2b03887a FG |
1489 | let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev(); |
1490 | while let Some(rib) = lifetime_rib_iter.next() { | |
04454e1e | 1491 | let normalized_ident = ident.normalize_to_macros_2_0(); |
923072b8 | 1492 | if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) { |
064997fb | 1493 | self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named); |
923072b8 | 1494 | |
49aad941 | 1495 | if let LifetimeRes::Param { param, binder } = res { |
923072b8 FG |
1496 | match self.lifetime_uses.entry(param) { |
1497 | Entry::Vacant(v) => { | |
1498 | debug!("First use of {:?} at {:?}", res, ident.span); | |
1499 | let use_set = self | |
1500 | .lifetime_ribs | |
1501 | .iter() | |
1502 | .rev() | |
1503 | .find_map(|rib| match rib.kind { | |
1504 | // Do not suggest eliding a lifetime where an anonymous | |
1505 | // lifetime would be illegal. | |
1506 | LifetimeRibKind::Item | |
064997fb FG |
1507 | | LifetimeRibKind::AnonymousReportError |
1508 | | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many), | |
49aad941 FG |
1509 | // An anonymous lifetime is legal here, and bound to the right |
1510 | // place, go ahead. | |
1511 | LifetimeRibKind::AnonymousCreateParameter { | |
1512 | binder: anon_binder, | |
1513 | .. | |
1514 | } => Some(if binder == anon_binder { | |
1515 | LifetimeUseSet::One { use_span: ident.span, use_ctxt } | |
1516 | } else { | |
1517 | LifetimeUseSet::Many | |
1518 | }), | |
064997fb FG |
1519 | // Only report if eliding the lifetime would have the same |
1520 | // semantics. | |
1521 | LifetimeRibKind::Elided(r) => Some(if res == r { | |
1522 | LifetimeUseSet::One { use_span: ident.span, use_ctxt } | |
1523 | } else { | |
1524 | LifetimeUseSet::Many | |
1525 | }), | |
353b0b11 | 1526 | LifetimeRibKind::Generics { .. } |
49aad941 FG |
1527 | | LifetimeRibKind::ConstParamTy => None, |
1528 | LifetimeRibKind::ConcreteAnonConst(_) => { | |
2b03887a FG |
1529 | span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind) |
1530 | } | |
923072b8 FG |
1531 | }) |
1532 | .unwrap_or(LifetimeUseSet::Many); | |
1533 | debug!(?use_ctxt, ?use_set); | |
1534 | v.insert(use_set); | |
1535 | } | |
1536 | Entry::Occupied(mut o) => { | |
1537 | debug!("Many uses of {:?} at {:?}", res, ident.span); | |
1538 | *o.get_mut() = LifetimeUseSet::Many; | |
1539 | } | |
1540 | } | |
1541 | } | |
04454e1e FG |
1542 | return; |
1543 | } | |
1544 | ||
1545 | match rib.kind { | |
1546 | LifetimeRibKind::Item => break, | |
49aad941 FG |
1547 | LifetimeRibKind::ConstParamTy => { |
1548 | self.emit_non_static_lt_in_const_param_ty_error(lifetime); | |
064997fb FG |
1549 | self.record_lifetime_res( |
1550 | lifetime.id, | |
1551 | LifetimeRes::Error, | |
1552 | LifetimeElisionCandidate::Ignore, | |
1553 | ); | |
04454e1e FG |
1554 | return; |
1555 | } | |
49aad941 FG |
1556 | LifetimeRibKind::ConcreteAnonConst(cause) => { |
1557 | self.emit_forbidden_non_static_lifetime_error(cause, lifetime); | |
064997fb FG |
1558 | self.record_lifetime_res( |
1559 | lifetime.id, | |
1560 | LifetimeRes::Error, | |
1561 | LifetimeElisionCandidate::Ignore, | |
1562 | ); | |
04454e1e FG |
1563 | return; |
1564 | } | |
2b03887a FG |
1565 | LifetimeRibKind::AnonymousCreateParameter { .. } |
1566 | | LifetimeRibKind::Elided(_) | |
1567 | | LifetimeRibKind::Generics { .. } | |
1568 | | LifetimeRibKind::ElisionFailure | |
1569 | | LifetimeRibKind::AnonymousReportError => {} | |
04454e1e FG |
1570 | } |
1571 | } | |
1572 | ||
1573 | let mut outer_res = None; | |
2b03887a | 1574 | for rib in lifetime_rib_iter { |
04454e1e FG |
1575 | let normalized_ident = ident.normalize_to_macros_2_0(); |
1576 | if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) { | |
1577 | outer_res = Some(outer); | |
1578 | break; | |
1579 | } | |
1580 | } | |
1581 | ||
1582 | self.emit_undeclared_lifetime_error(lifetime, outer_res); | |
064997fb | 1583 | self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named); |
04454e1e FG |
1584 | } |
1585 | ||
f2b60f7d | 1586 | #[instrument(level = "debug", skip(self))] |
04454e1e FG |
1587 | fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) { |
1588 | debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); | |
1589 | ||
064997fb FG |
1590 | let missing_lifetime = MissingLifetime { |
1591 | id: lifetime.id, | |
1592 | span: lifetime.ident.span, | |
1593 | kind: if elided { | |
1594 | MissingLifetimeKind::Ampersand | |
1595 | } else { | |
1596 | MissingLifetimeKind::Underscore | |
1597 | }, | |
1598 | count: 1, | |
1599 | }; | |
1600 | let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime); | |
9c376795 | 1601 | for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { |
064997fb | 1602 | debug!(?rib.kind); |
04454e1e | 1603 | match rib.kind { |
923072b8 FG |
1604 | LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { |
1605 | let res = self.create_fresh_lifetime(lifetime.id, lifetime.ident, binder); | |
064997fb | 1606 | self.record_lifetime_res(lifetime.id, res, elision_candidate); |
04454e1e FG |
1607 | return; |
1608 | } | |
1609 | LifetimeRibKind::AnonymousReportError => { | |
1610 | let (msg, note) = if elided { | |
1611 | ( | |
1612 | "`&` without an explicit lifetime name cannot be used here", | |
1613 | "explicit lifetime name needed here", | |
1614 | ) | |
1615 | } else { | |
1616 | ("`'_` cannot be used here", "`'_` is a reserved lifetime name") | |
1617 | }; | |
9c376795 | 1618 | let mut diag = rustc_errors::struct_span_err!( |
9ffffee4 | 1619 | self.r.tcx.sess, |
04454e1e FG |
1620 | lifetime.ident.span, |
1621 | E0637, | |
1622 | "{}", | |
1623 | msg, | |
9c376795 FG |
1624 | ); |
1625 | diag.span_label(lifetime.ident.span, note); | |
1626 | if elided { | |
1627 | for rib in self.lifetime_ribs[i..].iter().rev() { | |
1628 | if let LifetimeRibKind::Generics { | |
1629 | span, | |
1630 | kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound, | |
1631 | .. | |
1632 | } = &rib.kind | |
1633 | { | |
1634 | diag.span_help( | |
1635 | *span, | |
1636 | "consider introducing a higher-ranked lifetime here with `for<'a>`", | |
1637 | ); | |
1638 | break; | |
1639 | } | |
1640 | } | |
1641 | } | |
1642 | diag.emit(); | |
064997fb | 1643 | self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); |
04454e1e FG |
1644 | return; |
1645 | } | |
064997fb FG |
1646 | LifetimeRibKind::Elided(res) => { |
1647 | self.record_lifetime_res(lifetime.id, res, elision_candidate); | |
1648 | return; | |
1649 | } | |
1650 | LifetimeRibKind::ElisionFailure => { | |
1651 | self.diagnostic_metadata.current_elision_failures.push(missing_lifetime); | |
1652 | self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); | |
04454e1e FG |
1653 | return; |
1654 | } | |
1655 | LifetimeRibKind::Item => break, | |
49aad941 FG |
1656 | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {} |
1657 | LifetimeRibKind::ConcreteAnonConst(_) => { | |
1658 | // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`. | |
2b03887a FG |
1659 | span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind) |
1660 | } | |
04454e1e FG |
1661 | } |
1662 | } | |
064997fb FG |
1663 | self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); |
1664 | self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); | |
04454e1e FG |
1665 | } |
1666 | ||
f2b60f7d | 1667 | #[instrument(level = "debug", skip(self))] |
04454e1e FG |
1668 | fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) { |
1669 | let id = self.r.next_node_id(); | |
064997fb FG |
1670 | let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) }; |
1671 | ||
04454e1e FG |
1672 | self.record_lifetime_res( |
1673 | anchor_id, | |
1674 | LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, | |
064997fb | 1675 | LifetimeElisionCandidate::Ignore, |
04454e1e | 1676 | ); |
04454e1e FG |
1677 | self.resolve_anonymous_lifetime(<, true); |
1678 | } | |
1679 | ||
f2b60f7d | 1680 | #[instrument(level = "debug", skip(self))] |
923072b8 | 1681 | fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, binder: NodeId) -> LifetimeRes { |
04454e1e FG |
1682 | debug_assert_eq!(ident.name, kw::UnderscoreLifetime); |
1683 | debug!(?ident.span); | |
04454e1e | 1684 | |
923072b8 FG |
1685 | // Leave the responsibility to create the `LocalDefId` to lowering. |
1686 | let param = self.r.next_node_id(); | |
1687 | let res = LifetimeRes::Fresh { param, binder }; | |
1688 | ||
1689 | // Record the created lifetime parameter so lowering can pick it up and add it to HIR. | |
1690 | self.r | |
1691 | .extra_lifetime_params_map | |
1692 | .entry(binder) | |
1693 | .or_insert_with(Vec::new) | |
1694 | .push((ident, param, res)); | |
1695 | res | |
04454e1e FG |
1696 | } |
1697 | ||
f2b60f7d | 1698 | #[instrument(level = "debug", skip(self))] |
04454e1e FG |
1699 | fn resolve_elided_lifetimes_in_path( |
1700 | &mut self, | |
1701 | path_id: NodeId, | |
1702 | partial_res: PartialRes, | |
1703 | path: &[Segment], | |
1704 | source: PathSource<'_>, | |
1705 | path_span: Span, | |
1706 | ) { | |
1707 | let proj_start = path.len() - partial_res.unresolved_segments(); | |
1708 | for (i, segment) in path.iter().enumerate() { | |
1709 | if segment.has_lifetime_args { | |
1710 | continue; | |
1711 | } | |
1712 | let Some(segment_id) = segment.id else { | |
1713 | continue; | |
1714 | }; | |
1715 | ||
1716 | // Figure out if this is a type/trait segment, | |
1717 | // which may need lifetime elision performed. | |
1718 | let type_def_id = match partial_res.base_res() { | |
353b0b11 FG |
1719 | Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => { |
1720 | self.r.tcx.parent(def_id) | |
1721 | } | |
1722 | Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => { | |
1723 | self.r.tcx.parent(def_id) | |
1724 | } | |
04454e1e FG |
1725 | Res::Def(DefKind::Struct, def_id) |
1726 | | Res::Def(DefKind::Union, def_id) | |
1727 | | Res::Def(DefKind::Enum, def_id) | |
1728 | | Res::Def(DefKind::TyAlias, def_id) | |
1729 | | Res::Def(DefKind::Trait, def_id) | |
1730 | if i + 1 == proj_start => | |
1731 | { | |
1732 | def_id | |
1733 | } | |
1734 | _ => continue, | |
1735 | }; | |
1736 | ||
1737 | let expected_lifetimes = self.r.item_generics_num_lifetimes(type_def_id); | |
1738 | if expected_lifetimes == 0 { | |
1739 | continue; | |
1740 | } | |
1741 | ||
064997fb FG |
1742 | let node_ids = self.r.next_node_ids(expected_lifetimes); |
1743 | self.record_lifetime_res( | |
1744 | segment_id, | |
1745 | LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end }, | |
1746 | LifetimeElisionCandidate::Ignore, | |
1747 | ); | |
1748 | ||
1749 | let inferred = match source { | |
1750 | PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => false, | |
04454e1e FG |
1751 | PathSource::Expr(..) |
1752 | | PathSource::Pat | |
1753 | | PathSource::Struct | |
064997fb | 1754 | | PathSource::TupleStruct(..) => true, |
04454e1e | 1755 | }; |
064997fb FG |
1756 | if inferred { |
1757 | // Do not create a parameter for patterns and expressions: type checking can infer | |
1758 | // the appropriate lifetime for us. | |
1759 | for id in node_ids { | |
1760 | self.record_lifetime_res( | |
1761 | id, | |
1762 | LifetimeRes::Infer, | |
1763 | LifetimeElisionCandidate::Named, | |
1764 | ); | |
1765 | } | |
1766 | continue; | |
1767 | } | |
923072b8 FG |
1768 | |
1769 | let elided_lifetime_span = if segment.has_generic_args { | |
1770 | // If there are brackets, but not generic arguments, then use the opening bracket | |
1771 | segment.args_span.with_hi(segment.args_span.lo() + BytePos(1)) | |
1772 | } else { | |
1773 | // If there are no brackets, use the identifier span. | |
1774 | // HACK: we use find_ancestor_inside to properly suggest elided spans in paths | |
1775 | // originating from macros, since the segment's span might be from a macro arg. | |
1776 | segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) | |
1777 | }; | |
1778 | let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span); | |
1779 | ||
064997fb FG |
1780 | let missing_lifetime = MissingLifetime { |
1781 | id: node_ids.start, | |
1782 | span: elided_lifetime_span, | |
1783 | kind: if segment.has_generic_args { | |
1784 | MissingLifetimeKind::Comma | |
1785 | } else { | |
1786 | MissingLifetimeKind::Brackets | |
1787 | }, | |
1788 | count: expected_lifetimes, | |
1789 | }; | |
923072b8 | 1790 | let mut should_lint = true; |
04454e1e FG |
1791 | for rib in self.lifetime_ribs.iter().rev() { |
1792 | match rib.kind { | |
1793 | // In create-parameter mode we error here because we don't want to support | |
1794 | // deprecated impl elision in new features like impl elision and `async fn`, | |
1795 | // both of which work using the `CreateParameter` mode: | |
1796 | // | |
1797 | // impl Foo for std::cell::Ref<u32> // note lack of '_ | |
1798 | // async fn foo(_: std::cell::Ref<u32>) { ... } | |
923072b8 | 1799 | LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } => { |
9ffffee4 | 1800 | let sess = self.r.tcx.sess; |
923072b8 FG |
1801 | let mut err = rustc_errors::struct_span_err!( |
1802 | sess, | |
1803 | path_span, | |
1804 | E0726, | |
1805 | "implicit elided lifetime not allowed here" | |
1806 | ); | |
1807 | rustc_errors::add_elided_lifetime_in_path_suggestion( | |
1808 | sess.source_map(), | |
1809 | &mut err, | |
1810 | expected_lifetimes, | |
1811 | path_span, | |
1812 | !segment.has_generic_args, | |
1813 | elided_lifetime_span, | |
1814 | ); | |
923072b8 FG |
1815 | err.emit(); |
1816 | should_lint = false; | |
1817 | ||
1818 | for id in node_ids { | |
064997fb FG |
1819 | self.record_lifetime_res( |
1820 | id, | |
1821 | LifetimeRes::Error, | |
1822 | LifetimeElisionCandidate::Named, | |
1823 | ); | |
923072b8 FG |
1824 | } |
1825 | break; | |
1826 | } | |
1827 | // Do not create a parameter for patterns and expressions. | |
1828 | LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { | |
064997fb FG |
1829 | // Group all suggestions into the first record. |
1830 | let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); | |
923072b8 FG |
1831 | for id in node_ids { |
1832 | let res = self.create_fresh_lifetime(id, ident, binder); | |
064997fb FG |
1833 | self.record_lifetime_res( |
1834 | id, | |
1835 | res, | |
1836 | replace(&mut candidate, LifetimeElisionCandidate::Named), | |
1837 | ); | |
1838 | } | |
1839 | break; | |
1840 | } | |
1841 | LifetimeRibKind::Elided(res) => { | |
1842 | let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); | |
1843 | for id in node_ids { | |
1844 | self.record_lifetime_res( | |
1845 | id, | |
1846 | res, | |
1847 | replace(&mut candidate, LifetimeElisionCandidate::Ignore), | |
1848 | ); | |
923072b8 | 1849 | } |
04454e1e FG |
1850 | break; |
1851 | } | |
064997fb FG |
1852 | LifetimeRibKind::ElisionFailure => { |
1853 | self.diagnostic_metadata.current_elision_failures.push(missing_lifetime); | |
923072b8 | 1854 | for id in node_ids { |
064997fb FG |
1855 | self.record_lifetime_res( |
1856 | id, | |
1857 | LifetimeRes::Error, | |
1858 | LifetimeElisionCandidate::Ignore, | |
1859 | ); | |
923072b8 | 1860 | } |
04454e1e FG |
1861 | break; |
1862 | } | |
923072b8 | 1863 | // `LifetimeRes::Error`, which would usually be used in the case of |
9c376795 | 1864 | // `ReportError`, is unsuitable here, as we don't emit an error yet. Instead, |
923072b8 FG |
1865 | // we simply resolve to an implicit lifetime, which will be checked later, at |
1866 | // which point a suitable error will be emitted. | |
04454e1e | 1867 | LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { |
923072b8 | 1868 | for id in node_ids { |
064997fb FG |
1869 | self.record_lifetime_res( |
1870 | id, | |
1871 | LifetimeRes::Error, | |
1872 | LifetimeElisionCandidate::Ignore, | |
1873 | ); | |
923072b8 | 1874 | } |
064997fb | 1875 | self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); |
04454e1e FG |
1876 | break; |
1877 | } | |
49aad941 FG |
1878 | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {} |
1879 | LifetimeRibKind::ConcreteAnonConst(_) => { | |
1880 | // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`. | |
2b03887a FG |
1881 | span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind) |
1882 | } | |
04454e1e FG |
1883 | } |
1884 | } | |
1885 | ||
923072b8 | 1886 | if should_lint { |
04454e1e FG |
1887 | self.r.lint_buffer.buffer_lint_with_diagnostic( |
1888 | lint::builtin::ELIDED_LIFETIMES_IN_PATHS, | |
1889 | segment_id, | |
1890 | elided_lifetime_span, | |
1891 | "hidden lifetime parameters in types are deprecated", | |
1892 | lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths( | |
1893 | expected_lifetimes, | |
1894 | path_span, | |
1895 | !segment.has_generic_args, | |
1896 | elided_lifetime_span, | |
1897 | ), | |
1898 | ); | |
1899 | } | |
1900 | } | |
1901 | } | |
1902 | ||
f2b60f7d | 1903 | #[instrument(level = "debug", skip(self))] |
064997fb FG |
1904 | fn record_lifetime_res( |
1905 | &mut self, | |
1906 | id: NodeId, | |
1907 | res: LifetimeRes, | |
1908 | candidate: LifetimeElisionCandidate, | |
1909 | ) { | |
04454e1e FG |
1910 | if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { |
1911 | panic!( | |
1912 | "lifetime {:?} resolved multiple times ({:?} before, {:?} now)", | |
1913 | id, prev_res, res | |
1914 | ) | |
1915 | } | |
064997fb FG |
1916 | match res { |
1917 | LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { | |
1918 | if let Some(ref mut candidates) = self.lifetime_elision_candidates { | |
f2b60f7d | 1919 | candidates.push((res, candidate)); |
064997fb FG |
1920 | } |
1921 | } | |
1922 | LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} | |
1923 | } | |
1924 | } | |
1925 | ||
f2b60f7d | 1926 | #[instrument(level = "debug", skip(self))] |
064997fb FG |
1927 | fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) { |
1928 | if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { | |
1929 | panic!( | |
1930 | "lifetime parameter {:?} resolved multiple times ({:?} before, {:?} now)", | |
1931 | id, prev_res, res | |
1932 | ) | |
1933 | } | |
1934 | } | |
1935 | ||
1936 | /// Perform resolution of a function signature, accounting for lifetime elision. | |
f2b60f7d | 1937 | #[instrument(level = "debug", skip(self, inputs))] |
064997fb FG |
1938 | fn resolve_fn_signature( |
1939 | &mut self, | |
1940 | fn_id: NodeId, | |
1941 | has_self: bool, | |
1942 | inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone, | |
1943 | output_ty: &'ast FnRetTy, | |
1944 | ) { | |
1945 | // Add each argument to the rib. | |
1946 | let elision_lifetime = self.resolve_fn_params(has_self, inputs); | |
1947 | debug!(?elision_lifetime); | |
1948 | ||
1949 | let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures); | |
1950 | let output_rib = if let Ok(res) = elision_lifetime.as_ref() { | |
487cf647 | 1951 | self.r.lifetime_elision_allowed.insert(fn_id); |
064997fb FG |
1952 | LifetimeRibKind::Elided(*res) |
1953 | } else { | |
1954 | LifetimeRibKind::ElisionFailure | |
1955 | }; | |
1956 | self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, &output_ty)); | |
1957 | let elision_failures = | |
1958 | replace(&mut self.diagnostic_metadata.current_elision_failures, outer_failures); | |
1959 | if !elision_failures.is_empty() { | |
1960 | let Err(failure_info) = elision_lifetime else { bug!() }; | |
1961 | self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); | |
1962 | } | |
1963 | } | |
1964 | ||
1965 | /// Resolve inside function parameters and parameter types. | |
1966 | /// Returns the lifetime for elision in fn return type, | |
1967 | /// or diagnostic information in case of elision failure. | |
1968 | fn resolve_fn_params( | |
1969 | &mut self, | |
1970 | has_self: bool, | |
1971 | inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>, | |
1972 | ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> { | |
f2b60f7d FG |
1973 | enum Elision { |
1974 | /// We have not found any candidate. | |
1975 | None, | |
1976 | /// We have a candidate bound to `self`. | |
1977 | Self_(LifetimeRes), | |
1978 | /// We have a candidate bound to a parameter. | |
1979 | Param(LifetimeRes), | |
1980 | /// We failed elision. | |
1981 | Err, | |
1982 | } | |
1983 | ||
1984 | // Save elision state to reinstate it later. | |
1985 | let outer_candidates = self.lifetime_elision_candidates.take(); | |
064997fb | 1986 | |
f2b60f7d FG |
1987 | // Result of elision. |
1988 | let mut elision_lifetime = Elision::None; | |
1989 | // Information for diagnostics. | |
064997fb | 1990 | let mut parameter_info = Vec::new(); |
f2b60f7d | 1991 | let mut all_candidates = Vec::new(); |
064997fb FG |
1992 | |
1993 | let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; | |
1994 | for (index, (pat, ty)) in inputs.enumerate() { | |
1995 | debug!(?pat, ?ty); | |
2b03887a FG |
1996 | self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { |
1997 | if let Some(pat) = pat { | |
1998 | this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); | |
1999 | } | |
2000 | }); | |
f2b60f7d FG |
2001 | |
2002 | // Record elision candidates only for this parameter. | |
2003 | debug_assert_matches!(self.lifetime_elision_candidates, None); | |
2004 | self.lifetime_elision_candidates = Some(Default::default()); | |
064997fb | 2005 | self.visit_ty(ty); |
f2b60f7d | 2006 | let local_candidates = self.lifetime_elision_candidates.take(); |
064997fb | 2007 | |
f2b60f7d FG |
2008 | if let Some(candidates) = local_candidates { |
2009 | let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect(); | |
2010 | let lifetime_count = distinct.len(); | |
2011 | if lifetime_count != 0 { | |
064997fb FG |
2012 | parameter_info.push(ElisionFnParameter { |
2013 | index, | |
2014 | ident: if let Some(pat) = pat && let PatKind::Ident(_, ident, _) = pat.kind { | |
2015 | Some(ident) | |
2016 | } else { | |
2017 | None | |
2018 | }, | |
f2b60f7d | 2019 | lifetime_count, |
064997fb FG |
2020 | span: ty.span, |
2021 | }); | |
f2b60f7d FG |
2022 | all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| { |
2023 | match candidate { | |
2024 | LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => { | |
2025 | None | |
2026 | } | |
2027 | LifetimeElisionCandidate::Missing(missing) => Some(missing), | |
2028 | } | |
2029 | })); | |
2030 | } | |
2031 | let mut distinct_iter = distinct.into_iter(); | |
2032 | if let Some(res) = distinct_iter.next() { | |
2033 | match elision_lifetime { | |
2034 | // We are the first parameter to bind lifetimes. | |
2035 | Elision::None => { | |
2036 | if distinct_iter.next().is_none() { | |
2037 | // We have a single lifetime => success. | |
2038 | elision_lifetime = Elision::Param(res) | |
2039 | } else { | |
487cf647 | 2040 | // We have multiple lifetimes => error. |
f2b60f7d FG |
2041 | elision_lifetime = Elision::Err; |
2042 | } | |
2043 | } | |
2044 | // We have 2 parameters that bind lifetimes => error. | |
2045 | Elision::Param(_) => elision_lifetime = Elision::Err, | |
2046 | // `self` elision takes precedence over everything else. | |
2047 | Elision::Self_(_) | Elision::Err => {} | |
2048 | } | |
064997fb | 2049 | } |
064997fb FG |
2050 | } |
2051 | ||
2052 | // Handle `self` specially. | |
2053 | if index == 0 && has_self { | |
2054 | let self_lifetime = self.find_lifetime_for_self(ty); | |
2055 | if let Set1::One(lifetime) = self_lifetime { | |
f2b60f7d FG |
2056 | // We found `self` elision. |
2057 | elision_lifetime = Elision::Self_(lifetime); | |
064997fb | 2058 | } else { |
f2b60f7d FG |
2059 | // We do not have `self` elision: disregard the `Elision::Param` that we may |
2060 | // have found. | |
2061 | elision_lifetime = Elision::None; | |
064997fb FG |
2062 | } |
2063 | } | |
2064 | debug!("(resolving function / closure) recorded parameter"); | |
2065 | } | |
2066 | ||
f2b60f7d FG |
2067 | // Reinstate elision state. |
2068 | debug_assert_matches!(self.lifetime_elision_candidates, None); | |
2069 | self.lifetime_elision_candidates = outer_candidates; | |
064997fb | 2070 | |
f2b60f7d | 2071 | if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime { |
064997fb FG |
2072 | return Ok(res); |
2073 | } | |
2074 | ||
f2b60f7d FG |
2075 | // We do not have a candidate. |
2076 | Err((all_candidates, parameter_info)) | |
064997fb FG |
2077 | } |
2078 | ||
2079 | /// List all the lifetimes that appear in the provided type. | |
2080 | fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> { | |
9ffffee4 FG |
2081 | struct SelfVisitor<'r, 'a, 'tcx> { |
2082 | r: &'r Resolver<'a, 'tcx>, | |
064997fb FG |
2083 | impl_self: Option<Res>, |
2084 | lifetime: Set1<LifetimeRes>, | |
2085 | } | |
2086 | ||
9ffffee4 | 2087 | impl SelfVisitor<'_, '_, '_> { |
064997fb FG |
2088 | // Look for `self: &'a Self` - also desugared from `&'a self`, |
2089 | // and if that matches, use it for elision and return early. | |
2090 | fn is_self_ty(&self, ty: &Ty) -> bool { | |
2091 | match ty.kind { | |
2092 | TyKind::ImplicitSelf => true, | |
2093 | TyKind::Path(None, _) => { | |
2b03887a FG |
2094 | let path_res = self.r.partial_res_map[&ty.id].full_res(); |
2095 | if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res { | |
064997fb FG |
2096 | return true; |
2097 | } | |
2b03887a | 2098 | self.impl_self.is_some() && path_res == self.impl_self |
064997fb FG |
2099 | } |
2100 | _ => false, | |
2101 | } | |
2102 | } | |
2103 | } | |
2104 | ||
9ffffee4 | 2105 | impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> { |
064997fb FG |
2106 | fn visit_ty(&mut self, ty: &'a Ty) { |
2107 | trace!("SelfVisitor considering ty={:?}", ty); | |
9c376795 | 2108 | if let TyKind::Ref(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) { |
064997fb FG |
2109 | let lt_id = if let Some(lt) = lt { |
2110 | lt.id | |
2111 | } else { | |
2112 | let res = self.r.lifetimes_res_map[&ty.id]; | |
2113 | let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() }; | |
2114 | start | |
2115 | }; | |
2116 | let lt_res = self.r.lifetimes_res_map[<_id]; | |
2117 | trace!("SelfVisitor inserting res={:?}", lt_res); | |
2118 | self.lifetime.insert(lt_res); | |
2119 | } | |
2120 | visit::walk_ty(self, ty) | |
2121 | } | |
49aad941 FG |
2122 | |
2123 | // A type may have an expression as a const generic argument. | |
2124 | // We do not want to recurse into those. | |
2125 | fn visit_expr(&mut self, _: &'a Expr) {} | |
064997fb FG |
2126 | } |
2127 | ||
2128 | let impl_self = self | |
2129 | .diagnostic_metadata | |
2130 | .current_self_type | |
2131 | .as_ref() | |
2132 | .and_then(|ty| { | |
2133 | if let TyKind::Path(None, _) = ty.kind { | |
2134 | self.r.partial_res_map.get(&ty.id) | |
2135 | } else { | |
2136 | None | |
2137 | } | |
2138 | }) | |
2b03887a | 2139 | .and_then(|res| res.full_res()) |
064997fb FG |
2140 | .filter(|res| { |
2141 | // Permit the types that unambiguously always | |
2142 | // result in the same type constructor being used | |
2143 | // (it can't differ between `Self` and `self`). | |
2144 | matches!( | |
2145 | res, | |
2146 | Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_) | |
2147 | ) | |
2148 | }); | |
2149 | let mut visitor = SelfVisitor { r: self.r, impl_self, lifetime: Set1::Empty }; | |
2150 | visitor.visit_ty(ty); | |
2151 | trace!("SelfVisitor found={:?}", visitor.lifetime); | |
2152 | visitor.lifetime | |
04454e1e FG |
2153 | } |
2154 | ||
f035d41b XL |
2155 | /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved |
2156 | /// label and reports an error if the label is not found or is unreachable. | |
923072b8 | 2157 | fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'a>> { |
f035d41b XL |
2158 | let mut suggestion = None; |
2159 | ||
f035d41b XL |
2160 | for i in (0..self.label_ribs.len()).rev() { |
2161 | let rib = &self.label_ribs[i]; | |
2162 | ||
49aad941 | 2163 | if let RibKind::MacroDefinition(def) = rib.kind { |
416331ca XL |
2164 | // If an invocation of this macro created `ident`, give up on `ident` |
2165 | // and switch to `ident`'s source from the macro definition. | |
f035d41b XL |
2166 | if def == self.r.macro_def(label.span.ctxt()) { |
2167 | label.span.remove_mark(); | |
416331ca XL |
2168 | } |
2169 | } | |
f035d41b XL |
2170 | |
2171 | let ident = label.normalize_to_macro_rules(); | |
2172 | if let Some((ident, id)) = rib.bindings.get_key_value(&ident) { | |
04454e1e | 2173 | let definition_span = ident.span; |
f035d41b | 2174 | return if self.is_label_valid_from_rib(i) { |
923072b8 | 2175 | Ok((*id, definition_span)) |
f035d41b | 2176 | } else { |
923072b8 FG |
2177 | Err(ResolutionError::UnreachableLabel { |
2178 | name: label.name, | |
2179 | definition_span, | |
2180 | suggestion, | |
2181 | }) | |
f035d41b | 2182 | }; |
416331ca | 2183 | } |
f035d41b XL |
2184 | |
2185 | // Diagnostics: Check if this rib contains a label with a similar name, keep track of | |
2186 | // the first such label that is encountered. | |
2187 | suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label)); | |
416331ca | 2188 | } |
f035d41b | 2189 | |
923072b8 | 2190 | Err(ResolutionError::UndeclaredLabel { name: label.name, suggestion }) |
416331ca XL |
2191 | } |
2192 | ||
f035d41b XL |
2193 | /// Determine whether or not a label from the `rib_index`th label rib is reachable. |
2194 | fn is_label_valid_from_rib(&self, rib_index: usize) -> bool { | |
2195 | let ribs = &self.label_ribs[rib_index + 1..]; | |
2196 | ||
2197 | for rib in ribs { | |
923072b8 FG |
2198 | if rib.kind.is_label_barrier() { |
2199 | return false; | |
f035d41b XL |
2200 | } |
2201 | } | |
2202 | ||
2203 | true | |
2204 | } | |
2205 | ||
dfeec247 | 2206 | fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { |
416331ca XL |
2207 | debug!("resolve_adt"); |
2208 | self.with_current_self_item(item, |this| { | |
04454e1e FG |
2209 | this.with_generic_param_rib( |
2210 | &generics.params, | |
49aad941 | 2211 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
04454e1e | 2212 | LifetimeRibKind::Generics { |
923072b8 | 2213 | binder: item.id, |
04454e1e FG |
2214 | kind: LifetimeBinderKind::Item, |
2215 | span: generics.span, | |
2216 | }, | |
2217 | |this| { | |
2218 | let item_def_id = this.r.local_def_id(item.id).to_def_id(); | |
2219 | this.with_self_rib( | |
2b03887a FG |
2220 | Res::SelfTyAlias { |
2221 | alias_to: item_def_id, | |
2222 | forbid_generic: false, | |
2223 | is_trait_impl: false, | |
2224 | }, | |
04454e1e FG |
2225 | |this| { |
2226 | visit::walk_item(this, item); | |
2227 | }, | |
2228 | ); | |
2229 | }, | |
2230 | ); | |
416331ca XL |
2231 | }); |
2232 | } | |
2233 | ||
2234 | fn future_proof_import(&mut self, use_tree: &UseTree) { | |
2235 | let segments = &use_tree.prefix.segments; | |
2236 | if !segments.is_empty() { | |
2237 | let ident = segments[0].ident; | |
9ffffee4 | 2238 | if ident.is_path_segment_keyword() || ident.span.is_rust_2015() { |
416331ca XL |
2239 | return; |
2240 | } | |
2241 | ||
2242 | let nss = match use_tree.kind { | |
2243 | UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..], | |
2244 | _ => &[TypeNS], | |
2245 | }; | |
2246 | let report_error = |this: &Self, ns| { | |
2247 | let what = if ns == TypeNS { "type parameters" } else { "local variables" }; | |
3dfed10e XL |
2248 | if this.should_report_errs() { |
2249 | this.r | |
9ffffee4 FG |
2250 | .tcx |
2251 | .sess | |
49aad941 | 2252 | .span_err(ident.span, format!("imports cannot refer to {}", what)); |
3dfed10e | 2253 | } |
416331ca XL |
2254 | }; |
2255 | ||
2256 | for &ns in nss { | |
04454e1e | 2257 | match self.maybe_resolve_ident_in_lexical_scope(ident, ns) { |
416331ca XL |
2258 | Some(LexicalScopeBinding::Res(..)) => { |
2259 | report_error(self, ns); | |
2260 | } | |
2261 | Some(LexicalScopeBinding::Item(binding)) => { | |
5e7ed085 | 2262 | if let Some(LexicalScopeBinding::Res(..)) = |
04454e1e | 2263 | self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding)) |
dfeec247 | 2264 | { |
416331ca XL |
2265 | report_error(self, ns); |
2266 | } | |
416331ca XL |
2267 | } |
2268 | None => {} | |
2269 | } | |
2270 | } | |
2271 | } else if let UseTreeKind::Nested(use_trees) = &use_tree.kind { | |
2272 | for (use_tree, _) in use_trees { | |
2273 | self.future_proof_import(use_tree); | |
2274 | } | |
2275 | } | |
2276 | } | |
2277 | ||
dfeec247 | 2278 | fn resolve_item(&mut self, item: &'ast Item) { |
9ffffee4 FG |
2279 | let mod_inner_docs = |
2280 | matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs); | |
2281 | if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) { | |
2282 | self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); | |
2283 | } | |
2284 | ||
416331ca | 2285 | let name = item.ident.name; |
e74abb32 | 2286 | debug!("(resolving item) resolving {} ({:?})", name, item.kind); |
416331ca | 2287 | |
e74abb32 | 2288 | match item.kind { |
04454e1e FG |
2289 | ItemKind::TyAlias(box TyAlias { ref generics, .. }) => { |
2290 | self.with_generic_param_rib( | |
2291 | &generics.params, | |
49aad941 | 2292 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
04454e1e | 2293 | LifetimeRibKind::Generics { |
923072b8 | 2294 | binder: item.id, |
04454e1e FG |
2295 | kind: LifetimeBinderKind::Item, |
2296 | span: generics.span, | |
2297 | }, | |
2298 | |this| visit::walk_item(this, item), | |
2299 | ); | |
2300 | } | |
2301 | ||
2302 | ItemKind::Fn(box Fn { ref generics, .. }) => { | |
2303 | self.with_generic_param_rib( | |
2304 | &generics.params, | |
49aad941 | 2305 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
04454e1e | 2306 | LifetimeRibKind::Generics { |
923072b8 | 2307 | binder: item.id, |
04454e1e FG |
2308 | kind: LifetimeBinderKind::Function, |
2309 | span: generics.span, | |
2310 | }, | |
2311 | |this| visit::walk_item(this, item), | |
2312 | ); | |
416331ca XL |
2313 | } |
2314 | ||
dfeec247 XL |
2315 | ItemKind::Enum(_, ref generics) |
2316 | | ItemKind::Struct(_, ref generics) | |
2317 | | ItemKind::Union(_, ref generics) => { | |
416331ca XL |
2318 | self.resolve_adt(item, generics); |
2319 | } | |
2320 | ||
3c0e092e | 2321 | ItemKind::Impl(box Impl { |
dfeec247 XL |
2322 | ref generics, |
2323 | ref of_trait, | |
2324 | ref self_ty, | |
2325 | items: ref impl_items, | |
2326 | .. | |
5869c6ff | 2327 | }) => { |
04454e1e | 2328 | self.diagnostic_metadata.current_impl_items = Some(impl_items); |
9ffffee4 FG |
2329 | self.resolve_implementation( |
2330 | &item.attrs, | |
2331 | generics, | |
2332 | of_trait, | |
2333 | &self_ty, | |
2334 | item.id, | |
2335 | impl_items, | |
2336 | ); | |
04454e1e | 2337 | self.diagnostic_metadata.current_impl_items = None; |
dfeec247 | 2338 | } |
416331ca | 2339 | |
3c0e092e | 2340 | ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => { |
416331ca | 2341 | // Create a new rib for the trait-wide type parameters. |
04454e1e FG |
2342 | self.with_generic_param_rib( |
2343 | &generics.params, | |
49aad941 | 2344 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
04454e1e | 2345 | LifetimeRibKind::Generics { |
923072b8 | 2346 | binder: item.id, |
04454e1e FG |
2347 | kind: LifetimeBinderKind::Item, |
2348 | span: generics.span, | |
2349 | }, | |
2350 | |this| { | |
2351 | let local_def_id = this.r.local_def_id(item.id).to_def_id(); | |
2b03887a FG |
2352 | this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| { |
2353 | this.visit_generics(generics); | |
2354 | walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits); | |
2355 | this.resolve_trait_items(items); | |
2356 | }); | |
04454e1e FG |
2357 | }, |
2358 | ); | |
416331ca XL |
2359 | } |
2360 | ||
2361 | ItemKind::TraitAlias(ref generics, ref bounds) => { | |
2362 | // Create a new rib for the trait-wide type parameters. | |
04454e1e FG |
2363 | self.with_generic_param_rib( |
2364 | &generics.params, | |
49aad941 | 2365 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
04454e1e | 2366 | LifetimeRibKind::Generics { |
923072b8 | 2367 | binder: item.id, |
04454e1e FG |
2368 | kind: LifetimeBinderKind::Item, |
2369 | span: generics.span, | |
2370 | }, | |
2371 | |this| { | |
2372 | let local_def_id = this.r.local_def_id(item.id).to_def_id(); | |
2b03887a FG |
2373 | this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| { |
2374 | this.visit_generics(generics); | |
2375 | walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); | |
2376 | }); | |
04454e1e FG |
2377 | }, |
2378 | ); | |
416331ca XL |
2379 | } |
2380 | ||
9ffffee4 | 2381 | ItemKind::Mod(..) => { |
416331ca | 2382 | self.with_scope(item.id, |this| { |
9ffffee4 FG |
2383 | if mod_inner_docs { |
2384 | this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); | |
2385 | } | |
2386 | let old_macro_rules = this.parent_scope.macro_rules; | |
416331ca | 2387 | visit::walk_item(this, item); |
9ffffee4 FG |
2388 | // Maintain macro_rules scopes in the same way as during early resolution |
2389 | // for diagnostics and doc links. | |
2390 | if item.attrs.iter().all(|attr| { | |
2391 | !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape) | |
2392 | }) { | |
2393 | this.parent_scope.macro_rules = old_macro_rules; | |
2394 | } | |
416331ca XL |
2395 | }); |
2396 | } | |
2397 | ||
353b0b11 FG |
2398 | ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) |
2399 | | ItemKind::Const(box ast::ConstItem { ref ty, ref expr, .. }) => { | |
2b03887a | 2400 | self.with_static_rib(|this| { |
064997fb FG |
2401 | this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { |
2402 | this.visit_ty(ty); | |
2403 | }); | |
2404 | this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { | |
2405 | if let Some(expr) = expr { | |
2406 | let constant_item_kind = match item.kind { | |
2407 | ItemKind::Const(..) => ConstantItemKind::Const, | |
2408 | ItemKind::Static(..) => ConstantItemKind::Static, | |
2409 | _ => unreachable!(), | |
2410 | }; | |
2411 | // We already forbid generic params because of the above item rib, | |
2412 | // so it doesn't matter whether this is a trivial constant. | |
2413 | this.with_constant_rib( | |
2414 | IsRepeatExpr::No, | |
f2b60f7d | 2415 | ConstantHasGenerics::Yes, |
064997fb FG |
2416 | Some((item.ident, constant_item_kind)), |
2417 | |this| this.visit_expr(expr), | |
2418 | ); | |
2419 | } | |
2420 | }); | |
416331ca XL |
2421 | }); |
2422 | } | |
2423 | ||
2424 | ItemKind::Use(ref use_tree) => { | |
2425 | self.future_proof_import(use_tree); | |
2426 | } | |
2427 | ||
9ffffee4 FG |
2428 | ItemKind::MacroDef(ref macro_def) => { |
2429 | // Maintain macro_rules scopes in the same way as during early resolution | |
2430 | // for diagnostics and doc links. | |
2431 | if macro_def.macro_rules { | |
2432 | let def_id = self.r.local_def_id(item.id); | |
2433 | self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id]; | |
2434 | } | |
416331ca XL |
2435 | } |
2436 | ||
9ffffee4 | 2437 | ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) => { |
17df50a5 XL |
2438 | visit::walk_item(self, item); |
2439 | } | |
2440 | ||
9ffffee4 FG |
2441 | ItemKind::ExternCrate(..) => {} |
2442 | ||
ba9703b0 | 2443 | ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), |
416331ca XL |
2444 | } |
2445 | } | |
2446 | ||
04454e1e FG |
2447 | fn with_generic_param_rib<'c, F>( |
2448 | &'c mut self, | |
923072b8 | 2449 | params: &'c [GenericParam], |
04454e1e FG |
2450 | kind: RibKind<'a>, |
2451 | lifetime_kind: LifetimeRibKind, | |
2452 | f: F, | |
2453 | ) where | |
dfeec247 | 2454 | F: FnOnce(&mut Self), |
416331ca XL |
2455 | { |
2456 | debug!("with_generic_param_rib"); | |
923072b8 FG |
2457 | let LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind, .. } |
2458 | = lifetime_kind else { panic!() }; | |
2459 | ||
e74abb32 XL |
2460 | let mut function_type_rib = Rib::new(kind); |
2461 | let mut function_value_rib = Rib::new(kind); | |
04454e1e | 2462 | let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind); |
e74abb32 | 2463 | let mut seen_bindings = FxHashMap::default(); |
923072b8 FG |
2464 | // Store all seen lifetimes names from outer scopes. |
2465 | let mut seen_lifetimes = FxHashSet::default(); | |
e74abb32 XL |
2466 | |
2467 | // We also can't shadow bindings from the parent item | |
49aad941 | 2468 | if let RibKind::AssocItem = kind { |
e74abb32 | 2469 | let mut add_bindings_for_ns = |ns| { |
dfeec247 XL |
2470 | let parent_rib = self.ribs[ns] |
2471 | .iter() | |
49aad941 | 2472 | .rfind(|r| matches!(r.kind, RibKind::Item(_))) |
e74abb32 | 2473 | .expect("associated item outside of an item"); |
353b0b11 | 2474 | seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); |
e74abb32 XL |
2475 | }; |
2476 | add_bindings_for_ns(ValueNS); | |
2477 | add_bindings_for_ns(TypeNS); | |
2478 | } | |
2479 | ||
923072b8 FG |
2480 | // Forbid shadowing lifetime bindings |
2481 | for rib in self.lifetime_ribs.iter().rev() { | |
2482 | seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident)); | |
2483 | if let LifetimeRibKind::Item = rib.kind { | |
2484 | break; | |
2485 | } | |
2486 | } | |
2487 | ||
04454e1e | 2488 | for param in params { |
ba9703b0 | 2489 | let ident = param.ident.normalize_to_macros_2_0(); |
e74abb32 XL |
2490 | debug!("with_generic_param_rib: {}", param.id); |
2491 | ||
923072b8 FG |
2492 | if let GenericParamKind::Lifetime = param.kind |
2493 | && let Some(&original) = seen_lifetimes.get(&ident) | |
2494 | { | |
9ffffee4 | 2495 | diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident); |
923072b8 | 2496 | // Record lifetime res, so lowering knows there is something fishy. |
064997fb | 2497 | self.record_lifetime_param(param.id, LifetimeRes::Error); |
923072b8 FG |
2498 | continue; |
2499 | } | |
2500 | ||
fc512014 XL |
2501 | match seen_bindings.entry(ident) { |
2502 | Entry::Occupied(entry) => { | |
2503 | let span = *entry.get(); | |
2504 | let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span); | |
923072b8 FG |
2505 | self.report_error(param.ident.span, err); |
2506 | if let GenericParamKind::Lifetime = param.kind { | |
2507 | // Record lifetime res, so lowering knows there is something fishy. | |
064997fb | 2508 | self.record_lifetime_param(param.id, LifetimeRes::Error); |
04454e1e | 2509 | } |
487cf647 | 2510 | continue; |
fc512014 XL |
2511 | } |
2512 | Entry::Vacant(entry) => { | |
2513 | entry.insert(param.ident.span); | |
2514 | } | |
e74abb32 | 2515 | } |
e74abb32 | 2516 | |
04454e1e FG |
2517 | if param.ident.name == kw::UnderscoreLifetime { |
2518 | rustc_errors::struct_span_err!( | |
9ffffee4 | 2519 | self.r.tcx.sess, |
04454e1e FG |
2520 | param.ident.span, |
2521 | E0637, | |
2522 | "`'_` cannot be used here" | |
2523 | ) | |
2524 | .span_label(param.ident.span, "`'_` is a reserved lifetime name") | |
2525 | .emit(); | |
923072b8 | 2526 | // Record lifetime res, so lowering knows there is something fishy. |
064997fb | 2527 | self.record_lifetime_param(param.id, LifetimeRes::Error); |
04454e1e FG |
2528 | continue; |
2529 | } | |
2530 | ||
2531 | if param.ident.name == kw::StaticLifetime { | |
2532 | rustc_errors::struct_span_err!( | |
9ffffee4 | 2533 | self.r.tcx.sess, |
04454e1e FG |
2534 | param.ident.span, |
2535 | E0262, | |
2536 | "invalid lifetime parameter name: `{}`", | |
2537 | param.ident, | |
2538 | ) | |
2539 | .span_label(param.ident.span, "'static is a reserved lifetime name") | |
2540 | .emit(); | |
923072b8 | 2541 | // Record lifetime res, so lowering knows there is something fishy. |
064997fb | 2542 | self.record_lifetime_param(param.id, LifetimeRes::Error); |
04454e1e FG |
2543 | continue; |
2544 | } | |
2545 | ||
2546 | let def_id = self.r.local_def_id(param.id); | |
2547 | ||
e74abb32 | 2548 | // Plain insert (no renaming). |
fc512014 XL |
2549 | let (rib, def_kind) = match param.kind { |
2550 | GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam), | |
2551 | GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam), | |
04454e1e | 2552 | GenericParamKind::Lifetime => { |
923072b8 | 2553 | let res = LifetimeRes::Param { param: def_id, binder }; |
064997fb | 2554 | self.record_lifetime_param(param.id, res); |
04454e1e FG |
2555 | function_lifetime_rib.bindings.insert(ident, (param.id, res)); |
2556 | continue; | |
2557 | } | |
fc512014 | 2558 | }; |
923072b8 FG |
2559 | |
2560 | let res = match kind { | |
49aad941 FG |
2561 | RibKind::Item(..) | RibKind::AssocItem => Res::Def(def_kind, def_id.to_def_id()), |
2562 | RibKind::Normal => { | |
9ffffee4 FG |
2563 | if self.r.tcx.sess.features_untracked().non_lifetime_binders { |
2564 | Res::Def(def_kind, def_id.to_def_id()) | |
2565 | } else { | |
2566 | Res::Err | |
2567 | } | |
2568 | } | |
064997fb | 2569 | _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind), |
923072b8 | 2570 | }; |
fc512014 XL |
2571 | self.r.record_partial_res(param.id, PartialRes::new(res)); |
2572 | rib.bindings.insert(ident, res); | |
416331ca XL |
2573 | } |
2574 | ||
04454e1e | 2575 | self.lifetime_ribs.push(function_lifetime_rib); |
e74abb32 XL |
2576 | self.ribs[ValueNS].push(function_value_rib); |
2577 | self.ribs[TypeNS].push(function_type_rib); | |
2578 | ||
416331ca XL |
2579 | f(self); |
2580 | ||
e74abb32 XL |
2581 | self.ribs[TypeNS].pop(); |
2582 | self.ribs[ValueNS].pop(); | |
064997fb FG |
2583 | let function_lifetime_rib = self.lifetime_ribs.pop().unwrap(); |
2584 | ||
2585 | // Do not account for the parameters we just bound for function lifetime elision. | |
2586 | if let Some(ref mut candidates) = self.lifetime_elision_candidates { | |
2587 | for (_, res) in function_lifetime_rib.bindings.values() { | |
f2b60f7d | 2588 | candidates.retain(|(r, _)| r != res); |
064997fb FG |
2589 | } |
2590 | } | |
923072b8 FG |
2591 | |
2592 | if let LifetimeBinderKind::BareFnType | |
2593 | | LifetimeBinderKind::WhereBound | |
2594 | | LifetimeBinderKind::Function | |
2595 | | LifetimeBinderKind::ImplBlock = generics_kind | |
2596 | { | |
2597 | self.maybe_report_lifetime_uses(generics_span, params) | |
2598 | } | |
416331ca XL |
2599 | } |
2600 | ||
e1599b0c XL |
2601 | fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { |
2602 | self.label_ribs.push(Rib::new(kind)); | |
416331ca XL |
2603 | f(self); |
2604 | self.label_ribs.pop(); | |
2605 | } | |
2606 | ||
2b03887a | 2607 | fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) { |
49aad941 | 2608 | let kind = RibKind::Item(HasGenericParams::No); |
2b03887a | 2609 | self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) |
416331ca XL |
2610 | } |
2611 | ||
49aad941 | 2612 | // HACK(min_const_generics, generic_const_exprs): We |
29967ef6 XL |
2613 | // want to keep allowing `[0; std::mem::size_of::<*mut T>()]` |
2614 | // with a future compat lint for now. We do this by adding an | |
2615 | // additional special case for repeat expressions. | |
2616 | // | |
2617 | // Note that we intentionally still forbid `[0; N + 1]` during | |
2618 | // name resolution so that we don't extend the future | |
2619 | // compat lint to new cases. | |
04454e1e | 2620 | #[instrument(level = "debug", skip(self, f))] |
29967ef6 XL |
2621 | fn with_constant_rib( |
2622 | &mut self, | |
2623 | is_repeat: IsRepeatExpr, | |
f2b60f7d | 2624 | may_use_generics: ConstantHasGenerics, |
5869c6ff | 2625 | item: Option<(Ident, ConstantItemKind)>, |
29967ef6 XL |
2626 | f: impl FnOnce(&mut Self), |
2627 | ) { | |
49aad941 FG |
2628 | let f = |this: &mut Self| { |
2629 | this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| { | |
2630 | this.with_rib( | |
2631 | TypeNS, | |
2632 | RibKind::ConstantItem( | |
2633 | may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes), | |
2634 | item, | |
2635 | ), | |
2636 | |this| { | |
2637 | this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f); | |
2638 | }, | |
2639 | ) | |
2640 | }) | |
2641 | }; | |
2642 | ||
2643 | if let ConstantHasGenerics::No(cause) = may_use_generics { | |
2644 | self.with_lifetime_rib(LifetimeRibKind::ConcreteAnonConst(cause), f) | |
2645 | } else { | |
2646 | f(self) | |
2647 | } | |
416331ca XL |
2648 | } |
2649 | ||
e1599b0c | 2650 | fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T { |
416331ca | 2651 | // Handle nested impls (inside fn bodies) |
dfeec247 XL |
2652 | let previous_value = |
2653 | replace(&mut self.diagnostic_metadata.current_self_type, Some(self_type.clone())); | |
416331ca | 2654 | let result = f(self); |
e74abb32 | 2655 | self.diagnostic_metadata.current_self_type = previous_value; |
416331ca XL |
2656 | result |
2657 | } | |
2658 | ||
e1599b0c | 2659 | fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T { |
dfeec247 XL |
2660 | let previous_value = |
2661 | replace(&mut self.diagnostic_metadata.current_self_item, Some(self_item.id)); | |
416331ca | 2662 | let result = f(self); |
e74abb32 | 2663 | self.diagnostic_metadata.current_self_item = previous_value; |
416331ca XL |
2664 | result |
2665 | } | |
2666 | ||
29967ef6 | 2667 | /// When evaluating a `trait` use its associated types' idents for suggestions in E0412. |
923072b8 | 2668 | fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) { |
5869c6ff XL |
2669 | let trait_assoc_items = |
2670 | replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(&trait_items)); | |
923072b8 FG |
2671 | |
2672 | let walk_assoc_item = | |
2673 | |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| { | |
2674 | this.with_generic_param_rib( | |
2675 | &generics.params, | |
49aad941 | 2676 | RibKind::AssocItem, |
923072b8 FG |
2677 | LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind }, |
2678 | |this| visit::walk_assoc_item(this, item, AssocCtxt::Trait), | |
2679 | ); | |
2680 | }; | |
2681 | ||
2682 | for item in trait_items { | |
9ffffee4 | 2683 | self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); |
923072b8 | 2684 | match &item.kind { |
353b0b11 | 2685 | AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => { |
923072b8 FG |
2686 | self.visit_ty(ty); |
2687 | // Only impose the restrictions of `ConstRibKind` for an | |
2688 | // actual constant expression in a provided default. | |
353b0b11 | 2689 | if let Some(expr) = expr { |
923072b8 FG |
2690 | // We allow arbitrary const expressions inside of associated consts, |
2691 | // even if they are potentially not const evaluatable. | |
2692 | // | |
2693 | // Type parameters can already be used and as associated consts are | |
2694 | // not used as part of the type system, this is far less surprising. | |
064997fb FG |
2695 | self.with_lifetime_rib( |
2696 | LifetimeRibKind::Elided(LifetimeRes::Infer), | |
2697 | |this| { | |
2698 | this.with_constant_rib( | |
2699 | IsRepeatExpr::No, | |
f2b60f7d | 2700 | ConstantHasGenerics::Yes, |
064997fb FG |
2701 | None, |
2702 | |this| this.visit_expr(expr), | |
2703 | ) | |
2704 | }, | |
923072b8 FG |
2705 | ); |
2706 | } | |
2707 | } | |
2708 | AssocItemKind::Fn(box Fn { generics, .. }) => { | |
2709 | walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); | |
2710 | } | |
2b03887a | 2711 | AssocItemKind::Type(box TyAlias { generics, .. }) => self |
064997fb FG |
2712 | .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { |
2713 | walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) | |
2714 | }), | |
923072b8 FG |
2715 | AssocItemKind::MacCall(_) => { |
2716 | panic!("unexpanded macro in resolve!") | |
2717 | } | |
2718 | }; | |
2719 | } | |
2720 | ||
29967ef6 | 2721 | self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items; |
416331ca XL |
2722 | } |
2723 | ||
2724 | /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). | |
e1599b0c XL |
2725 | fn with_optional_trait_ref<T>( |
2726 | &mut self, | |
2727 | opt_trait_ref: Option<&TraitRef>, | |
923072b8 | 2728 | self_type: &'ast Ty, |
dfeec247 | 2729 | f: impl FnOnce(&mut Self, Option<DefId>) -> T, |
e1599b0c | 2730 | ) -> T { |
416331ca XL |
2731 | let mut new_val = None; |
2732 | let mut new_id = None; | |
2733 | if let Some(trait_ref) = opt_trait_ref { | |
2734 | let path: Vec<_> = Segment::from_path(&trait_ref.path); | |
923072b8 FG |
2735 | self.diagnostic_metadata.currently_processing_impl_trait = |
2736 | Some((trait_ref.clone(), self_type.clone())); | |
416331ca | 2737 | let res = self.smart_resolve_path_fragment( |
487cf647 | 2738 | &None, |
416331ca | 2739 | &path, |
416331ca | 2740 | PathSource::Trait(AliasPossibility::No), |
04454e1e | 2741 | Finalize::new(trait_ref.ref_id, trait_ref.path.span), |
353b0b11 | 2742 | RecordPartialRes::Yes, |
dfeec247 | 2743 | ); |
923072b8 | 2744 | self.diagnostic_metadata.currently_processing_impl_trait = None; |
2b03887a | 2745 | if let Some(def_id) = res.expect_full_res().opt_def_id() { |
5e7ed085 FG |
2746 | new_id = Some(def_id); |
2747 | new_val = Some((self.r.expect_module(def_id), trait_ref.clone())); | |
416331ca XL |
2748 | } |
2749 | } | |
2750 | let original_trait_ref = replace(&mut self.current_trait_ref, new_val); | |
2751 | let result = f(self, new_id); | |
2752 | self.current_trait_ref = original_trait_ref; | |
2753 | result | |
2754 | } | |
2755 | ||
e1599b0c | 2756 | fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) { |
49aad941 | 2757 | let mut self_type_rib = Rib::new(RibKind::Normal); |
416331ca XL |
2758 | |
2759 | // Plain insert (no renaming, since types are not currently hygienic) | |
e1599b0c XL |
2760 | self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); |
2761 | self.ribs[ns].push(self_type_rib); | |
416331ca | 2762 | f(self); |
e1599b0c | 2763 | self.ribs[ns].pop(); |
416331ca XL |
2764 | } |
2765 | ||
e1599b0c XL |
2766 | fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) { |
2767 | self.with_self_rib_ns(TypeNS, self_res, f) | |
416331ca XL |
2768 | } |
2769 | ||
dfeec247 XL |
2770 | fn resolve_implementation( |
2771 | &mut self, | |
9ffffee4 | 2772 | attrs: &[ast::Attribute], |
dfeec247 XL |
2773 | generics: &'ast Generics, |
2774 | opt_trait_reference: &'ast Option<TraitRef>, | |
2775 | self_type: &'ast Ty, | |
2776 | item_id: NodeId, | |
74b04a01 | 2777 | impl_items: &'ast [P<AssocItem>], |
dfeec247 | 2778 | ) { |
416331ca XL |
2779 | debug!("resolve_implementation"); |
2780 | // If applicable, create a rib for the type parameters. | |
923072b8 FG |
2781 | self.with_generic_param_rib( |
2782 | &generics.params, | |
49aad941 | 2783 | RibKind::Item(HasGenericParams::Yes(generics.span)), |
923072b8 FG |
2784 | LifetimeRibKind::Generics { |
2785 | span: generics.span, | |
2786 | binder: item_id, | |
064997fb | 2787 | kind: LifetimeBinderKind::ImplBlock, |
923072b8 FG |
2788 | }, |
2789 | |this| { | |
2790 | // Dummy self type for better errors if `Self` is used in the trait path. | |
2b03887a | 2791 | this.with_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| { |
923072b8 FG |
2792 | this.with_lifetime_rib( |
2793 | LifetimeRibKind::AnonymousCreateParameter { | |
2794 | binder: item_id, | |
2795 | report_in_path: true | |
2796 | }, | |
2797 | |this| { | |
2798 | // Resolve the trait reference, if necessary. | |
2799 | this.with_optional_trait_ref( | |
2800 | opt_trait_reference.as_ref(), | |
2801 | self_type, | |
2802 | |this, trait_id| { | |
9ffffee4 FG |
2803 | this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id)); |
2804 | ||
923072b8 FG |
2805 | let item_def_id = this.r.local_def_id(item_id); |
2806 | ||
2807 | // Register the trait definitions from here. | |
2808 | if let Some(trait_id) = trait_id { | |
064997fb FG |
2809 | this.r |
2810 | .trait_impls | |
2811 | .entry(trait_id) | |
2812 | .or_default() | |
2813 | .push(item_def_id); | |
923072b8 | 2814 | } |
04454e1e | 2815 | |
923072b8 | 2816 | let item_def_id = item_def_id.to_def_id(); |
2b03887a FG |
2817 | let res = Res::SelfTyAlias { |
2818 | alias_to: item_def_id, | |
2819 | forbid_generic: false, | |
2820 | is_trait_impl: trait_id.is_some() | |
923072b8 FG |
2821 | }; |
2822 | this.with_self_rib(res, |this| { | |
2823 | if let Some(trait_ref) = opt_trait_reference.as_ref() { | |
2824 | // Resolve type arguments in the trait path. | |
2825 | visit::walk_trait_ref(this, trait_ref); | |
2826 | } | |
2827 | // Resolve the self type. | |
2828 | this.visit_ty(self_type); | |
2829 | // Resolve the generic parameters. | |
2830 | this.visit_generics(generics); | |
2831 | ||
2832 | // Resolve the items within the impl. | |
064997fb FG |
2833 | this.with_current_self_type(self_type, |this| { |
2834 | this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { | |
2835 | debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); | |
2b03887a | 2836 | let mut seen_trait_items = Default::default(); |
064997fb | 2837 | for item in impl_items { |
9ffffee4 | 2838 | this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id); |
064997fb FG |
2839 | } |
2840 | }); | |
2841 | }); | |
04454e1e FG |
2842 | }); |
2843 | }, | |
064997fb | 2844 | ) |
923072b8 FG |
2845 | }, |
2846 | ); | |
416331ca | 2847 | }); |
923072b8 FG |
2848 | }, |
2849 | ); | |
2850 | } | |
2851 | ||
2b03887a FG |
2852 | fn resolve_impl_item( |
2853 | &mut self, | |
2854 | item: &'ast AssocItem, | |
2855 | seen_trait_items: &mut FxHashMap<DefId, Span>, | |
9ffffee4 | 2856 | trait_id: Option<DefId>, |
2b03887a | 2857 | ) { |
923072b8 | 2858 | use crate::ResolutionError::*; |
9ffffee4 | 2859 | self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis))); |
923072b8 | 2860 | match &item.kind { |
353b0b11 | 2861 | AssocItemKind::Const(box ast::ConstItem { ty, expr, .. }) => { |
923072b8 FG |
2862 | debug!("resolve_implementation AssocItemKind::Const"); |
2863 | // If this is a trait impl, ensure the const | |
2864 | // exists in trait | |
2865 | self.check_trait_item( | |
2866 | item.id, | |
2867 | item.ident, | |
2868 | &item.kind, | |
2869 | ValueNS, | |
2870 | item.span, | |
2b03887a | 2871 | seen_trait_items, |
923072b8 FG |
2872 | |i, s, c| ConstNotMemberOfTrait(i, s, c), |
2873 | ); | |
2874 | ||
2875 | self.visit_ty(ty); | |
353b0b11 | 2876 | if let Some(expr) = expr { |
923072b8 FG |
2877 | // We allow arbitrary const expressions inside of associated consts, |
2878 | // even if they are potentially not const evaluatable. | |
2879 | // | |
2880 | // Type parameters can already be used and as associated consts are | |
2881 | // not used as part of the type system, this is far less surprising. | |
064997fb FG |
2882 | self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { |
2883 | this.with_constant_rib( | |
2884 | IsRepeatExpr::No, | |
f2b60f7d | 2885 | ConstantHasGenerics::Yes, |
064997fb FG |
2886 | None, |
2887 | |this| this.visit_expr(expr), | |
2888 | ) | |
923072b8 FG |
2889 | }); |
2890 | } | |
2891 | } | |
2892 | AssocItemKind::Fn(box Fn { generics, .. }) => { | |
2893 | debug!("resolve_implementation AssocItemKind::Fn"); | |
2894 | // We also need a new scope for the impl item type parameters. | |
2895 | self.with_generic_param_rib( | |
2896 | &generics.params, | |
49aad941 | 2897 | RibKind::AssocItem, |
923072b8 FG |
2898 | LifetimeRibKind::Generics { |
2899 | binder: item.id, | |
2900 | span: generics.span, | |
2901 | kind: LifetimeBinderKind::Function, | |
2902 | }, | |
2903 | |this| { | |
2904 | // If this is a trait impl, ensure the method | |
2905 | // exists in trait | |
2906 | this.check_trait_item( | |
2907 | item.id, | |
2908 | item.ident, | |
2909 | &item.kind, | |
2910 | ValueNS, | |
2911 | item.span, | |
2b03887a | 2912 | seen_trait_items, |
923072b8 FG |
2913 | |i, s, c| MethodNotMemberOfTrait(i, s, c), |
2914 | ); | |
2915 | ||
2916 | visit::walk_assoc_item(this, item, AssocCtxt::Impl) | |
2917 | }, | |
2918 | ); | |
2919 | } | |
2b03887a FG |
2920 | AssocItemKind::Type(box TyAlias { generics, .. }) => { |
2921 | debug!("resolve_implementation AssocItemKind::Type"); | |
923072b8 FG |
2922 | // We also need a new scope for the impl item type parameters. |
2923 | self.with_generic_param_rib( | |
2924 | &generics.params, | |
49aad941 | 2925 | RibKind::AssocItem, |
923072b8 FG |
2926 | LifetimeRibKind::Generics { |
2927 | binder: item.id, | |
2928 | span: generics.span, | |
2929 | kind: LifetimeBinderKind::Item, | |
2930 | }, | |
2931 | |this| { | |
064997fb FG |
2932 | this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { |
2933 | // If this is a trait impl, ensure the type | |
2934 | // exists in trait | |
2935 | this.check_trait_item( | |
2936 | item.id, | |
2937 | item.ident, | |
2938 | &item.kind, | |
2939 | TypeNS, | |
2940 | item.span, | |
2b03887a | 2941 | seen_trait_items, |
064997fb FG |
2942 | |i, s, c| TypeNotMemberOfTrait(i, s, c), |
2943 | ); | |
923072b8 | 2944 | |
064997fb FG |
2945 | visit::walk_assoc_item(this, item, AssocCtxt::Impl) |
2946 | }); | |
923072b8 FG |
2947 | }, |
2948 | ); | |
2949 | } | |
2950 | AssocItemKind::MacCall(_) => { | |
2951 | panic!("unexpanded macro in resolve!") | |
2952 | } | |
2953 | } | |
416331ca XL |
2954 | } |
2955 | ||
c295e0f8 XL |
2956 | fn check_trait_item<F>( |
2957 | &mut self, | |
5099ac24 FG |
2958 | id: NodeId, |
2959 | mut ident: Ident, | |
c295e0f8 XL |
2960 | kind: &AssocItemKind, |
2961 | ns: Namespace, | |
2962 | span: Span, | |
2b03887a | 2963 | seen_trait_items: &mut FxHashMap<DefId, Span>, |
c295e0f8 XL |
2964 | err: F, |
2965 | ) where | |
04454e1e | 2966 | F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>, |
416331ca | 2967 | { |
5099ac24 FG |
2968 | // If there is a TraitRef in scope for an impl, then the method must be in the trait. |
2969 | let Some((module, _)) = &self.current_trait_ref else { return; }; | |
2970 | ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); | |
49aad941 | 2971 | let key = BindingKey::new(ident, ns); |
5099ac24 FG |
2972 | let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); |
2973 | debug!(?binding); | |
2974 | if binding.is_none() { | |
2975 | // We could not find the trait item in the correct namespace. | |
2976 | // Check the other namespace to report an error. | |
2977 | let ns = match ns { | |
2978 | ValueNS => TypeNS, | |
2979 | TypeNS => ValueNS, | |
2980 | _ => ns, | |
2981 | }; | |
49aad941 | 2982 | let key = BindingKey::new(ident, ns); |
5099ac24 FG |
2983 | binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); |
2984 | debug!(?binding); | |
2985 | } | |
2986 | let Some(binding) = binding else { | |
2987 | // We could not find the method: report an error. | |
2988 | let candidate = self.find_similarly_named_assoc_item(ident.name, kind); | |
2989 | let path = &self.current_trait_ref.as_ref().unwrap().1.path; | |
04454e1e FG |
2990 | let path_names = path_names_to_string(path); |
2991 | self.report_error(span, err(ident, path_names, candidate)); | |
5099ac24 FG |
2992 | return; |
2993 | }; | |
2994 | ||
2995 | let res = binding.res(); | |
2b03887a FG |
2996 | let Res::Def(def_kind, id_in_trait) = res else { bug!() }; |
2997 | ||
2998 | match seen_trait_items.entry(id_in_trait) { | |
2999 | Entry::Occupied(entry) => { | |
3000 | self.report_error( | |
3001 | span, | |
3002 | ResolutionError::TraitImplDuplicate { | |
3003 | name: ident.name, | |
3004 | old_span: *entry.get(), | |
3005 | trait_item_span: binding.span, | |
3006 | }, | |
3007 | ); | |
3008 | return; | |
3009 | } | |
3010 | Entry::Vacant(entry) => { | |
3011 | entry.insert(span); | |
3012 | } | |
3013 | }; | |
3014 | ||
5099ac24 | 3015 | match (def_kind, kind) { |
2b03887a | 3016 | (DefKind::AssocTy, AssocItemKind::Type(..)) |
5099ac24 FG |
3017 | | (DefKind::AssocFn, AssocItemKind::Fn(..)) |
3018 | | (DefKind::AssocConst, AssocItemKind::Const(..)) => { | |
3019 | self.r.record_partial_res(id, PartialRes::new(res)); | |
3020 | return; | |
416331ca | 3021 | } |
5099ac24 | 3022 | _ => {} |
416331ca | 3023 | } |
5099ac24 FG |
3024 | |
3025 | // The method kind does not correspond to what appeared in the trait, report. | |
3026 | let path = &self.current_trait_ref.as_ref().unwrap().1.path; | |
3027 | let (code, kind) = match kind { | |
3028 | AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"), | |
3029 | AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"), | |
2b03887a | 3030 | AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"), |
5099ac24 FG |
3031 | AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), |
3032 | }; | |
04454e1e | 3033 | let trait_path = path_names_to_string(path); |
5099ac24 FG |
3034 | self.report_error( |
3035 | span, | |
3036 | ResolutionError::TraitImplMismatch { | |
3037 | name: ident.name, | |
3038 | kind, | |
3039 | code, | |
04454e1e | 3040 | trait_path, |
5099ac24 FG |
3041 | trait_item_span: binding.span, |
3042 | }, | |
3043 | ); | |
416331ca XL |
3044 | } |
3045 | ||
dfeec247 | 3046 | fn resolve_params(&mut self, params: &'ast [Param]) { |
e1599b0c | 3047 | let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; |
2b03887a FG |
3048 | self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { |
3049 | for Param { pat, .. } in params { | |
3050 | this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings); | |
3051 | } | |
3052 | }); | |
3053 | for Param { ty, .. } in params { | |
e1599b0c | 3054 | self.visit_ty(ty); |
e1599b0c XL |
3055 | } |
3056 | } | |
3057 | ||
dfeec247 | 3058 | fn resolve_local(&mut self, local: &'ast Local) { |
3dfed10e | 3059 | debug!("resolving local ({:?})", local); |
416331ca XL |
3060 | // Resolve the type. |
3061 | walk_list!(self, visit_ty, &local.ty); | |
3062 | ||
3063 | // Resolve the initializer. | |
94222f64 XL |
3064 | if let Some((init, els)) = local.kind.init_else_opt() { |
3065 | self.visit_expr(init); | |
3066 | ||
3067 | // Resolve the `else` block | |
3068 | if let Some(els) = els { | |
3069 | self.visit_block(els); | |
3070 | } | |
3071 | } | |
416331ca XL |
3072 | |
3073 | // Resolve the pattern. | |
e1599b0c | 3074 | self.resolve_pattern_top(&local.pat, PatternSource::Let); |
416331ca XL |
3075 | } |
3076 | ||
e1599b0c XL |
3077 | /// build a map from pattern identifiers to binding-info's. |
3078 | /// this is done hygienically. This could arise for a macro | |
3079 | /// that expands into an or-pattern where one 'x' was from the | |
3080 | /// user and one 'x' came from the macro. | |
416331ca XL |
3081 | fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { |
3082 | let mut binding_map = FxHashMap::default(); | |
3083 | ||
3084 | pat.walk(&mut |pat| { | |
e74abb32 | 3085 | match pat.kind { |
f2b60f7d | 3086 | PatKind::Ident(annotation, ident, ref sub_pat) |
e1599b0c XL |
3087 | if sub_pat.is_some() || self.is_base_res_local(pat.id) => |
3088 | { | |
f2b60f7d | 3089 | binding_map.insert(ident, BindingInfo { span: ident.span, annotation }); |
416331ca | 3090 | } |
e1599b0c XL |
3091 | PatKind::Or(ref ps) => { |
3092 | // Check the consistency of this or-pattern and | |
3093 | // then add all bindings to the larger map. | |
3094 | for bm in self.check_consistent_bindings(ps) { | |
3095 | binding_map.extend(bm); | |
3096 | } | |
3097 | return false; | |
3098 | } | |
3099 | _ => {} | |
416331ca | 3100 | } |
e1599b0c | 3101 | |
416331ca XL |
3102 | true |
3103 | }); | |
3104 | ||
3105 | binding_map | |
3106 | } | |
3107 | ||
e1599b0c | 3108 | fn is_base_res_local(&self, nid: NodeId) -> bool { |
2b03887a FG |
3109 | matches!( |
3110 | self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()), | |
3111 | Some(Res::Local(..)) | |
3112 | ) | |
e1599b0c XL |
3113 | } |
3114 | ||
3115 | /// Checks that all of the arms in an or-pattern have exactly the | |
3116 | /// same set of bindings, with the same binding modes for each. | |
3117 | fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> { | |
416331ca XL |
3118 | let mut missing_vars = FxHashMap::default(); |
3119 | let mut inconsistent_vars = FxHashMap::default(); | |
3120 | ||
e1599b0c | 3121 | // 1) Compute the binding maps of all arms. |
dfeec247 | 3122 | let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>(); |
e1599b0c XL |
3123 | |
3124 | // 2) Record any missing bindings or binding mode inconsistencies. | |
3125 | for (map_outer, pat_outer) in pats.iter().enumerate().map(|(idx, pat)| (&maps[idx], pat)) { | |
3126 | // Check against all arms except for the same pattern which is always self-consistent. | |
dfeec247 XL |
3127 | let inners = pats |
3128 | .iter() | |
3129 | .enumerate() | |
e1599b0c XL |
3130 | .filter(|(_, pat)| pat.id != pat_outer.id) |
3131 | .flat_map(|(idx, _)| maps[idx].iter()) | |
3132 | .map(|(key, binding)| (key.name, map_outer.get(&key), binding)); | |
3133 | ||
3134 | for (name, info, &binding_inner) in inners { | |
3135 | match info { | |
dfeec247 XL |
3136 | None => { |
3137 | // The inner binding is missing in the outer. | |
3138 | let binding_error = | |
3139 | missing_vars.entry(name).or_insert_with(|| BindingError { | |
e1599b0c XL |
3140 | name, |
3141 | origin: BTreeSet::new(), | |
3142 | target: BTreeSet::new(), | |
3143 | could_be_path: name.as_str().starts_with(char::is_uppercase), | |
3144 | }); | |
3145 | binding_error.origin.insert(binding_inner.span); | |
3146 | binding_error.target.insert(pat_outer.span); | |
3147 | } | |
3148 | Some(binding_outer) => { | |
f2b60f7d | 3149 | if binding_outer.annotation != binding_inner.annotation { |
e1599b0c XL |
3150 | // The binding modes in the outer and inner bindings differ. |
3151 | inconsistent_vars | |
3152 | .entry(name) | |
3153 | .or_insert((binding_inner.span, binding_outer.span)); | |
416331ca XL |
3154 | } |
3155 | } | |
3156 | } | |
3157 | } | |
3158 | } | |
3159 | ||
e1599b0c | 3160 | // 3) Report all missing variables we found. |
04454e1e FG |
3161 | let mut missing_vars = missing_vars.into_iter().collect::<Vec<_>>(); |
3162 | missing_vars.sort_by_key(|&(sym, ref _err)| sym); | |
f035d41b | 3163 | |
04454e1e FG |
3164 | for (name, mut v) in missing_vars.into_iter() { |
3165 | if inconsistent_vars.contains_key(&name) { | |
416331ca XL |
3166 | v.could_be_path = false; |
3167 | } | |
3dfed10e | 3168 | self.report_error( |
416331ca | 3169 | *v.origin.iter().next().unwrap(), |
04454e1e | 3170 | ResolutionError::VariableNotBoundInPattern(v, self.parent_scope), |
dfeec247 | 3171 | ); |
416331ca XL |
3172 | } |
3173 | ||
e1599b0c | 3174 | // 4) Report all inconsistencies in binding modes we found. |
416331ca XL |
3175 | let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>(); |
3176 | inconsistent_vars.sort(); | |
3177 | for (name, v) in inconsistent_vars { | |
3dfed10e | 3178 | self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1)); |
416331ca | 3179 | } |
416331ca | 3180 | |
e1599b0c XL |
3181 | // 5) Finally bubble up all the binding maps. |
3182 | maps | |
416331ca XL |
3183 | } |
3184 | ||
e1599b0c | 3185 | /// Check the consistency of the outermost or-patterns. |
dfeec247 | 3186 | fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) { |
e74abb32 | 3187 | pat.walk(&mut |pat| match pat.kind { |
e1599b0c XL |
3188 | PatKind::Or(ref ps) => { |
3189 | self.check_consistent_bindings(ps); | |
3190 | false | |
dfeec247 | 3191 | } |
e1599b0c XL |
3192 | _ => true, |
3193 | }) | |
416331ca XL |
3194 | } |
3195 | ||
dfeec247 | 3196 | fn resolve_arm(&mut self, arm: &'ast Arm) { |
49aad941 | 3197 | self.with_rib(ValueNS, RibKind::Normal, |this| { |
e1599b0c XL |
3198 | this.resolve_pattern_top(&arm.pat, PatternSource::Match); |
3199 | walk_list!(this, visit_expr, &arm.guard); | |
3200 | this.visit_expr(&arm.body); | |
3201 | }); | |
416331ca XL |
3202 | } |
3203 | ||
e1599b0c | 3204 | /// Arising from `source`, resolve a top level pattern. |
dfeec247 | 3205 | fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) { |
e1599b0c XL |
3206 | let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; |
3207 | self.resolve_pattern(pat, pat_src, &mut bindings); | |
3208 | } | |
416331ca | 3209 | |
e1599b0c XL |
3210 | fn resolve_pattern( |
3211 | &mut self, | |
dfeec247 | 3212 | pat: &'ast Pat, |
e1599b0c XL |
3213 | pat_src: PatternSource, |
3214 | bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>, | |
3215 | ) { | |
a2a8927a XL |
3216 | // We walk the pattern before declaring the pattern's inner bindings, |
3217 | // so that we avoid resolving a literal expression to a binding defined | |
3218 | // by the pattern. | |
3219 | visit::walk_pat(self, pat); | |
e1599b0c XL |
3220 | self.resolve_pattern_inner(pat, pat_src, bindings); |
3221 | // This has to happen *after* we determine which pat_idents are variants: | |
3222 | self.check_consistent_bindings_top(pat); | |
416331ca XL |
3223 | } |
3224 | ||
e1599b0c XL |
3225 | /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. |
3226 | /// | |
3227 | /// ### `bindings` | |
3228 | /// | |
3229 | /// A stack of sets of bindings accumulated. | |
3230 | /// | |
3231 | /// In each set, `PatBoundCtx::Product` denotes that a found binding in it should | |
3232 | /// be interpreted as re-binding an already bound binding. This results in an error. | |
3233 | /// Meanwhile, `PatBound::Or` denotes that a found binding in the set should result | |
3234 | /// in reusing this binding rather than creating a fresh one. | |
3235 | /// | |
3236 | /// When called at the top level, the stack must have a single element | |
3237 | /// with `PatBound::Product`. Otherwise, pushing to the stack happens as | |
3238 | /// or-patterns (`p_0 | ... | p_n`) are encountered and the context needs | |
3239 | /// to be switched to `PatBoundCtx::Or` and then `PatBoundCtx::Product` for each `p_i`. | |
3240 | /// When each `p_i` has been dealt with, the top set is merged with its parent. | |
3241 | /// When a whole or-pattern has been dealt with, the thing happens. | |
3242 | /// | |
3243 | /// See the implementation and `fresh_binding` for more details. | |
3244 | fn resolve_pattern_inner( | |
3245 | &mut self, | |
3246 | pat: &Pat, | |
3247 | pat_src: PatternSource, | |
3248 | bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>, | |
3249 | ) { | |
416331ca | 3250 | // Visit all direct subpatterns of this pattern. |
416331ca | 3251 | pat.walk(&mut |pat| { |
e74abb32 XL |
3252 | debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind); |
3253 | match pat.kind { | |
e1599b0c XL |
3254 | PatKind::Ident(bmode, ident, ref sub) => { |
3255 | // First try to resolve the identifier as some existing entity, | |
3256 | // then fall back to a fresh binding. | |
3257 | let has_sub = sub.is_some(); | |
dfeec247 | 3258 | let res = self |
5e7ed085 | 3259 | .try_resolve_as_non_binding(pat_src, bmode, ident, has_sub) |
e1599b0c | 3260 | .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); |
416331ca | 3261 | self.r.record_partial_res(pat.id, PartialRes::new(res)); |
cdc7bbd5 | 3262 | self.r.record_pat_span(pat.id, pat.span); |
416331ca | 3263 | } |
17df50a5 | 3264 | PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => { |
1b1a35ee XL |
3265 | self.smart_resolve_path( |
3266 | pat.id, | |
487cf647 | 3267 | qself, |
1b1a35ee XL |
3268 | path, |
3269 | PathSource::TupleStruct( | |
3270 | pat.span, | |
3271 | self.r.arenas.alloc_pattern_spans(sub_patterns.iter().map(|p| p.span)), | |
3272 | ), | |
3273 | ); | |
416331ca | 3274 | } |
416331ca | 3275 | PatKind::Path(ref qself, ref path) => { |
487cf647 | 3276 | self.smart_resolve_path(pat.id, qself, path, PathSource::Pat); |
416331ca | 3277 | } |
17df50a5 | 3278 | PatKind::Struct(ref qself, ref path, ..) => { |
487cf647 | 3279 | self.smart_resolve_path(pat.id, qself, path, PathSource::Struct); |
416331ca | 3280 | } |
e1599b0c XL |
3281 | PatKind::Or(ref ps) => { |
3282 | // Add a new set of bindings to the stack. `Or` here records that when a | |
3283 | // binding already exists in this set, it should not result in an error because | |
3284 | // `V1(a) | V2(a)` must be allowed and are checked for consistency later. | |
3285 | bindings.push((PatBoundCtx::Or, Default::default())); | |
3286 | for p in ps { | |
3287 | // Now we need to switch back to a product context so that each | |
3288 | // part of the or-pattern internally rejects already bound names. | |
3289 | // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad. | |
3290 | bindings.push((PatBoundCtx::Product, Default::default())); | |
3291 | self.resolve_pattern_inner(p, pat_src, bindings); | |
3292 | // Move up the non-overlapping bindings to the or-pattern. | |
3293 | // Existing bindings just get "merged". | |
3294 | let collected = bindings.pop().unwrap().1; | |
3295 | bindings.last_mut().unwrap().1.extend(collected); | |
3296 | } | |
3297 | // This or-pattern itself can itself be part of a product, | |
3298 | // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`. | |
3299 | // Both cases bind `a` again in a product pattern and must be rejected. | |
3300 | let collected = bindings.pop().unwrap().1; | |
3301 | bindings.last_mut().unwrap().1.extend(collected); | |
3302 | ||
3303 | // Prevent visiting `ps` as we've already done so above. | |
3304 | return false; | |
3305 | } | |
416331ca XL |
3306 | _ => {} |
3307 | } | |
3308 | true | |
3309 | }); | |
e1599b0c | 3310 | } |
416331ca | 3311 | |
e1599b0c XL |
3312 | fn fresh_binding( |
3313 | &mut self, | |
3314 | ident: Ident, | |
3315 | pat_id: NodeId, | |
3316 | pat_src: PatternSource, | |
3317 | bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>, | |
3318 | ) -> Res { | |
3319 | // Add the binding to the local ribs, if it doesn't already exist in the bindings map. | |
3320 | // (We must not add it if it's in the bindings map because that breaks the assumptions | |
3321 | // later passes make about or-patterns.) | |
ba9703b0 | 3322 | let ident = ident.normalize_to_macro_rules(); |
e1599b0c | 3323 | |
60c5eb7d XL |
3324 | let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident)); |
3325 | // Already bound in a product pattern? e.g. `(a, a)` which is not allowed. | |
3326 | let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product); | |
3327 | // Already bound in an or-pattern? e.g. `V1(a) | V2(a)`. | |
3328 | // This is *required* for consistency which is checked later. | |
3329 | let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or); | |
e1599b0c XL |
3330 | |
3331 | if already_bound_and { | |
3332 | // Overlap in a product pattern somewhere; report an error. | |
3333 | use ResolutionError::*; | |
3334 | let error = match pat_src { | |
3335 | // `fn f(a: u8, a: u8)`: | |
3336 | PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList, | |
3337 | // `Variant(a, a)`: | |
3338 | _ => IdentifierBoundMoreThanOnceInSamePattern, | |
3339 | }; | |
3dfed10e | 3340 | self.report_error(ident.span, error(ident.name)); |
e1599b0c XL |
3341 | } |
3342 | ||
3343 | // Record as bound if it's valid: | |
5869c6ff | 3344 | let ident_valid = ident.name != kw::Empty; |
e1599b0c XL |
3345 | if ident_valid { |
3346 | bindings.last_mut().unwrap().1.insert(ident); | |
3347 | } | |
3348 | ||
3349 | if already_bound_or { | |
3350 | // `Variant1(a) | Variant2(a)`, ok | |
3351 | // Reuse definition from the first `a`. | |
3352 | self.innermost_rib_bindings(ValueNS)[&ident] | |
3353 | } else { | |
3354 | let res = Res::Local(pat_id); | |
3355 | if ident_valid { | |
3356 | // A completely fresh binding add to the set if it's valid. | |
3357 | self.innermost_rib_bindings(ValueNS).insert(ident, res); | |
3358 | } | |
3359 | res | |
3360 | } | |
3361 | } | |
3362 | ||
3363 | fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> { | |
3364 | &mut self.ribs[ns].last_mut().unwrap().bindings | |
3365 | } | |
3366 | ||
3367 | fn try_resolve_as_non_binding( | |
3368 | &mut self, | |
3369 | pat_src: PatternSource, | |
f2b60f7d | 3370 | ann: BindingAnnotation, |
e1599b0c XL |
3371 | ident: Ident, |
3372 | has_sub: bool, | |
3373 | ) -> Option<Res> { | |
e1599b0c XL |
3374 | // An immutable (no `mut`) by-value (no `ref`) binding pattern without |
3375 | // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could | |
3376 | // also be interpreted as a path to e.g. a constant, variant, etc. | |
f2b60f7d | 3377 | let is_syntactic_ambiguity = !has_sub && ann == BindingAnnotation::NONE; |
e1599b0c | 3378 | |
04454e1e | 3379 | let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?; |
ba9703b0 XL |
3380 | let (res, binding) = match ls_binding { |
3381 | LexicalScopeBinding::Item(binding) | |
3382 | if is_syntactic_ambiguity && binding.is_ambiguity() => | |
dfeec247 | 3383 | { |
ba9703b0 XL |
3384 | // For ambiguous bindings we don't know all their definitions and cannot check |
3385 | // whether they can be shadowed by fresh bindings or not, so force an error. | |
3386 | // issues/33118#issuecomment-233962221 (see below) still applies here, | |
3387 | // but we have to ignore it for backward compatibility. | |
94222f64 | 3388 | self.r.record_use(ident, binding, false); |
ba9703b0 XL |
3389 | return None; |
3390 | } | |
3391 | LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)), | |
3392 | LexicalScopeBinding::Res(res) => (res, None), | |
3393 | }; | |
3394 | ||
3395 | match res { | |
3396 | Res::SelfCtor(_) // See #70549. | |
3397 | | Res::Def( | |
3398 | DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::ConstParam, | |
3399 | _, | |
3400 | ) if is_syntactic_ambiguity => { | |
3401 | // Disambiguate in favor of a unit struct/variant or constant pattern. | |
3402 | if let Some(binding) = binding { | |
94222f64 | 3403 | self.r.record_use(ident, binding, false); |
ba9703b0 | 3404 | } |
e1599b0c XL |
3405 | Some(res) |
3406 | } | |
5e7ed085 | 3407 | Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static(_), _) => { |
e1599b0c XL |
3408 | // This is unambiguously a fresh binding, either syntactically |
3409 | // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves | |
3410 | // to something unusable as a pattern (e.g., constructor function), | |
3411 | // but we still conservatively report an error, see | |
3412 | // issues/33118#issuecomment-233962221 for one reason why. | |
17df50a5 XL |
3413 | let binding = binding.expect("no binding for a ctor or static"); |
3414 | self.report_error( | |
3415 | ident.span, | |
3416 | ResolutionError::BindingShadowsSomethingUnacceptable { | |
064997fb | 3417 | shadowing_binding: pat_src, |
17df50a5 XL |
3418 | name: ident.name, |
3419 | participle: if binding.is_import() { "imported" } else { "defined" }, | |
3420 | article: binding.res().article(), | |
064997fb | 3421 | shadowed_binding: binding.res(), |
17df50a5 XL |
3422 | shadowed_binding_span: binding.span, |
3423 | }, | |
3424 | ); | |
3425 | None | |
3426 | } | |
3427 | Res::Def(DefKind::ConstParam, def_id) => { | |
3428 | // Same as for DefKind::Const above, but here, `binding` is `None`, so we | |
3429 | // have to construct the error differently | |
3dfed10e | 3430 | self.report_error( |
e1599b0c | 3431 | ident.span, |
17df50a5 | 3432 | ResolutionError::BindingShadowsSomethingUnacceptable { |
064997fb | 3433 | shadowing_binding: pat_src, |
17df50a5 XL |
3434 | name: ident.name, |
3435 | participle: "defined", | |
3436 | article: res.article(), | |
064997fb | 3437 | shadowed_binding: res, |
353b0b11 | 3438 | shadowed_binding_span: self.r.def_span(def_id), |
17df50a5 | 3439 | } |
e1599b0c XL |
3440 | ); |
3441 | None | |
3442 | } | |
ba9703b0 | 3443 | Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => { |
e1599b0c XL |
3444 | // These entities are explicitly allowed to be shadowed by fresh bindings. |
3445 | None | |
3446 | } | |
04454e1e FG |
3447 | Res::SelfCtor(_) => { |
3448 | // We resolve `Self` in pattern position as an ident sometimes during recovery, | |
3449 | // so delay a bug instead of ICEing. | |
9ffffee4 | 3450 | self.r.tcx.sess.delay_span_bug( |
04454e1e FG |
3451 | ident.span, |
3452 | "unexpected `SelfCtor` in pattern, expected identifier" | |
3453 | ); | |
3454 | None | |
3455 | } | |
ba9703b0 XL |
3456 | _ => span_bug!( |
3457 | ident.span, | |
3458 | "unexpected resolution for an identifier in pattern: {:?}", | |
3459 | res, | |
3460 | ), | |
e1599b0c | 3461 | } |
416331ca XL |
3462 | } |
3463 | ||
3464 | // High-level and context dependent path resolution routine. | |
3465 | // Resolves the path and records the resolution into definition map. | |
3466 | // If resolution fails tries several techniques to find likely | |
3467 | // resolution candidates, suggest imports or other help, and report | |
3468 | // errors in user friendly way. | |
dfeec247 XL |
3469 | fn smart_resolve_path( |
3470 | &mut self, | |
3471 | id: NodeId, | |
487cf647 | 3472 | qself: &Option<P<QSelf>>, |
dfeec247 XL |
3473 | path: &Path, |
3474 | source: PathSource<'ast>, | |
3475 | ) { | |
416331ca | 3476 | self.smart_resolve_path_fragment( |
416331ca XL |
3477 | qself, |
3478 | &Segment::from_path(path), | |
416331ca | 3479 | source, |
04454e1e | 3480 | Finalize::new(id, path.span), |
353b0b11 | 3481 | RecordPartialRes::Yes, |
416331ca XL |
3482 | ); |
3483 | } | |
3484 | ||
9c376795 | 3485 | #[instrument(level = "debug", skip(self))] |
dfeec247 XL |
3486 | fn smart_resolve_path_fragment( |
3487 | &mut self, | |
487cf647 | 3488 | qself: &Option<P<QSelf>>, |
dfeec247 | 3489 | path: &[Segment], |
dfeec247 | 3490 | source: PathSource<'ast>, |
5e7ed085 | 3491 | finalize: Finalize, |
353b0b11 | 3492 | record_partial_res: RecordPartialRes, |
dfeec247 | 3493 | ) -> PartialRes { |
416331ca | 3494 | let ns = source.namespace(); |
416331ca | 3495 | |
04454e1e | 3496 | let Finalize { node_id, path_span, .. } = finalize; |
416331ca | 3497 | let report_errors = |this: &mut Self, res: Option<Res>| { |
3dfed10e | 3498 | if this.should_report_errs() { |
5e7ed085 FG |
3499 | let (err, candidates) = |
3500 | this.smart_resolve_report_errors(path, path_span, source, res); | |
3dfed10e | 3501 | |
c295e0f8 | 3502 | let def_id = this.parent_scope.module.nearest_parent_mod(); |
3dfed10e | 3503 | let instead = res.is_some(); |
9c376795 FG |
3504 | let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range |
3505 | && path[0].ident.span.lo() == end.span.lo() | |
3506 | { | |
3507 | let mut sugg = "."; | |
3508 | let mut span = start.span.between(end.span); | |
3509 | if span.lo() + BytePos(2) == span.hi() { | |
3510 | // There's no space between the start, the range op and the end, suggest | |
3511 | // removal which will look better. | |
3512 | span = span.with_lo(span.lo() + BytePos(1)); | |
3513 | sugg = ""; | |
3514 | } | |
3515 | Some(( | |
3516 | span, | |
3517 | "you might have meant to write `.` instead of `..`", | |
3518 | sugg.to_string(), | |
3519 | Applicability::MaybeIncorrect, | |
3520 | )) | |
353b0b11 FG |
3521 | } else if res.is_none() && let PathSource::Type | PathSource::Expr(_) = source { |
3522 | this.suggest_adding_generic_parameter(path, source) | |
9c376795 FG |
3523 | } else { |
3524 | None | |
3525 | }; | |
3dfed10e XL |
3526 | |
3527 | this.r.use_injections.push(UseError { | |
3528 | err, | |
3529 | candidates, | |
3530 | def_id, | |
3531 | instead, | |
3532 | suggestion, | |
04454e1e | 3533 | path: path.into(), |
2b03887a | 3534 | is_call: source.is_call(), |
3dfed10e XL |
3535 | }); |
3536 | } | |
f035d41b | 3537 | |
416331ca XL |
3538 | PartialRes::new(Res::Err) |
3539 | }; | |
3540 | ||
f035d41b XL |
3541 | // For paths originating from calls (like in `HashMap::new()`), tries |
3542 | // to enrich the plain `failed to resolve: ...` message with hints | |
3543 | // about possible missing imports. | |
3544 | // | |
3545 | // Similar thing, for types, happens in `report_errors` above. | |
3546 | let report_errors_for_call = |this: &mut Self, parent_err: Spanned<ResolutionError<'a>>| { | |
f035d41b XL |
3547 | // Before we start looking for candidates, we have to get our hands |
3548 | // on the type user is trying to perform invocation on; basically: | |
5869c6ff | 3549 | // we're transforming `HashMap::new` into just `HashMap`. |
487cf647 | 3550 | let prefix_path = match path.split_last() { |
5869c6ff XL |
3551 | Some((_, path)) if !path.is_empty() => path, |
3552 | _ => return Some(parent_err), | |
f035d41b XL |
3553 | }; |
3554 | ||
3555 | let (mut err, candidates) = | |
487cf647 | 3556 | this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None); |
f035d41b XL |
3557 | |
3558 | // There are two different error messages user might receive at | |
3559 | // this point: | |
3560 | // - E0412 cannot find type `{}` in this scope | |
3561 | // - E0433 failed to resolve: use of undeclared type or module `{}` | |
3562 | // | |
3563 | // The first one is emitted for paths in type-position, and the | |
3564 | // latter one - for paths in expression-position. | |
3565 | // | |
3566 | // Thus (since we're in expression-position at this point), not to | |
487cf647 | 3567 | // confuse the user, we want to keep the *message* from E0433 (so |
f035d41b XL |
3568 | // `parent_err`), but we want *hints* from E0412 (so `err`). |
3569 | // | |
3570 | // And that's what happens below - we're just mixing both messages | |
3571 | // into a single one. | |
3572 | let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); | |
3573 | ||
487cf647 | 3574 | // overwrite all properties with the parent's error message |
f035d41b XL |
3575 | err.message = take(&mut parent_err.message); |
3576 | err.code = take(&mut parent_err.code); | |
487cf647 | 3577 | swap(&mut err.span, &mut parent_err.span); |
f035d41b | 3578 | err.children = take(&mut parent_err.children); |
487cf647 FG |
3579 | err.sort_span = parent_err.sort_span; |
3580 | err.is_lint = parent_err.is_lint; | |
3581 | ||
3582 | // merge the parent's suggestions with the typo suggestions | |
3583 | fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) { | |
3584 | match res1 { | |
3585 | Ok(vec1) => match res2 { | |
3586 | Ok(mut vec2) => vec1.append(&mut vec2), | |
3587 | Err(e) => *res1 = Err(e), | |
3588 | }, | |
3589 | Err(_) => (), | |
3590 | }; | |
3591 | } | |
3592 | append_result(&mut err.suggestions, parent_err.suggestions.clone()); | |
f035d41b | 3593 | |
5e7ed085 | 3594 | parent_err.cancel(); |
f035d41b | 3595 | |
c295e0f8 | 3596 | let def_id = this.parent_scope.module.nearest_parent_mod(); |
f035d41b | 3597 | |
3dfed10e | 3598 | if this.should_report_errs() { |
487cf647 FG |
3599 | if candidates.is_empty() { |
3600 | if path.len() == 2 && prefix_path.len() == 1 { | |
3601 | // Delay to check whether methond name is an associated function or not | |
3602 | // ``` | |
3603 | // let foo = Foo {}; | |
3604 | // foo::bar(); // possibly suggest to foo.bar(); | |
3605 | //``` | |
3606 | err.stash( | |
3607 | prefix_path[0].ident.span, | |
3608 | rustc_errors::StashKey::CallAssocMethod, | |
3609 | ); | |
3610 | } else { | |
3611 | // When there is no suggested imports, we can just emit the error | |
3612 | // and suggestions immediately. Note that we bypass the usually error | |
3613 | // reporting routine (ie via `self.r.report_error`) because we need | |
3614 | // to post-process the `ResolutionError` above. | |
3615 | err.emit(); | |
3616 | } | |
3617 | } else { | |
3618 | // If there are suggested imports, the error reporting is delayed | |
3619 | this.r.use_injections.push(UseError { | |
3620 | err, | |
3621 | candidates, | |
3622 | def_id, | |
3623 | instead: false, | |
3624 | suggestion: None, | |
3625 | path: prefix_path.into(), | |
3626 | is_call: source.is_call(), | |
3627 | }); | |
3628 | } | |
3dfed10e XL |
3629 | } else { |
3630 | err.cancel(); | |
3631 | } | |
f035d41b XL |
3632 | |
3633 | // We don't return `Some(parent_err)` here, because the error will | |
487cf647 | 3634 | // be already printed either immediately or as part of the `use` injections |
f035d41b XL |
3635 | None |
3636 | }; | |
3637 | ||
416331ca | 3638 | let partial_res = match self.resolve_qpath_anywhere( |
416331ca XL |
3639 | qself, |
3640 | path, | |
3641 | ns, | |
5e7ed085 | 3642 | path_span, |
416331ca | 3643 | source.defer_to_typeck(), |
5e7ed085 | 3644 | finalize, |
416331ca | 3645 | ) { |
2b03887a FG |
3646 | Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => { |
3647 | if source.is_expected(res) || res == Res::Err { | |
416331ca XL |
3648 | partial_res |
3649 | } else { | |
2b03887a | 3650 | report_errors(self, Some(res)) |
416331ca XL |
3651 | } |
3652 | } | |
f035d41b XL |
3653 | |
3654 | Ok(Some(partial_res)) if source.defer_to_typeck() => { | |
416331ca XL |
3655 | // Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B` |
3656 | // or `<T>::A::B`. If `B` should be resolved in value namespace then | |
3657 | // it needs to be added to the trait map. | |
3658 | if ns == ValueNS { | |
3659 | let item_name = path.last().unwrap().ident; | |
5869c6ff | 3660 | let traits = self.traits_in_scope(item_name, ns); |
04454e1e | 3661 | self.r.trait_map.insert(node_id, traits); |
416331ca XL |
3662 | } |
3663 | ||
6a06907d | 3664 | if PrimTy::from_name(path[0].ident.name).is_some() { |
fc512014 XL |
3665 | let mut std_path = Vec::with_capacity(1 + path.len()); |
3666 | ||
3667 | std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std))); | |
3668 | std_path.extend(path); | |
416331ca | 3669 | if let PathResult::Module(_) | PathResult::NonModule(_) = |
04454e1e | 3670 | self.resolve_path(&std_path, Some(ns), None) |
dfeec247 | 3671 | { |
f035d41b | 3672 | // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8` |
dfeec247 | 3673 | let item_span = |
5e7ed085 | 3674 | path.iter().last().map_or(path_span, |segment| segment.ident.span); |
f035d41b | 3675 | |
5e7ed085 FG |
3676 | self.r.confused_type_with_std_module.insert(item_span, path_span); |
3677 | self.r.confused_type_with_std_module.insert(path_span, path_span); | |
416331ca XL |
3678 | } |
3679 | } | |
f035d41b | 3680 | |
416331ca XL |
3681 | partial_res |
3682 | } | |
f035d41b XL |
3683 | |
3684 | Err(err) => { | |
3685 | if let Some(err) = report_errors_for_call(self, err) { | |
3dfed10e | 3686 | self.report_error(err.span, err.node); |
f035d41b XL |
3687 | } |
3688 | ||
3689 | PartialRes::new(Res::Err) | |
3690 | } | |
3691 | ||
dfeec247 | 3692 | _ => report_errors(self, None), |
416331ca XL |
3693 | }; |
3694 | ||
353b0b11 | 3695 | if record_partial_res == RecordPartialRes::Yes { |
416331ca | 3696 | // Avoid recording definition of `A::B` in `<T as A>::B::C`. |
04454e1e FG |
3697 | self.r.record_partial_res(node_id, partial_res); |
3698 | self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); | |
416331ca | 3699 | } |
f035d41b | 3700 | |
416331ca XL |
3701 | partial_res |
3702 | } | |
3703 | ||
5e7ed085 | 3704 | fn self_type_is_available(&mut self) -> bool { |
04454e1e FG |
3705 | let binding = self |
3706 | .maybe_resolve_ident_in_lexical_scope(Ident::with_dummy_span(kw::SelfUpper), TypeNS); | |
416331ca XL |
3707 | if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false } |
3708 | } | |
3709 | ||
5e7ed085 | 3710 | fn self_value_is_available(&mut self, self_span: Span) -> bool { |
416331ca | 3711 | let ident = Ident::new(kw::SelfLower, self_span); |
04454e1e | 3712 | let binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS); |
416331ca XL |
3713 | if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false } |
3714 | } | |
3715 | ||
3dfed10e XL |
3716 | /// A wrapper around [`Resolver::report_error`]. |
3717 | /// | |
3718 | /// This doesn't emit errors for function bodies if this is rustdoc. | |
04454e1e | 3719 | fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) { |
3dfed10e XL |
3720 | if self.should_report_errs() { |
3721 | self.r.report_error(span, resolution_error); | |
3722 | } | |
3723 | } | |
3724 | ||
3725 | #[inline] | |
3726 | /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items. | |
3727 | fn should_report_errs(&self) -> bool { | |
9ffffee4 | 3728 | !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body) |
3dfed10e XL |
3729 | } |
3730 | ||
416331ca XL |
3731 | // Resolve in alternative namespaces if resolution in the primary namespace fails. |
3732 | fn resolve_qpath_anywhere( | |
3733 | &mut self, | |
487cf647 | 3734 | qself: &Option<P<QSelf>>, |
416331ca XL |
3735 | path: &[Segment], |
3736 | primary_ns: Namespace, | |
3737 | span: Span, | |
3738 | defer_to_typeck: bool, | |
5e7ed085 | 3739 | finalize: Finalize, |
f035d41b | 3740 | ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'a>>> { |
416331ca | 3741 | let mut fin_res = None; |
f035d41b | 3742 | |
fc512014 | 3743 | for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() { |
416331ca | 3744 | if i == 0 || ns != primary_ns { |
5e7ed085 | 3745 | match self.resolve_qpath(qself, path, ns, finalize)? { |
dfeec247 XL |
3746 | Some(partial_res) |
3747 | if partial_res.unresolved_segments() == 0 || defer_to_typeck => | |
3748 | { | |
f035d41b | 3749 | return Ok(Some(partial_res)); |
dfeec247 XL |
3750 | } |
3751 | partial_res => { | |
3752 | if fin_res.is_none() { | |
fc512014 | 3753 | fin_res = partial_res; |
dfeec247 XL |
3754 | } |
3755 | } | |
416331ca XL |
3756 | } |
3757 | } | |
3758 | } | |
3759 | ||
416331ca | 3760 | assert!(primary_ns != MacroNS); |
f035d41b | 3761 | |
416331ca XL |
3762 | if qself.is_none() { |
3763 | let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident); | |
1b1a35ee | 3764 | let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None }; |
dfeec247 XL |
3765 | if let Ok((_, res)) = |
3766 | self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false) | |
3767 | { | |
f035d41b | 3768 | return Ok(Some(PartialRes::new(res))); |
416331ca XL |
3769 | } |
3770 | } | |
3771 | ||
f035d41b | 3772 | Ok(fin_res) |
416331ca XL |
3773 | } |
3774 | ||
3775 | /// Handles paths that may refer to associated items. | |
3776 | fn resolve_qpath( | |
3777 | &mut self, | |
487cf647 | 3778 | qself: &Option<P<QSelf>>, |
416331ca XL |
3779 | path: &[Segment], |
3780 | ns: Namespace, | |
5e7ed085 | 3781 | finalize: Finalize, |
f035d41b | 3782 | ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'a>>> { |
416331ca | 3783 | debug!( |
5e7ed085 FG |
3784 | "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})", |
3785 | qself, path, ns, finalize, | |
416331ca XL |
3786 | ); |
3787 | ||
3788 | if let Some(qself) = qself { | |
3789 | if qself.position == 0 { | |
3790 | // This is a case like `<T>::B`, where there is no | |
9c376795 | 3791 | // trait to resolve. In that case, we leave the `B` |
416331ca | 3792 | // segment to be resolved by type-check. |
f035d41b | 3793 | return Ok(Some(PartialRes::with_unresolved_segments( |
04454e1e | 3794 | Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()), |
dfeec247 | 3795 | path.len(), |
f035d41b | 3796 | ))); |
416331ca XL |
3797 | } |
3798 | ||
353b0b11 FG |
3799 | let num_privacy_errors = self.r.privacy_errors.len(); |
3800 | // Make sure that `A` in `<T as A>::B::C` is a trait. | |
3801 | let trait_res = self.smart_resolve_path_fragment( | |
3802 | &None, | |
3803 | &path[..qself.position], | |
3804 | PathSource::Trait(AliasPossibility::No), | |
3805 | Finalize::new(finalize.node_id, qself.path_span), | |
3806 | RecordPartialRes::No, | |
3807 | ); | |
3808 | ||
3809 | if trait_res.expect_full_res() == Res::Err { | |
3810 | return Ok(Some(trait_res)); | |
3811 | } | |
3812 | ||
3813 | // Truncate additional privacy errors reported above, | |
3814 | // because they'll be recomputed below. | |
3815 | self.r.privacy_errors.truncate(num_privacy_errors); | |
3816 | ||
3817 | // Make sure `A::B` in `<T as A>::B::C` is a trait item. | |
416331ca XL |
3818 | // |
3819 | // Currently, `path` names the full item (`A::B::C`, in | |
9c376795 | 3820 | // our example). so we extract the prefix of that that is |
416331ca XL |
3821 | // the trait (the slice upto and including |
3822 | // `qself.position`). And then we recursively resolve that, | |
3823 | // but with `qself` set to `None`. | |
416331ca XL |
3824 | let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; |
3825 | let partial_res = self.smart_resolve_path_fragment( | |
487cf647 | 3826 | &None, |
416331ca | 3827 | &path[..=qself.position], |
416331ca | 3828 | PathSource::TraitItem(ns), |
04454e1e | 3829 | Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), |
353b0b11 | 3830 | RecordPartialRes::No, |
416331ca XL |
3831 | ); |
3832 | ||
3833 | // The remaining segments (the `C` in our example) will | |
3834 | // have to be resolved by type-check, since that requires doing | |
3835 | // trait resolution. | |
f035d41b | 3836 | return Ok(Some(PartialRes::with_unresolved_segments( |
416331ca XL |
3837 | partial_res.base_res(), |
3838 | partial_res.unresolved_segments() + path.len() - qself.position - 1, | |
f035d41b | 3839 | ))); |
416331ca XL |
3840 | } |
3841 | ||
04454e1e | 3842 | let result = match self.resolve_path(&path, Some(ns), Some(finalize)) { |
416331ca XL |
3843 | PathResult::NonModule(path_res) => path_res, |
3844 | PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { | |
3845 | PartialRes::new(module.res().unwrap()) | |
3846 | } | |
3847 | // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we | |
3848 | // don't report an error right away, but try to fallback to a primitive type. | |
3849 | // So, we are still able to successfully resolve something like | |
3850 | // | |
3851 | // use std::u8; // bring module u8 in scope | |
3852 | // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 | |
3853 | // u8::max_value() // OK, resolves to associated function <u8>::max_value, | |
49aad941 | 3854 | // // not to nonexistent std::u8::max_value |
416331ca XL |
3855 | // } |
3856 | // | |
3857 | // Such behavior is required for backward compatibility. | |
3858 | // The same fallback is used when `a` resolves to nothing. | |
dfeec247 XL |
3859 | PathResult::Module(ModuleOrUniformRoot::Module(_)) | PathResult::Failed { .. } |
3860 | if (ns == TypeNS || path.len() > 1) | |
6a06907d | 3861 | && PrimTy::from_name(path[0].ident.name).is_some() => |
dfeec247 | 3862 | { |
6a06907d | 3863 | let prim = PrimTy::from_name(path[0].ident.name).unwrap(); |
416331ca XL |
3864 | PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) |
3865 | } | |
dfeec247 XL |
3866 | PathResult::Module(ModuleOrUniformRoot::Module(module)) => { |
3867 | PartialRes::new(module.res().unwrap()) | |
3868 | } | |
416331ca | 3869 | PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => { |
f035d41b | 3870 | return Err(respan(span, ResolutionError::FailedToResolve { label, suggestion })); |
416331ca | 3871 | } |
f035d41b XL |
3872 | PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None), |
3873 | PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"), | |
416331ca XL |
3874 | }; |
3875 | ||
dfeec247 | 3876 | if path.len() > 1 |
2b03887a FG |
3877 | && let Some(res) = result.full_res() |
3878 | && res != Res::Err | |
dfeec247 XL |
3879 | && path[0].ident.name != kw::PathRoot |
3880 | && path[0].ident.name != kw::DollarCrate | |
3881 | { | |
416331ca | 3882 | let unqualified_result = { |
04454e1e | 3883 | match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { |
2b03887a | 3884 | PathResult::NonModule(path_res) => path_res.expect_full_res(), |
dfeec247 XL |
3885 | PathResult::Module(ModuleOrUniformRoot::Module(module)) => { |
3886 | module.res().unwrap() | |
3887 | } | |
f035d41b | 3888 | _ => return Ok(Some(result)), |
416331ca XL |
3889 | } |
3890 | }; | |
2b03887a | 3891 | if res == unqualified_result { |
416331ca | 3892 | let lint = lint::builtin::UNUSED_QUALIFICATIONS; |
04454e1e FG |
3893 | self.r.lint_buffer.buffer_lint( |
3894 | lint, | |
3895 | finalize.node_id, | |
3896 | finalize.path_span, | |
3897 | "unnecessary qualification", | |
3898 | ) | |
416331ca XL |
3899 | } |
3900 | } | |
3901 | ||
f035d41b | 3902 | Ok(Some(result)) |
416331ca XL |
3903 | } |
3904 | ||
e1599b0c | 3905 | fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) { |
416331ca | 3906 | if let Some(label) = label { |
60c5eb7d XL |
3907 | if label.ident.as_str().as_bytes()[1] != b'_' { |
3908 | self.diagnostic_metadata.unused_labels.insert(id, label.ident.span); | |
3909 | } | |
923072b8 FG |
3910 | |
3911 | if let Ok((_, orig_span)) = self.resolve_label(label.ident) { | |
9ffffee4 | 3912 | diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident) |
923072b8 FG |
3913 | } |
3914 | ||
49aad941 | 3915 | self.with_label_rib(RibKind::Normal, |this| { |
ba9703b0 | 3916 | let ident = label.ident.normalize_to_macro_rules(); |
416331ca XL |
3917 | this.label_ribs.last_mut().unwrap().bindings.insert(ident, id); |
3918 | f(this); | |
3919 | }); | |
3920 | } else { | |
3921 | f(self); | |
3922 | } | |
3923 | } | |
3924 | ||
dfeec247 | 3925 | fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &'ast Block) { |
416331ca XL |
3926 | self.with_resolved_label(label, id, |this| this.visit_block(block)); |
3927 | } | |
3928 | ||
dfeec247 | 3929 | fn resolve_block(&mut self, block: &'ast Block) { |
e1599b0c XL |
3930 | debug!("(resolving block) entering block"); |
3931 | // Move down in the graph, if there's an anonymous module rooted here. | |
3932 | let orig_module = self.parent_scope.module; | |
3933 | let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference | |
3934 | ||
3935 | let mut num_macro_definition_ribs = 0; | |
3936 | if let Some(anonymous_module) = anonymous_module { | |
3937 | debug!("(resolving block) found anonymous module, moving down"); | |
49aad941 FG |
3938 | self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module))); |
3939 | self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module))); | |
e1599b0c XL |
3940 | self.parent_scope.module = anonymous_module; |
3941 | } else { | |
49aad941 | 3942 | self.ribs[ValueNS].push(Rib::new(RibKind::Normal)); |
e1599b0c XL |
3943 | } |
3944 | ||
94222f64 XL |
3945 | let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take(); |
3946 | if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) = | |
3947 | (block.could_be_bare_literal, &block.stmts[..]) | |
04454e1e | 3948 | && let ExprKind::Type(..) = expr.kind |
94222f64 | 3949 | { |
04454e1e FG |
3950 | self.diagnostic_metadata.current_block_could_be_bare_struct_literal = |
3951 | Some(block.span); | |
94222f64 | 3952 | } |
e1599b0c XL |
3953 | // Descend into the block. |
3954 | for stmt in &block.stmts { | |
04454e1e FG |
3955 | if let StmtKind::Item(ref item) = stmt.kind |
3956 | && let ItemKind::MacroDef(..) = item.kind { | |
3957 | num_macro_definition_ribs += 1; | |
3958 | let res = self.r.local_def_id(item.id).to_def_id(); | |
49aad941 FG |
3959 | self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res))); |
3960 | self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res))); | |
e1599b0c XL |
3961 | } |
3962 | ||
3963 | self.visit_stmt(stmt); | |
3964 | } | |
94222f64 | 3965 | self.diagnostic_metadata.current_block_could_be_bare_struct_literal = prev; |
e1599b0c XL |
3966 | |
3967 | // Move back up. | |
3968 | self.parent_scope.module = orig_module; | |
dfeec247 | 3969 | for _ in 0..num_macro_definition_ribs { |
e1599b0c XL |
3970 | self.ribs[ValueNS].pop(); |
3971 | self.label_ribs.pop(); | |
3972 | } | |
9c376795 | 3973 | self.last_block_rib = self.ribs[ValueNS].pop(); |
e1599b0c XL |
3974 | if anonymous_module.is_some() { |
3975 | self.ribs[TypeNS].pop(); | |
3976 | } | |
3977 | debug!("(resolving block) leaving block"); | |
3978 | } | |
3979 | ||
49aad941 FG |
3980 | fn resolve_anon_const(&mut self, constant: &'ast AnonConst, anon_const_kind: AnonConstKind) { |
3981 | debug!( | |
3982 | "resolve_anon_const(constant: {:?}, anon_const_kind: {:?})", | |
3983 | constant, anon_const_kind | |
29967ef6 | 3984 | ); |
49aad941 FG |
3985 | |
3986 | self.resolve_anon_const_manual( | |
3987 | constant.value.is_potential_trivial_const_arg(), | |
3988 | anon_const_kind, | |
3989 | |this| this.resolve_expr(&constant.value, None), | |
3990 | ) | |
29967ef6 XL |
3991 | } |
3992 | ||
49aad941 FG |
3993 | /// There are a few places that we need to resolve an anon const but we did not parse an |
3994 | /// anon const so cannot provide an `&'ast AnonConst`. Right now this is just unbraced | |
3995 | /// const arguments that were parsed as type arguments, and `legact_const_generics` which | |
3996 | /// parse as normal function argument expressions. To avoid duplicating the code for resolving | |
3997 | /// an anon const we have this function which lets the caller manually call `resolve_expr` or | |
3998 | /// `smart_resolve_path`. | |
3999 | fn resolve_anon_const_manual( | |
4000 | &mut self, | |
4001 | is_trivial_const_arg: bool, | |
4002 | anon_const_kind: AnonConstKind, | |
4003 | resolve_expr: impl FnOnce(&mut Self), | |
4004 | ) { | |
4005 | let is_repeat_expr = match anon_const_kind { | |
4006 | AnonConstKind::ConstArg(is_repeat_expr) => is_repeat_expr, | |
4007 | _ => IsRepeatExpr::No, | |
4008 | }; | |
4009 | ||
4010 | let may_use_generics = match anon_const_kind { | |
4011 | AnonConstKind::EnumDiscriminant => { | |
4012 | ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant) | |
4013 | } | |
4014 | AnonConstKind::InlineConst => ConstantHasGenerics::Yes, | |
4015 | AnonConstKind::ConstArg(_) => { | |
4016 | if self.r.tcx.features().generic_const_exprs || is_trivial_const_arg { | |
4017 | ConstantHasGenerics::Yes | |
4018 | } else { | |
4019 | ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg) | |
4020 | } | |
4021 | } | |
4022 | }; | |
4023 | ||
4024 | self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| { | |
4025 | this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| { | |
4026 | resolve_expr(this); | |
4027 | }); | |
04454e1e FG |
4028 | }); |
4029 | } | |
4030 | ||
dfeec247 | 4031 | fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) { |
416331ca XL |
4032 | // First, record candidate traits for this expression if it could |
4033 | // result in the invocation of a method call. | |
4034 | ||
4035 | self.record_candidate_traits_for_expr_if_necessary(expr); | |
4036 | ||
4037 | // Next, resolve the node. | |
e74abb32 | 4038 | match expr.kind { |
416331ca | 4039 | ExprKind::Path(ref qself, ref path) => { |
487cf647 | 4040 | self.smart_resolve_path(expr.id, qself, path, PathSource::Expr(parent)); |
416331ca XL |
4041 | visit::walk_expr(self, expr); |
4042 | } | |
4043 | ||
6a06907d | 4044 | ExprKind::Struct(ref se) => { |
487cf647 | 4045 | self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct); |
416331ca XL |
4046 | visit::walk_expr(self, expr); |
4047 | } | |
4048 | ||
4049 | ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { | |
923072b8 FG |
4050 | match self.resolve_label(label.ident) { |
4051 | Ok((node_id, _)) => { | |
4052 | // Since this res is a label, it is never read. | |
4053 | self.r.label_res_map.insert(expr.id, node_id); | |
4054 | self.diagnostic_metadata.unused_labels.remove(&node_id); | |
4055 | } | |
4056 | Err(error) => { | |
4057 | self.report_error(label.ident.span, error); | |
4058 | } | |
416331ca XL |
4059 | } |
4060 | ||
4061 | // visit `break` argument if any | |
4062 | visit::walk_expr(self, expr); | |
4063 | } | |
4064 | ||
5869c6ff XL |
4065 | ExprKind::Break(None, Some(ref e)) => { |
4066 | // We use this instead of `visit::walk_expr` to keep the parent expr around for | |
4067 | // better diagnostics. | |
4068 | self.resolve_expr(e, Some(&expr)); | |
4069 | } | |
4070 | ||
94222f64 | 4071 | ExprKind::Let(ref pat, ref scrutinee, _) => { |
416331ca | 4072 | self.visit_expr(scrutinee); |
e1599b0c | 4073 | self.resolve_pattern_top(pat, PatternSource::Let); |
416331ca XL |
4074 | } |
4075 | ||
4076 | ExprKind::If(ref cond, ref then, ref opt_else) => { | |
49aad941 | 4077 | self.with_rib(ValueNS, RibKind::Normal, |this| { |
1b1a35ee | 4078 | let old = this.diagnostic_metadata.in_if_condition.replace(cond); |
e1599b0c | 4079 | this.visit_expr(cond); |
1b1a35ee | 4080 | this.diagnostic_metadata.in_if_condition = old; |
e1599b0c XL |
4081 | this.visit_block(then); |
4082 | }); | |
f9f354fc XL |
4083 | if let Some(expr) = opt_else { |
4084 | self.visit_expr(expr); | |
4085 | } | |
416331ca XL |
4086 | } |
4087 | ||
487cf647 FG |
4088 | ExprKind::Loop(ref block, label, _) => { |
4089 | self.resolve_labeled_block(label, expr.id, &block) | |
4090 | } | |
416331ca | 4091 | |
e1599b0c | 4092 | ExprKind::While(ref cond, ref block, label) => { |
416331ca | 4093 | self.with_resolved_label(label, expr.id, |this| { |
49aad941 | 4094 | this.with_rib(ValueNS, RibKind::Normal, |this| { |
a2a8927a | 4095 | let old = this.diagnostic_metadata.in_if_condition.replace(cond); |
e1599b0c | 4096 | this.visit_expr(cond); |
a2a8927a | 4097 | this.diagnostic_metadata.in_if_condition = old; |
e1599b0c XL |
4098 | this.visit_block(block); |
4099 | }) | |
416331ca XL |
4100 | }); |
4101 | } | |
4102 | ||
e1599b0c XL |
4103 | ExprKind::ForLoop(ref pat, ref iter_expr, ref block, label) => { |
4104 | self.visit_expr(iter_expr); | |
49aad941 | 4105 | self.with_rib(ValueNS, RibKind::Normal, |this| { |
e1599b0c XL |
4106 | this.resolve_pattern_top(pat, PatternSource::For); |
4107 | this.resolve_labeled_block(label, expr.id, block); | |
4108 | }); | |
416331ca XL |
4109 | } |
4110 | ||
4111 | ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block), | |
4112 | ||
4113 | // Equivalent to `visit::walk_expr` + passing some context to children. | |
4114 | ExprKind::Field(ref subexpression, _) => { | |
4115 | self.resolve_expr(subexpression, Some(expr)); | |
4116 | } | |
487cf647 | 4117 | ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => { |
2b03887a | 4118 | self.resolve_expr(receiver, Some(expr)); |
487cf647 FG |
4119 | for arg in args { |
4120 | self.resolve_expr(arg, None); | |
416331ca | 4121 | } |
487cf647 | 4122 | self.visit_path_segment(seg); |
416331ca XL |
4123 | } |
4124 | ||
4125 | ExprKind::Call(ref callee, ref arguments) => { | |
4126 | self.resolve_expr(callee, Some(expr)); | |
cdc7bbd5 | 4127 | let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default(); |
6a06907d XL |
4128 | for (idx, argument) in arguments.iter().enumerate() { |
4129 | // Constant arguments need to be treated as AnonConst since | |
4130 | // that is how they will be later lowered to HIR. | |
4131 | if const_args.contains(&idx) { | |
49aad941 FG |
4132 | self.resolve_anon_const_manual( |
4133 | argument.is_potential_trivial_const_arg(), | |
4134 | AnonConstKind::ConstArg(IsRepeatExpr::No), | |
4135 | |this| this.resolve_expr(argument, None), | |
6a06907d XL |
4136 | ); |
4137 | } else { | |
4138 | self.resolve_expr(argument, None); | |
4139 | } | |
416331ca XL |
4140 | } |
4141 | } | |
49aad941 | 4142 | ExprKind::Type(ref _type_expr, ref _ty) => { |
416331ca | 4143 | visit::walk_expr(self, expr); |
416331ca | 4144 | } |
487cf647 | 4145 | // `async |x| ...` gets desugared to `|x| async {...}`, so we need to |
416331ca XL |
4146 | // resolve the arguments within the proper scopes so that usages of them inside the |
4147 | // closure are detected as upvars rather than normal closure arg usages. | |
487cf647 FG |
4148 | ExprKind::Closure(box ast::Closure { |
4149 | asyncness: Async::Yes { .. }, | |
4150 | ref fn_decl, | |
4151 | ref body, | |
4152 | .. | |
4153 | }) => { | |
49aad941 FG |
4154 | self.with_rib(ValueNS, RibKind::Normal, |this| { |
4155 | this.with_label_rib(RibKind::ClosureOrAsync, |this| { | |
f035d41b XL |
4156 | // Resolve arguments: |
4157 | this.resolve_params(&fn_decl.inputs); | |
4158 | // No need to resolve return type -- | |
4159 | // the outer closure return type is `FnRetTy::Default`. | |
e1599b0c | 4160 | |
f035d41b XL |
4161 | // Now resolve the inner closure |
4162 | { | |
4163 | // No need to resolve arguments: the inner closure has none. | |
4164 | // Resolve the return type: | |
4165 | visit::walk_fn_ret_ty(this, &fn_decl.output); | |
4166 | // Resolve the body | |
4167 | this.visit_expr(body); | |
4168 | } | |
4169 | }) | |
e1599b0c | 4170 | }); |
416331ca | 4171 | } |
923072b8 | 4172 | // For closures, ClosureOrAsyncRibKind is added in visit_fn |
487cf647 FG |
4173 | ExprKind::Closure(box ast::Closure { |
4174 | binder: ClosureBinder::For { ref generic_params, span }, | |
4175 | .. | |
4176 | }) => { | |
064997fb FG |
4177 | self.with_generic_param_rib( |
4178 | &generic_params, | |
49aad941 | 4179 | RibKind::Normal, |
064997fb FG |
4180 | LifetimeRibKind::Generics { |
4181 | binder: expr.id, | |
4182 | kind: LifetimeBinderKind::Closure, | |
4183 | span, | |
4184 | }, | |
4185 | |this| visit::walk_expr(this, expr), | |
4186 | ); | |
4187 | } | |
923072b8 FG |
4188 | ExprKind::Closure(..) => visit::walk_expr(self, expr), |
4189 | ExprKind::Async(..) => { | |
49aad941 | 4190 | self.with_label_rib(RibKind::ClosureOrAsync, |this| visit::walk_expr(this, expr)); |
f035d41b | 4191 | } |
29967ef6 XL |
4192 | ExprKind::Repeat(ref elem, ref ct) => { |
4193 | self.visit_expr(elem); | |
49aad941 | 4194 | self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes)); |
04454e1e FG |
4195 | } |
4196 | ExprKind::ConstBlock(ref ct) => { | |
49aad941 | 4197 | self.resolve_anon_const(ct, AnonConstKind::InlineConst); |
29967ef6 | 4198 | } |
5099ac24 FG |
4199 | ExprKind::Index(ref elem, ref idx) => { |
4200 | self.resolve_expr(elem, Some(expr)); | |
4201 | self.visit_expr(idx); | |
4202 | } | |
487cf647 FG |
4203 | ExprKind::Assign(ref lhs, ref rhs, _) => { |
4204 | if !self.diagnostic_metadata.is_assign_rhs { | |
4205 | self.diagnostic_metadata.in_assignment = Some(expr); | |
4206 | } | |
4207 | self.visit_expr(lhs); | |
4208 | self.diagnostic_metadata.is_assign_rhs = true; | |
4209 | self.diagnostic_metadata.in_assignment = None; | |
4210 | self.visit_expr(rhs); | |
4211 | self.diagnostic_metadata.is_assign_rhs = false; | |
2b03887a | 4212 | } |
9c376795 FG |
4213 | ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => { |
4214 | self.diagnostic_metadata.in_range = Some((start, end)); | |
4215 | self.resolve_expr(start, Some(expr)); | |
4216 | self.resolve_expr(end, Some(expr)); | |
4217 | self.diagnostic_metadata.in_range = None; | |
4218 | } | |
416331ca XL |
4219 | _ => { |
4220 | visit::walk_expr(self, expr); | |
4221 | } | |
4222 | } | |
4223 | } | |
4224 | ||
dfeec247 | 4225 | fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) { |
e74abb32 | 4226 | match expr.kind { |
416331ca | 4227 | ExprKind::Field(_, ident) => { |
9ffffee4 FG |
4228 | // #6890: Even though you can't treat a method like a field, |
4229 | // we need to add any trait methods we find that match the | |
4230 | // field name so that we can do some nice error reporting | |
416331ca | 4231 | // later on in typeck. |
5869c6ff | 4232 | let traits = self.traits_in_scope(ident, ValueNS); |
3c0e092e | 4233 | self.r.trait_map.insert(expr.id, traits); |
416331ca | 4234 | } |
487cf647 | 4235 | ExprKind::MethodCall(ref call) => { |
dfeec247 | 4236 | debug!("(recording candidate traits for expr) recording traits for {}", expr.id); |
487cf647 | 4237 | let traits = self.traits_in_scope(call.seg.ident, ValueNS); |
3c0e092e | 4238 | self.r.trait_map.insert(expr.id, traits); |
416331ca XL |
4239 | } |
4240 | _ => { | |
4241 | // Nothing to do. | |
4242 | } | |
4243 | } | |
4244 | } | |
4245 | ||
5869c6ff XL |
4246 | fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> { |
4247 | self.r.traits_in_scope( | |
4248 | self.current_trait_ref.as_ref().map(|(module, _)| *module), | |
4249 | &self.parent_scope, | |
4250 | ident.span.ctxt(), | |
4251 | Some((ident.name, ns)), | |
4252 | ) | |
416331ca | 4253 | } |
2b03887a FG |
4254 | |
4255 | /// Construct the list of in-scope lifetime parameters for async lowering. | |
4256 | /// We include all lifetime parameters, either named or "Fresh". | |
4257 | /// The order of those parameters does not matter, as long as it is | |
4258 | /// deterministic. | |
4259 | fn record_lifetime_params_for_async( | |
4260 | &mut self, | |
4261 | fn_id: NodeId, | |
4262 | async_node_id: Option<(NodeId, Span)>, | |
4263 | ) { | |
4264 | if let Some((async_node_id, span)) = async_node_id { | |
4265 | let mut extra_lifetime_params = | |
4266 | self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); | |
4267 | for rib in self.lifetime_ribs.iter().rev() { | |
4268 | extra_lifetime_params.extend( | |
4269 | rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)), | |
4270 | ); | |
4271 | match rib.kind { | |
4272 | LifetimeRibKind::Item => break, | |
4273 | LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { | |
4274 | if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) { | |
4275 | extra_lifetime_params.extend(earlier_fresh); | |
4276 | } | |
4277 | } | |
4278 | LifetimeRibKind::Generics { .. } => {} | |
4279 | _ => { | |
4280 | // We are in a function definition. We should only find `Generics` | |
4281 | // and `AnonymousCreateParameter` inside the innermost `Item`. | |
4282 | span_bug!(span, "unexpected rib kind: {:?}", rib.kind) | |
4283 | } | |
4284 | } | |
4285 | } | |
4286 | self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); | |
4287 | } | |
4288 | } | |
9ffffee4 | 4289 | |
49aad941 | 4290 | fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> { |
9ffffee4 FG |
4291 | // FIXME: This caching may be incorrect in case of multiple `macro_rules` |
4292 | // items with the same name in the same module. | |
4293 | // Also hygiene is not considered. | |
4294 | let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions); | |
49aad941 | 4295 | let res = *doc_link_resolutions |
9ffffee4 FG |
4296 | .entry(self.parent_scope.module.nearest_parent_mod().expect_local()) |
4297 | .or_default() | |
4298 | .entry((Symbol::intern(path_str), ns)) | |
4299 | .or_insert_with_key(|(path, ns)| { | |
4300 | let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope); | |
4301 | if let Some(res) = res | |
4302 | && let Some(def_id) = res.opt_def_id() | |
4303 | && !def_id.is_local() | |
4304 | && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro) | |
4305 | && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) { | |
4306 | // Encoding foreign def ids in proc macro crate metadata will ICE. | |
4307 | return None; | |
4308 | } | |
4309 | res | |
49aad941 | 4310 | }); |
9ffffee4 FG |
4311 | self.r.doc_link_resolutions = doc_link_resolutions; |
4312 | res | |
4313 | } | |
4314 | ||
4315 | fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) { | |
4316 | match self.r.tcx.sess.opts.resolve_doc_links { | |
4317 | ResolveDocLinks::None => return, | |
4318 | ResolveDocLinks::ExportedMetadata | |
4319 | if !self.r.tcx.sess.crate_types().iter().copied().any(CrateType::has_metadata) | |
4320 | || !maybe_exported.eval(self.r) => | |
4321 | { | |
4322 | return; | |
4323 | } | |
353b0b11 FG |
4324 | ResolveDocLinks::Exported |
4325 | if !maybe_exported.eval(self.r) | |
4326 | && !rustdoc::has_primitive_or_keyword_docs(attrs) => | |
4327 | { | |
9ffffee4 FG |
4328 | return; |
4329 | } | |
4330 | ResolveDocLinks::ExportedMetadata | |
4331 | | ResolveDocLinks::Exported | |
4332 | | ResolveDocLinks::All => {} | |
4333 | } | |
4334 | ||
4335 | if !attrs.iter().any(|attr| attr.may_have_doc_links()) { | |
4336 | return; | |
4337 | } | |
4338 | ||
4339 | let mut need_traits_in_scope = false; | |
4340 | for path_str in rustdoc::attrs_to_preprocessed_links(attrs) { | |
4341 | // Resolve all namespaces due to no disambiguator or for diagnostics. | |
4342 | let mut any_resolved = false; | |
4343 | let mut need_assoc = false; | |
4344 | for ns in [TypeNS, ValueNS, MacroNS] { | |
49aad941 FG |
4345 | if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) { |
4346 | // Rustdoc ignores tool attribute resolutions and attempts | |
4347 | // to resolve their prefixes for diagnostics. | |
4348 | any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool)); | |
9ffffee4 FG |
4349 | } else if ns != MacroNS { |
4350 | need_assoc = true; | |
4351 | } | |
4352 | } | |
4353 | ||
4354 | // Resolve all prefixes for type-relative resolution or for diagnostics. | |
4355 | if need_assoc || !any_resolved { | |
4356 | let mut path = &path_str[..]; | |
4357 | while let Some(idx) = path.rfind("::") { | |
4358 | path = &path[..idx]; | |
4359 | need_traits_in_scope = true; | |
4360 | for ns in [TypeNS, ValueNS, MacroNS] { | |
4361 | self.resolve_and_cache_rustdoc_path(path, ns); | |
4362 | } | |
4363 | } | |
4364 | } | |
4365 | } | |
4366 | ||
4367 | if need_traits_in_scope { | |
4368 | // FIXME: hygiene is not considered. | |
4369 | let mut doc_link_traits_in_scope = std::mem::take(&mut self.r.doc_link_traits_in_scope); | |
4370 | doc_link_traits_in_scope | |
4371 | .entry(self.parent_scope.module.nearest_parent_mod().expect_local()) | |
4372 | .or_insert_with(|| { | |
4373 | self.r | |
4374 | .traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None) | |
4375 | .into_iter() | |
4376 | .filter_map(|tr| { | |
4377 | if !tr.def_id.is_local() | |
4378 | && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro) | |
4379 | && matches!( | |
4380 | self.r.tcx.sess.opts.resolve_doc_links, | |
4381 | ResolveDocLinks::ExportedMetadata | |
4382 | ) | |
4383 | { | |
4384 | // Encoding foreign def ids in proc macro crate metadata will ICE. | |
4385 | return None; | |
4386 | } | |
4387 | Some(tr.def_id) | |
4388 | }) | |
4389 | .collect() | |
4390 | }); | |
4391 | self.r.doc_link_traits_in_scope = doc_link_traits_in_scope; | |
4392 | } | |
4393 | } | |
04454e1e | 4394 | } |
94222f64 | 4395 | |
9ffffee4 FG |
4396 | struct LifetimeCountVisitor<'a, 'b, 'tcx> { |
4397 | r: &'b mut Resolver<'a, 'tcx>, | |
04454e1e FG |
4398 | } |
4399 | ||
4400 | /// Walks the whole crate in DFS order, visiting each item, counting the declared number of | |
4401 | /// lifetime generic parameters. | |
9ffffee4 | 4402 | impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> { |
04454e1e FG |
4403 | fn visit_item(&mut self, item: &'ast Item) { |
4404 | match &item.kind { | |
4405 | ItemKind::TyAlias(box TyAlias { ref generics, .. }) | |
4406 | | ItemKind::Fn(box Fn { ref generics, .. }) | |
4407 | | ItemKind::Enum(_, ref generics) | |
4408 | | ItemKind::Struct(_, ref generics) | |
4409 | | ItemKind::Union(_, ref generics) | |
4410 | | ItemKind::Impl(box Impl { ref generics, .. }) | |
4411 | | ItemKind::Trait(box Trait { ref generics, .. }) | |
4412 | | ItemKind::TraitAlias(ref generics, _) => { | |
4413 | let def_id = self.r.local_def_id(item.id); | |
4414 | let count = generics | |
4415 | .params | |
4416 | .iter() | |
4417 | .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. })) | |
4418 | .count(); | |
4419 | self.r.item_generics_num_lifetimes.insert(def_id, count); | |
4420 | } | |
4421 | ||
4422 | ItemKind::Mod(..) | |
4423 | | ItemKind::ForeignMod(..) | |
4424 | | ItemKind::Static(..) | |
4425 | | ItemKind::Const(..) | |
4426 | | ItemKind::Use(..) | |
4427 | | ItemKind::ExternCrate(..) | |
4428 | | ItemKind::MacroDef(..) | |
4429 | | ItemKind::GlobalAsm(..) | |
4430 | | ItemKind::MacCall(..) => {} | |
4431 | } | |
4432 | visit::walk_item(self, item) | |
94222f64 | 4433 | } |
416331ca XL |
4434 | } |
4435 | ||
9ffffee4 | 4436 | impl<'a, 'tcx> Resolver<'a, 'tcx> { |
416331ca | 4437 | pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { |
04454e1e | 4438 | visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate); |
416331ca | 4439 | let mut late_resolution_visitor = LateResolutionVisitor::new(self); |
9ffffee4 | 4440 | late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); |
416331ca | 4441 | visit::walk_crate(&mut late_resolution_visitor, krate); |
e74abb32 XL |
4442 | for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() { |
4443 | self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); | |
416331ca XL |
4444 | } |
4445 | } | |
4446 | } |