]>
Commit | Line | Data |
---|---|---|
c34b1796 | 1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | #![crate_name = "rustc_resolve"] | |
e9174d1e | 12 | #![unstable(feature = "rustc_private", issue = "27812")] |
1a4d82fc JJ |
13 | #![crate_type = "dylib"] |
14 | #![crate_type = "rlib"] | |
e9174d1e | 15 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", |
62682a34 | 16 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", |
e9174d1e | 17 | html_root_url = "https://doc.rust-lang.org/nightly/")] |
7453a54e | 18 | #![cfg_attr(not(stage0), deny(warnings))] |
1a4d82fc | 19 | |
d9579d0f | 20 | #![feature(associated_consts)] |
54a0048b | 21 | #![feature(borrow_state)] |
c30ab7b3 | 22 | #![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))] |
1a4d82fc | 23 | #![feature(rustc_diagnostic_macros)] |
85aaf69f SL |
24 | #![feature(rustc_private)] |
25 | #![feature(staged_api)] | |
1a4d82fc | 26 | |
92a42be0 SL |
27 | #[macro_use] |
28 | extern crate log; | |
29 | #[macro_use] | |
30 | extern crate syntax; | |
3157f602 XL |
31 | extern crate syntax_pos; |
32 | extern crate rustc_errors as errors; | |
9cc50fc6 | 33 | extern crate arena; |
92a42be0 | 34 | #[macro_use] |
1a4d82fc JJ |
35 | extern crate rustc; |
36 | ||
1a4d82fc | 37 | use self::Namespace::*; |
1a4d82fc JJ |
38 | use self::ResolveResult::*; |
39 | use self::FallbackSuggestion::*; | |
40 | use self::TypeParameters::*; | |
41 | use self::RibKind::*; | |
1a4d82fc JJ |
42 | use self::UseLexicalScopeFlag::*; |
43 | use self::ModulePrefixResult::*; | |
1a4d82fc | 44 | |
c30ab7b3 | 45 | use rustc::hir::map::{Definitions, DefCollector}; |
a7813a04 | 46 | use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; |
9e0c209e | 47 | use rustc::middle::cstore::CrateLoader; |
1a4d82fc JJ |
48 | use rustc::session::Session; |
49 | use rustc::lint; | |
54a0048b | 50 | use rustc::hir::def::*; |
9e0c209e | 51 | use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; |
a7813a04 | 52 | use rustc::ty; |
a7813a04 XL |
53 | use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; |
54 | use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; | |
1a4d82fc | 55 | |
c30ab7b3 | 56 | use syntax::ext::hygiene::{Mark, SyntaxContext}; |
7453a54e | 57 | use syntax::ast::{self, FloatTy}; |
c30ab7b3 SL |
58 | use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, SpannedIdent, IntTy, UintTy}; |
59 | use syntax::ext::base::SyntaxExtension; | |
a7813a04 | 60 | use syntax::parse::token::{self, keywords}; |
9cc50fc6 | 61 | use syntax::util::lev_distance::find_best_match_for_name; |
e9174d1e | 62 | |
a7813a04 | 63 | use syntax::visit::{self, FnKind, Visitor}; |
9e0c209e | 64 | use syntax::attr; |
a7813a04 XL |
65 | use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind}; |
66 | use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics}; | |
67 | use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; | |
3157f602 XL |
68 | use syntax::ast::{Local, Mutability, Pat, PatKind, Path}; |
69 | use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind}; | |
70 | ||
9e0c209e | 71 | use syntax_pos::{Span, DUMMY_SP}; |
3157f602 | 72 | use errors::DiagnosticBuilder; |
1a4d82fc | 73 | |
1a4d82fc JJ |
74 | use std::cell::{Cell, RefCell}; |
75 | use std::fmt; | |
76 | use std::mem::replace; | |
c30ab7b3 | 77 | use std::rc::Rc; |
85aaf69f | 78 | |
7453a54e | 79 | use resolve_imports::{ImportDirective, NameResolution}; |
c30ab7b3 | 80 | use macros::{InvocationData, LegacyBinding, LegacyScope}; |
c34b1796 | 81 | |
85aaf69f SL |
82 | // NB: This module needs to be declared first so diagnostics are |
83 | // registered before they are used. | |
54a0048b | 84 | mod diagnostics; |
1a4d82fc | 85 | |
9e0c209e | 86 | mod macros; |
1a4d82fc | 87 | mod check_unused; |
1a4d82fc | 88 | mod build_reduced_graph; |
c34b1796 | 89 | mod resolve_imports; |
1a4d82fc | 90 | |
92a42be0 SL |
91 | enum SuggestionType { |
92 | Macro(String), | |
9cc50fc6 | 93 | Function(token::InternedString), |
92a42be0 SL |
94 | NotFound, |
95 | } | |
96 | ||
7453a54e | 97 | /// Candidates for a name resolution failure |
54a0048b | 98 | struct SuggestedCandidates { |
7453a54e SL |
99 | name: String, |
100 | candidates: Vec<Path>, | |
101 | } | |
102 | ||
54a0048b | 103 | enum ResolutionError<'a> { |
c1a9b12d SL |
104 | /// error E0401: can't use type parameters from outer function |
105 | TypeParametersFromOuterFunction, | |
106 | /// error E0402: cannot use an outer type parameter in this context | |
107 | OuterTypeParameterContext, | |
108 | /// error E0403: the name is already used for a type parameter in this type parameter list | |
9e0c209e | 109 | NameAlreadyUsedInTypeParameterList(Name, &'a Span), |
c1a9b12d SL |
110 | /// error E0404: is not a trait |
111 | IsNotATrait(&'a str), | |
112 | /// error E0405: use of undeclared trait name | |
7453a54e | 113 | UndeclaredTraitName(&'a str, SuggestedCandidates), |
c1a9b12d SL |
114 | /// error E0407: method is not a member of trait |
115 | MethodNotMemberOfTrait(Name, &'a str), | |
116 | /// error E0437: type is not a member of trait | |
117 | TypeNotMemberOfTrait(Name, &'a str), | |
118 | /// error E0438: const is not a member of trait | |
119 | ConstNotMemberOfTrait(Name, &'a str), | |
a7813a04 XL |
120 | /// error E0408: variable `{}` from pattern #{} is not bound in pattern #{} |
121 | VariableNotBoundInPattern(Name, usize, usize), | |
c1a9b12d | 122 | /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1 |
9e0c209e | 123 | VariableBoundWithDifferentMode(Name, usize, Span), |
c1a9b12d SL |
124 | /// error E0411: use of `Self` outside of an impl or trait |
125 | SelfUsedOutsideImplOrTrait, | |
126 | /// error E0412: use of undeclared | |
7453a54e | 127 | UseOfUndeclared(&'a str, &'a str, SuggestedCandidates), |
c1a9b12d SL |
128 | /// error E0415: identifier is bound more than once in this parameter list |
129 | IdentifierBoundMoreThanOnceInParameterList(&'a str), | |
130 | /// error E0416: identifier is bound more than once in the same pattern | |
131 | IdentifierBoundMoreThanOnceInSamePattern(&'a str), | |
c1a9b12d SL |
132 | /// error E0423: is a struct variant name, but this expression uses it like a function name |
133 | StructVariantUsedAsFunction(&'a str), | |
134 | /// error E0424: `self` is not available in a static method | |
135 | SelfNotAvailableInStaticMethod, | |
136 | /// error E0425: unresolved name | |
3157f602 XL |
137 | UnresolvedName { |
138 | path: &'a str, | |
139 | message: &'a str, | |
140 | context: UnresolvedNameContext<'a>, | |
141 | is_static_method: bool, | |
142 | is_field: bool, | |
143 | def: Def, | |
144 | }, | |
c1a9b12d SL |
145 | /// error E0426: use of undeclared label |
146 | UndeclaredLabel(&'a str), | |
c1a9b12d SL |
147 | /// error E0429: `self` imports are only allowed within a { } list |
148 | SelfImportsOnlyAllowedWithin, | |
149 | /// error E0430: `self` import can only appear once in the list | |
150 | SelfImportCanOnlyAppearOnceInTheList, | |
151 | /// error E0431: `self` import can only appear in an import list with a non-empty prefix | |
152 | SelfImportOnlyInImportListWithNonEmptyPrefix, | |
153 | /// error E0432: unresolved import | |
e9174d1e | 154 | UnresolvedImport(Option<(&'a str, &'a str)>), |
c1a9b12d SL |
155 | /// error E0433: failed to resolve |
156 | FailedToResolve(&'a str), | |
157 | /// error E0434: can't capture dynamic environment in a fn item | |
158 | CannotCaptureDynamicEnvironmentInFnItem, | |
159 | /// error E0435: attempt to use a non-constant value in a constant | |
160 | AttemptToUseNonConstantValueInConstant, | |
3157f602 | 161 | /// error E0530: X bindings cannot shadow Ys |
5bcae85e | 162 | BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>), |
3157f602 XL |
163 | /// error E0531: unresolved pattern path kind `name` |
164 | PatPathUnresolved(&'a str, &'a Path), | |
165 | /// error E0532: expected pattern path kind, found another pattern path kind | |
166 | PatPathUnexpected(&'a str, &'a str, &'a Path), | |
c1a9b12d SL |
167 | } |
168 | ||
9cc50fc6 SL |
169 | /// Context of where `ResolutionError::UnresolvedName` arose. |
170 | #[derive(Clone, PartialEq, Eq, Debug)] | |
a7813a04 XL |
171 | enum UnresolvedNameContext<'a> { |
172 | /// `PathIsMod(parent)` indicates that a given path, used in | |
9cc50fc6 | 173 | /// expression context, actually resolved to a module rather than |
a7813a04 XL |
174 | /// a value. The optional expression attached to the variant is the |
175 | /// the parent of the erroneous path expression. | |
176 | PathIsMod(Option<&'a Expr>), | |
9cc50fc6 SL |
177 | |
178 | /// `Other` means we have no extra information about the context | |
179 | /// of the unresolved name error. (Maybe we could eliminate all | |
180 | /// such cases; but for now, this is an information-free default.) | |
181 | Other, | |
182 | } | |
183 | ||
a7813a04 | 184 | fn resolve_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, |
3157f602 | 185 | span: syntax_pos::Span, |
a7813a04 | 186 | resolution_error: ResolutionError<'c>) { |
9cc50fc6 SL |
187 | resolve_struct_error(resolver, span, resolution_error).emit(); |
188 | } | |
189 | ||
a7813a04 | 190 | fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, |
3157f602 | 191 | span: syntax_pos::Span, |
a7813a04 XL |
192 | resolution_error: ResolutionError<'c>) |
193 | -> DiagnosticBuilder<'a> { | |
c1a9b12d | 194 | if !resolver.emit_errors { |
9cc50fc6 | 195 | return resolver.session.diagnostic().struct_dummy(); |
c1a9b12d | 196 | } |
9cc50fc6 | 197 | |
c1a9b12d SL |
198 | match resolution_error { |
199 | ResolutionError::TypeParametersFromOuterFunction => { | |
a7813a04 XL |
200 | let mut err = struct_span_err!(resolver.session, |
201 | span, | |
202 | E0401, | |
203 | "can't use type parameters from outer function; \ | |
204 | try using a local type parameter instead"); | |
205 | err.span_label(span, &format!("use of type variable from outer function")); | |
206 | err | |
92a42be0 | 207 | } |
c1a9b12d | 208 | ResolutionError::OuterTypeParameterContext => { |
9cc50fc6 SL |
209 | struct_span_err!(resolver.session, |
210 | span, | |
211 | E0402, | |
212 | "cannot use an outer type parameter in this context") | |
92a42be0 | 213 | } |
9e0c209e SL |
214 | ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => { |
215 | let mut err = struct_span_err!(resolver.session, | |
216 | span, | |
217 | E0403, | |
218 | "the name `{}` is already used for a type parameter \ | |
219 | in this type parameter list", | |
220 | name); | |
221 | err.span_label(span, &format!("already used")); | |
222 | err.span_label(first_use_span.clone(), &format!("first use of `{}`", name)); | |
223 | err | |
224 | ||
92a42be0 | 225 | } |
c1a9b12d | 226 | ResolutionError::IsNotATrait(name) => { |
5bcae85e SL |
227 | let mut err = struct_span_err!(resolver.session, |
228 | span, | |
229 | E0404, | |
230 | "`{}` is not a trait", | |
231 | name); | |
232 | err.span_label(span, &format!("not a trait")); | |
233 | err | |
92a42be0 | 234 | } |
7453a54e SL |
235 | ResolutionError::UndeclaredTraitName(name, candidates) => { |
236 | let mut err = struct_span_err!(resolver.session, | |
237 | span, | |
238 | E0405, | |
239 | "trait `{}` is not in scope", | |
240 | name); | |
a7813a04 XL |
241 | show_candidates(&mut err, &candidates); |
242 | err.span_label(span, &format!("`{}` is not in scope", name)); | |
7453a54e | 243 | err |
92a42be0 | 244 | } |
c1a9b12d | 245 | ResolutionError::MethodNotMemberOfTrait(method, trait_) => { |
9e0c209e SL |
246 | let mut err = struct_span_err!(resolver.session, |
247 | span, | |
248 | E0407, | |
249 | "method `{}` is not a member of trait `{}`", | |
250 | method, | |
251 | trait_); | |
252 | err.span_label(span, &format!("not a member of trait `{}`", trait_)); | |
253 | err | |
92a42be0 | 254 | } |
c1a9b12d | 255 | ResolutionError::TypeNotMemberOfTrait(type_, trait_) => { |
9e0c209e | 256 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
257 | span, |
258 | E0437, | |
259 | "type `{}` is not a member of trait `{}`", | |
260 | type_, | |
9e0c209e SL |
261 | trait_); |
262 | err.span_label(span, &format!("not a member of trait `{}`", trait_)); | |
263 | err | |
92a42be0 | 264 | } |
c1a9b12d | 265 | ResolutionError::ConstNotMemberOfTrait(const_, trait_) => { |
9e0c209e | 266 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
267 | span, |
268 | E0438, | |
269 | "const `{}` is not a member of trait `{}`", | |
270 | const_, | |
9e0c209e SL |
271 | trait_); |
272 | err.span_label(span, &format!("not a member of trait `{}`", trait_)); | |
273 | err | |
92a42be0 | 274 | } |
a7813a04 | 275 | ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => { |
c30ab7b3 | 276 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
277 | span, |
278 | E0408, | |
a7813a04 | 279 | "variable `{}` from pattern #{} is not bound in pattern #{}", |
9cc50fc6 | 280 | variable_name, |
a7813a04 | 281 | from, |
c30ab7b3 SL |
282 | to); |
283 | err.span_label(span, &format!("pattern doesn't bind `{}`", variable_name)); | |
284 | err | |
92a42be0 | 285 | } |
9e0c209e SL |
286 | ResolutionError::VariableBoundWithDifferentMode(variable_name, |
287 | pattern_number, | |
288 | first_binding_span) => { | |
289 | let mut err = struct_span_err!(resolver.session, | |
9cc50fc6 SL |
290 | span, |
291 | E0409, | |
292 | "variable `{}` is bound with different mode in pattern #{} than in \ | |
293 | pattern #1", | |
294 | variable_name, | |
9e0c209e SL |
295 | pattern_number); |
296 | err.span_label(span, &format!("bound in different ways")); | |
297 | err.span_label(first_binding_span, &format!("first binding")); | |
298 | err | |
92a42be0 | 299 | } |
c1a9b12d | 300 | ResolutionError::SelfUsedOutsideImplOrTrait => { |
a7813a04 XL |
301 | let mut err = struct_span_err!(resolver.session, |
302 | span, | |
303 | E0411, | |
304 | "use of `Self` outside of an impl or trait"); | |
305 | err.span_label(span, &format!("used outside of impl or trait")); | |
306 | err | |
92a42be0 | 307 | } |
7453a54e SL |
308 | ResolutionError::UseOfUndeclared(kind, name, candidates) => { |
309 | let mut err = struct_span_err!(resolver.session, | |
310 | span, | |
311 | E0412, | |
312 | "{} `{}` is undefined or not in scope", | |
313 | kind, | |
314 | name); | |
a7813a04 XL |
315 | show_candidates(&mut err, &candidates); |
316 | err.span_label(span, &format!("undefined or not in scope")); | |
7453a54e | 317 | err |
92a42be0 | 318 | } |
c1a9b12d | 319 | ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { |
a7813a04 | 320 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
321 | span, |
322 | E0415, | |
323 | "identifier `{}` is bound more than once in this parameter list", | |
a7813a04 XL |
324 | identifier); |
325 | err.span_label(span, &format!("used as parameter more than once")); | |
326 | err | |
92a42be0 | 327 | } |
c1a9b12d | 328 | ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { |
a7813a04 | 329 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
330 | span, |
331 | E0416, | |
332 | "identifier `{}` is bound more than once in the same pattern", | |
a7813a04 XL |
333 | identifier); |
334 | err.span_label(span, &format!("used in a pattern more than once")); | |
335 | err | |
92a42be0 | 336 | } |
c1a9b12d | 337 | ResolutionError::StructVariantUsedAsFunction(path_name) => { |
9e0c209e | 338 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
339 | span, |
340 | E0423, | |
341 | "`{}` is the name of a struct or struct variant, but this expression \ | |
342 | uses it like a function name", | |
9e0c209e SL |
343 | path_name); |
344 | err.span_label(span, &format!("struct called like a function")); | |
345 | err | |
92a42be0 | 346 | } |
c1a9b12d | 347 | ResolutionError::SelfNotAvailableInStaticMethod => { |
9e0c209e | 348 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
349 | span, |
350 | E0424, | |
9e0c209e SL |
351 | "`self` is not available in a static method"); |
352 | err.span_label(span, &format!("not available in static method")); | |
353 | err.note(&format!("maybe a `self` argument is missing?")); | |
354 | err | |
9cc50fc6 | 355 | } |
3157f602 XL |
356 | ResolutionError::UnresolvedName { path, message: msg, context, is_static_method, |
357 | is_field, def } => { | |
9cc50fc6 SL |
358 | let mut err = struct_span_err!(resolver.session, |
359 | span, | |
360 | E0425, | |
9e0c209e SL |
361 | "unresolved name `{}`", |
362 | path); | |
363 | if msg != "" { | |
364 | err.span_label(span, &msg); | |
365 | } else { | |
366 | err.span_label(span, &format!("unresolved name")); | |
367 | } | |
368 | ||
9cc50fc6 | 369 | match context { |
3157f602 XL |
370 | UnresolvedNameContext::Other => { |
371 | if msg.is_empty() && is_static_method && is_field { | |
372 | err.help("this is an associated function, you don't have access to \ | |
373 | this type's fields or methods"); | |
374 | } | |
375 | } | |
a7813a04 XL |
376 | UnresolvedNameContext::PathIsMod(parent) => { |
377 | err.help(&match parent.map(|parent| &parent.node) { | |
378 | Some(&ExprKind::Field(_, ident)) => { | |
3157f602 | 379 | format!("to reference an item from the `{module}` module, \ |
a7813a04 XL |
380 | use `{module}::{ident}`", |
381 | module = path, | |
382 | ident = ident.node) | |
9cc50fc6 | 383 | } |
9e0c209e | 384 | Some(&ExprKind::MethodCall(ident, ..)) => { |
3157f602 | 385 | format!("to call a function from the `{module}` module, \ |
a7813a04 XL |
386 | use `{module}::{ident}(..)`", |
387 | module = path, | |
388 | ident = ident.node) | |
389 | } | |
390 | _ => { | |
3157f602 XL |
391 | format!("{def} `{module}` cannot be used as an expression", |
392 | def = def.kind_name(), | |
a7813a04 XL |
393 | module = path) |
394 | } | |
395 | }); | |
9cc50fc6 SL |
396 | } |
397 | } | |
398 | err | |
92a42be0 | 399 | } |
c1a9b12d | 400 | ResolutionError::UndeclaredLabel(name) => { |
9e0c209e SL |
401 | let mut err = struct_span_err!(resolver.session, |
402 | span, | |
403 | E0426, | |
404 | "use of undeclared label `{}`", | |
405 | name); | |
406 | err.span_label(span, &format!("undeclared label `{}`",&name)); | |
407 | err | |
92a42be0 | 408 | } |
c1a9b12d | 409 | ResolutionError::SelfImportsOnlyAllowedWithin => { |
9cc50fc6 SL |
410 | struct_span_err!(resolver.session, |
411 | span, | |
412 | E0429, | |
413 | "{}", | |
414 | "`self` imports are only allowed within a { } list") | |
92a42be0 | 415 | } |
c1a9b12d | 416 | ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { |
9cc50fc6 SL |
417 | struct_span_err!(resolver.session, |
418 | span, | |
419 | E0430, | |
420 | "`self` import can only appear once in the list") | |
92a42be0 | 421 | } |
c1a9b12d | 422 | ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { |
9cc50fc6 SL |
423 | struct_span_err!(resolver.session, |
424 | span, | |
425 | E0431, | |
426 | "`self` import can only appear in an import list with a \ | |
427 | non-empty prefix") | |
c1a9b12d SL |
428 | } |
429 | ResolutionError::UnresolvedImport(name) => { | |
430 | let msg = match name { | |
9e0c209e | 431 | Some((n, _)) => format!("unresolved import `{}`", n), |
92a42be0 | 432 | None => "unresolved import".to_owned(), |
c1a9b12d | 433 | }; |
9e0c209e SL |
434 | let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg); |
435 | if let Some((_, p)) = name { | |
436 | err.span_label(span, &p); | |
437 | } | |
438 | err | |
92a42be0 | 439 | } |
c1a9b12d | 440 | ResolutionError::FailedToResolve(msg) => { |
5bcae85e SL |
441 | let mut err = struct_span_err!(resolver.session, span, E0433, |
442 | "failed to resolve. {}", msg); | |
443 | err.span_label(span, &msg); | |
444 | err | |
92a42be0 | 445 | } |
c1a9b12d | 446 | ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { |
9cc50fc6 SL |
447 | struct_span_err!(resolver.session, |
448 | span, | |
449 | E0434, | |
450 | "{}", | |
451 | "can't capture dynamic environment in a fn item; use the || { ... } \ | |
452 | closure form instead") | |
92a42be0 SL |
453 | } |
454 | ResolutionError::AttemptToUseNonConstantValueInConstant => { | |
9e0c209e | 455 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
456 | span, |
457 | E0435, | |
9e0c209e SL |
458 | "attempt to use a non-constant value in a constant"); |
459 | err.span_label(span, &format!("non-constant used with constant")); | |
460 | err | |
92a42be0 | 461 | } |
5bcae85e | 462 | ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => { |
9e0c209e | 463 | let shadows_what = PathResolution::new(binding.def()).kind_name(); |
3157f602 XL |
464 | let mut err = struct_span_err!(resolver.session, |
465 | span, | |
466 | E0530, | |
467 | "{}s cannot shadow {}s", what_binding, shadows_what); | |
468 | err.span_label(span, &format!("cannot be named the same as a {}", shadows_what)); | |
5bcae85e SL |
469 | let participle = if binding.is_import() { "imported" } else { "defined" }; |
470 | let msg = &format!("a {} `{}` is {} here", shadows_what, name, participle); | |
471 | err.span_label(binding.span, msg); | |
3157f602 XL |
472 | err |
473 | } | |
474 | ResolutionError::PatPathUnresolved(expected_what, path) => { | |
475 | struct_span_err!(resolver.session, | |
476 | span, | |
477 | E0531, | |
478 | "unresolved {} `{}`", | |
479 | expected_what, | |
c30ab7b3 | 480 | path) |
3157f602 XL |
481 | } |
482 | ResolutionError::PatPathUnexpected(expected_what, found_what, path) => { | |
483 | struct_span_err!(resolver.session, | |
484 | span, | |
485 | E0532, | |
486 | "expected {}, found {} `{}`", | |
487 | expected_what, | |
488 | found_what, | |
c30ab7b3 | 489 | path) |
3157f602 | 490 | } |
c1a9b12d SL |
491 | } |
492 | } | |
493 | ||
c34b1796 | 494 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
495 | struct BindingInfo { |
496 | span: Span, | |
497 | binding_mode: BindingMode, | |
498 | } | |
499 | ||
500 | // Map from the name in a pattern to its binding mode. | |
c30ab7b3 | 501 | type BindingMap = FnvHashMap<Ident, BindingInfo>; |
1a4d82fc | 502 | |
3157f602 XL |
503 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
504 | enum PatternSource { | |
505 | Match, | |
506 | IfLet, | |
507 | WhileLet, | |
508 | Let, | |
509 | For, | |
510 | FnParam, | |
511 | } | |
512 | ||
513 | impl PatternSource { | |
514 | fn is_refutable(self) -> bool { | |
515 | match self { | |
516 | PatternSource::Match | PatternSource::IfLet | PatternSource::WhileLet => true, | |
517 | PatternSource::Let | PatternSource::For | PatternSource::FnParam => false, | |
518 | } | |
519 | } | |
520 | fn descr(self) -> &'static str { | |
521 | match self { | |
522 | PatternSource::Match => "match binding", | |
523 | PatternSource::IfLet => "if let binding", | |
524 | PatternSource::WhileLet => "while let binding", | |
525 | PatternSource::Let => "let binding", | |
526 | PatternSource::For => "for binding", | |
527 | PatternSource::FnParam => "function parameter", | |
528 | } | |
529 | } | |
1a4d82fc JJ |
530 | } |
531 | ||
c34b1796 | 532 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
e9174d1e | 533 | pub enum Namespace { |
1a4d82fc | 534 | TypeNS, |
92a42be0 | 535 | ValueNS, |
1a4d82fc JJ |
536 | } |
537 | ||
3157f602 | 538 | impl<'a> Visitor for Resolver<'a> { |
1a4d82fc JJ |
539 | fn visit_item(&mut self, item: &Item) { |
540 | self.resolve_item(item); | |
541 | } | |
542 | fn visit_arm(&mut self, arm: &Arm) { | |
543 | self.resolve_arm(arm); | |
544 | } | |
545 | fn visit_block(&mut self, block: &Block) { | |
546 | self.resolve_block(block); | |
547 | } | |
548 | fn visit_expr(&mut self, expr: &Expr) { | |
a7813a04 | 549 | self.resolve_expr(expr, None); |
1a4d82fc JJ |
550 | } |
551 | fn visit_local(&mut self, local: &Local) { | |
552 | self.resolve_local(local); | |
553 | } | |
554 | fn visit_ty(&mut self, ty: &Ty) { | |
555 | self.resolve_type(ty); | |
556 | } | |
a7813a04 | 557 | fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::TraitBoundModifier) { |
c34b1796 AL |
558 | match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) { |
559 | Ok(def) => self.record_def(tref.trait_ref.ref_id, def), | |
92a42be0 SL |
560 | Err(_) => { |
561 | // error already reported | |
9cc50fc6 | 562 | self.record_def(tref.trait_ref.ref_id, err_path_resolution()) |
92a42be0 | 563 | } |
c34b1796 | 564 | } |
a7813a04 | 565 | visit::walk_poly_trait_ref(self, tref, m); |
c34b1796 | 566 | } |
92a42be0 | 567 | fn visit_variant(&mut self, |
a7813a04 | 568 | variant: &ast::Variant, |
92a42be0 SL |
569 | generics: &Generics, |
570 | item_id: ast::NodeId) { | |
c34b1796 AL |
571 | if let Some(ref dis_expr) = variant.node.disr_expr { |
572 | // resolve the discriminator expr as a constant | |
573 | self.with_constant_rib(|this| { | |
92a42be0 | 574 | this.visit_expr(dis_expr); |
c34b1796 AL |
575 | }); |
576 | } | |
1a4d82fc | 577 | |
a7813a04 | 578 | // `visit::walk_variant` without the discriminant expression. |
92a42be0 SL |
579 | self.visit_variant_data(&variant.node.data, |
580 | variant.node.name, | |
581 | generics, | |
582 | item_id, | |
583 | variant.span); | |
c34b1796 | 584 | } |
a7813a04 | 585 | fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { |
c34b1796 | 586 | let type_parameters = match foreign_item.node { |
a7813a04 | 587 | ForeignItemKind::Fn(_, ref generics) => { |
9e0c209e | 588 | HasTypeParameters(generics, ItemRibKind) |
c34b1796 | 589 | } |
a7813a04 | 590 | ForeignItemKind::Static(..) => NoTypeParameters, |
c34b1796 AL |
591 | }; |
592 | self.with_type_parameter_rib(type_parameters, |this| { | |
a7813a04 | 593 | visit::walk_foreign_item(this, foreign_item); |
c34b1796 AL |
594 | }); |
595 | } | |
596 | fn visit_fn(&mut self, | |
3157f602 XL |
597 | function_kind: FnKind, |
598 | declaration: &FnDecl, | |
599 | block: &Block, | |
c34b1796 AL |
600 | _: Span, |
601 | node_id: NodeId) { | |
602 | let rib_kind = match function_kind { | |
9e0c209e | 603 | FnKind::ItemFn(_, generics, ..) => { |
c34b1796 AL |
604 | self.visit_generics(generics); |
605 | ItemRibKind | |
606 | } | |
a7813a04 | 607 | FnKind::Method(_, sig, _) => { |
c34b1796 | 608 | self.visit_generics(&sig.generics); |
3157f602 | 609 | MethodRibKind(!sig.decl.has_self()) |
c34b1796 | 610 | } |
a7813a04 | 611 | FnKind::Closure => ClosureRibKind(node_id), |
c34b1796 AL |
612 | }; |
613 | self.resolve_function(rib_kind, declaration, block); | |
614 | } | |
1a4d82fc JJ |
615 | } |
616 | ||
7453a54e | 617 | pub type ErrorMessage = Option<(Span, String)>; |
1a4d82fc | 618 | |
7453a54e SL |
619 | #[derive(Clone, PartialEq, Eq)] |
620 | pub enum ResolveResult<T> { | |
92a42be0 SL |
621 | Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message. |
622 | Indeterminate, // Couldn't determine due to unresolved globs. | |
623 | Success(T), // Successfully resolved the import. | |
1a4d82fc JJ |
624 | } |
625 | ||
626 | impl<T> ResolveResult<T> { | |
7453a54e SL |
627 | fn and_then<U, F: FnOnce(T) -> ResolveResult<U>>(self, f: F) -> ResolveResult<U> { |
628 | match self { | |
629 | Failed(msg) => Failed(msg), | |
630 | Indeterminate => Indeterminate, | |
631 | Success(t) => f(t), | |
632 | } | |
633 | } | |
634 | ||
635 | fn success(self) -> Option<T> { | |
636 | match self { | |
637 | Success(t) => Some(t), | |
638 | _ => None, | |
92a42be0 | 639 | } |
1a4d82fc JJ |
640 | } |
641 | } | |
642 | ||
643 | enum FallbackSuggestion { | |
644 | NoSuggestion, | |
645 | Field, | |
1a4d82fc | 646 | TraitItem, |
1a4d82fc JJ |
647 | TraitMethod(String), |
648 | } | |
649 | ||
c34b1796 | 650 | #[derive(Copy, Clone)] |
a7813a04 | 651 | enum TypeParameters<'a, 'b> { |
1a4d82fc | 652 | NoTypeParameters, |
92a42be0 | 653 | HasTypeParameters(// Type parameters. |
a7813a04 | 654 | &'b Generics, |
1a4d82fc | 655 | |
92a42be0 | 656 | // The kind of the rib used for type parameters. |
a7813a04 | 657 | RibKind<'a>), |
1a4d82fc JJ |
658 | } |
659 | ||
660 | // The rib kind controls the translation of local | |
7453a54e | 661 | // definitions (`Def::Local`) to upvars (`Def::Upvar`). |
c34b1796 | 662 | #[derive(Copy, Clone, Debug)] |
7453a54e | 663 | enum RibKind<'a> { |
1a4d82fc JJ |
664 | // No translation needs to be applied. |
665 | NormalRibKind, | |
666 | ||
667 | // We passed through a closure scope at the given node ID. | |
668 | // Translate upvars as appropriate. | |
85aaf69f | 669 | ClosureRibKind(NodeId /* func id */), |
1a4d82fc JJ |
670 | |
671 | // We passed through an impl or trait and are now in one of its | |
672 | // methods. Allow references to ty params that impl or trait | |
673 | // binds. Disallow any other upvars (including other ty params that are | |
674 | // upvars). | |
3157f602 XL |
675 | // |
676 | // The boolean value represents the fact that this method is static or not. | |
677 | MethodRibKind(bool), | |
1a4d82fc JJ |
678 | |
679 | // We passed through an item scope. Disallow upvars. | |
680 | ItemRibKind, | |
681 | ||
682 | // We're in a constant item. Can't refer to dynamic stuff. | |
92a42be0 | 683 | ConstantItemRibKind, |
7453a54e SL |
684 | |
685 | // We passed through a module. | |
686 | ModuleRibKind(Module<'a>), | |
5bcae85e SL |
687 | |
688 | // We passed through a `macro_rules!` statement with the given expansion | |
689 | MacroDefinition(Mark), | |
1a4d82fc JJ |
690 | } |
691 | ||
c34b1796 | 692 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
693 | enum UseLexicalScopeFlag { |
694 | DontUseLexicalScope, | |
92a42be0 | 695 | UseLexicalScope, |
1a4d82fc JJ |
696 | } |
697 | ||
9cc50fc6 | 698 | enum ModulePrefixResult<'a> { |
1a4d82fc | 699 | NoPrefixFound, |
9cc50fc6 | 700 | PrefixFound(Module<'a>, usize), |
1a4d82fc JJ |
701 | } |
702 | ||
1a4d82fc | 703 | /// One local scope. |
85aaf69f | 704 | #[derive(Debug)] |
7453a54e | 705 | struct Rib<'a> { |
c30ab7b3 | 706 | bindings: FnvHashMap<Ident, Def>, |
7453a54e | 707 | kind: RibKind<'a>, |
1a4d82fc JJ |
708 | } |
709 | ||
7453a54e SL |
710 | impl<'a> Rib<'a> { |
711 | fn new(kind: RibKind<'a>) -> Rib<'a> { | |
1a4d82fc | 712 | Rib { |
9e0c209e | 713 | bindings: FnvHashMap(), |
92a42be0 SL |
714 | kind: kind, |
715 | } | |
716 | } | |
717 | } | |
718 | ||
719 | /// A definition along with the index of the rib it was found on | |
720 | struct LocalDef { | |
721 | ribs: Option<(Namespace, usize)>, | |
722 | def: Def, | |
723 | } | |
724 | ||
725 | impl LocalDef { | |
726 | fn from_def(def: Def) -> Self { | |
727 | LocalDef { | |
728 | ribs: None, | |
729 | def: def, | |
1a4d82fc JJ |
730 | } |
731 | } | |
732 | } | |
733 | ||
54a0048b SL |
734 | enum LexicalScopeBinding<'a> { |
735 | Item(&'a NameBinding<'a>), | |
736 | LocalDef(LocalDef), | |
737 | } | |
738 | ||
739 | impl<'a> LexicalScopeBinding<'a> { | |
740 | fn local_def(self) -> LocalDef { | |
741 | match self { | |
742 | LexicalScopeBinding::LocalDef(local_def) => local_def, | |
9e0c209e | 743 | LexicalScopeBinding::Item(binding) => LocalDef::from_def(binding.def()), |
54a0048b SL |
744 | } |
745 | } | |
746 | ||
5bcae85e | 747 | fn item(self) -> Option<&'a NameBinding<'a>> { |
54a0048b | 748 | match self { |
5bcae85e | 749 | LexicalScopeBinding::Item(binding) => Some(binding), |
54a0048b SL |
750 | _ => None, |
751 | } | |
752 | } | |
753 | } | |
754 | ||
9e0c209e SL |
755 | enum ModuleKind { |
756 | Block(NodeId), | |
757 | Def(Def, Name), | |
1a4d82fc JJ |
758 | } |
759 | ||
760 | /// One node in the tree of modules. | |
9cc50fc6 | 761 | pub struct ModuleS<'a> { |
9e0c209e SL |
762 | parent: Option<Module<'a>>, |
763 | kind: ModuleKind, | |
764 | ||
765 | // The node id of the closest normal module (`mod`) ancestor (including this module). | |
766 | normal_ancestor_id: Option<NodeId>, | |
1a4d82fc | 767 | |
54a0048b SL |
768 | // If the module is an extern crate, `def` is root of the external crate and `extern_crate_id` |
769 | // is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None). | |
770 | extern_crate_id: Option<NodeId>, | |
1a4d82fc | 771 | |
9e0c209e | 772 | resolutions: RefCell<FnvHashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>, |
1a4d82fc | 773 | |
9e0c209e | 774 | no_implicit_prelude: bool, |
1a4d82fc | 775 | |
9e0c209e | 776 | glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>, |
54a0048b | 777 | globs: RefCell<Vec<&'a ImportDirective<'a>>>, |
e9174d1e | 778 | |
54a0048b | 779 | // Used to memoize the traits in this module for faster searches through all traits in scope. |
a7813a04 | 780 | traits: RefCell<Option<Box<[(Name, &'a NameBinding<'a>)]>>>, |
e9174d1e | 781 | |
1a4d82fc JJ |
782 | // Whether this module is populated. If not populated, any attempt to |
783 | // access the children must be preceded with a | |
784 | // `populate_module_if_necessary` call. | |
785 | populated: Cell<bool>, | |
786 | } | |
787 | ||
9cc50fc6 SL |
788 | pub type Module<'a> = &'a ModuleS<'a>; |
789 | ||
790 | impl<'a> ModuleS<'a> { | |
9e0c209e | 791 | fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self { |
9cc50fc6 | 792 | ModuleS { |
9e0c209e SL |
793 | parent: parent, |
794 | kind: kind, | |
795 | normal_ancestor_id: None, | |
54a0048b | 796 | extern_crate_id: None, |
9e0c209e SL |
797 | resolutions: RefCell::new(FnvHashMap()), |
798 | no_implicit_prelude: false, | |
54a0048b SL |
799 | glob_importers: RefCell::new(Vec::new()), |
800 | globs: RefCell::new((Vec::new())), | |
801 | traits: RefCell::new(None), | |
9e0c209e | 802 | populated: Cell::new(true), |
7453a54e SL |
803 | } |
804 | } | |
805 | ||
806 | fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) { | |
807 | for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() { | |
54a0048b | 808 | name_resolution.borrow().binding.map(|binding| f(name, ns, binding)); |
7453a54e SL |
809 | } |
810 | } | |
811 | ||
9e0c209e SL |
812 | fn def(&self) -> Option<Def> { |
813 | match self.kind { | |
814 | ModuleKind::Def(def, _) => Some(def), | |
815 | _ => None, | |
816 | } | |
817 | } | |
818 | ||
92a42be0 | 819 | fn def_id(&self) -> Option<DefId> { |
9e0c209e | 820 | self.def().as_ref().map(Def::def_id) |
92a42be0 SL |
821 | } |
822 | ||
a7813a04 | 823 | // `self` resolves to the first module ancestor that `is_normal`. |
7453a54e | 824 | fn is_normal(&self) -> bool { |
9e0c209e SL |
825 | match self.kind { |
826 | ModuleKind::Def(Def::Mod(_), _) => true, | |
92a42be0 | 827 | _ => false, |
1a4d82fc JJ |
828 | } |
829 | } | |
830 | ||
7453a54e | 831 | fn is_trait(&self) -> bool { |
9e0c209e SL |
832 | match self.kind { |
833 | ModuleKind::Def(Def::Trait(_), _) => true, | |
7453a54e | 834 | _ => false, |
e9174d1e SL |
835 | } |
836 | } | |
c30ab7b3 SL |
837 | |
838 | fn is_local(&self) -> bool { | |
839 | self.normal_ancestor_id.is_some() | |
840 | } | |
1a4d82fc JJ |
841 | } |
842 | ||
9cc50fc6 | 843 | impl<'a> fmt::Debug for ModuleS<'a> { |
1a4d82fc | 844 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
9e0c209e | 845 | write!(f, "{:?}", self.def()) |
1a4d82fc JJ |
846 | } |
847 | } | |
848 | ||
92a42be0 | 849 | // Records a possibly-private value, type, or module definition. |
54a0048b | 850 | #[derive(Clone, Debug)] |
7453a54e | 851 | pub struct NameBinding<'a> { |
7453a54e | 852 | kind: NameBindingKind<'a>, |
a7813a04 XL |
853 | span: Span, |
854 | vis: ty::Visibility, | |
1a4d82fc JJ |
855 | } |
856 | ||
5bcae85e SL |
857 | pub trait ToNameBinding<'a> { |
858 | fn to_name_binding(self) -> NameBinding<'a>; | |
859 | } | |
860 | ||
861 | impl<'a> ToNameBinding<'a> for NameBinding<'a> { | |
862 | fn to_name_binding(self) -> NameBinding<'a> { | |
863 | self | |
864 | } | |
865 | } | |
866 | ||
54a0048b | 867 | #[derive(Clone, Debug)] |
7453a54e | 868 | enum NameBindingKind<'a> { |
92a42be0 | 869 | Def(Def), |
9cc50fc6 | 870 | Module(Module<'a>), |
7453a54e SL |
871 | Import { |
872 | binding: &'a NameBinding<'a>, | |
a7813a04 | 873 | directive: &'a ImportDirective<'a>, |
9e0c209e | 874 | used: Cell<bool>, |
7453a54e | 875 | }, |
9e0c209e SL |
876 | Ambiguity { |
877 | b1: &'a NameBinding<'a>, | |
878 | b2: &'a NameBinding<'a>, | |
879 | } | |
1a4d82fc JJ |
880 | } |
881 | ||
54a0048b SL |
882 | struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>); |
883 | ||
9e0c209e SL |
884 | struct AmbiguityError<'a> { |
885 | span: Span, | |
886 | name: Name, | |
887 | b1: &'a NameBinding<'a>, | |
888 | b2: &'a NameBinding<'a>, | |
889 | } | |
890 | ||
7453a54e | 891 | impl<'a> NameBinding<'a> { |
9e0c209e | 892 | fn module(&self) -> Result<Module<'a>, bool /* true if an error has already been reported */> { |
7453a54e | 893 | match self.kind { |
9e0c209e | 894 | NameBindingKind::Module(module) => Ok(module), |
7453a54e | 895 | NameBindingKind::Import { binding, .. } => binding.module(), |
9e0c209e SL |
896 | NameBindingKind::Def(Def::Err) => Err(true), |
897 | NameBindingKind::Def(_) => Err(false), | |
898 | NameBindingKind::Ambiguity { .. } => Err(false), | |
1a4d82fc JJ |
899 | } |
900 | } | |
901 | ||
9e0c209e | 902 | fn def(&self) -> Def { |
7453a54e | 903 | match self.kind { |
9e0c209e SL |
904 | NameBindingKind::Def(def) => def, |
905 | NameBindingKind::Module(module) => module.def().unwrap(), | |
7453a54e | 906 | NameBindingKind::Import { binding, .. } => binding.def(), |
9e0c209e | 907 | NameBindingKind::Ambiguity { .. } => Def::Err, |
1a4d82fc JJ |
908 | } |
909 | } | |
1a4d82fc | 910 | |
a7813a04 XL |
911 | // We sometimes need to treat variants as `pub` for backwards compatibility |
912 | fn pseudo_vis(&self) -> ty::Visibility { | |
913 | if self.is_variant() { ty::Visibility::Public } else { self.vis } | |
1a4d82fc | 914 | } |
c34b1796 | 915 | |
a7813a04 XL |
916 | fn is_variant(&self) -> bool { |
917 | match self.kind { | |
c30ab7b3 SL |
918 | NameBindingKind::Def(Def::Variant(..)) | |
919 | NameBindingKind::Def(Def::VariantCtor(..)) => true, | |
a7813a04 XL |
920 | _ => false, |
921 | } | |
92a42be0 SL |
922 | } |
923 | ||
7453a54e | 924 | fn is_extern_crate(&self) -> bool { |
9e0c209e | 925 | self.module().ok().and_then(|module| module.extern_crate_id).is_some() |
92a42be0 | 926 | } |
92a42be0 | 927 | |
7453a54e SL |
928 | fn is_import(&self) -> bool { |
929 | match self.kind { | |
930 | NameBindingKind::Import { .. } => true, | |
931 | _ => false, | |
c34b1796 AL |
932 | } |
933 | } | |
a7813a04 XL |
934 | |
935 | fn is_glob_import(&self) -> bool { | |
936 | match self.kind { | |
937 | NameBindingKind::Import { directive, .. } => directive.is_glob(), | |
9e0c209e | 938 | NameBindingKind::Ambiguity { .. } => true, |
a7813a04 XL |
939 | _ => false, |
940 | } | |
941 | } | |
942 | ||
943 | fn is_importable(&self) -> bool { | |
9e0c209e | 944 | match self.def() { |
a7813a04 XL |
945 | Def::AssociatedConst(..) | Def::Method(..) | Def::AssociatedTy(..) => false, |
946 | _ => true, | |
947 | } | |
948 | } | |
1a4d82fc JJ |
949 | } |
950 | ||
951 | /// Interns the names of the primitive types. | |
952 | struct PrimitiveTypeTable { | |
9e0c209e | 953 | primitive_types: FnvHashMap<Name, PrimTy>, |
1a4d82fc JJ |
954 | } |
955 | ||
956 | impl PrimitiveTypeTable { | |
957 | fn new() -> PrimitiveTypeTable { | |
9e0c209e | 958 | let mut table = PrimitiveTypeTable { primitive_types: FnvHashMap() }; |
92a42be0 SL |
959 | |
960 | table.intern("bool", TyBool); | |
961 | table.intern("char", TyChar); | |
7453a54e SL |
962 | table.intern("f32", TyFloat(FloatTy::F32)); |
963 | table.intern("f64", TyFloat(FloatTy::F64)); | |
964 | table.intern("isize", TyInt(IntTy::Is)); | |
965 | table.intern("i8", TyInt(IntTy::I8)); | |
966 | table.intern("i16", TyInt(IntTy::I16)); | |
967 | table.intern("i32", TyInt(IntTy::I32)); | |
968 | table.intern("i64", TyInt(IntTy::I64)); | |
92a42be0 | 969 | table.intern("str", TyStr); |
7453a54e SL |
970 | table.intern("usize", TyUint(UintTy::Us)); |
971 | table.intern("u8", TyUint(UintTy::U8)); | |
972 | table.intern("u16", TyUint(UintTy::U16)); | |
973 | table.intern("u32", TyUint(UintTy::U32)); | |
974 | table.intern("u64", TyUint(UintTy::U64)); | |
1a4d82fc JJ |
975 | |
976 | table | |
977 | } | |
978 | ||
979 | fn intern(&mut self, string: &str, primitive_type: PrimTy) { | |
980 | self.primitive_types.insert(token::intern(string), primitive_type); | |
981 | } | |
982 | } | |
983 | ||
984 | /// The main resolver class. | |
a7813a04 | 985 | pub struct Resolver<'a> { |
1a4d82fc JJ |
986 | session: &'a Session, |
987 | ||
3157f602 | 988 | pub definitions: Definitions, |
1a4d82fc | 989 | |
5bcae85e SL |
990 | // Maps the node id of a statement to the expansions of the `macro_rules!`s |
991 | // immediately above the statement (if appropriate). | |
9e0c209e | 992 | macros_at_scope: FnvHashMap<NodeId, Vec<Mark>>, |
5bcae85e | 993 | |
9cc50fc6 | 994 | graph_root: Module<'a>, |
1a4d82fc | 995 | |
3157f602 XL |
996 | prelude: Option<Module<'a>>, |
997 | ||
a7813a04 | 998 | trait_item_map: FnvHashMap<(Name, DefId), bool /* is static method? */>, |
1a4d82fc | 999 | |
c30ab7b3 SL |
1000 | // Names of fields of an item `DefId` accessible with dot syntax. |
1001 | // Used for hints during error reporting. | |
1002 | field_names: FnvHashMap<DefId, Vec<Name>>, | |
1a4d82fc | 1003 | |
9e0c209e SL |
1004 | // All imports known to succeed or fail. |
1005 | determined_imports: Vec<&'a ImportDirective<'a>>, | |
1006 | ||
1007 | // All non-determined imports. | |
1008 | indeterminate_imports: Vec<&'a ImportDirective<'a>>, | |
1a4d82fc JJ |
1009 | |
1010 | // The module that represents the current item scope. | |
9cc50fc6 | 1011 | current_module: Module<'a>, |
1a4d82fc JJ |
1012 | |
1013 | // The current set of local scopes, for values. | |
1014 | // FIXME #4948: Reuse ribs to avoid allocation. | |
7453a54e | 1015 | value_ribs: Vec<Rib<'a>>, |
1a4d82fc JJ |
1016 | |
1017 | // The current set of local scopes, for types. | |
7453a54e | 1018 | type_ribs: Vec<Rib<'a>>, |
1a4d82fc JJ |
1019 | |
1020 | // The current set of local scopes, for labels. | |
7453a54e | 1021 | label_ribs: Vec<Rib<'a>>, |
1a4d82fc JJ |
1022 | |
1023 | // The trait that the current context can refer to. | |
1024 | current_trait_ref: Option<(DefId, TraitRef)>, | |
1025 | ||
1026 | // The current self type if inside an impl (used for better errors). | |
1027 | current_self_type: Option<Ty>, | |
1028 | ||
1a4d82fc JJ |
1029 | // The idents for the primitive types. |
1030 | primitive_type_table: PrimitiveTypeTable, | |
1031 | ||
a7813a04 XL |
1032 | pub def_map: DefMap, |
1033 | pub freevars: FreevarMap, | |
92a42be0 | 1034 | freevars_seen: NodeMap<NodeMap<usize>>, |
a7813a04 XL |
1035 | pub export_map: ExportMap, |
1036 | pub trait_map: TraitMap, | |
1037 | ||
1038 | // A map from nodes to modules, both normal (`mod`) modules and anonymous modules. | |
1039 | // Anonymous modules are pseudo-modules that are implicitly created around items | |
1040 | // contained within blocks. | |
1041 | // | |
1042 | // For example, if we have this: | |
1043 | // | |
1044 | // fn f() { | |
1045 | // fn g() { | |
1046 | // ... | |
1047 | // } | |
1048 | // } | |
1049 | // | |
1050 | // There will be an anonymous module created around `g` with the ID of the | |
1051 | // entry block for `f`. | |
1052 | module_map: NodeMap<Module<'a>>, | |
1a4d82fc JJ |
1053 | |
1054 | // Whether or not to print error messages. Can be set to true | |
1055 | // when getting additional info for error message suggestions, | |
1056 | // so as to avoid printing duplicate errors | |
1057 | emit_errors: bool, | |
1058 | ||
a7813a04 | 1059 | pub make_glob_map: bool, |
1a4d82fc JJ |
1060 | // Maps imports to the names of items actually imported (this actually maps |
1061 | // all imports, but only glob imports are actually interesting). | |
a7813a04 | 1062 | pub glob_map: GlobMap, |
1a4d82fc | 1063 | |
9e0c209e SL |
1064 | used_imports: FnvHashSet<(NodeId, Namespace)>, |
1065 | used_crates: FnvHashSet<CrateNum>, | |
a7813a04 | 1066 | pub maybe_unused_trait_imports: NodeSet, |
e9174d1e | 1067 | |
54a0048b | 1068 | privacy_errors: Vec<PrivacyError<'a>>, |
9e0c209e | 1069 | ambiguity_errors: Vec<AmbiguityError<'a>>, |
c30ab7b3 | 1070 | disallowed_shadowing: Vec<&'a LegacyBinding<'a>>, |
9cc50fc6 SL |
1071 | |
1072 | arenas: &'a ResolverArenas<'a>, | |
9e0c209e SL |
1073 | dummy_binding: &'a NameBinding<'a>, |
1074 | new_import_semantics: bool, // true if `#![feature(item_like_imports)]` | |
1075 | ||
1076 | pub exported_macros: Vec<ast::MacroDef>, | |
9e0c209e SL |
1077 | crate_loader: &'a mut CrateLoader, |
1078 | macro_names: FnvHashSet<Name>, | |
c30ab7b3 SL |
1079 | builtin_macros: FnvHashMap<Name, Rc<SyntaxExtension>>, |
1080 | lexical_macro_resolutions: Vec<(Name, LegacyScope<'a>)>, | |
9e0c209e SL |
1081 | |
1082 | // Maps the `Mark` of an expansion to its containing module or block. | |
c30ab7b3 | 1083 | invocations: FnvHashMap<Mark, &'a InvocationData<'a>>, |
9cc50fc6 SL |
1084 | } |
1085 | ||
3157f602 | 1086 | pub struct ResolverArenas<'a> { |
9cc50fc6 | 1087 | modules: arena::TypedArena<ModuleS<'a>>, |
a7813a04 | 1088 | local_modules: RefCell<Vec<Module<'a>>>, |
7453a54e | 1089 | name_bindings: arena::TypedArena<NameBinding<'a>>, |
54a0048b SL |
1090 | import_directives: arena::TypedArena<ImportDirective<'a>>, |
1091 | name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>, | |
c30ab7b3 SL |
1092 | invocation_data: arena::TypedArena<InvocationData<'a>>, |
1093 | legacy_bindings: arena::TypedArena<LegacyBinding<'a>>, | |
54a0048b SL |
1094 | } |
1095 | ||
1096 | impl<'a> ResolverArenas<'a> { | |
1097 | fn alloc_module(&'a self, module: ModuleS<'a>) -> Module<'a> { | |
a7813a04 XL |
1098 | let module = self.modules.alloc(module); |
1099 | if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) { | |
1100 | self.local_modules.borrow_mut().push(module); | |
1101 | } | |
1102 | module | |
1103 | } | |
1104 | fn local_modules(&'a self) -> ::std::cell::Ref<'a, Vec<Module<'a>>> { | |
1105 | self.local_modules.borrow() | |
54a0048b SL |
1106 | } |
1107 | fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { | |
1108 | self.name_bindings.alloc(name_binding) | |
1109 | } | |
1110 | fn alloc_import_directive(&'a self, import_directive: ImportDirective<'a>) | |
1111 | -> &'a ImportDirective { | |
1112 | self.import_directives.alloc(import_directive) | |
1113 | } | |
1114 | fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> { | |
1115 | self.name_resolutions.alloc(Default::default()) | |
1116 | } | |
c30ab7b3 SL |
1117 | fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>) |
1118 | -> &'a InvocationData<'a> { | |
1119 | self.invocation_data.alloc(expansion_data) | |
1120 | } | |
1121 | fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { | |
1122 | self.legacy_bindings.alloc(binding) | |
1123 | } | |
1a4d82fc JJ |
1124 | } |
1125 | ||
a7813a04 | 1126 | impl<'a> ty::NodeIdTree for Resolver<'a> { |
9e0c209e SL |
1127 | fn is_descendant_of(&self, mut node: NodeId, ancestor: NodeId) -> bool { |
1128 | while node != ancestor { | |
1129 | node = match self.module_map[&node].parent { | |
1130 | Some(parent) => parent.normal_ancestor_id.unwrap(), | |
a7813a04 | 1131 | None => return false, |
9e0c209e | 1132 | } |
a7813a04 XL |
1133 | } |
1134 | true | |
1135 | } | |
1a4d82fc JJ |
1136 | } |
1137 | ||
a7813a04 XL |
1138 | impl<'a> hir::lowering::Resolver for Resolver<'a> { |
1139 | fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def { | |
1140 | let namespace = if is_value { ValueNS } else { TypeNS }; | |
1141 | match self.resolve_crate_relative_path(path.span, &path.segments, namespace) { | |
9e0c209e | 1142 | Ok(binding) => binding.def(), |
a7813a04 XL |
1143 | Err(true) => Def::Err, |
1144 | Err(false) => { | |
1145 | let path_name = &format!("{}", path); | |
1146 | let error = | |
3157f602 XL |
1147 | ResolutionError::UnresolvedName { |
1148 | path: path_name, | |
1149 | message: "", | |
1150 | context: UnresolvedNameContext::Other, | |
1151 | is_static_method: false, | |
1152 | is_field: false, | |
1153 | def: Def::Err, | |
1154 | }; | |
a7813a04 XL |
1155 | resolve_error(self, path.span, error); |
1156 | Def::Err | |
1157 | } | |
1158 | } | |
1159 | } | |
1160 | ||
1161 | fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> { | |
1162 | self.def_map.get(&id).cloned() | |
1163 | } | |
1164 | ||
1165 | fn record_resolution(&mut self, id: NodeId, def: Def) { | |
3157f602 | 1166 | self.def_map.insert(id, PathResolution::new(def)); |
a7813a04 XL |
1167 | } |
1168 | ||
9e0c209e SL |
1169 | fn definitions(&mut self) -> &mut Definitions { |
1170 | &mut self.definitions | |
a7813a04 XL |
1171 | } |
1172 | } | |
1173 | ||
1174 | trait Named { | |
c30ab7b3 | 1175 | fn ident(&self) -> Ident; |
a7813a04 XL |
1176 | } |
1177 | ||
1178 | impl Named for ast::PathSegment { | |
c30ab7b3 SL |
1179 | fn ident(&self) -> Ident { |
1180 | self.identifier | |
a7813a04 XL |
1181 | } |
1182 | } | |
1183 | ||
1184 | impl Named for hir::PathSegment { | |
c30ab7b3 SL |
1185 | fn ident(&self) -> Ident { |
1186 | Ident::with_empty_ctxt(self.name) | |
a7813a04 XL |
1187 | } |
1188 | } | |
1189 | ||
1190 | impl<'a> Resolver<'a> { | |
9e0c209e SL |
1191 | pub fn new(session: &'a Session, |
1192 | krate: &Crate, | |
1193 | make_glob_map: MakeGlobMap, | |
1194 | crate_loader: &'a mut CrateLoader, | |
1195 | arenas: &'a ResolverArenas<'a>) | |
3157f602 | 1196 | -> Resolver<'a> { |
9e0c209e SL |
1197 | let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX)); |
1198 | let graph_root = arenas.alloc_module(ModuleS { | |
1199 | normal_ancestor_id: Some(CRATE_NODE_ID), | |
1200 | no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"), | |
1201 | ..ModuleS::new(None, ModuleKind::Def(root_def, keywords::Invalid.name())) | |
1202 | }); | |
a7813a04 XL |
1203 | let mut module_map = NodeMap(); |
1204 | module_map.insert(CRATE_NODE_ID, graph_root); | |
1a4d82fc | 1205 | |
c30ab7b3 SL |
1206 | let mut definitions = Definitions::new(); |
1207 | DefCollector::new(&mut definitions).collect_root(); | |
1208 | ||
1209 | let mut invocations = FnvHashMap(); | |
1210 | invocations.insert(Mark::root(), | |
1211 | arenas.alloc_invocation_data(InvocationData::root(graph_root))); | |
9e0c209e | 1212 | |
1a4d82fc JJ |
1213 | Resolver { |
1214 | session: session, | |
1215 | ||
c30ab7b3 | 1216 | definitions: definitions, |
9e0c209e | 1217 | macros_at_scope: FnvHashMap(), |
1a4d82fc JJ |
1218 | |
1219 | // The outermost module has def ID 0; this is not reflected in the | |
1220 | // AST. | |
9cc50fc6 | 1221 | graph_root: graph_root, |
3157f602 | 1222 | prelude: None, |
1a4d82fc | 1223 | |
85aaf69f | 1224 | trait_item_map: FnvHashMap(), |
c30ab7b3 | 1225 | field_names: FnvHashMap(), |
1a4d82fc | 1226 | |
9e0c209e SL |
1227 | determined_imports: Vec::new(), |
1228 | indeterminate_imports: Vec::new(), | |
1a4d82fc | 1229 | |
92a42be0 | 1230 | current_module: graph_root, |
54a0048b SL |
1231 | value_ribs: vec![Rib::new(ModuleRibKind(graph_root))], |
1232 | type_ribs: vec![Rib::new(ModuleRibKind(graph_root))], | |
1a4d82fc JJ |
1233 | label_ribs: Vec::new(), |
1234 | ||
1235 | current_trait_ref: None, | |
1236 | current_self_type: None, | |
1237 | ||
1a4d82fc JJ |
1238 | primitive_type_table: PrimitiveTypeTable::new(), |
1239 | ||
a7813a04 | 1240 | def_map: NodeMap(), |
92a42be0 SL |
1241 | freevars: NodeMap(), |
1242 | freevars_seen: NodeMap(), | |
85aaf69f SL |
1243 | export_map: NodeMap(), |
1244 | trait_map: NodeMap(), | |
a7813a04 | 1245 | module_map: module_map, |
1a4d82fc JJ |
1246 | |
1247 | emit_errors: true, | |
1248 | make_glob_map: make_glob_map == MakeGlobMap::Yes, | |
54a0048b | 1249 | glob_map: NodeMap(), |
e9174d1e | 1250 | |
9e0c209e SL |
1251 | used_imports: FnvHashSet(), |
1252 | used_crates: FnvHashSet(), | |
a7813a04 XL |
1253 | maybe_unused_trait_imports: NodeSet(), |
1254 | ||
54a0048b | 1255 | privacy_errors: Vec::new(), |
9e0c209e | 1256 | ambiguity_errors: Vec::new(), |
c30ab7b3 | 1257 | disallowed_shadowing: Vec::new(), |
9cc50fc6 SL |
1258 | |
1259 | arenas: arenas, | |
9e0c209e SL |
1260 | dummy_binding: arenas.alloc_name_binding(NameBinding { |
1261 | kind: NameBindingKind::Def(Def::Err), | |
1262 | span: DUMMY_SP, | |
1263 | vis: ty::Visibility::Public, | |
1264 | }), | |
1265 | new_import_semantics: session.features.borrow().item_like_imports, | |
1266 | ||
1267 | exported_macros: Vec::new(), | |
9e0c209e SL |
1268 | crate_loader: crate_loader, |
1269 | macro_names: FnvHashSet(), | |
c30ab7b3 SL |
1270 | builtin_macros: FnvHashMap(), |
1271 | lexical_macro_resolutions: Vec::new(), | |
1272 | invocations: invocations, | |
9cc50fc6 SL |
1273 | } |
1274 | } | |
1275 | ||
3157f602 | 1276 | pub fn arenas() -> ResolverArenas<'a> { |
9cc50fc6 SL |
1277 | ResolverArenas { |
1278 | modules: arena::TypedArena::new(), | |
a7813a04 | 1279 | local_modules: RefCell::new(Vec::new()), |
7453a54e | 1280 | name_bindings: arena::TypedArena::new(), |
54a0048b SL |
1281 | import_directives: arena::TypedArena::new(), |
1282 | name_resolutions: arena::TypedArena::new(), | |
c30ab7b3 SL |
1283 | invocation_data: arena::TypedArena::new(), |
1284 | legacy_bindings: arena::TypedArena::new(), | |
1a4d82fc JJ |
1285 | } |
1286 | } | |
1287 | ||
3157f602 XL |
1288 | /// Entry point to crate resolution. |
1289 | pub fn resolve_crate(&mut self, krate: &Crate) { | |
c30ab7b3 SL |
1290 | // Collect `DefId`s for exported macro defs. |
1291 | for def in &krate.exported_macros { | |
1292 | DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| { | |
1293 | collector.visit_macro_def(def) | |
1294 | }) | |
1295 | } | |
1296 | ||
3157f602 XL |
1297 | self.current_module = self.graph_root; |
1298 | visit::walk_crate(self, krate); | |
1299 | ||
1300 | check_unused::check_crate(self, krate); | |
9e0c209e SL |
1301 | self.report_errors(); |
1302 | self.crate_loader.postprocess(krate); | |
3157f602 XL |
1303 | } |
1304 | ||
9e0c209e SL |
1305 | fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> { |
1306 | self.arenas.alloc_module(ModuleS { | |
1307 | normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None }, | |
1308 | populated: Cell::new(local), | |
1309 | ..ModuleS::new(Some(parent), kind) | |
1310 | }) | |
7453a54e SL |
1311 | } |
1312 | ||
1313 | fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec<Rib<'a>> { | |
1314 | match ns { ValueNS => &mut self.value_ribs, TypeNS => &mut self.type_ribs } | |
1315 | } | |
1316 | ||
9e0c209e SL |
1317 | fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) |
1318 | -> bool /* true if an error was reported */ { | |
7453a54e | 1319 | // track extern crates for unused_extern_crate lint |
9e0c209e | 1320 | if let Some(DefId { krate, .. }) = binding.module().ok().and_then(ModuleS::def_id) { |
7453a54e SL |
1321 | self.used_crates.insert(krate); |
1322 | } | |
1323 | ||
9e0c209e SL |
1324 | match binding.kind { |
1325 | NameBindingKind::Import { directive, binding, ref used } if !used.get() => { | |
1326 | used.set(true); | |
1327 | self.used_imports.insert((directive.id, ns)); | |
1328 | self.add_to_glob_map(directive.id, name); | |
1329 | self.record_use(name, ns, binding, span) | |
1330 | } | |
1331 | NameBindingKind::Import { .. } => false, | |
1332 | NameBindingKind::Ambiguity { b1, b2 } => { | |
1333 | let ambiguity_error = AmbiguityError { span: span, name: name, b1: b1, b2: b2 }; | |
1334 | self.ambiguity_errors.push(ambiguity_error); | |
1335 | true | |
1336 | } | |
1337 | _ => false | |
54a0048b | 1338 | } |
5bcae85e | 1339 | } |
7453a54e | 1340 | |
5bcae85e SL |
1341 | fn add_to_glob_map(&mut self, id: NodeId, name: Name) { |
1342 | if self.make_glob_map { | |
1343 | self.glob_map.entry(id).or_insert_with(FnvHashSet).insert(name); | |
1a4d82fc | 1344 | } |
1a4d82fc JJ |
1345 | } |
1346 | ||
9e0c209e SL |
1347 | fn expect_module(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Option<Span>) |
1348 | -> ResolveResult<Module<'a>> { | |
1349 | match binding.module() { | |
1350 | Ok(module) => Success(module), | |
1351 | Err(true) => Failed(None), | |
1352 | Err(false) => { | |
1353 | let msg = format!("Not a module `{}`", name); | |
1354 | Failed(span.map(|span| (span, msg))) | |
1355 | } | |
1356 | } | |
1357 | } | |
1358 | ||
5bcae85e | 1359 | /// Resolves the given module path from the given root `search_module`. |
1a4d82fc | 1360 | fn resolve_module_path_from_root(&mut self, |
5bcae85e | 1361 | mut search_module: Module<'a>, |
c30ab7b3 | 1362 | module_path: &[Ident], |
c34b1796 | 1363 | index: usize, |
9e0c209e | 1364 | span: Option<Span>) |
54a0048b | 1365 | -> ResolveResult<Module<'a>> { |
9e0c209e SL |
1366 | fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>) |
1367 | -> Option<Module<'a>> { | |
1368 | match this.resolve_name_in_module(module, needle, TypeNS, false, None) { | |
7453a54e | 1369 | Success(binding) if binding.is_extern_crate() => Some(module), |
9e0c209e SL |
1370 | _ => if let (&ModuleKind::Def(..), Some(parent)) = (&module.kind, module.parent) { |
1371 | search_parent_externals(this, needle, parent) | |
1372 | } else { | |
1373 | None | |
92a42be0 | 1374 | }, |
85aaf69f | 1375 | } |
1a4d82fc JJ |
1376 | } |
1377 | ||
1a4d82fc JJ |
1378 | let mut index = index; |
1379 | let module_path_len = module_path.len(); | |
1a4d82fc JJ |
1380 | |
1381 | // Resolve the module part of the path. This does not involve looking | |
1382 | // upward though scope chains; we simply resolve names directly in | |
1383 | // modules as we go. | |
1384 | while index < module_path_len { | |
c30ab7b3 | 1385 | let name = module_path[index].name; |
9e0c209e SL |
1386 | match self.resolve_name_in_module(search_module, name, TypeNS, false, span) { |
1387 | Failed(_) => { | |
c1a9b12d | 1388 | let segment_name = name.as_str(); |
9cc50fc6 | 1389 | let module_name = module_to_string(search_module); |
7453a54e | 1390 | let msg = if "???" == &module_name { |
9e0c209e SL |
1391 | let current_module = self.current_module; |
1392 | match search_parent_externals(self, name, current_module) { | |
1a4d82fc | 1393 | Some(module) => { |
c34b1796 | 1394 | let path_str = names_to_string(module_path); |
7453a54e | 1395 | let target_mod_str = module_to_string(&module); |
9e0c209e | 1396 | let current_mod_str = module_to_string(current_module); |
1a4d82fc JJ |
1397 | |
1398 | let prefix = if target_mod_str == current_mod_str { | |
1399 | "self::".to_string() | |
1400 | } else { | |
1401 | format!("{}::", target_mod_str) | |
1402 | }; | |
1403 | ||
1404 | format!("Did you mean `{}{}`?", prefix, path_str) | |
92a42be0 | 1405 | } |
c30ab7b3 | 1406 | None => format!("Maybe a missing `extern crate {};`?", segment_name), |
1a4d82fc JJ |
1407 | } |
1408 | } else { | |
92a42be0 | 1409 | format!("Could not find `{}` in `{}`", segment_name, module_name) |
1a4d82fc JJ |
1410 | }; |
1411 | ||
9e0c209e | 1412 | return Failed(span.map(|span| (span, msg))); |
1a4d82fc | 1413 | } |
1a4d82fc | 1414 | Indeterminate => { |
92a42be0 SL |
1415 | debug!("(resolving module path for import) module resolution is \ |
1416 | indeterminate: {}", | |
1417 | name); | |
1a4d82fc JJ |
1418 | return Indeterminate; |
1419 | } | |
7453a54e | 1420 | Success(binding) => { |
1a4d82fc JJ |
1421 | // Check to see whether there are type bindings, and, if |
1422 | // so, whether there is a module within. | |
9e0c209e SL |
1423 | match self.expect_module(name, binding, span) { |
1424 | Success(module) => search_module = module, | |
1425 | result @ _ => return result, | |
1a4d82fc JJ |
1426 | } |
1427 | } | |
1428 | } | |
1429 | ||
1430 | index += 1; | |
1431 | } | |
1432 | ||
54a0048b | 1433 | return Success(search_module); |
1a4d82fc JJ |
1434 | } |
1435 | ||
1436 | /// Attempts to resolve the module part of an import directive or path | |
1437 | /// rooted at the given module. | |
1a4d82fc | 1438 | fn resolve_module_path(&mut self, |
c30ab7b3 | 1439 | module_path: &[Ident], |
1a4d82fc | 1440 | use_lexical_scope: UseLexicalScopeFlag, |
9e0c209e | 1441 | span: Option<Span>) |
54a0048b | 1442 | -> ResolveResult<Module<'a>> { |
7453a54e | 1443 | if module_path.len() == 0 { |
54a0048b | 1444 | return Success(self.graph_root) // Use the crate root |
7453a54e | 1445 | } |
1a4d82fc JJ |
1446 | |
1447 | debug!("(resolving module path for import) processing `{}` rooted at `{}`", | |
c34b1796 | 1448 | names_to_string(module_path), |
54a0048b | 1449 | module_to_string(self.current_module)); |
1a4d82fc JJ |
1450 | |
1451 | // Resolve the module prefix, if any. | |
54a0048b | 1452 | let module_prefix_result = self.resolve_module_prefix(module_path, span); |
1a4d82fc JJ |
1453 | |
1454 | let search_module; | |
1455 | let start_index; | |
1a4d82fc | 1456 | match module_prefix_result { |
1a4d82fc JJ |
1457 | Failed(err) => return Failed(err), |
1458 | Indeterminate => { | |
92a42be0 | 1459 | debug!("(resolving module path for import) indeterminate; bailing"); |
1a4d82fc JJ |
1460 | return Indeterminate; |
1461 | } | |
1462 | Success(NoPrefixFound) => { | |
1463 | // There was no prefix, so we're considering the first element | |
1464 | // of the path. How we handle this depends on whether we were | |
1465 | // instructed to use lexical scope or not. | |
1466 | match use_lexical_scope { | |
1467 | DontUseLexicalScope => { | |
1468 | // This is a crate-relative path. We will start the | |
1469 | // resolution process at index zero. | |
9cc50fc6 | 1470 | search_module = self.graph_root; |
1a4d82fc | 1471 | start_index = 0; |
1a4d82fc JJ |
1472 | } |
1473 | UseLexicalScope => { | |
1474 | // This is not a crate-relative path. We resolve the | |
1475 | // first component of the path in the current lexical | |
1476 | // scope and then proceed to resolve below that. | |
c30ab7b3 | 1477 | let ident = module_path[0]; |
9e0c209e SL |
1478 | let lexical_binding = |
1479 | self.resolve_ident_in_lexical_scope(ident, TypeNS, span); | |
1480 | if let Some(binding) = lexical_binding.and_then(LexicalScopeBinding::item) { | |
1481 | match self.expect_module(ident.name, binding, span) { | |
1482 | Success(containing_module) => { | |
1483 | search_module = containing_module; | |
1484 | start_index = 1; | |
1485 | } | |
1486 | result @ _ => return result, | |
1a4d82fc | 1487 | } |
9e0c209e SL |
1488 | } else { |
1489 | let msg = | |
1490 | format!("Use of undeclared type or module `{}`", ident.name); | |
1491 | return Failed(span.map(|span| (span, msg))); | |
1a4d82fc JJ |
1492 | } |
1493 | } | |
1494 | } | |
1495 | } | |
1496 | Success(PrefixFound(ref containing_module, index)) => { | |
9cc50fc6 | 1497 | search_module = containing_module; |
1a4d82fc | 1498 | start_index = index; |
1a4d82fc JJ |
1499 | } |
1500 | } | |
1501 | ||
9e0c209e | 1502 | self.resolve_module_path_from_root(search_module, module_path, start_index, span) |
1a4d82fc JJ |
1503 | } |
1504 | ||
54a0048b SL |
1505 | /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. |
1506 | /// More specifically, we proceed up the hierarchy of scopes and return the binding for | |
1507 | /// `ident` in the first scope that defines it (or None if no scopes define it). | |
1508 | /// | |
1509 | /// A block's items are above its local variables in the scope hierarchy, regardless of where | |
1510 | /// the items are defined in the block. For example, | |
1511 | /// ```rust | |
1512 | /// fn f() { | |
1513 | /// g(); // Since there are no local variables in scope yet, this resolves to the item. | |
1514 | /// let g = || {}; | |
1515 | /// fn g() {} | |
1516 | /// g(); // This resolves to the local variable `g` since it shadows the item. | |
1517 | /// } | |
1518 | /// ``` | |
1519 | /// | |
1a4d82fc JJ |
1520 | /// Invariant: This must only be called during main resolution, not during |
1521 | /// import resolution. | |
54a0048b | 1522 | fn resolve_ident_in_lexical_scope(&mut self, |
c30ab7b3 | 1523 | mut ident: Ident, |
54a0048b | 1524 | ns: Namespace, |
9e0c209e | 1525 | record_used: Option<Span>) |
54a0048b | 1526 | -> Option<LexicalScopeBinding<'a>> { |
5bcae85e | 1527 | if ns == TypeNS { |
c30ab7b3 | 1528 | ident = Ident::with_empty_ctxt(ident.name); |
5bcae85e | 1529 | } |
54a0048b SL |
1530 | |
1531 | // Walk backwards up the ribs in scope. | |
1532 | for i in (0 .. self.get_ribs(ns).len()).rev() { | |
5bcae85e | 1533 | if let Some(def) = self.get_ribs(ns)[i].bindings.get(&ident).cloned() { |
54a0048b SL |
1534 | // The ident resolves to a type parameter or local variable. |
1535 | return Some(LexicalScopeBinding::LocalDef(LocalDef { | |
1536 | ribs: Some((ns, i)), | |
1537 | def: def, | |
1538 | })); | |
1539 | } | |
1540 | ||
1541 | if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind { | |
a7813a04 | 1542 | let name = ident.name; |
54a0048b SL |
1543 | let item = self.resolve_name_in_module(module, name, ns, true, record_used); |
1544 | if let Success(binding) = item { | |
1545 | // The ident resolves to an item. | |
1546 | return Some(LexicalScopeBinding::Item(binding)); | |
7453a54e | 1547 | } |
1a4d82fc | 1548 | |
9e0c209e SL |
1549 | if let ModuleKind::Block(..) = module.kind { // We can see through blocks |
1550 | } else if !module.no_implicit_prelude { | |
1551 | return self.prelude.and_then(|prelude| { | |
1552 | self.resolve_name_in_module(prelude, name, ns, false, None).success() | |
1553 | }).map(LexicalScopeBinding::Item) | |
1554 | } else { | |
1555 | return None; | |
3157f602 | 1556 | } |
1a4d82fc | 1557 | } |
5bcae85e SL |
1558 | |
1559 | if let MacroDefinition(mac) = self.get_ribs(ns)[i].kind { | |
1560 | // If an invocation of this macro created `ident`, give up on `ident` | |
1561 | // and switch to `ident`'s source from the macro definition. | |
1562 | let (source_ctxt, source_macro) = ident.ctxt.source(); | |
1563 | if source_macro == mac { | |
1564 | ident.ctxt = source_ctxt; | |
1565 | } | |
1566 | } | |
1a4d82fc | 1567 | } |
54a0048b SL |
1568 | |
1569 | None | |
1a4d82fc JJ |
1570 | } |
1571 | ||
1a4d82fc JJ |
1572 | /// Resolves a "module prefix". A module prefix is one or both of (a) `self::`; |
1573 | /// (b) some chain of `super::`. | |
1574 | /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * | |
c30ab7b3 | 1575 | fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option<Span>) |
9cc50fc6 | 1576 | -> ResolveResult<ModulePrefixResult<'a>> { |
c30ab7b3 SL |
1577 | if &*module_path[0].name.as_str() == "$crate" { |
1578 | return Success(PrefixFound(self.resolve_crate_var(module_path[0].ctxt), 1)); | |
1579 | } | |
1580 | ||
1a4d82fc JJ |
1581 | // Start at the current module if we see `self` or `super`, or at the |
1582 | // top of the crate otherwise. | |
c30ab7b3 | 1583 | let mut i = match &*module_path[0].name.as_str() { |
c1a9b12d SL |
1584 | "self" => 1, |
1585 | "super" => 0, | |
1586 | _ => return Success(NoPrefixFound), | |
1587 | }; | |
9e0c209e | 1588 | |
5bcae85e | 1589 | let mut containing_module = |
9e0c209e | 1590 | self.module_map[&self.current_module.normal_ancestor_id.unwrap()]; |
1a4d82fc JJ |
1591 | |
1592 | // Now loop through all the `super`s we find. | |
c30ab7b3 | 1593 | while i < module_path.len() && "super" == module_path[i].name.as_str() { |
1a4d82fc | 1594 | debug!("(resolving module prefix) resolving `super` at {}", |
7453a54e | 1595 | module_to_string(&containing_module)); |
9e0c209e SL |
1596 | if let Some(parent) = containing_module.parent { |
1597 | containing_module = self.module_map[&parent.normal_ancestor_id.unwrap()]; | |
1598 | i += 1; | |
1599 | } else { | |
1600 | let msg = "There are too many initial `super`s.".into(); | |
1601 | return Failed(span.map(|span| (span, msg))); | |
1a4d82fc JJ |
1602 | } |
1603 | } | |
1604 | ||
1605 | debug!("(resolving module prefix) finished resolving prefix at {}", | |
7453a54e | 1606 | module_to_string(&containing_module)); |
1a4d82fc JJ |
1607 | |
1608 | return Success(PrefixFound(containing_module, i)); | |
1609 | } | |
1610 | ||
c30ab7b3 SL |
1611 | fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a> { |
1612 | while crate_var_ctxt.source().0 != SyntaxContext::empty() { | |
1613 | crate_var_ctxt = crate_var_ctxt.source().0; | |
1614 | } | |
1615 | let module = self.invocations[&crate_var_ctxt.source().1].module.get(); | |
1616 | if module.is_local() { self.graph_root } else { module } | |
1617 | } | |
1618 | ||
1a4d82fc JJ |
1619 | // AST resolution |
1620 | // | |
1621 | // We maintain a list of value ribs and type ribs. | |
1622 | // | |
1623 | // Simultaneously, we keep track of the current position in the module | |
1624 | // graph in the `current_module` pointer. When we go to resolve a name in | |
1625 | // the value or type namespaces, we first look through all the ribs and | |
1626 | // then query the module graph. When we resolve a name in the module | |
1627 | // namespace, we can skip all the ribs (since nested modules are not | |
1628 | // allowed within blocks in Rust) and jump straight to the current module | |
1629 | // graph node. | |
1630 | // | |
1631 | // Named implementations are handled separately. When we find a method | |
1632 | // call, we consult the module node to find all of the implementations in | |
92a42be0 SL |
1633 | // scope. This information is lazily cached in the module node. We then |
1634 | // generate a fake "implementation scope" containing all the | |
1635 | // implementations thus found, for compatibility with old resolve pass. | |
1636 | ||
7453a54e | 1637 | fn with_scope<F>(&mut self, id: NodeId, f: F) |
92a42be0 SL |
1638 | where F: FnOnce(&mut Resolver) |
1639 | { | |
a7813a04 XL |
1640 | let module = self.module_map.get(&id).cloned(); // clones a reference |
1641 | if let Some(module) = module { | |
7453a54e | 1642 | // Move down in the graph. |
9e0c209e | 1643 | let orig_module = replace(&mut self.current_module, module); |
7453a54e SL |
1644 | self.value_ribs.push(Rib::new(ModuleRibKind(module))); |
1645 | self.type_ribs.push(Rib::new(ModuleRibKind(module))); | |
92a42be0 | 1646 | |
7453a54e | 1647 | f(self); |
1a4d82fc | 1648 | |
7453a54e SL |
1649 | self.current_module = orig_module; |
1650 | self.value_ribs.pop(); | |
1651 | self.type_ribs.pop(); | |
1652 | } else { | |
1653 | f(self); | |
1a4d82fc | 1654 | } |
1a4d82fc JJ |
1655 | } |
1656 | ||
1657 | /// Searches the current set of local scopes for labels. | |
1658 | /// Stops after meeting a closure. | |
c30ab7b3 | 1659 | fn search_label(&self, mut ident: Ident) -> Option<Def> { |
1a4d82fc JJ |
1660 | for rib in self.label_ribs.iter().rev() { |
1661 | match rib.kind { | |
1662 | NormalRibKind => { | |
1663 | // Continue | |
1664 | } | |
5bcae85e SL |
1665 | MacroDefinition(mac) => { |
1666 | // If an invocation of this macro created `ident`, give up on `ident` | |
1667 | // and switch to `ident`'s source from the macro definition. | |
1668 | let (source_ctxt, source_macro) = ident.ctxt.source(); | |
1669 | if source_macro == mac { | |
1670 | ident.ctxt = source_ctxt; | |
1671 | } | |
1672 | } | |
1a4d82fc JJ |
1673 | _ => { |
1674 | // Do not resolve labels across function boundary | |
92a42be0 | 1675 | return None; |
1a4d82fc JJ |
1676 | } |
1677 | } | |
5bcae85e | 1678 | let result = rib.bindings.get(&ident).cloned(); |
1a4d82fc | 1679 | if result.is_some() { |
92a42be0 | 1680 | return result; |
1a4d82fc JJ |
1681 | } |
1682 | } | |
1683 | None | |
1684 | } | |
1685 | ||
1a4d82fc | 1686 | fn resolve_item(&mut self, item: &Item) { |
a7813a04 | 1687 | let name = item.ident.name; |
1a4d82fc | 1688 | |
92a42be0 | 1689 | debug!("(resolving item) resolving {}", name); |
1a4d82fc JJ |
1690 | |
1691 | match item.node { | |
a7813a04 XL |
1692 | ItemKind::Enum(_, ref generics) | |
1693 | ItemKind::Ty(_, ref generics) | | |
9e0c209e SL |
1694 | ItemKind::Struct(_, ref generics) | |
1695 | ItemKind::Union(_, ref generics) | | |
1696 | ItemKind::Fn(.., ref generics, _) => { | |
1697 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), | |
a7813a04 | 1698 | |this| visit::walk_item(this, item)); |
1a4d82fc JJ |
1699 | } |
1700 | ||
a7813a04 | 1701 | ItemKind::DefaultImpl(_, ref trait_ref) => { |
9346a6ac | 1702 | self.with_optional_trait_ref(Some(trait_ref), |_, _| {}); |
c34b1796 | 1703 | } |
9e0c209e | 1704 | ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => |
c34b1796 | 1705 | self.resolve_implementation(generics, |
9346a6ac | 1706 | opt_trait_ref, |
7453a54e | 1707 | &self_type, |
9346a6ac | 1708 | item.id, |
a7813a04 | 1709 | impl_items), |
1a4d82fc | 1710 | |
a7813a04 | 1711 | ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => { |
1a4d82fc | 1712 | // Create a new rib for the trait-wide type parameters. |
9e0c209e | 1713 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { |
a7813a04 | 1714 | let local_def_id = this.definitions.local_def_id(item.id); |
7453a54e | 1715 | this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { |
9346a6ac | 1716 | this.visit_generics(generics); |
b039eaaf | 1717 | walk_list!(this, visit_ty_param_bound, bounds); |
9346a6ac AL |
1718 | |
1719 | for trait_item in trait_items { | |
d9579d0f | 1720 | match trait_item.node { |
a7813a04 | 1721 | TraitItemKind::Const(_, ref default) => { |
d9579d0f AL |
1722 | // Only impose the restrictions of |
1723 | // ConstRibKind if there's an actual constant | |
1724 | // expression in a provided default. | |
1725 | if default.is_some() { | |
1726 | this.with_constant_rib(|this| { | |
a7813a04 | 1727 | visit::walk_trait_item(this, trait_item) |
d9579d0f AL |
1728 | }); |
1729 | } else { | |
a7813a04 | 1730 | visit::walk_trait_item(this, trait_item) |
d9579d0f AL |
1731 | } |
1732 | } | |
a7813a04 | 1733 | TraitItemKind::Method(ref sig, _) => { |
d9579d0f AL |
1734 | let type_parameters = |
1735 | HasTypeParameters(&sig.generics, | |
3157f602 | 1736 | MethodRibKind(!sig.decl.has_self())); |
d9579d0f | 1737 | this.with_type_parameter_rib(type_parameters, |this| { |
a7813a04 | 1738 | visit::walk_trait_item(this, trait_item) |
d9579d0f | 1739 | }); |
9346a6ac | 1740 | } |
a7813a04 | 1741 | TraitItemKind::Type(..) => { |
d9579d0f | 1742 | this.with_type_parameter_rib(NoTypeParameters, |this| { |
a7813a04 | 1743 | visit::walk_trait_item(this, trait_item) |
d9579d0f | 1744 | }); |
9346a6ac | 1745 | } |
3157f602 | 1746 | TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), |
9346a6ac | 1747 | }; |
9346a6ac AL |
1748 | } |
1749 | }); | |
1a4d82fc | 1750 | }); |
1a4d82fc JJ |
1751 | } |
1752 | ||
a7813a04 | 1753 | ItemKind::Mod(_) | ItemKind::ForeignMod(_) => { |
7453a54e | 1754 | self.with_scope(item.id, |this| { |
a7813a04 | 1755 | visit::walk_item(this, item); |
1a4d82fc JJ |
1756 | }); |
1757 | } | |
1758 | ||
a7813a04 | 1759 | ItemKind::Const(..) | ItemKind::Static(..) => { |
1a4d82fc | 1760 | self.with_constant_rib(|this| { |
a7813a04 | 1761 | visit::walk_item(this, item); |
1a4d82fc JJ |
1762 | }); |
1763 | } | |
1764 | ||
a7813a04 | 1765 | ItemKind::Use(ref view_path) => { |
e9174d1e | 1766 | match view_path.node { |
a7813a04 | 1767 | ast::ViewPathList(ref prefix, ref items) => { |
b039eaaf SL |
1768 | // Resolve prefix of an import with empty braces (issue #28388) |
1769 | if items.is_empty() && !prefix.segments.is_empty() { | |
1770 | match self.resolve_crate_relative_path(prefix.span, | |
1771 | &prefix.segments, | |
1772 | TypeNS) { | |
a7813a04 | 1773 | Ok(binding) => { |
9e0c209e | 1774 | let def = binding.def(); |
3157f602 | 1775 | self.record_def(item.id, PathResolution::new(def)); |
a7813a04 | 1776 | } |
54a0048b SL |
1777 | Err(true) => self.record_def(item.id, err_path_resolution()), |
1778 | Err(false) => { | |
b039eaaf SL |
1779 | resolve_error(self, |
1780 | prefix.span, | |
1781 | ResolutionError::FailedToResolve( | |
1782 | &path_names_to_string(prefix, 0))); | |
9cc50fc6 | 1783 | self.record_def(item.id, err_path_resolution()); |
b039eaaf | 1784 | } |
e9174d1e SL |
1785 | } |
1786 | } | |
1787 | } | |
1788 | _ => {} | |
85aaf69f SL |
1789 | } |
1790 | } | |
1791 | ||
a7813a04 | 1792 | ItemKind::ExternCrate(_) => { |
1a4d82fc | 1793 | // do nothing, these are just around to be encoded |
85aaf69f | 1794 | } |
a7813a04 XL |
1795 | |
1796 | ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"), | |
1a4d82fc JJ |
1797 | } |
1798 | } | |
1799 | ||
7453a54e | 1800 | fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<'a, 'b>, f: F) |
92a42be0 | 1801 | where F: FnOnce(&mut Resolver) |
1a4d82fc JJ |
1802 | { |
1803 | match type_parameters { | |
9e0c209e | 1804 | HasTypeParameters(generics, rib_kind) => { |
1a4d82fc | 1805 | let mut function_type_rib = Rib::new(rib_kind); |
9e0c209e SL |
1806 | let mut seen_bindings = FnvHashMap(); |
1807 | for type_parameter in &generics.ty_params { | |
a7813a04 | 1808 | let name = type_parameter.ident.name; |
c34b1796 | 1809 | debug!("with_type_parameter_rib: {}", type_parameter.id); |
1a4d82fc | 1810 | |
9e0c209e SL |
1811 | if seen_bindings.contains_key(&name) { |
1812 | let span = seen_bindings.get(&name).unwrap(); | |
c1a9b12d SL |
1813 | resolve_error(self, |
1814 | type_parameter.span, | |
9e0c209e SL |
1815 | ResolutionError::NameAlreadyUsedInTypeParameterList(name, |
1816 | span)); | |
1a4d82fc | 1817 | } |
9e0c209e | 1818 | seen_bindings.entry(name).or_insert(type_parameter.span); |
1a4d82fc | 1819 | |
1a4d82fc | 1820 | // plain insert (no renaming) |
a7813a04 | 1821 | let def_id = self.definitions.local_def_id(type_parameter.id); |
9e0c209e | 1822 | let def = Def::TyParam(def_id); |
c30ab7b3 | 1823 | function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def); |
5bcae85e | 1824 | self.record_def(type_parameter.id, PathResolution::new(def)); |
1a4d82fc JJ |
1825 | } |
1826 | self.type_ribs.push(function_type_rib); | |
1827 | } | |
1828 | ||
1829 | NoTypeParameters => { | |
1830 | // Nothing to do. | |
1831 | } | |
1832 | } | |
1833 | ||
1834 | f(self); | |
1835 | ||
a7813a04 XL |
1836 | if let HasTypeParameters(..) = type_parameters { |
1837 | self.type_ribs.pop(); | |
1a4d82fc JJ |
1838 | } |
1839 | } | |
1840 | ||
92a42be0 SL |
1841 | fn with_label_rib<F>(&mut self, f: F) |
1842 | where F: FnOnce(&mut Resolver) | |
1a4d82fc JJ |
1843 | { |
1844 | self.label_ribs.push(Rib::new(NormalRibKind)); | |
c34b1796 | 1845 | f(self); |
a7813a04 | 1846 | self.label_ribs.pop(); |
1a4d82fc JJ |
1847 | } |
1848 | ||
92a42be0 SL |
1849 | fn with_constant_rib<F>(&mut self, f: F) |
1850 | where F: FnOnce(&mut Resolver) | |
c34b1796 AL |
1851 | { |
1852 | self.value_ribs.push(Rib::new(ConstantItemRibKind)); | |
1853 | self.type_ribs.push(Rib::new(ConstantItemRibKind)); | |
1854 | f(self); | |
a7813a04 XL |
1855 | self.type_ribs.pop(); |
1856 | self.value_ribs.pop(); | |
1a4d82fc JJ |
1857 | } |
1858 | ||
3157f602 XL |
1859 | fn resolve_function(&mut self, |
1860 | rib_kind: RibKind<'a>, | |
1861 | declaration: &FnDecl, | |
1862 | block: &Block) { | |
c34b1796 AL |
1863 | // Create a value rib for the function. |
1864 | self.value_ribs.push(Rib::new(rib_kind)); | |
1a4d82fc | 1865 | |
c34b1796 AL |
1866 | // Create a label rib for the function. |
1867 | self.label_ribs.push(Rib::new(rib_kind)); | |
1a4d82fc | 1868 | |
c34b1796 | 1869 | // Add each argument to the rib. |
9e0c209e | 1870 | let mut bindings_list = FnvHashMap(); |
c34b1796 | 1871 | for argument in &declaration.inputs { |
3157f602 | 1872 | self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); |
c34b1796 | 1873 | |
7453a54e | 1874 | self.visit_ty(&argument.ty); |
c34b1796 AL |
1875 | |
1876 | debug!("(resolving function) recorded argument"); | |
1a4d82fc | 1877 | } |
a7813a04 | 1878 | visit::walk_fn_ret_ty(self, &declaration.output); |
c34b1796 AL |
1879 | |
1880 | // Resolve the function body. | |
92a42be0 | 1881 | self.visit_block(block); |
1a4d82fc | 1882 | |
c34b1796 AL |
1883 | debug!("(resolving function) leaving function"); |
1884 | ||
a7813a04 XL |
1885 | self.label_ribs.pop(); |
1886 | self.value_ribs.pop(); | |
1a4d82fc JJ |
1887 | } |
1888 | ||
1889 | fn resolve_trait_reference(&mut self, | |
1890 | id: NodeId, | |
c34b1796 AL |
1891 | trait_path: &Path, |
1892 | path_depth: usize) | |
1893 | -> Result<PathResolution, ()> { | |
54a0048b | 1894 | self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| { |
5bcae85e SL |
1895 | match path_res.base_def { |
1896 | Def::Trait(_) => { | |
1897 | debug!("(resolving trait) found trait def: {:?}", path_res); | |
1898 | return Ok(path_res); | |
1a4d82fc | 1899 | } |
5bcae85e SL |
1900 | Def::Err => return Err(true), |
1901 | _ => {} | |
1a4d82fc | 1902 | } |
5bcae85e SL |
1903 | |
1904 | let mut err = resolve_struct_error(self, trait_path.span, { | |
1905 | ResolutionError::IsNotATrait(&path_names_to_string(trait_path, path_depth)) | |
1906 | }); | |
1907 | ||
1908 | // If it's a typedef, give a note | |
1909 | if let Def::TyAlias(..) = path_res.base_def { | |
1910 | err.note(&format!("type aliases cannot be used for traits")); | |
1911 | } | |
1912 | err.emit(); | |
1913 | Err(true) | |
54a0048b SL |
1914 | }).map_err(|error_reported| { |
1915 | if error_reported { return } | |
7453a54e SL |
1916 | |
1917 | // find possible candidates | |
1918 | let trait_name = trait_path.segments.last().unwrap().identifier.name; | |
1919 | let candidates = | |
1920 | self.lookup_candidates( | |
1921 | trait_name, | |
1922 | TypeNS, | |
1923 | |def| match def { | |
1924 | Def::Trait(_) => true, | |
1925 | _ => false, | |
1926 | }, | |
1927 | ); | |
1928 | ||
1929 | // create error object | |
1930 | let name = &path_names_to_string(trait_path, path_depth); | |
1931 | let error = | |
1932 | ResolutionError::UndeclaredTraitName( | |
1933 | name, | |
1934 | candidates, | |
1935 | ); | |
1936 | ||
1937 | resolve_error(self, trait_path.span, error); | |
54a0048b | 1938 | }) |
1a4d82fc JJ |
1939 | } |
1940 | ||
9346a6ac AL |
1941 | fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T |
1942 | where F: FnOnce(&mut Resolver) -> T | |
1a4d82fc JJ |
1943 | { |
1944 | // Handle nested impls (inside fn bodies) | |
1945 | let previous_value = replace(&mut self.current_self_type, Some(self_type.clone())); | |
1946 | let result = f(self); | |
1947 | self.current_self_type = previous_value; | |
1948 | result | |
1949 | } | |
1950 | ||
92a42be0 | 1951 | fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T |
9346a6ac | 1952 | where F: FnOnce(&mut Resolver, Option<DefId>) -> T |
1a4d82fc | 1953 | { |
c34b1796 | 1954 | let mut new_val = None; |
9346a6ac | 1955 | let mut new_id = None; |
c34b1796 | 1956 | if let Some(trait_ref) = opt_trait_ref { |
9346a6ac | 1957 | if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id, |
92a42be0 SL |
1958 | &trait_ref.path, |
1959 | 0) { | |
9346a6ac AL |
1960 | assert!(path_res.depth == 0); |
1961 | self.record_def(trait_ref.ref_id, path_res); | |
1962 | new_val = Some((path_res.base_def.def_id(), trait_ref.clone())); | |
1963 | new_id = Some(path_res.base_def.def_id()); | |
9cc50fc6 SL |
1964 | } else { |
1965 | self.record_def(trait_ref.ref_id, err_path_resolution()); | |
1a4d82fc | 1966 | } |
a7813a04 | 1967 | visit::walk_trait_ref(self, trait_ref); |
c34b1796 | 1968 | } |
1a4d82fc | 1969 | let original_trait_ref = replace(&mut self.current_trait_ref, new_val); |
9346a6ac | 1970 | let result = f(self, new_id); |
1a4d82fc JJ |
1971 | self.current_trait_ref = original_trait_ref; |
1972 | result | |
1973 | } | |
1974 | ||
9346a6ac AL |
1975 | fn with_self_rib<F>(&mut self, self_def: Def, f: F) |
1976 | where F: FnOnce(&mut Resolver) | |
1977 | { | |
1978 | let mut self_type_rib = Rib::new(NormalRibKind); | |
1979 | ||
1980 | // plain insert (no renaming, types are not currently hygienic....) | |
5bcae85e | 1981 | self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); |
9346a6ac AL |
1982 | self.type_ribs.push(self_type_rib); |
1983 | f(self); | |
a7813a04 | 1984 | self.type_ribs.pop(); |
9346a6ac AL |
1985 | } |
1986 | ||
1a4d82fc | 1987 | fn resolve_implementation(&mut self, |
1a4d82fc JJ |
1988 | generics: &Generics, |
1989 | opt_trait_reference: &Option<TraitRef>, | |
1990 | self_type: &Ty, | |
9346a6ac | 1991 | item_id: NodeId, |
92a42be0 | 1992 | impl_items: &[ImplItem]) { |
1a4d82fc | 1993 | // If applicable, create a rib for the type parameters. |
9e0c209e | 1994 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { |
1a4d82fc | 1995 | // Resolve the type parameters. |
c34b1796 | 1996 | this.visit_generics(generics); |
1a4d82fc JJ |
1997 | |
1998 | // Resolve the trait reference, if necessary. | |
9346a6ac | 1999 | this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { |
1a4d82fc | 2000 | // Resolve the self type. |
c34b1796 | 2001 | this.visit_ty(self_type); |
1a4d82fc | 2002 | |
9e0c209e SL |
2003 | let item_def_id = this.definitions.local_def_id(item_id); |
2004 | this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| { | |
9346a6ac AL |
2005 | this.with_current_self_type(self_type, |this| { |
2006 | for impl_item in impl_items { | |
a7813a04 | 2007 | this.resolve_visibility(&impl_item.vis); |
9346a6ac | 2008 | match impl_item.node { |
a7813a04 | 2009 | ImplItemKind::Const(..) => { |
c1a9b12d | 2010 | // If this is a trait impl, ensure the const |
d9579d0f | 2011 | // exists in trait |
a7813a04 | 2012 | this.check_trait_item(impl_item.ident.name, |
c1a9b12d SL |
2013 | impl_item.span, |
2014 | |n, s| ResolutionError::ConstNotMemberOfTrait(n, s)); | |
a7813a04 | 2015 | visit::walk_impl_item(this, impl_item); |
d9579d0f | 2016 | } |
a7813a04 | 2017 | ImplItemKind::Method(ref sig, _) => { |
9346a6ac AL |
2018 | // If this is a trait impl, ensure the method |
2019 | // exists in trait | |
a7813a04 | 2020 | this.check_trait_item(impl_item.ident.name, |
c1a9b12d SL |
2021 | impl_item.span, |
2022 | |n, s| ResolutionError::MethodNotMemberOfTrait(n, s)); | |
9346a6ac AL |
2023 | |
2024 | // We also need a new scope for the method- | |
2025 | // specific type parameters. | |
2026 | let type_parameters = | |
2027 | HasTypeParameters(&sig.generics, | |
3157f602 | 2028 | MethodRibKind(!sig.decl.has_self())); |
9346a6ac | 2029 | this.with_type_parameter_rib(type_parameters, |this| { |
a7813a04 | 2030 | visit::walk_impl_item(this, impl_item); |
9346a6ac AL |
2031 | }); |
2032 | } | |
a7813a04 | 2033 | ImplItemKind::Type(ref ty) => { |
c1a9b12d | 2034 | // If this is a trait impl, ensure the type |
9346a6ac | 2035 | // exists in trait |
a7813a04 | 2036 | this.check_trait_item(impl_item.ident.name, |
c1a9b12d SL |
2037 | impl_item.span, |
2038 | |n, s| ResolutionError::TypeNotMemberOfTrait(n, s)); | |
1a4d82fc | 2039 | |
9346a6ac AL |
2040 | this.visit_ty(ty); |
2041 | } | |
a7813a04 | 2042 | ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), |
1a4d82fc JJ |
2043 | } |
2044 | } | |
9346a6ac | 2045 | }); |
1a4d82fc JJ |
2046 | }); |
2047 | }); | |
2048 | }); | |
1a4d82fc JJ |
2049 | } |
2050 | ||
c1a9b12d | 2051 | fn check_trait_item<F>(&self, name: Name, span: Span, err: F) |
92a42be0 SL |
2052 | where F: FnOnce(Name, &str) -> ResolutionError |
2053 | { | |
2054 | // If there is a TraitRef in scope for an impl, then the method must be in the | |
2055 | // trait. | |
85aaf69f | 2056 | if let Some((did, ref trait_ref)) = self.current_trait_ref { |
c34b1796 AL |
2057 | if !self.trait_item_map.contains_key(&(name, did)) { |
2058 | let path_str = path_names_to_string(&trait_ref.path, 0); | |
7453a54e | 2059 | resolve_error(self, span, err(name, &path_str)); |
1a4d82fc JJ |
2060 | } |
2061 | } | |
2062 | } | |
2063 | ||
1a4d82fc JJ |
2064 | fn resolve_local(&mut self, local: &Local) { |
2065 | // Resolve the type. | |
b039eaaf | 2066 | walk_list!(self, visit_ty, &local.ty); |
1a4d82fc | 2067 | |
c34b1796 | 2068 | // Resolve the initializer. |
b039eaaf | 2069 | walk_list!(self, visit_expr, &local.init); |
1a4d82fc JJ |
2070 | |
2071 | // Resolve the pattern. | |
9e0c209e | 2072 | self.resolve_pattern(&local.pat, PatternSource::Let, &mut FnvHashMap()); |
1a4d82fc JJ |
2073 | } |
2074 | ||
2075 | // build a map from pattern identifiers to binding-info's. | |
2076 | // this is done hygienically. This could arise for a macro | |
2077 | // that expands into an or-pattern where one 'x' was from the | |
2078 | // user and one 'x' came from the macro. | |
2079 | fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { | |
9e0c209e | 2080 | let mut binding_map = FnvHashMap(); |
a7813a04 XL |
2081 | |
2082 | pat.walk(&mut |pat| { | |
2083 | if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { | |
2084 | if sub_pat.is_some() || match self.def_map.get(&pat.id) { | |
2085 | Some(&PathResolution { base_def: Def::Local(..), .. }) => true, | |
2086 | _ => false, | |
2087 | } { | |
2088 | let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; | |
5bcae85e | 2089 | binding_map.insert(ident.node, binding_info); |
a7813a04 XL |
2090 | } |
2091 | } | |
2092 | true | |
1a4d82fc | 2093 | }); |
a7813a04 XL |
2094 | |
2095 | binding_map | |
1a4d82fc JJ |
2096 | } |
2097 | ||
2098 | // check that all of the arms in an or-pattern have exactly the | |
2099 | // same set of bindings, with the same binding modes for each. | |
2100 | fn check_consistent_bindings(&mut self, arm: &Arm) { | |
9346a6ac | 2101 | if arm.pats.is_empty() { |
92a42be0 | 2102 | return; |
1a4d82fc | 2103 | } |
7453a54e | 2104 | let map_0 = self.binding_mode_map(&arm.pats[0]); |
1a4d82fc | 2105 | for (i, p) in arm.pats.iter().enumerate() { |
7453a54e | 2106 | let map_i = self.binding_mode_map(&p); |
1a4d82fc | 2107 | |
85aaf69f | 2108 | for (&key, &binding_0) in &map_0 { |
1a4d82fc | 2109 | match map_i.get(&key) { |
92a42be0 | 2110 | None => { |
5bcae85e SL |
2111 | let error = ResolutionError::VariableNotBoundInPattern(key.name, 1, i + 1); |
2112 | resolve_error(self, p.span, error); | |
92a42be0 SL |
2113 | } |
2114 | Some(binding_i) => { | |
2115 | if binding_0.binding_mode != binding_i.binding_mode { | |
2116 | resolve_error(self, | |
2117 | binding_i.span, | |
9e0c209e SL |
2118 | ResolutionError::VariableBoundWithDifferentMode( |
2119 | key.name, | |
2120 | i + 1, | |
2121 | binding_0.span)); | |
92a42be0 | 2122 | } |
1a4d82fc | 2123 | } |
1a4d82fc JJ |
2124 | } |
2125 | } | |
2126 | ||
85aaf69f | 2127 | for (&key, &binding) in &map_i { |
1a4d82fc | 2128 | if !map_0.contains_key(&key) { |
c1a9b12d SL |
2129 | resolve_error(self, |
2130 | binding.span, | |
5bcae85e | 2131 | ResolutionError::VariableNotBoundInPattern(key.name, i + 1, 1)); |
1a4d82fc JJ |
2132 | } |
2133 | } | |
2134 | } | |
2135 | } | |
2136 | ||
2137 | fn resolve_arm(&mut self, arm: &Arm) { | |
2138 | self.value_ribs.push(Rib::new(NormalRibKind)); | |
2139 | ||
9e0c209e | 2140 | let mut bindings_list = FnvHashMap(); |
85aaf69f | 2141 | for pattern in &arm.pats { |
3157f602 | 2142 | self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list); |
1a4d82fc JJ |
2143 | } |
2144 | ||
2145 | // This has to happen *after* we determine which | |
2146 | // pat_idents are variants | |
2147 | self.check_consistent_bindings(arm); | |
2148 | ||
b039eaaf | 2149 | walk_list!(self, visit_expr, &arm.guard); |
7453a54e | 2150 | self.visit_expr(&arm.body); |
1a4d82fc | 2151 | |
a7813a04 | 2152 | self.value_ribs.pop(); |
1a4d82fc JJ |
2153 | } |
2154 | ||
2155 | fn resolve_block(&mut self, block: &Block) { | |
2156 | debug!("(resolving block) entering block"); | |
1a4d82fc | 2157 | // Move down in the graph, if there's an anonymous module rooted here. |
9cc50fc6 | 2158 | let orig_module = self.current_module; |
a7813a04 | 2159 | let anonymous_module = self.module_map.get(&block.id).cloned(); // clones a reference |
7453a54e | 2160 | |
5bcae85e | 2161 | let mut num_macro_definition_ribs = 0; |
7453a54e SL |
2162 | if let Some(anonymous_module) = anonymous_module { |
2163 | debug!("(resolving block) found anonymous module, moving down"); | |
2164 | self.value_ribs.push(Rib::new(ModuleRibKind(anonymous_module))); | |
2165 | self.type_ribs.push(Rib::new(ModuleRibKind(anonymous_module))); | |
2166 | self.current_module = anonymous_module; | |
2167 | } else { | |
2168 | self.value_ribs.push(Rib::new(NormalRibKind)); | |
85aaf69f SL |
2169 | } |
2170 | ||
1a4d82fc | 2171 | // Descend into the block. |
5bcae85e SL |
2172 | for stmt in &block.stmts { |
2173 | if let Some(marks) = self.macros_at_scope.remove(&stmt.id) { | |
2174 | num_macro_definition_ribs += marks.len() as u32; | |
2175 | for mark in marks { | |
2176 | self.value_ribs.push(Rib::new(MacroDefinition(mark))); | |
2177 | self.label_ribs.push(Rib::new(MacroDefinition(mark))); | |
2178 | } | |
2179 | } | |
2180 | ||
2181 | self.visit_stmt(stmt); | |
2182 | } | |
1a4d82fc JJ |
2183 | |
2184 | // Move back up. | |
a7813a04 | 2185 | self.current_module = orig_module; |
5bcae85e SL |
2186 | for _ in 0 .. num_macro_definition_ribs { |
2187 | self.value_ribs.pop(); | |
2188 | self.label_ribs.pop(); | |
2189 | } | |
a7813a04 XL |
2190 | self.value_ribs.pop(); |
2191 | if let Some(_) = anonymous_module { | |
2192 | self.type_ribs.pop(); | |
e9174d1e | 2193 | } |
1a4d82fc JJ |
2194 | debug!("(resolving block) leaving block"); |
2195 | } | |
2196 | ||
2197 | fn resolve_type(&mut self, ty: &Ty) { | |
2198 | match ty.node { | |
a7813a04 | 2199 | TyKind::Path(ref maybe_qself, ref path) => { |
c34b1796 AL |
2200 | // This is a path in the type namespace. Walk through scopes |
2201 | // looking for it. | |
3157f602 XL |
2202 | if let Some(def) = self.resolve_possibly_assoc_item(ty.id, maybe_qself.as_ref(), |
2203 | path, TypeNS) { | |
2204 | match def.base_def { | |
2205 | Def::Mod(..) if def.depth == 0 => { | |
2206 | self.session.span_err(path.span, "expected type, found module"); | |
2207 | self.record_def(ty.id, err_path_resolution()); | |
2208 | } | |
2209 | _ => { | |
2210 | // Write the result into the def map. | |
2211 | debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}", | |
2212 | path_names_to_string(path, 0), ty.id, def); | |
2213 | self.record_def(ty.id, def); | |
2214 | } | |
2215 | } | |
54a0048b SL |
2216 | } else { |
2217 | self.record_def(ty.id, err_path_resolution()); | |
1a4d82fc | 2218 | |
54a0048b SL |
2219 | // Keep reporting some errors even if they're ignored above. |
2220 | if let Err(true) = self.resolve_path(ty.id, path, 0, TypeNS) { | |
2221 | // `resolve_path` already reported the error | |
2222 | } else { | |
c34b1796 AL |
2223 | let kind = if maybe_qself.is_some() { |
2224 | "associated type" | |
2225 | } else { | |
2226 | "type name" | |
2227 | }; | |
1a4d82fc | 2228 | |
92a42be0 SL |
2229 | let is_invalid_self_type_name = path.segments.len() > 0 && |
2230 | maybe_qself.is_none() && | |
2231 | path.segments[0].identifier.name == | |
a7813a04 | 2232 | keywords::SelfType.name(); |
c1a9b12d SL |
2233 | if is_invalid_self_type_name { |
2234 | resolve_error(self, | |
2235 | ty.span, | |
2236 | ResolutionError::SelfUsedOutsideImplOrTrait); | |
62682a34 | 2237 | } else { |
7453a54e SL |
2238 | let segment = path.segments.last(); |
2239 | let segment = segment.expect("missing name in path"); | |
2240 | let type_name = segment.identifier.name; | |
2241 | ||
2242 | let candidates = | |
2243 | self.lookup_candidates( | |
2244 | type_name, | |
2245 | TypeNS, | |
2246 | |def| match def { | |
2247 | Def::Trait(_) | | |
2248 | Def::Enum(_) | | |
2249 | Def::Struct(_) | | |
9e0c209e | 2250 | Def::Union(_) | |
7453a54e SL |
2251 | Def::TyAlias(_) => true, |
2252 | _ => false, | |
2253 | }, | |
2254 | ); | |
2255 | ||
2256 | // create error object | |
2257 | let name = &path_names_to_string(path, 0); | |
2258 | let error = | |
2259 | ResolutionError::UseOfUndeclared( | |
2260 | kind, | |
2261 | name, | |
2262 | candidates, | |
2263 | ); | |
2264 | ||
2265 | resolve_error(self, ty.span, error); | |
c1a9b12d | 2266 | } |
c34b1796 | 2267 | } |
85aaf69f | 2268 | } |
1a4d82fc | 2269 | } |
c34b1796 | 2270 | _ => {} |
1a4d82fc | 2271 | } |
c34b1796 | 2272 | // Resolve embedded types. |
a7813a04 | 2273 | visit::walk_ty(self, ty); |
1a4d82fc JJ |
2274 | } |
2275 | ||
3157f602 | 2276 | fn fresh_binding(&mut self, |
9e0c209e | 2277 | ident: &SpannedIdent, |
3157f602 XL |
2278 | pat_id: NodeId, |
2279 | outer_pat_id: NodeId, | |
2280 | pat_src: PatternSource, | |
c30ab7b3 | 2281 | bindings: &mut FnvHashMap<Ident, NodeId>) |
3157f602 XL |
2282 | -> PathResolution { |
2283 | // Add the binding to the local ribs, if it | |
2284 | // doesn't already exist in the bindings map. (We | |
2285 | // must not add it if it's in the bindings map | |
2286 | // because that breaks the assumptions later | |
2287 | // passes make about or-patterns.) | |
9e0c209e | 2288 | let mut def = Def::Local(self.definitions.local_def_id(pat_id)); |
5bcae85e | 2289 | match bindings.get(&ident.node).cloned() { |
3157f602 XL |
2290 | Some(id) if id == outer_pat_id => { |
2291 | // `Variant(a, a)`, error | |
2292 | resolve_error( | |
2293 | self, | |
2294 | ident.span, | |
2295 | ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( | |
2296 | &ident.node.name.as_str()) | |
2297 | ); | |
3157f602 XL |
2298 | } |
2299 | Some(..) if pat_src == PatternSource::FnParam => { | |
2300 | // `fn f(a: u8, a: u8)`, error | |
2301 | resolve_error( | |
2302 | self, | |
2303 | ident.span, | |
2304 | ResolutionError::IdentifierBoundMoreThanOnceInParameterList( | |
2305 | &ident.node.name.as_str()) | |
2306 | ); | |
3157f602 XL |
2307 | } |
2308 | Some(..) if pat_src == PatternSource::Match => { | |
2309 | // `Variant1(a) | Variant2(a)`, ok | |
2310 | // Reuse definition from the first `a`. | |
5bcae85e | 2311 | def = self.value_ribs.last_mut().unwrap().bindings[&ident.node]; |
3157f602 XL |
2312 | } |
2313 | Some(..) => { | |
2314 | span_bug!(ident.span, "two bindings with the same name from \ | |
2315 | unexpected pattern source {:?}", pat_src); | |
2316 | } | |
2317 | None => { | |
5bcae85e | 2318 | // A completely fresh binding, add to the lists if it's valid. |
3157f602 | 2319 | if ident.node.name != keywords::Invalid.name() { |
5bcae85e SL |
2320 | bindings.insert(ident.node, outer_pat_id); |
2321 | self.value_ribs.last_mut().unwrap().bindings.insert(ident.node, def); | |
1a4d82fc | 2322 | } |
3157f602 | 2323 | } |
5bcae85e | 2324 | } |
1a4d82fc | 2325 | |
3157f602 XL |
2326 | PathResolution::new(def) |
2327 | } | |
a7813a04 | 2328 | |
3157f602 XL |
2329 | fn resolve_pattern_path<ExpectedFn>(&mut self, |
2330 | pat_id: NodeId, | |
2331 | qself: Option<&QSelf>, | |
2332 | path: &Path, | |
2333 | namespace: Namespace, | |
2334 | expected_fn: ExpectedFn, | |
2335 | expected_what: &str) | |
2336 | where ExpectedFn: FnOnce(Def) -> bool | |
2337 | { | |
2338 | let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id, | |
2339 | qself, path, namespace) { | |
2340 | if resolution.depth == 0 { | |
5bcae85e | 2341 | if expected_fn(resolution.base_def) || resolution.base_def == Def::Err { |
3157f602 XL |
2342 | resolution |
2343 | } else { | |
2344 | resolve_error( | |
2345 | self, | |
2346 | path.span, | |
2347 | ResolutionError::PatPathUnexpected(expected_what, | |
2348 | resolution.kind_name(), path) | |
2349 | ); | |
2350 | err_path_resolution() | |
2351 | } | |
2352 | } else { | |
2353 | // Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B` | |
2354 | // or `<T>::A::B`. If `B` should be resolved in value namespace then | |
2355 | // it needs to be added to the trait map. | |
2356 | if namespace == ValueNS { | |
2357 | let item_name = path.segments.last().unwrap().identifier.name; | |
2358 | let traits = self.get_traits_containing_item(item_name); | |
2359 | self.trait_map.insert(pat_id, traits); | |
d9579d0f | 2360 | } |
3157f602 XL |
2361 | resolution |
2362 | } | |
2363 | } else { | |
2364 | if let Err(false) = self.resolve_path(pat_id, path, 0, namespace) { | |
2365 | resolve_error( | |
2366 | self, | |
2367 | path.span, | |
2368 | ResolutionError::PatPathUnresolved(expected_what, path) | |
2369 | ); | |
2370 | } | |
2371 | err_path_resolution() | |
2372 | }; | |
d9579d0f | 2373 | |
3157f602 XL |
2374 | self.record_def(pat_id, resolution); |
2375 | } | |
2376 | ||
c30ab7b3 SL |
2377 | fn resolve_struct_path(&mut self, node_id: NodeId, path: &Path) { |
2378 | // Resolution logic is equivalent for expressions and patterns, | |
2379 | // reuse `resolve_pattern_path` for both. | |
2380 | self.resolve_pattern_path(node_id, None, path, TypeNS, |def| { | |
2381 | match def { | |
2382 | Def::Struct(..) | Def::Union(..) | Def::Variant(..) | | |
2383 | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true, | |
2384 | _ => false, | |
2385 | } | |
2386 | }, "struct, variant or union type"); | |
2387 | } | |
2388 | ||
3157f602 XL |
2389 | fn resolve_pattern(&mut self, |
2390 | pat: &Pat, | |
2391 | pat_src: PatternSource, | |
2392 | // Maps idents to the node ID for the | |
2393 | // outermost pattern that binds them. | |
c30ab7b3 | 2394 | bindings: &mut FnvHashMap<Ident, NodeId>) { |
3157f602 XL |
2395 | // Visit all direct subpatterns of this pattern. |
2396 | let outer_pat_id = pat.id; | |
2397 | pat.walk(&mut |pat| { | |
2398 | match pat.node { | |
2399 | PatKind::Ident(bmode, ref ident, ref opt_pat) => { | |
2400 | // First try to resolve the identifier as some existing | |
2401 | // entity, then fall back to a fresh binding. | |
9e0c209e | 2402 | let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None) |
5bcae85e | 2403 | .and_then(LexicalScopeBinding::item); |
9e0c209e | 2404 | let resolution = binding.map(NameBinding::def).and_then(|def| { |
3157f602 XL |
2405 | let always_binding = !pat_src.is_refutable() || opt_pat.is_some() || |
2406 | bmode != BindingMode::ByValue(Mutability::Immutable); | |
2407 | match def { | |
c30ab7b3 SL |
2408 | Def::StructCtor(_, CtorKind::Const) | |
2409 | Def::VariantCtor(_, CtorKind::Const) | | |
2410 | Def::Const(..) if !always_binding => { | |
2411 | // A unit struct/variant or constant pattern. | |
9e0c209e SL |
2412 | let name = ident.node.name; |
2413 | self.record_use(name, ValueNS, binding.unwrap(), ident.span); | |
5bcae85e | 2414 | Some(PathResolution::new(def)) |
d9579d0f | 2415 | } |
c30ab7b3 SL |
2416 | Def::StructCtor(..) | Def::VariantCtor(..) | |
2417 | Def::Const(..) | Def::Static(..) => { | |
3157f602 | 2418 | // A fresh binding that shadows something unacceptable. |
c1a9b12d SL |
2419 | resolve_error( |
2420 | self, | |
3157f602 XL |
2421 | ident.span, |
2422 | ResolutionError::BindingShadowsSomethingUnacceptable( | |
5bcae85e | 2423 | pat_src.descr(), ident.node.name, binding.unwrap()) |
c1a9b12d | 2424 | ); |
5bcae85e | 2425 | None |
3157f602 XL |
2426 | } |
2427 | Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => { | |
2428 | // These entities are explicitly allowed | |
2429 | // to be shadowed by fresh bindings. | |
5bcae85e | 2430 | None |
3157f602 XL |
2431 | } |
2432 | def => { | |
2433 | span_bug!(ident.span, "unexpected definition for an \ | |
c30ab7b3 | 2434 | identifier in pattern: {:?}", def); |
c34b1796 | 2435 | } |
1a4d82fc | 2436 | } |
5bcae85e | 2437 | }).unwrap_or_else(|| { |
3157f602 | 2438 | self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings) |
5bcae85e | 2439 | }); |
3157f602 XL |
2440 | |
2441 | self.record_def(pat.id, resolution); | |
1a4d82fc JJ |
2442 | } |
2443 | ||
9e0c209e | 2444 | PatKind::TupleStruct(ref path, ..) => { |
3157f602 XL |
2445 | self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| { |
2446 | match def { | |
c30ab7b3 SL |
2447 | Def::StructCtor(_, CtorKind::Fn) | |
2448 | Def::VariantCtor(_, CtorKind::Fn) => true, | |
3157f602 | 2449 | _ => false, |
1a4d82fc | 2450 | } |
c30ab7b3 | 2451 | }, "tuple struct/variant"); |
c34b1796 AL |
2452 | } |
2453 | ||
3157f602 XL |
2454 | PatKind::Path(ref qself, ref path) => { |
2455 | self.resolve_pattern_path(pat.id, qself.as_ref(), path, ValueNS, |def| { | |
2456 | match def { | |
c30ab7b3 SL |
2457 | Def::StructCtor(_, CtorKind::Const) | |
2458 | Def::VariantCtor(_, CtorKind::Const) | | |
5bcae85e | 2459 | Def::Const(..) | Def::AssociatedConst(..) => true, |
3157f602 XL |
2460 | _ => false, |
2461 | } | |
c30ab7b3 | 2462 | }, "unit struct/variant or constant"); |
1a4d82fc JJ |
2463 | } |
2464 | ||
9e0c209e | 2465 | PatKind::Struct(ref path, ..) => { |
c30ab7b3 | 2466 | self.resolve_struct_path(pat.id, path); |
1a4d82fc | 2467 | } |
3157f602 XL |
2468 | |
2469 | _ => {} | |
1a4d82fc JJ |
2470 | } |
2471 | true | |
2472 | }); | |
a7813a04 | 2473 | |
3157f602 | 2474 | visit::walk_pat(self, pat); |
1a4d82fc JJ |
2475 | } |
2476 | ||
d9579d0f AL |
2477 | /// Handles paths that may refer to associated items |
2478 | fn resolve_possibly_assoc_item(&mut self, | |
2479 | id: NodeId, | |
3157f602 | 2480 | maybe_qself: Option<&QSelf>, |
d9579d0f | 2481 | path: &Path, |
54a0048b | 2482 | namespace: Namespace) |
3157f602 | 2483 | -> Option<PathResolution> { |
d9579d0f AL |
2484 | let max_assoc_types; |
2485 | ||
2486 | match maybe_qself { | |
2487 | Some(qself) => { | |
2488 | if qself.position == 0 { | |
3157f602 XL |
2489 | // FIXME: Create some fake resolution that can't possibly be a type. |
2490 | return Some(PathResolution { | |
2491 | base_def: Def::Mod(self.definitions.local_def_id(ast::CRATE_NODE_ID)), | |
2492 | depth: path.segments.len(), | |
2493 | }); | |
d9579d0f AL |
2494 | } |
2495 | max_assoc_types = path.segments.len() - qself.position; | |
2496 | // Make sure the trait is valid. | |
2497 | let _ = self.resolve_trait_reference(id, path, max_assoc_types); | |
2498 | } | |
2499 | None => { | |
2500 | max_assoc_types = path.segments.len(); | |
2501 | } | |
2502 | } | |
2503 | ||
2504 | let mut resolution = self.with_no_errors(|this| { | |
54a0048b | 2505 | this.resolve_path(id, path, 0, namespace).ok() |
d9579d0f AL |
2506 | }); |
2507 | for depth in 1..max_assoc_types { | |
2508 | if resolution.is_some() { | |
2509 | break; | |
2510 | } | |
2511 | self.with_no_errors(|this| { | |
3157f602 XL |
2512 | let partial_resolution = this.resolve_path(id, path, depth, TypeNS).ok(); |
2513 | if let Some(Def::Mod(..)) = partial_resolution.map(|r| r.base_def) { | |
2514 | // Modules cannot have associated items | |
2515 | } else { | |
2516 | resolution = partial_resolution; | |
2517 | } | |
d9579d0f AL |
2518 | }); |
2519 | } | |
3157f602 | 2520 | resolution |
d9579d0f AL |
2521 | } |
2522 | ||
c34b1796 | 2523 | /// Skips `path_depth` trailing segments, which is also reflected in the |
54a0048b SL |
2524 | /// returned value. See `hir::def::PathResolution` for more info. |
2525 | fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace) | |
2526 | -> Result<PathResolution, bool /* true if an error was reported */ > { | |
a7813a04 XL |
2527 | debug!("resolve_path(id={:?} path={:?}, path_depth={:?})", id, path, path_depth); |
2528 | ||
c34b1796 | 2529 | let span = path.span; |
92a42be0 | 2530 | let segments = &path.segments[..path.segments.len() - path_depth]; |
1a4d82fc | 2531 | |
3157f602 | 2532 | let mk_res = |def| PathResolution { base_def: def, depth: path_depth }; |
1a4d82fc JJ |
2533 | |
2534 | if path.global { | |
a7813a04 | 2535 | let binding = self.resolve_crate_relative_path(span, segments, namespace); |
9e0c209e | 2536 | return binding.map(|binding| mk_res(binding.def())); |
1a4d82fc JJ |
2537 | } |
2538 | ||
2539 | // Try to find a path to an item in a module. | |
9cc50fc6 | 2540 | let last_ident = segments.last().unwrap().identifier; |
54a0048b SL |
2541 | // Resolve a single identifier with fallback to primitive types |
2542 | let resolve_identifier_with_fallback = |this: &mut Self, record_used| { | |
2543 | let def = this.resolve_identifier(last_ident, namespace, record_used); | |
2544 | match def { | |
2545 | None | Some(LocalDef{def: Def::Mod(..), ..}) if namespace == TypeNS => | |
2546 | this.primitive_type_table | |
2547 | .primitive_types | |
a7813a04 | 2548 | .get(&last_ident.name) |
54a0048b SL |
2549 | .map_or(def, |prim_ty| Some(LocalDef::from_def(Def::PrimTy(*prim_ty)))), |
2550 | _ => def | |
2551 | } | |
2552 | }; | |
1a4d82fc | 2553 | |
54a0048b SL |
2554 | if segments.len() == 1 { |
2555 | // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we | |
2556 | // don't report an error right away, but try to fallback to a primitive type. | |
2557 | // So, we are still able to successfully resolve something like | |
2558 | // | |
2559 | // use std::u8; // bring module u8 in scope | |
2560 | // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 | |
2561 | // u8::max_value() // OK, resolves to associated function <u8>::max_value, | |
2562 | // // not to non-existent std::u8::max_value | |
2563 | // } | |
2564 | // | |
2565 | // Such behavior is required for backward compatibility. | |
2566 | // The same fallback is used when `a` resolves to nothing. | |
9e0c209e | 2567 | let def = resolve_identifier_with_fallback(self, Some(span)).ok_or(false); |
54a0048b SL |
2568 | return def.and_then(|def| self.adjust_local_def(def, span).ok_or(true)).map(mk_res); |
2569 | } | |
2570 | ||
9e0c209e | 2571 | let unqualified_def = resolve_identifier_with_fallback(self, None); |
a7813a04 XL |
2572 | let qualified_binding = self.resolve_module_relative_path(span, segments, namespace); |
2573 | match (qualified_binding, unqualified_def) { | |
c30ab7b3 SL |
2574 | (Ok(binding), Some(ref ud)) if binding.def() == ud.def && |
2575 | segments[0].identifier.name.as_str() != "$crate" => { | |
c34b1796 AL |
2576 | self.session |
2577 | .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, | |
92a42be0 SL |
2578 | id, |
2579 | span, | |
c34b1796 AL |
2580 | "unnecessary qualification".to_string()); |
2581 | } | |
2582 | _ => {} | |
1a4d82fc JJ |
2583 | } |
2584 | ||
9e0c209e | 2585 | qualified_binding.map(|binding| mk_res(binding.def())) |
1a4d82fc JJ |
2586 | } |
2587 | ||
92a42be0 | 2588 | // Resolve a single identifier |
1a4d82fc | 2589 | fn resolve_identifier(&mut self, |
c30ab7b3 | 2590 | identifier: Ident, |
1a4d82fc | 2591 | namespace: Namespace, |
9e0c209e | 2592 | record_used: Option<Span>) |
92a42be0 | 2593 | -> Option<LocalDef> { |
a7813a04 | 2594 | if identifier.name == keywords::Invalid.name() { |
5bcae85e | 2595 | return None; |
7453a54e SL |
2596 | } |
2597 | ||
54a0048b SL |
2598 | self.resolve_ident_in_lexical_scope(identifier, namespace, record_used) |
2599 | .map(LexicalScopeBinding::local_def) | |
1a4d82fc JJ |
2600 | } |
2601 | ||
92a42be0 SL |
2602 | // Resolve a local definition, potentially adjusting for closures. |
2603 | fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> { | |
2604 | let ribs = match local_def.ribs { | |
2605 | Some((TypeNS, i)) => &self.type_ribs[i + 1..], | |
2606 | Some((ValueNS, i)) => &self.value_ribs[i + 1..], | |
2607 | _ => &[] as &[_], | |
2608 | }; | |
2609 | let mut def = local_def.def; | |
2610 | match def { | |
7453a54e | 2611 | Def::Upvar(..) => { |
54a0048b | 2612 | span_bug!(span, "unexpected {:?} in bindings", def) |
1a4d82fc | 2613 | } |
9e0c209e | 2614 | Def::Local(def_id) => { |
92a42be0 SL |
2615 | for rib in ribs { |
2616 | match rib.kind { | |
5bcae85e | 2617 | NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => { |
92a42be0 SL |
2618 | // Nothing to do. Continue. |
2619 | } | |
2620 | ClosureRibKind(function_id) => { | |
2621 | let prev_def = def; | |
9e0c209e | 2622 | let node_id = self.definitions.as_local_node_id(def_id).unwrap(); |
92a42be0 SL |
2623 | |
2624 | let seen = self.freevars_seen | |
2625 | .entry(function_id) | |
2626 | .or_insert_with(|| NodeMap()); | |
2627 | if let Some(&index) = seen.get(&node_id) { | |
9e0c209e | 2628 | def = Def::Upvar(def_id, index, function_id); |
92a42be0 | 2629 | continue; |
1a4d82fc | 2630 | } |
92a42be0 SL |
2631 | let vec = self.freevars |
2632 | .entry(function_id) | |
2633 | .or_insert_with(|| vec![]); | |
2634 | let depth = vec.len(); | |
2635 | vec.push(Freevar { | |
2636 | def: prev_def, | |
2637 | span: span, | |
2638 | }); | |
2639 | ||
9e0c209e | 2640 | def = Def::Upvar(def_id, depth, function_id); |
92a42be0 SL |
2641 | seen.insert(node_id, depth); |
2642 | } | |
3157f602 | 2643 | ItemRibKind | MethodRibKind(_) => { |
92a42be0 SL |
2644 | // This was an attempt to access an upvar inside a |
2645 | // named function item. This is not allowed, so we | |
2646 | // report an error. | |
2647 | resolve_error(self, | |
2648 | span, | |
2649 | ResolutionError::CannotCaptureDynamicEnvironmentInFnItem); | |
2650 | return None; | |
1a4d82fc | 2651 | } |
92a42be0 SL |
2652 | ConstantItemRibKind => { |
2653 | // Still doesn't deal with upvars | |
2654 | resolve_error(self, | |
2655 | span, | |
2656 | ResolutionError::AttemptToUseNonConstantValueInConstant); | |
2657 | return None; | |
1a4d82fc JJ |
2658 | } |
2659 | } | |
2660 | } | |
2661 | } | |
7453a54e | 2662 | Def::TyParam(..) | Def::SelfTy(..) => { |
92a42be0 SL |
2663 | for rib in ribs { |
2664 | match rib.kind { | |
3157f602 | 2665 | NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) | |
5bcae85e | 2666 | ModuleRibKind(..) | MacroDefinition(..) => { |
92a42be0 SL |
2667 | // Nothing to do. Continue. |
2668 | } | |
2669 | ItemRibKind => { | |
2670 | // This was an attempt to use a type parameter outside | |
2671 | // its scope. | |
1a4d82fc | 2672 | |
92a42be0 SL |
2673 | resolve_error(self, |
2674 | span, | |
2675 | ResolutionError::TypeParametersFromOuterFunction); | |
2676 | return None; | |
2677 | } | |
2678 | ConstantItemRibKind => { | |
2679 | // see #9186 | |
2680 | resolve_error(self, span, ResolutionError::OuterTypeParameterContext); | |
2681 | return None; | |
2682 | } | |
2683 | } | |
1a4d82fc JJ |
2684 | } |
2685 | } | |
92a42be0 | 2686 | _ => {} |
1a4d82fc | 2687 | } |
92a42be0 | 2688 | return Some(def); |
1a4d82fc JJ |
2689 | } |
2690 | ||
2691 | // resolve a "module-relative" path, e.g. a::b::c | |
2692 | fn resolve_module_relative_path(&mut self, | |
c34b1796 | 2693 | span: Span, |
a7813a04 | 2694 | segments: &[ast::PathSegment], |
1a4d82fc | 2695 | namespace: Namespace) |
a7813a04 XL |
2696 | -> Result<&'a NameBinding<'a>, |
2697 | bool /* true if an error was reported */> { | |
c30ab7b3 SL |
2698 | let module_path = |
2699 | segments.split_last().unwrap().1.iter().map(|ps| ps.identifier).collect::<Vec<_>>(); | |
1a4d82fc JJ |
2700 | |
2701 | let containing_module; | |
9e0c209e | 2702 | match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) { |
1a4d82fc | 2703 | Failed(err) => { |
9e0c209e SL |
2704 | if let Some((span, msg)) = err { |
2705 | resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); | |
2706 | } | |
54a0048b | 2707 | return Err(true); |
1a4d82fc | 2708 | } |
54a0048b SL |
2709 | Indeterminate => return Err(false), |
2710 | Success(resulting_module) => { | |
1a4d82fc | 2711 | containing_module = resulting_module; |
1a4d82fc JJ |
2712 | } |
2713 | } | |
2714 | ||
c34b1796 | 2715 | let name = segments.last().unwrap().identifier.name; |
9e0c209e SL |
2716 | let result = |
2717 | self.resolve_name_in_module(containing_module, name, namespace, false, Some(span)); | |
2718 | result.success().ok_or(false) | |
1a4d82fc JJ |
2719 | } |
2720 | ||
2721 | /// Invariant: This must be called only during main resolution, not during | |
2722 | /// import resolution. | |
a7813a04 XL |
2723 | fn resolve_crate_relative_path<T>(&mut self, span: Span, segments: &[T], namespace: Namespace) |
2724 | -> Result<&'a NameBinding<'a>, | |
2725 | bool /* true if an error was reported */> | |
2726 | where T: Named, | |
2727 | { | |
c30ab7b3 | 2728 | let module_path = segments.split_last().unwrap().1.iter().map(T::ident).collect::<Vec<_>>(); |
9cc50fc6 | 2729 | let root_module = self.graph_root; |
1a4d82fc JJ |
2730 | |
2731 | let containing_module; | |
9e0c209e | 2732 | match self.resolve_module_path_from_root(root_module, &module_path, 0, Some(span)) { |
1a4d82fc | 2733 | Failed(err) => { |
9e0c209e SL |
2734 | if let Some((span, msg)) = err { |
2735 | resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); | |
2736 | } | |
54a0048b | 2737 | return Err(true); |
1a4d82fc JJ |
2738 | } |
2739 | ||
54a0048b | 2740 | Indeterminate => return Err(false), |
1a4d82fc | 2741 | |
54a0048b | 2742 | Success(resulting_module) => { |
1a4d82fc | 2743 | containing_module = resulting_module; |
1a4d82fc JJ |
2744 | } |
2745 | } | |
2746 | ||
c30ab7b3 | 2747 | let name = segments.last().unwrap().ident().name; |
9e0c209e SL |
2748 | let result = |
2749 | self.resolve_name_in_module(containing_module, name, namespace, false, Some(span)); | |
2750 | result.success().ok_or(false) | |
1a4d82fc JJ |
2751 | } |
2752 | ||
92a42be0 SL |
2753 | fn with_no_errors<T, F>(&mut self, f: F) -> T |
2754 | where F: FnOnce(&mut Resolver) -> T | |
1a4d82fc JJ |
2755 | { |
2756 | self.emit_errors = false; | |
2757 | let rs = f(self); | |
2758 | self.emit_errors = true; | |
2759 | rs | |
2760 | } | |
2761 | ||
5bcae85e SL |
2762 | // Calls `f` with a `Resolver` whose current lexical scope is `module`'s lexical scope, |
2763 | // i.e. the module's items and the prelude (unless the module is `#[no_implicit_prelude]`). | |
2764 | // FIXME #34673: This needs testing. | |
2765 | pub fn with_module_lexical_scope<T, F>(&mut self, module: Module<'a>, f: F) -> T | |
2766 | where F: FnOnce(&mut Resolver<'a>) -> T, | |
2767 | { | |
2768 | self.with_empty_ribs(|this| { | |
2769 | this.value_ribs.push(Rib::new(ModuleRibKind(module))); | |
2770 | this.type_ribs.push(Rib::new(ModuleRibKind(module))); | |
2771 | f(this) | |
2772 | }) | |
2773 | } | |
2774 | ||
2775 | fn with_empty_ribs<T, F>(&mut self, f: F) -> T | |
2776 | where F: FnOnce(&mut Resolver<'a>) -> T, | |
2777 | { | |
5bcae85e SL |
2778 | let value_ribs = replace(&mut self.value_ribs, Vec::new()); |
2779 | let type_ribs = replace(&mut self.type_ribs, Vec::new()); | |
2780 | let label_ribs = replace(&mut self.label_ribs, Vec::new()); | |
2781 | ||
2782 | let result = f(self); | |
2783 | self.value_ribs = value_ribs; | |
2784 | self.type_ribs = type_ribs; | |
2785 | self.label_ribs = label_ribs; | |
2786 | result | |
2787 | } | |
2788 | ||
1a4d82fc | 2789 | fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion { |
a7813a04 | 2790 | fn extract_node_id(t: &Ty) -> Option<NodeId> { |
1a4d82fc | 2791 | match t.node { |
a7813a04 XL |
2792 | TyKind::Path(None, _) => Some(t.id), |
2793 | TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty), | |
1a4d82fc JJ |
2794 | // This doesn't handle the remaining `Ty` variants as they are not |
2795 | // that commonly the self_type, it might be interesting to provide | |
2796 | // support for those in future. | |
2797 | _ => None, | |
2798 | } | |
2799 | } | |
2800 | ||
a7813a04 | 2801 | if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) { |
1a4d82fc | 2802 | // Look for a field with the same name in the current self_type. |
3157f602 XL |
2803 | if let Some(resolution) = self.def_map.get(&node_id) { |
2804 | match resolution.base_def { | |
c30ab7b3 SL |
2805 | Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => { |
2806 | if let Some(field_names) = self.field_names.get(&did) { | |
2807 | if field_names.iter().any(|&field_name| name == field_name) { | |
3157f602 XL |
2808 | return Field; |
2809 | } | |
1a4d82fc JJ |
2810 | } |
2811 | } | |
3157f602 XL |
2812 | _ => {} |
2813 | } | |
1a4d82fc JJ |
2814 | } |
2815 | } | |
2816 | ||
1a4d82fc | 2817 | // Look for a method in the current trait. |
c34b1796 | 2818 | if let Some((trait_did, ref trait_ref)) = self.current_trait_ref { |
a7813a04 XL |
2819 | if let Some(&is_static_method) = self.trait_item_map.get(&(name, trait_did)) { |
2820 | if is_static_method { | |
c34b1796 AL |
2821 | return TraitMethod(path_names_to_string(&trait_ref.path, 0)); |
2822 | } else { | |
2823 | return TraitItem; | |
1a4d82fc JJ |
2824 | } |
2825 | } | |
1a4d82fc JJ |
2826 | } |
2827 | ||
2828 | NoSuggestion | |
2829 | } | |
2830 | ||
9cc50fc6 | 2831 | fn find_best_match(&mut self, name: &str) -> SuggestionType { |
9e0c209e | 2832 | if let Some(macro_name) = self.macro_names.iter().find(|n| n.as_str() == name) { |
92a42be0 SL |
2833 | return SuggestionType::Macro(format!("{}!", macro_name)); |
2834 | } | |
2835 | ||
9cc50fc6 SL |
2836 | let names = self.value_ribs |
2837 | .iter() | |
2838 | .rev() | |
5bcae85e | 2839 | .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name)); |
1a4d82fc | 2840 | |
9cc50fc6 | 2841 | if let Some(found) = find_best_match_for_name(names, name, None) { |
7453a54e | 2842 | if name != found { |
9cc50fc6 | 2843 | return SuggestionType::Function(found); |
1a4d82fc | 2844 | } |
9cc50fc6 | 2845 | } SuggestionType::NotFound |
1a4d82fc JJ |
2846 | } |
2847 | ||
9e0c209e | 2848 | fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) { |
a7813a04 | 2849 | if let Some(label) = label { |
5bcae85e | 2850 | let def = Def::Label(id); |
a7813a04 | 2851 | self.with_label_rib(|this| { |
9e0c209e | 2852 | this.label_ribs.last_mut().unwrap().bindings.insert(label.node, def); |
a7813a04 XL |
2853 | this.visit_block(block); |
2854 | }); | |
2855 | } else { | |
2856 | self.visit_block(block); | |
2857 | } | |
2858 | } | |
2859 | ||
2860 | fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { | |
1a4d82fc JJ |
2861 | // First, record candidate traits for this expression if it could |
2862 | // result in the invocation of a method call. | |
2863 | ||
2864 | self.record_candidate_traits_for_expr_if_necessary(expr); | |
2865 | ||
2866 | // Next, resolve the node. | |
2867 | match expr.node { | |
a7813a04 | 2868 | ExprKind::Path(ref maybe_qself, ref path) => { |
1a4d82fc JJ |
2869 | // This is a local path in the value namespace. Walk through |
2870 | // scopes looking for it. | |
3157f602 XL |
2871 | if let Some(path_res) = self.resolve_possibly_assoc_item(expr.id, |
2872 | maybe_qself.as_ref(), path, ValueNS) { | |
1a4d82fc | 2873 | // Check if struct variant |
c30ab7b3 SL |
2874 | let is_struct_variant = match path_res.base_def { |
2875 | Def::VariantCtor(_, CtorKind::Fictive) => true, | |
2876 | _ => false, | |
7453a54e SL |
2877 | }; |
2878 | if is_struct_variant { | |
c34b1796 | 2879 | let path_name = path_names_to_string(path, 0); |
c1a9b12d | 2880 | |
9cc50fc6 SL |
2881 | let mut err = resolve_struct_error(self, |
2882 | expr.span, | |
7453a54e | 2883 | ResolutionError::StructVariantUsedAsFunction(&path_name)); |
1a4d82fc | 2884 | |
92a42be0 | 2885 | let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", |
c34b1796 AL |
2886 | path_name); |
2887 | if self.emit_errors { | |
a7813a04 | 2888 | err.help(&msg); |
c34b1796 | 2889 | } else { |
9cc50fc6 | 2890 | err.span_help(expr.span, &msg); |
c34b1796 | 2891 | } |
9cc50fc6 SL |
2892 | err.emit(); |
2893 | self.record_def(expr.id, err_path_resolution()); | |
c34b1796 | 2894 | } else { |
1a4d82fc JJ |
2895 | // Write the result into the def map. |
2896 | debug!("(resolving expr) resolved `{}`", | |
c34b1796 AL |
2897 | path_names_to_string(path, 0)); |
2898 | ||
2899 | // Partial resolutions will need the set of traits in scope, | |
2900 | // so they can be completed during typeck. | |
2901 | if path_res.depth != 0 { | |
2902 | let method_name = path.segments.last().unwrap().identifier.name; | |
d9579d0f | 2903 | let traits = self.get_traits_containing_item(method_name); |
c34b1796 AL |
2904 | self.trait_map.insert(expr.id, traits); |
2905 | } | |
1a4d82fc | 2906 | |
c34b1796 | 2907 | self.record_def(expr.id, path_res); |
1a4d82fc | 2908 | } |
c34b1796 AL |
2909 | } else { |
2910 | // Be helpful if the name refers to a struct | |
c34b1796 AL |
2911 | let path_name = path_names_to_string(path, 0); |
2912 | let type_res = self.with_no_errors(|this| { | |
54a0048b | 2913 | this.resolve_path(expr.id, path, 0, TypeNS) |
c34b1796 | 2914 | }); |
9cc50fc6 SL |
2915 | |
2916 | self.record_def(expr.id, err_path_resolution()); | |
c34b1796 | 2917 | |
54a0048b SL |
2918 | if let Ok(Def::Struct(..)) = type_res.map(|r| r.base_def) { |
2919 | let error_variant = | |
2920 | ResolutionError::StructVariantUsedAsFunction(&path_name); | |
2921 | let mut err = resolve_struct_error(self, expr.span, error_variant); | |
2922 | ||
2923 | let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", | |
2924 | path_name); | |
2925 | ||
2926 | if self.emit_errors { | |
a7813a04 | 2927 | err.help(&msg); |
54a0048b SL |
2928 | } else { |
2929 | err.span_help(expr.span, &msg); | |
2930 | } | |
2931 | err.emit(); | |
2932 | } else { | |
2933 | // Keep reporting some errors even if they're ignored above. | |
2934 | if let Err(true) = self.resolve_path(expr.id, path, 0, ValueNS) { | |
2935 | // `resolve_path` already reported the error | |
2936 | } else { | |
c34b1796 | 2937 | let mut method_scope = false; |
3157f602 | 2938 | let mut is_static = false; |
c34b1796 AL |
2939 | self.value_ribs.iter().rev().all(|rib| { |
2940 | method_scope = match rib.kind { | |
3157f602 XL |
2941 | MethodRibKind(is_static_) => { |
2942 | is_static = is_static_; | |
2943 | true | |
2944 | } | |
c34b1796 AL |
2945 | ItemRibKind | ConstantItemRibKind => false, |
2946 | _ => return true, // Keep advancing | |
2947 | }; | |
2948 | false // Stop advancing | |
2949 | }); | |
1a4d82fc | 2950 | |
a7813a04 XL |
2951 | if method_scope && |
2952 | &path_name[..] == keywords::SelfValue.name().as_str() { | |
92a42be0 SL |
2953 | resolve_error(self, |
2954 | expr.span, | |
2955 | ResolutionError::SelfNotAvailableInStaticMethod); | |
c34b1796 AL |
2956 | } else { |
2957 | let last_name = path.segments.last().unwrap().identifier.name; | |
3157f602 XL |
2958 | let (mut msg, is_field) = |
2959 | match self.find_fallback_in_self_type(last_name) { | |
c34b1796 AL |
2960 | NoSuggestion => { |
2961 | // limit search to 5 to reduce the number | |
2962 | // of stupid suggestions | |
3157f602 | 2963 | (match self.find_best_match(&path_name) { |
92a42be0 SL |
2964 | SuggestionType::Macro(s) => { |
2965 | format!("the macro `{}`", s) | |
2966 | } | |
2967 | SuggestionType::Function(s) => format!("`{}`", s), | |
2968 | SuggestionType::NotFound => "".to_string(), | |
3157f602 XL |
2969 | }, false) |
2970 | } | |
2971 | Field => { | |
2972 | (if is_static && method_scope { | |
2973 | "".to_string() | |
2974 | } else { | |
2975 | format!("`self.{}`", path_name) | |
2976 | }, true) | |
c34b1796 | 2977 | } |
3157f602 | 2978 | TraitItem => (format!("to call `self.{}`", path_name), false), |
a7813a04 | 2979 | TraitMethod(path_str) => |
3157f602 | 2980 | (format!("to call `{}::{}`", path_str, path_name), false), |
c34b1796 AL |
2981 | }; |
2982 | ||
9cc50fc6 | 2983 | let mut context = UnresolvedNameContext::Other; |
3157f602 | 2984 | let mut def = Def::Err; |
9346a6ac | 2985 | if !msg.is_empty() { |
9e0c209e | 2986 | msg = format!("did you mean {}?", msg); |
9cc50fc6 | 2987 | } else { |
5bcae85e | 2988 | // we display a help message if this is a module |
c30ab7b3 SL |
2989 | let name_path: Vec<_> = |
2990 | path.segments.iter().map(|seg| seg.identifier).collect(); | |
9cc50fc6 | 2991 | |
54a0048b | 2992 | match self.resolve_module_path(&name_path[..], |
7453a54e | 2993 | UseLexicalScope, |
9e0c209e | 2994 | Some(expr.span)) { |
3157f602 | 2995 | Success(e) => { |
9e0c209e | 2996 | if let Some(def_type) = e.def() { |
3157f602 XL |
2997 | def = def_type; |
2998 | } | |
a7813a04 | 2999 | context = UnresolvedNameContext::PathIsMod(parent); |
9cc50fc6 SL |
3000 | }, |
3001 | _ => {}, | |
3002 | }; | |
1a4d82fc | 3003 | } |
c34b1796 | 3004 | |
c1a9b12d SL |
3005 | resolve_error(self, |
3006 | expr.span, | |
3157f602 XL |
3007 | ResolutionError::UnresolvedName { |
3008 | path: &path_name, | |
3009 | message: &msg, | |
3010 | context: context, | |
3011 | is_static_method: method_scope && is_static, | |
3012 | is_field: is_field, | |
3013 | def: def, | |
3014 | }); | |
1a4d82fc JJ |
3015 | } |
3016 | } | |
3017 | } | |
3018 | } | |
3019 | ||
a7813a04 | 3020 | visit::walk_expr(self, expr); |
1a4d82fc JJ |
3021 | } |
3022 | ||
9e0c209e | 3023 | ExprKind::Struct(ref path, ..) => { |
c30ab7b3 | 3024 | self.resolve_struct_path(expr.id, path); |
1a4d82fc | 3025 | |
a7813a04 | 3026 | visit::walk_expr(self, expr); |
1a4d82fc JJ |
3027 | } |
3028 | ||
3157f602 | 3029 | ExprKind::Break(Some(label)) | ExprKind::Continue(Some(label)) => { |
5bcae85e | 3030 | match self.search_label(label.node) { |
1a4d82fc | 3031 | None => { |
9cc50fc6 | 3032 | self.record_def(expr.id, err_path_resolution()); |
c1a9b12d | 3033 | resolve_error(self, |
e9174d1e SL |
3034 | label.span, |
3035 | ResolutionError::UndeclaredLabel(&label.node.name.as_str())) | |
1a4d82fc | 3036 | } |
54a0048b | 3037 | Some(def @ Def::Label(_)) => { |
1a4d82fc | 3038 | // Since this def is a label, it is never read. |
3157f602 | 3039 | self.record_def(expr.id, PathResolution::new(def)) |
1a4d82fc JJ |
3040 | } |
3041 | Some(_) => { | |
54a0048b | 3042 | span_bug!(expr.span, "label wasn't mapped to a label def!") |
1a4d82fc JJ |
3043 | } |
3044 | } | |
3045 | } | |
3046 | ||
a7813a04 XL |
3047 | ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { |
3048 | self.visit_expr(subexpression); | |
3049 | ||
3050 | self.value_ribs.push(Rib::new(NormalRibKind)); | |
9e0c209e | 3051 | self.resolve_pattern(pattern, PatternSource::IfLet, &mut FnvHashMap()); |
a7813a04 XL |
3052 | self.visit_block(if_block); |
3053 | self.value_ribs.pop(); | |
3054 | ||
3055 | optional_else.as_ref().map(|expr| self.visit_expr(expr)); | |
3056 | } | |
3057 | ||
9e0c209e SL |
3058 | ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block), |
3059 | ||
3060 | ExprKind::While(ref subexpression, ref block, label) => { | |
3061 | self.visit_expr(subexpression); | |
3062 | self.resolve_labeled_block(label, expr.id, &block); | |
3063 | } | |
3064 | ||
a7813a04 XL |
3065 | ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => { |
3066 | self.visit_expr(subexpression); | |
3067 | self.value_ribs.push(Rib::new(NormalRibKind)); | |
9e0c209e | 3068 | self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FnvHashMap()); |
a7813a04 | 3069 | |
9e0c209e | 3070 | self.resolve_labeled_block(label, expr.id, block); |
a7813a04 XL |
3071 | |
3072 | self.value_ribs.pop(); | |
3073 | } | |
3074 | ||
3075 | ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { | |
3076 | self.visit_expr(subexpression); | |
3077 | self.value_ribs.push(Rib::new(NormalRibKind)); | |
9e0c209e | 3078 | self.resolve_pattern(pattern, PatternSource::For, &mut FnvHashMap()); |
a7813a04 | 3079 | |
9e0c209e | 3080 | self.resolve_labeled_block(label, expr.id, block); |
a7813a04 XL |
3081 | |
3082 | self.value_ribs.pop(); | |
3083 | } | |
3084 | ||
3085 | ExprKind::Field(ref subexpression, _) => { | |
3086 | self.resolve_expr(subexpression, Some(expr)); | |
3087 | } | |
3088 | ExprKind::MethodCall(_, ref types, ref arguments) => { | |
3089 | let mut arguments = arguments.iter(); | |
3090 | self.resolve_expr(arguments.next().unwrap(), Some(expr)); | |
3091 | for argument in arguments { | |
3092 | self.resolve_expr(argument, None); | |
3093 | } | |
3094 | for ty in types.iter() { | |
3095 | self.visit_ty(ty); | |
3096 | } | |
3097 | } | |
3098 | ||
1a4d82fc | 3099 | _ => { |
a7813a04 | 3100 | visit::walk_expr(self, expr); |
1a4d82fc JJ |
3101 | } |
3102 | } | |
3103 | } | |
3104 | ||
3105 | fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) { | |
3106 | match expr.node { | |
a7813a04 | 3107 | ExprKind::Field(_, name) => { |
1a4d82fc JJ |
3108 | // FIXME(#6890): Even though you can't treat a method like a |
3109 | // field, we need to add any trait methods we find that match | |
3110 | // the field name so that we can do some nice error reporting | |
3111 | // later on in typeck. | |
a7813a04 | 3112 | let traits = self.get_traits_containing_item(name.node.name); |
1a4d82fc JJ |
3113 | self.trait_map.insert(expr.id, traits); |
3114 | } | |
9e0c209e | 3115 | ExprKind::MethodCall(name, ..) => { |
92a42be0 | 3116 | debug!("(recording candidate traits for expr) recording traits for {}", |
1a4d82fc | 3117 | expr.id); |
a7813a04 | 3118 | let traits = self.get_traits_containing_item(name.node.name); |
1a4d82fc JJ |
3119 | self.trait_map.insert(expr.id, traits); |
3120 | } | |
3121 | _ => { | |
3122 | // Nothing to do. | |
3123 | } | |
3124 | } | |
3125 | } | |
3126 | ||
a7813a04 | 3127 | fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> { |
92a42be0 | 3128 | debug!("(getting traits containing item) looking for '{}'", name); |
1a4d82fc | 3129 | |
a7813a04 XL |
3130 | fn add_trait_info(found_traits: &mut Vec<TraitCandidate>, |
3131 | trait_def_id: DefId, | |
3132 | import_id: Option<NodeId>, | |
3133 | name: Name) { | |
b039eaaf | 3134 | debug!("(adding trait info) found trait {:?} for method '{}'", |
92a42be0 SL |
3135 | trait_def_id, |
3136 | name); | |
a7813a04 XL |
3137 | found_traits.push(TraitCandidate { |
3138 | def_id: trait_def_id, | |
3139 | import_id: import_id, | |
3140 | }); | |
1a4d82fc JJ |
3141 | } |
3142 | ||
3143 | let mut found_traits = Vec::new(); | |
54a0048b SL |
3144 | // Look for the current trait. |
3145 | if let Some((trait_def_id, _)) = self.current_trait_ref { | |
3146 | if self.trait_item_map.contains_key(&(name, trait_def_id)) { | |
a7813a04 | 3147 | add_trait_info(&mut found_traits, trait_def_id, None, name); |
1a4d82fc | 3148 | } |
54a0048b | 3149 | } |
1a4d82fc | 3150 | |
54a0048b SL |
3151 | let mut search_module = self.current_module; |
3152 | loop { | |
1a4d82fc | 3153 | // Look for trait children. |
3157f602 | 3154 | let mut search_in_module = |this: &mut Self, module: Module<'a>| { |
54a0048b SL |
3155 | let mut traits = module.traits.borrow_mut(); |
3156 | if traits.is_none() { | |
3157 | let mut collected_traits = Vec::new(); | |
a7813a04 | 3158 | module.for_each_child(|name, ns, binding| { |
54a0048b | 3159 | if ns != TypeNS { return } |
9e0c209e | 3160 | if let Def::Trait(_) = binding.def() { |
a7813a04 | 3161 | collected_traits.push((name, binding)); |
54a0048b SL |
3162 | } |
3163 | }); | |
3164 | *traits = Some(collected_traits.into_boxed_slice()); | |
1a4d82fc | 3165 | } |
1a4d82fc | 3166 | |
a7813a04 | 3167 | for &(trait_name, binding) in traits.as_ref().unwrap().iter() { |
9e0c209e | 3168 | let trait_def_id = binding.def().def_id(); |
3157f602 | 3169 | if this.trait_item_map.contains_key(&(name, trait_def_id)) { |
a7813a04 XL |
3170 | let mut import_id = None; |
3171 | if let NameBindingKind::Import { directive, .. } = binding.kind { | |
3172 | let id = directive.id; | |
3157f602 | 3173 | this.maybe_unused_trait_imports.insert(id); |
5bcae85e | 3174 | this.add_to_glob_map(id, trait_name); |
a7813a04 XL |
3175 | import_id = Some(id); |
3176 | } | |
3177 | add_trait_info(&mut found_traits, trait_def_id, import_id, name); | |
54a0048b | 3178 | } |
1a4d82fc | 3179 | } |
54a0048b | 3180 | }; |
3157f602 | 3181 | search_in_module(self, search_module); |
1a4d82fc | 3182 | |
9e0c209e SL |
3183 | if let ModuleKind::Block(..) = search_module.kind { |
3184 | search_module = search_module.parent.unwrap(); | |
3185 | } else { | |
3186 | if !search_module.no_implicit_prelude { | |
3187 | self.prelude.map(|prelude| search_in_module(self, prelude)); | |
1a4d82fc | 3188 | } |
9e0c209e | 3189 | break; |
1a4d82fc JJ |
3190 | } |
3191 | } | |
3192 | ||
3193 | found_traits | |
3194 | } | |
3195 | ||
7453a54e SL |
3196 | /// When name resolution fails, this method can be used to look up candidate |
3197 | /// entities with the expected name. It allows filtering them using the | |
3198 | /// supplied predicate (which should be used to only accept the types of | |
3199 | /// definitions expected e.g. traits). The lookup spans across all crates. | |
3200 | /// | |
3201 | /// NOTE: The method does not look into imports, but this is not a problem, | |
3202 | /// since we report the definitions (thus, the de-aliased imports). | |
3203 | fn lookup_candidates<FilterFn>(&mut self, | |
3204 | lookup_name: Name, | |
3205 | namespace: Namespace, | |
3206 | filter_fn: FilterFn) -> SuggestedCandidates | |
3207 | where FilterFn: Fn(Def) -> bool { | |
3208 | ||
3209 | let mut lookup_results = Vec::new(); | |
3210 | let mut worklist = Vec::new(); | |
3211 | worklist.push((self.graph_root, Vec::new(), false)); | |
3212 | ||
3213 | while let Some((in_module, | |
3214 | path_segments, | |
3215 | in_module_is_extern)) = worklist.pop() { | |
54a0048b | 3216 | self.populate_module_if_necessary(in_module); |
7453a54e SL |
3217 | |
3218 | in_module.for_each_child(|name, ns, name_binding| { | |
3219 | ||
3220 | // avoid imports entirely | |
3221 | if name_binding.is_import() { return; } | |
3222 | ||
3223 | // collect results based on the filter function | |
9e0c209e SL |
3224 | if name == lookup_name && ns == namespace { |
3225 | if filter_fn(name_binding.def()) { | |
7453a54e | 3226 | // create the path |
c30ab7b3 | 3227 | let ident = Ident::with_empty_ctxt(name); |
7453a54e SL |
3228 | let params = PathParameters::none(); |
3229 | let segment = PathSegment { | |
3230 | identifier: ident, | |
3231 | parameters: params, | |
3232 | }; | |
a7813a04 | 3233 | let span = name_binding.span; |
7453a54e SL |
3234 | let mut segms = path_segments.clone(); |
3235 | segms.push(segment); | |
7453a54e SL |
3236 | let path = Path { |
3237 | span: span, | |
3238 | global: true, | |
3239 | segments: segms, | |
3240 | }; | |
3241 | // the entity is accessible in the following cases: | |
3242 | // 1. if it's defined in the same crate, it's always | |
3243 | // accessible (since private entities can be made public) | |
3244 | // 2. if it's defined in another crate, it's accessible | |
3245 | // only if both the module is public and the entity is | |
3246 | // declared as public (due to pruning, we don't explore | |
3247 | // outside crate private modules => no need to check this) | |
a7813a04 | 3248 | if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { |
7453a54e SL |
3249 | lookup_results.push(path); |
3250 | } | |
3251 | } | |
3252 | } | |
3253 | ||
3254 | // collect submodules to explore | |
9e0c209e | 3255 | if let Ok(module) = name_binding.module() { |
7453a54e | 3256 | // form the path |
9e0c209e SL |
3257 | let path_segments = match module.kind { |
3258 | _ if module.parent.is_none() => path_segments.clone(), | |
3259 | ModuleKind::Def(_, name) => { | |
7453a54e | 3260 | let mut paths = path_segments.clone(); |
c30ab7b3 | 3261 | let ident = Ident::with_empty_ctxt(name); |
7453a54e SL |
3262 | let params = PathParameters::none(); |
3263 | let segm = PathSegment { | |
3264 | identifier: ident, | |
3265 | parameters: params, | |
3266 | }; | |
3267 | paths.push(segm); | |
3268 | paths | |
3269 | } | |
54a0048b | 3270 | _ => bug!(), |
7453a54e SL |
3271 | }; |
3272 | ||
a7813a04 | 3273 | if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { |
7453a54e SL |
3274 | // add the module to the lookup |
3275 | let is_extern = in_module_is_extern || name_binding.is_extern_crate(); | |
9e0c209e | 3276 | if !worklist.iter().any(|&(m, ..)| m.def() == module.def()) { |
3157f602 XL |
3277 | worklist.push((module, path_segments, is_extern)); |
3278 | } | |
7453a54e SL |
3279 | } |
3280 | } | |
3281 | }) | |
3282 | } | |
3283 | ||
3284 | SuggestedCandidates { | |
3285 | name: lookup_name.as_str().to_string(), | |
3286 | candidates: lookup_results, | |
3287 | } | |
3288 | } | |
3289 | ||
c34b1796 AL |
3290 | fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { |
3291 | debug!("(recording def) recording {:?} for {}", resolution, node_id); | |
a7813a04 XL |
3292 | if let Some(prev_res) = self.def_map.insert(node_id, resolution) { |
3293 | panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution); | |
1a4d82fc JJ |
3294 | } |
3295 | } | |
3296 | ||
a7813a04 XL |
3297 | fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { |
3298 | let (path, id) = match *vis { | |
3299 | ast::Visibility::Public => return ty::Visibility::Public, | |
3300 | ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID), | |
3301 | ast::Visibility::Restricted { ref path, id } => (path, id), | |
3302 | ast::Visibility::Inherited => { | |
9e0c209e | 3303 | return ty::Visibility::Restricted(self.current_module.normal_ancestor_id.unwrap()); |
a7813a04 XL |
3304 | } |
3305 | }; | |
3306 | ||
c30ab7b3 | 3307 | let segments: Vec<_> = path.segments.iter().map(|seg| seg.identifier).collect(); |
3157f602 | 3308 | let mut path_resolution = err_path_resolution(); |
9e0c209e | 3309 | let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, Some(path.span)) { |
a7813a04 | 3310 | Success(module) => { |
9e0c209e SL |
3311 | path_resolution = PathResolution::new(module.def().unwrap()); |
3312 | ty::Visibility::Restricted(module.normal_ancestor_id.unwrap()) | |
a7813a04 | 3313 | } |
9e0c209e SL |
3314 | Indeterminate => unreachable!(), |
3315 | Failed(err) => { | |
3316 | if let Some((span, msg)) = err { | |
3317 | self.session.span_err(span, &format!("failed to resolve module path. {}", msg)); | |
3318 | } | |
a7813a04 XL |
3319 | ty::Visibility::Public |
3320 | } | |
3321 | }; | |
3157f602 | 3322 | self.def_map.insert(id, path_resolution); |
a7813a04 XL |
3323 | if !self.is_accessible(vis) { |
3324 | let msg = format!("visibilities can only be restricted to ancestor modules"); | |
3325 | self.session.span_err(path.span, &msg); | |
3326 | } | |
3327 | vis | |
54a0048b SL |
3328 | } |
3329 | ||
a7813a04 | 3330 | fn is_accessible(&self, vis: ty::Visibility) -> bool { |
9e0c209e | 3331 | vis.is_accessible_from(self.current_module.normal_ancestor_id.unwrap(), self) |
a7813a04 XL |
3332 | } |
3333 | ||
9e0c209e SL |
3334 | fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool { |
3335 | vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self) | |
54a0048b SL |
3336 | } |
3337 | ||
c30ab7b3 SL |
3338 | fn report_errors(&mut self) { |
3339 | self.report_shadowing_errors(); | |
9e0c209e SL |
3340 | let mut reported_spans = FnvHashSet(); |
3341 | ||
3342 | for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors { | |
3343 | if !reported_spans.insert(span) { continue } | |
3344 | let msg1 = format!("`{}` could resolve to the name imported here", name); | |
3345 | let msg2 = format!("`{}` could also resolve to the name imported here", name); | |
3346 | self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) | |
3347 | .span_note(b1.span, &msg1) | |
3348 | .span_note(b2.span, &msg2) | |
3349 | .note(&format!("Consider adding an explicit import of `{}` to disambiguate", name)) | |
3350 | .emit(); | |
3351 | } | |
3352 | ||
54a0048b SL |
3353 | for &PrivacyError(span, name, binding) in &self.privacy_errors { |
3354 | if !reported_spans.insert(span) { continue } | |
3355 | if binding.is_extern_crate() { | |
3356 | // Warn when using an inaccessible extern crate. | |
3357 | let node_id = binding.module().unwrap().extern_crate_id.unwrap(); | |
3358 | let msg = format!("extern crate `{}` is private", name); | |
3359 | self.session.add_lint(lint::builtin::INACCESSIBLE_EXTERN_CRATE, node_id, span, msg); | |
3360 | } else { | |
9e0c209e | 3361 | let def = binding.def(); |
54a0048b SL |
3362 | self.session.span_err(span, &format!("{} `{}` is private", def.kind_name(), name)); |
3363 | } | |
3364 | } | |
3365 | } | |
3366 | ||
c30ab7b3 SL |
3367 | fn report_shadowing_errors(&mut self) { |
3368 | for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { | |
3369 | self.resolve_macro_name(scope, name); | |
3370 | } | |
3371 | ||
3372 | let mut reported_errors = FnvHashSet(); | |
3373 | for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { | |
3374 | if self.resolve_macro_name(binding.parent, binding.name).is_some() && | |
3375 | reported_errors.insert((binding.name, binding.span)) { | |
3376 | let msg = format!("`{}` is already in scope", binding.name); | |
3377 | self.session.struct_span_err(binding.span, &msg) | |
3378 | .note("macro-expanded `macro_rules!`s may not shadow \ | |
3379 | existing macros (see RFC 1560)") | |
3380 | .emit(); | |
3381 | } | |
3382 | } | |
3383 | } | |
3384 | ||
54a0048b SL |
3385 | fn report_conflict(&self, |
3386 | parent: Module, | |
3387 | name: Name, | |
3388 | ns: Namespace, | |
3389 | binding: &NameBinding, | |
3390 | old_binding: &NameBinding) { | |
3391 | // Error on the second of two conflicting names | |
a7813a04 | 3392 | if old_binding.span.lo > binding.span.lo { |
54a0048b SL |
3393 | return self.report_conflict(parent, name, ns, old_binding, binding); |
3394 | } | |
3395 | ||
9e0c209e SL |
3396 | let container = match parent.kind { |
3397 | ModuleKind::Def(Def::Mod(_), _) => "module", | |
3398 | ModuleKind::Def(Def::Trait(_), _) => "trait", | |
3399 | ModuleKind::Block(..) => "block", | |
54a0048b SL |
3400 | _ => "enum", |
3401 | }; | |
3402 | ||
3403 | let (participle, noun) = match old_binding.is_import() || old_binding.is_extern_crate() { | |
3404 | true => ("imported", "import"), | |
3405 | false => ("defined", "definition"), | |
3406 | }; | |
3407 | ||
a7813a04 | 3408 | let span = binding.span; |
54a0048b SL |
3409 | let msg = { |
3410 | let kind = match (ns, old_binding.module()) { | |
3411 | (ValueNS, _) => "a value", | |
9e0c209e SL |
3412 | (TypeNS, Ok(module)) if module.extern_crate_id.is_some() => "an extern crate", |
3413 | (TypeNS, Ok(module)) if module.is_normal() => "a module", | |
3414 | (TypeNS, Ok(module)) if module.is_trait() => "a trait", | |
54a0048b SL |
3415 | (TypeNS, _) => "a type", |
3416 | }; | |
3417 | format!("{} named `{}` has already been {} in this {}", | |
3418 | kind, name, participle, container) | |
3419 | }; | |
3420 | ||
3421 | let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) { | |
9e0c209e SL |
3422 | (true, true) => { |
3423 | let mut e = struct_span_err!(self.session, span, E0259, "{}", msg); | |
3424 | e.span_label(span, &format!("`{}` was already imported", name)); | |
3425 | e | |
3426 | }, | |
5bcae85e SL |
3427 | (true, _) | (_, true) if binding.is_import() || old_binding.is_import() => { |
3428 | let mut e = struct_span_err!(self.session, span, E0254, "{}", msg); | |
3429 | e.span_label(span, &"already imported"); | |
3430 | e | |
3431 | }, | |
9e0c209e SL |
3432 | (true, _) | (_, true) => { |
3433 | let mut e = struct_span_err!(self.session, span, E0260, "{}", msg); | |
3434 | e.span_label(span, &format!("`{}` already imported", name)); | |
3435 | e | |
3436 | }, | |
54a0048b | 3437 | _ => match (old_binding.is_import(), binding.is_import()) { |
9e0c209e SL |
3438 | (false, false) => { |
3439 | let mut e = struct_span_err!(self.session, span, E0428, "{}", msg); | |
3440 | e.span_label(span, &format!("already defined")); | |
3441 | e | |
3442 | }, | |
5bcae85e SL |
3443 | (true, true) => { |
3444 | let mut e = struct_span_err!(self.session, span, E0252, "{}", msg); | |
3445 | e.span_label(span, &format!("already imported")); | |
3446 | e | |
3447 | }, | |
a7813a04 XL |
3448 | _ => { |
3449 | let mut e = struct_span_err!(self.session, span, E0255, "{}", msg); | |
3450 | e.span_label(span, &format!("`{}` was already imported", name)); | |
3451 | e | |
3452 | } | |
54a0048b SL |
3453 | }, |
3454 | }; | |
3455 | ||
3157f602 | 3456 | if old_binding.span != syntax_pos::DUMMY_SP { |
a7813a04 | 3457 | err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name)); |
54a0048b SL |
3458 | } |
3459 | err.emit(); | |
3460 | } | |
3461 | } | |
c34b1796 | 3462 | |
c30ab7b3 | 3463 | fn names_to_string(names: &[Ident]) -> String { |
c34b1796 AL |
3464 | let mut first = true; |
3465 | let mut result = String::new(); | |
c30ab7b3 | 3466 | for ident in names { |
c34b1796 AL |
3467 | if first { |
3468 | first = false | |
3469 | } else { | |
3470 | result.push_str("::") | |
3471 | } | |
c30ab7b3 | 3472 | result.push_str(&ident.name.as_str()); |
92a42be0 | 3473 | } |
c34b1796 AL |
3474 | result |
3475 | } | |
3476 | ||
3477 | fn path_names_to_string(path: &Path, depth: usize) -> String { | |
c30ab7b3 SL |
3478 | let names: Vec<_> = |
3479 | path.segments[..path.segments.len() - depth].iter().map(|seg| seg.identifier).collect(); | |
3480 | names_to_string(&names) | |
c34b1796 AL |
3481 | } |
3482 | ||
7453a54e SL |
3483 | /// When an entity with a given name is not available in scope, we search for |
3484 | /// entities with that name in all crates. This method allows outputting the | |
3485 | /// results of this search in a programmer-friendly way | |
3486 | fn show_candidates(session: &mut DiagnosticBuilder, | |
7453a54e SL |
3487 | candidates: &SuggestedCandidates) { |
3488 | ||
3489 | let paths = &candidates.candidates; | |
3490 | ||
3491 | if paths.len() > 0 { | |
3492 | // don't show more than MAX_CANDIDATES results, so | |
3493 | // we're consistent with the trait suggestions | |
3494 | const MAX_CANDIDATES: usize = 5; | |
3495 | ||
3496 | // we want consistent results across executions, but candidates are produced | |
3497 | // by iterating through a hash map, so make sure they are ordered: | |
3498 | let mut path_strings: Vec<_> = paths.into_iter() | |
3499 | .map(|p| path_names_to_string(&p, 0)) | |
3500 | .collect(); | |
3501 | path_strings.sort(); | |
3502 | ||
3503 | // behave differently based on how many candidates we have: | |
3504 | if !paths.is_empty() { | |
3505 | if paths.len() == 1 { | |
a7813a04 | 3506 | session.help( |
54a0048b | 3507 | &format!("you can import it into scope: `use {};`.", |
7453a54e SL |
3508 | &path_strings[0]), |
3509 | ); | |
3510 | } else { | |
a7813a04 | 3511 | session.help("you can import several candidates \ |
7453a54e SL |
3512 | into scope (`use ...;`):"); |
3513 | let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1; | |
3514 | ||
3515 | for (idx, path_string) in path_strings.iter().enumerate() { | |
3516 | if idx == MAX_CANDIDATES - 1 && count > 1 { | |
a7813a04 | 3517 | session.help( |
7453a54e SL |
3518 | &format!(" and {} other candidates", count).to_string(), |
3519 | ); | |
3520 | break; | |
3521 | } else { | |
a7813a04 | 3522 | session.help( |
7453a54e SL |
3523 | &format!(" `{}`", path_string).to_string(), |
3524 | ); | |
3525 | } | |
3526 | } | |
3527 | } | |
3528 | } | |
3529 | } else { | |
3530 | // nothing found: | |
a7813a04 | 3531 | session.help( |
7453a54e SL |
3532 | &format!("no candidates by the name of `{}` found in your \ |
3533 | project; maybe you misspelled the name or forgot to import \ | |
3534 | an external crate?", candidates.name.to_string()), | |
3535 | ); | |
3536 | }; | |
3537 | } | |
3538 | ||
c34b1796 | 3539 | /// A somewhat inefficient routine to obtain the name of a module. |
7453a54e | 3540 | fn module_to_string(module: Module) -> String { |
c34b1796 AL |
3541 | let mut names = Vec::new(); |
3542 | ||
c30ab7b3 | 3543 | fn collect_mod(names: &mut Vec<Ident>, module: Module) { |
9e0c209e SL |
3544 | if let ModuleKind::Def(_, name) = module.kind { |
3545 | if let Some(parent) = module.parent { | |
c30ab7b3 | 3546 | names.push(Ident::with_empty_ctxt(name)); |
9e0c209e | 3547 | collect_mod(names, parent); |
c34b1796 | 3548 | } |
9e0c209e SL |
3549 | } else { |
3550 | // danger, shouldn't be ident? | |
c30ab7b3 SL |
3551 | names.push(token::str_to_ident("<opaque>")); |
3552 | collect_mod(names, module.parent.unwrap()); | |
c34b1796 AL |
3553 | } |
3554 | } | |
3555 | collect_mod(&mut names, module); | |
3556 | ||
9346a6ac | 3557 | if names.is_empty() { |
c34b1796 AL |
3558 | return "???".to_string(); |
3559 | } | |
c30ab7b3 | 3560 | names_to_string(&names.into_iter().rev().collect::<Vec<_>>()) |
c34b1796 AL |
3561 | } |
3562 | ||
9cc50fc6 | 3563 | fn err_path_resolution() -> PathResolution { |
3157f602 | 3564 | PathResolution::new(Def::Err) |
9cc50fc6 SL |
3565 | } |
3566 | ||
c34b1796 | 3567 | #[derive(PartialEq,Copy, Clone)] |
1a4d82fc JJ |
3568 | pub enum MakeGlobMap { |
3569 | Yes, | |
92a42be0 | 3570 | No, |
1a4d82fc JJ |
3571 | } |
3572 | ||
d9579d0f | 3573 | __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } |