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