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