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