]>
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 | ||
e9174d1e | 11 | #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", |
62682a34 | 12 | html_favicon_url = "https://doc.rust-lang.org/favicon.ico", |
e9174d1e | 13 | html_root_url = "https://doc.rust-lang.org/nightly/")] |
1a4d82fc | 14 | |
94b46f34 | 15 | #![feature(crate_visibility_modifier)] |
1a4d82fc | 16 | #![feature(rustc_diagnostic_macros)] |
83c7162d | 17 | #![feature(slice_sort_by_cached_key)] |
7cac9316 | 18 | |
92a42be0 SL |
19 | #[macro_use] |
20 | extern crate log; | |
21 | #[macro_use] | |
22 | extern crate syntax; | |
3157f602 XL |
23 | extern crate syntax_pos; |
24 | extern crate rustc_errors as errors; | |
9cc50fc6 | 25 | extern crate arena; |
92a42be0 | 26 | #[macro_use] |
1a4d82fc | 27 | extern crate rustc; |
abe05a73 | 28 | extern crate rustc_data_structures; |
1a4d82fc | 29 | |
94b46f34 XL |
30 | pub use rustc::hir::def::{Namespace, PerNS}; |
31 | ||
1a4d82fc JJ |
32 | use self::TypeParameters::*; |
33 | use self::RibKind::*; | |
1a4d82fc | 34 | |
c30ab7b3 | 35 | use rustc::hir::map::{Definitions, DefCollector}; |
a7813a04 | 36 | use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; |
ea8adc8c | 37 | use rustc::middle::cstore::{CrateStore, CrateLoader}; |
1a4d82fc JJ |
38 | use rustc::session::Session; |
39 | use rustc::lint; | |
54a0048b | 40 | use rustc::hir::def::*; |
94b46f34 | 41 | use rustc::hir::def::Namespace::*; |
7cac9316 | 42 | use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; |
a7813a04 | 43 | use rustc::ty; |
a7813a04 | 44 | use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; |
8bb4bdeb | 45 | use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; |
1a4d82fc | 46 | |
94b46f34 | 47 | use syntax::codemap::CodeMap; |
2c00a5a8 | 48 | use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext}; |
83c7162d | 49 | use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; |
c30ab7b3 | 50 | use syntax::ext::base::SyntaxExtension; |
7cac9316 | 51 | use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; |
8bb4bdeb | 52 | use syntax::ext::base::MacroKind; |
476ff2be | 53 | use syntax::symbol::{Symbol, keywords}; |
9cc50fc6 | 54 | use syntax::util::lev_distance::find_best_match_for_name; |
e9174d1e | 55 | |
a7813a04 | 56 | use syntax::visit::{self, FnKind, Visitor}; |
9e0c209e | 57 | use syntax::attr; |
a7813a04 | 58 | use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind}; |
ff7c6d11 | 59 | use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics}; |
a7813a04 | 60 | use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; |
2c00a5a8 | 61 | use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; |
32a655c1 | 62 | use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; |
0531ce1d | 63 | use syntax::feature_gate::{feature_err, GateIssue}; |
0531ce1d | 64 | use syntax::ptr::P; |
3157f602 | 65 | |
476ff2be | 66 | use syntax_pos::{Span, DUMMY_SP, MultiSpan}; |
abe05a73 | 67 | use errors::{DiagnosticBuilder, DiagnosticId}; |
1a4d82fc | 68 | |
1a4d82fc | 69 | use std::cell::{Cell, RefCell}; |
32a655c1 | 70 | use std::cmp; |
8bb4bdeb | 71 | use std::collections::BTreeSet; |
1a4d82fc | 72 | use std::fmt; |
2c00a5a8 | 73 | use std::iter; |
1a4d82fc | 74 | use std::mem::replace; |
0531ce1d | 75 | use rustc_data_structures::sync::Lrc; |
85aaf69f | 76 | |
476ff2be | 77 | use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; |
cc61c64b | 78 | use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding}; |
c34b1796 | 79 | |
85aaf69f SL |
80 | // NB: This module needs to be declared first so diagnostics are |
81 | // registered before they are used. | |
54a0048b | 82 | mod diagnostics; |
1a4d82fc | 83 | |
9e0c209e | 84 | mod macros; |
1a4d82fc | 85 | mod check_unused; |
1a4d82fc | 86 | mod build_reduced_graph; |
c34b1796 | 87 | mod resolve_imports; |
1a4d82fc | 88 | |
32a655c1 SL |
89 | /// A free importable items suggested in case of resolution failure. |
90 | struct ImportSuggestion { | |
91 | path: Path, | |
92a42be0 SL |
92 | } |
93 | ||
32a655c1 SL |
94 | /// A field or associated item from self type suggested in case of resolution failure. |
95 | enum AssocSuggestion { | |
96 | Field, | |
97 | MethodWithSelf, | |
98 | AssocItem, | |
7453a54e SL |
99 | } |
100 | ||
8bb4bdeb XL |
101 | #[derive(Eq)] |
102 | struct BindingError { | |
103 | name: Name, | |
104 | origin: BTreeSet<Span>, | |
105 | target: BTreeSet<Span>, | |
106 | } | |
107 | ||
108 | impl PartialOrd for BindingError { | |
109 | fn partial_cmp(&self, other: &BindingError) -> Option<cmp::Ordering> { | |
110 | Some(self.cmp(other)) | |
111 | } | |
112 | } | |
113 | ||
114 | impl PartialEq for BindingError { | |
115 | fn eq(&self, other: &BindingError) -> bool { | |
116 | self.name == other.name | |
117 | } | |
118 | } | |
119 | ||
120 | impl Ord for BindingError { | |
121 | fn cmp(&self, other: &BindingError) -> cmp::Ordering { | |
122 | self.name.cmp(&other.name) | |
123 | } | |
124 | } | |
125 | ||
54a0048b | 126 | enum ResolutionError<'a> { |
c1a9b12d | 127 | /// error E0401: can't use type parameters from outer function |
0531ce1d | 128 | TypeParametersFromOuterFunction(Def), |
c1a9b12d | 129 | /// error E0403: the name is already used for a type parameter in this type parameter list |
9e0c209e | 130 | NameAlreadyUsedInTypeParameterList(Name, &'a Span), |
c1a9b12d SL |
131 | /// error E0407: method is not a member of trait |
132 | MethodNotMemberOfTrait(Name, &'a str), | |
133 | /// error E0437: type is not a member of trait | |
134 | TypeNotMemberOfTrait(Name, &'a str), | |
135 | /// error E0438: const is not a member of trait | |
136 | ConstNotMemberOfTrait(Name, &'a str), | |
8bb4bdeb XL |
137 | /// error E0408: variable `{}` is not bound in all patterns |
138 | VariableNotBoundInPattern(&'a BindingError), | |
139 | /// error E0409: variable `{}` is bound in inconsistent ways within the same match arm | |
140 | VariableBoundWithDifferentMode(Name, Span), | |
c1a9b12d SL |
141 | /// error E0415: identifier is bound more than once in this parameter list |
142 | IdentifierBoundMoreThanOnceInParameterList(&'a str), | |
143 | /// error E0416: identifier is bound more than once in the same pattern | |
144 | IdentifierBoundMoreThanOnceInSamePattern(&'a str), | |
c1a9b12d | 145 | /// error E0426: use of undeclared label |
abe05a73 | 146 | UndeclaredLabel(&'a str, Option<Name>), |
c1a9b12d SL |
147 | /// error E0429: `self` imports are only allowed within a { } list |
148 | SelfImportsOnlyAllowedWithin, | |
149 | /// error E0430: `self` import can only appear once in the list | |
150 | SelfImportCanOnlyAppearOnceInTheList, | |
151 | /// error E0431: `self` import can only appear in an import list with a non-empty prefix | |
152 | SelfImportOnlyInImportListWithNonEmptyPrefix, | |
153 | /// error E0432: unresolved import | |
3b2f2976 | 154 | UnresolvedImport(Option<(Span, &'a str, &'a str)>), |
c1a9b12d SL |
155 | /// error E0433: failed to resolve |
156 | FailedToResolve(&'a str), | |
157 | /// error E0434: can't capture dynamic environment in a fn item | |
158 | CannotCaptureDynamicEnvironmentInFnItem, | |
159 | /// error E0435: attempt to use a non-constant value in a constant | |
160 | AttemptToUseNonConstantValueInConstant, | |
3157f602 | 161 | /// error E0530: X bindings cannot shadow Ys |
5bcae85e | 162 | BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>), |
8bb4bdeb XL |
163 | /// error E0128: type parameters with a default cannot use forward declared identifiers |
164 | ForwardDeclaredTyParam, | |
9cc50fc6 SL |
165 | } |
166 | ||
0531ce1d XL |
167 | /// Combines an error with provided span and emits it |
168 | /// | |
169 | /// This takes the error provided, combines it with the span and any additional spans inside the | |
170 | /// error and emits it. | |
32a655c1 SL |
171 | fn resolve_error<'sess, 'a>(resolver: &'sess Resolver, |
172 | span: Span, | |
173 | resolution_error: ResolutionError<'a>) { | |
9cc50fc6 SL |
174 | resolve_struct_error(resolver, span, resolution_error).emit(); |
175 | } | |
176 | ||
32a655c1 SL |
177 | fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver, |
178 | span: Span, | |
179 | resolution_error: ResolutionError<'a>) | |
180 | -> DiagnosticBuilder<'sess> { | |
c1a9b12d | 181 | match resolution_error { |
0531ce1d | 182 | ResolutionError::TypeParametersFromOuterFunction(outer_def) => { |
a7813a04 XL |
183 | let mut err = struct_span_err!(resolver.session, |
184 | span, | |
185 | E0401, | |
0531ce1d | 186 | "can't use type parameters from outer function"); |
7cac9316 | 187 | err.span_label(span, "use of type variable from outer function"); |
0531ce1d XL |
188 | |
189 | let cm = resolver.session.codemap(); | |
190 | match outer_def { | |
191 | Def::SelfTy(_, maybe_impl_defid) => { | |
192 | if let Some(impl_span) = maybe_impl_defid.map_or(None, | |
193 | |def_id| resolver.definitions.opt_span(def_id)) { | |
194 | err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span), | |
195 | "`Self` type implicitely declared here, on the `impl`"); | |
196 | } | |
197 | }, | |
198 | Def::TyParam(typaram_defid) => { | |
199 | if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) { | |
200 | err.span_label(typaram_span, "type variable from outer function"); | |
201 | } | |
202 | }, | |
203 | Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) | | |
204 | Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) | | |
205 | Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) | | |
206 | Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) | | |
207 | Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) | | |
94b46f34 | 208 | Def::Existential(..) | |
0531ce1d XL |
209 | Def::Macro(..) | Def::GlobalAsm(..) | Def::Err => |
210 | bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \ | |
211 | Def::TyParam") | |
212 | } | |
213 | ||
214 | // Try to retrieve the span of the function signature and generate a new message with | |
215 | // a local type parameter | |
216 | let sugg_msg = "try using a local type parameter instead"; | |
94b46f34 | 217 | if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) { |
0531ce1d XL |
218 | // Suggest the modification to the user |
219 | err.span_suggestion(sugg_span, | |
220 | sugg_msg, | |
221 | new_snippet); | |
94b46f34 | 222 | } else if let Some(sp) = cm.generate_fn_name_span(span) { |
0531ce1d XL |
223 | err.span_label(sp, "try adding a local type parameter in this method instead"); |
224 | } else { | |
225 | err.help("try using a local type parameter instead"); | |
226 | } | |
227 | ||
a7813a04 | 228 | err |
92a42be0 | 229 | } |
9e0c209e SL |
230 | ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => { |
231 | let mut err = struct_span_err!(resolver.session, | |
232 | span, | |
233 | E0403, | |
234 | "the name `{}` is already used for a type parameter \ | |
235 | in this type parameter list", | |
236 | name); | |
7cac9316 XL |
237 | err.span_label(span, "already used"); |
238 | err.span_label(first_use_span.clone(), format!("first use of `{}`", name)); | |
9e0c209e | 239 | err |
92a42be0 | 240 | } |
c1a9b12d | 241 | ResolutionError::MethodNotMemberOfTrait(method, trait_) => { |
9e0c209e SL |
242 | let mut err = struct_span_err!(resolver.session, |
243 | span, | |
244 | E0407, | |
245 | "method `{}` is not a member of trait `{}`", | |
246 | method, | |
247 | trait_); | |
7cac9316 | 248 | err.span_label(span, format!("not a member of trait `{}`", trait_)); |
9e0c209e | 249 | err |
92a42be0 | 250 | } |
c1a9b12d | 251 | ResolutionError::TypeNotMemberOfTrait(type_, trait_) => { |
9e0c209e | 252 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
253 | span, |
254 | E0437, | |
255 | "type `{}` is not a member of trait `{}`", | |
256 | type_, | |
9e0c209e | 257 | trait_); |
7cac9316 | 258 | err.span_label(span, format!("not a member of trait `{}`", trait_)); |
9e0c209e | 259 | err |
92a42be0 | 260 | } |
c1a9b12d | 261 | ResolutionError::ConstNotMemberOfTrait(const_, trait_) => { |
9e0c209e | 262 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
263 | span, |
264 | E0438, | |
265 | "const `{}` is not a member of trait `{}`", | |
266 | const_, | |
9e0c209e | 267 | trait_); |
7cac9316 | 268 | err.span_label(span, format!("not a member of trait `{}`", trait_)); |
9e0c209e | 269 | err |
92a42be0 | 270 | } |
8bb4bdeb XL |
271 | ResolutionError::VariableNotBoundInPattern(binding_error) => { |
272 | let target_sp = binding_error.target.iter().map(|x| *x).collect::<Vec<_>>(); | |
273 | let msp = MultiSpan::from_spans(target_sp.clone()); | |
274 | let msg = format!("variable `{}` is not bound in all patterns", binding_error.name); | |
abe05a73 XL |
275 | let mut err = resolver.session.struct_span_err_with_code( |
276 | msp, | |
277 | &msg, | |
278 | DiagnosticId::Error("E0408".into()), | |
279 | ); | |
8bb4bdeb | 280 | for sp in target_sp { |
7cac9316 | 281 | err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name)); |
8bb4bdeb XL |
282 | } |
283 | let origin_sp = binding_error.origin.iter().map(|x| *x).collect::<Vec<_>>(); | |
284 | for sp in origin_sp { | |
7cac9316 | 285 | err.span_label(sp, "variable not in all patterns"); |
8bb4bdeb | 286 | } |
c30ab7b3 | 287 | err |
92a42be0 | 288 | } |
9e0c209e | 289 | ResolutionError::VariableBoundWithDifferentMode(variable_name, |
9e0c209e SL |
290 | first_binding_span) => { |
291 | let mut err = struct_span_err!(resolver.session, | |
9cc50fc6 SL |
292 | span, |
293 | E0409, | |
8bb4bdeb XL |
294 | "variable `{}` is bound in inconsistent \ |
295 | ways within the same match arm", | |
296 | variable_name); | |
7cac9316 XL |
297 | err.span_label(span, "bound in different ways"); |
298 | err.span_label(first_binding_span, "first binding"); | |
9e0c209e | 299 | err |
92a42be0 | 300 | } |
c1a9b12d | 301 | ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { |
a7813a04 | 302 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
303 | span, |
304 | E0415, | |
305 | "identifier `{}` is bound more than once in this parameter list", | |
a7813a04 | 306 | identifier); |
7cac9316 | 307 | err.span_label(span, "used as parameter more than once"); |
a7813a04 | 308 | err |
92a42be0 | 309 | } |
c1a9b12d | 310 | ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { |
a7813a04 | 311 | let mut err = struct_span_err!(resolver.session, |
9cc50fc6 SL |
312 | span, |
313 | E0416, | |
314 | "identifier `{}` is bound more than once in the same pattern", | |
a7813a04 | 315 | identifier); |
7cac9316 | 316 | err.span_label(span, "used in a pattern more than once"); |
a7813a04 | 317 | err |
92a42be0 | 318 | } |
abe05a73 | 319 | ResolutionError::UndeclaredLabel(name, lev_candidate) => { |
9e0c209e SL |
320 | let mut err = struct_span_err!(resolver.session, |
321 | span, | |
322 | E0426, | |
323 | "use of undeclared label `{}`", | |
324 | name); | |
abe05a73 XL |
325 | if let Some(lev_candidate) = lev_candidate { |
326 | err.span_label(span, format!("did you mean `{}`?", lev_candidate)); | |
327 | } else { | |
328 | err.span_label(span, format!("undeclared label `{}`", name)); | |
329 | } | |
9e0c209e | 330 | err |
92a42be0 | 331 | } |
c1a9b12d | 332 | ResolutionError::SelfImportsOnlyAllowedWithin => { |
9cc50fc6 SL |
333 | struct_span_err!(resolver.session, |
334 | span, | |
335 | E0429, | |
336 | "{}", | |
337 | "`self` imports are only allowed within a { } list") | |
92a42be0 | 338 | } |
c1a9b12d | 339 | ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { |
ff7c6d11 XL |
340 | let mut err = struct_span_err!(resolver.session, span, E0430, |
341 | "`self` import can only appear once in an import list"); | |
342 | err.span_label(span, "can only appear once in an import list"); | |
343 | err | |
92a42be0 | 344 | } |
c1a9b12d | 345 | ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { |
ff7c6d11 XL |
346 | let mut err = struct_span_err!(resolver.session, span, E0431, |
347 | "`self` import can only appear in an import list with \ | |
348 | a non-empty prefix"); | |
349 | err.span_label(span, "can only appear in an import list with a non-empty prefix"); | |
350 | err | |
c1a9b12d SL |
351 | } |
352 | ResolutionError::UnresolvedImport(name) => { | |
3b2f2976 XL |
353 | let (span, msg) = match name { |
354 | Some((sp, n, _)) => (sp, format!("unresolved import `{}`", n)), | |
355 | None => (span, "unresolved import".to_owned()), | |
c1a9b12d | 356 | }; |
9e0c209e | 357 | let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg); |
3b2f2976 | 358 | if let Some((_, _, p)) = name { |
7cac9316 | 359 | err.span_label(span, p); |
9e0c209e SL |
360 | } |
361 | err | |
92a42be0 | 362 | } |
c1a9b12d | 363 | ResolutionError::FailedToResolve(msg) => { |
5bcae85e SL |
364 | let mut err = struct_span_err!(resolver.session, span, E0433, |
365 | "failed to resolve. {}", msg); | |
7cac9316 | 366 | err.span_label(span, msg); |
5bcae85e | 367 | err |
92a42be0 | 368 | } |
c1a9b12d | 369 | ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { |
ff7c6d11 XL |
370 | let mut err = struct_span_err!(resolver.session, |
371 | span, | |
372 | E0434, | |
373 | "{}", | |
374 | "can't capture dynamic environment in a fn item"); | |
375 | err.help("use the `|| { ... }` closure form instead"); | |
376 | err | |
92a42be0 SL |
377 | } |
378 | ResolutionError::AttemptToUseNonConstantValueInConstant => { | |
ff7c6d11 XL |
379 | let mut err = struct_span_err!(resolver.session, span, E0435, |
380 | "attempt to use a non-constant value in a constant"); | |
041b39d2 | 381 | err.span_label(span, "non-constant value"); |
9e0c209e | 382 | err |
92a42be0 | 383 | } |
5bcae85e | 384 | ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => { |
9e0c209e | 385 | let shadows_what = PathResolution::new(binding.def()).kind_name(); |
3157f602 XL |
386 | let mut err = struct_span_err!(resolver.session, |
387 | span, | |
388 | E0530, | |
389 | "{}s cannot shadow {}s", what_binding, shadows_what); | |
7cac9316 | 390 | err.span_label(span, format!("cannot be named the same as a {}", shadows_what)); |
5bcae85e | 391 | let participle = if binding.is_import() { "imported" } else { "defined" }; |
7cac9316 | 392 | let msg = format!("a {} `{}` is {} here", shadows_what, name, participle); |
5bcae85e | 393 | err.span_label(binding.span, msg); |
3157f602 XL |
394 | err |
395 | } | |
8bb4bdeb XL |
396 | ResolutionError::ForwardDeclaredTyParam => { |
397 | let mut err = struct_span_err!(resolver.session, span, E0128, | |
398 | "type parameters with a default cannot use \ | |
399 | forward declared identifiers"); | |
ff7c6d11 | 400 | err.span_label(span, format!("defaulted type parameters cannot be forward declared")); |
8bb4bdeb XL |
401 | err |
402 | } | |
c1a9b12d SL |
403 | } |
404 | } | |
405 | ||
0531ce1d XL |
406 | /// Adjust the impl span so that just the `impl` keyword is taken by removing |
407 | /// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and | |
408 | /// everything after the first whitespace (`"impl Iterator for A" -> "impl"`) | |
409 | /// | |
410 | /// Attention: The method used is very fragile since it essentially duplicates the work of the | |
411 | /// parser. If you need to use this function or something similar, please consider updating the | |
412 | /// codemap functions and this function to something more robust. | |
413 | fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span { | |
414 | let impl_span = cm.span_until_char(impl_span, '<'); | |
415 | let impl_span = cm.span_until_whitespace(impl_span); | |
416 | impl_span | |
417 | } | |
418 | ||
8bb4bdeb | 419 | #[derive(Copy, Clone, Debug)] |
1a4d82fc JJ |
420 | struct BindingInfo { |
421 | span: Span, | |
422 | binding_mode: BindingMode, | |
423 | } | |
424 | ||
0531ce1d | 425 | /// Map from the name in a pattern to its binding mode. |
476ff2be | 426 | type BindingMap = FxHashMap<Ident, BindingInfo>; |
1a4d82fc | 427 | |
3157f602 XL |
428 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
429 | enum PatternSource { | |
430 | Match, | |
431 | IfLet, | |
432 | WhileLet, | |
433 | Let, | |
434 | For, | |
435 | FnParam, | |
436 | } | |
437 | ||
438 | impl PatternSource { | |
3157f602 XL |
439 | fn descr(self) -> &'static str { |
440 | match self { | |
441 | PatternSource::Match => "match binding", | |
442 | PatternSource::IfLet => "if let binding", | |
443 | PatternSource::WhileLet => "while let binding", | |
444 | PatternSource::Let => "let binding", | |
445 | PatternSource::For => "for binding", | |
446 | PatternSource::FnParam => "function parameter", | |
447 | } | |
448 | } | |
1a4d82fc JJ |
449 | } |
450 | ||
ff7c6d11 XL |
451 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
452 | enum AliasPossibility { | |
453 | No, | |
454 | Maybe, | |
455 | } | |
456 | ||
32a655c1 SL |
457 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
458 | enum PathSource<'a> { | |
459 | // Type paths `Path`. | |
460 | Type, | |
461 | // Trait paths in bounds or impls. | |
ff7c6d11 | 462 | Trait(AliasPossibility), |
32a655c1 | 463 | // Expression paths `path`, with optional parent context. |
8bb4bdeb | 464 | Expr(Option<&'a Expr>), |
32a655c1 SL |
465 | // Paths in path patterns `Path`. |
466 | Pat, | |
467 | // Paths in struct expressions and patterns `Path { .. }`. | |
468 | Struct, | |
469 | // Paths in tuple struct patterns `Path(..)`. | |
470 | TupleStruct, | |
471 | // `m::A::B` in `<T as m::A>::B::C`. | |
472 | TraitItem(Namespace), | |
473 | // Path in `pub(path)` | |
474 | Visibility, | |
475 | // Path in `use a::b::{...};` | |
476 | ImportPrefix, | |
477 | } | |
478 | ||
479 | impl<'a> PathSource<'a> { | |
480 | fn namespace(self) -> Namespace { | |
481 | match self { | |
ff7c6d11 | 482 | PathSource::Type | PathSource::Trait(_) | PathSource::Struct | |
32a655c1 SL |
483 | PathSource::Visibility | PathSource::ImportPrefix => TypeNS, |
484 | PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS, | |
485 | PathSource::TraitItem(ns) => ns, | |
486 | } | |
487 | } | |
488 | ||
489 | fn global_by_default(self) -> bool { | |
490 | match self { | |
491 | PathSource::Visibility | PathSource::ImportPrefix => true, | |
492 | PathSource::Type | PathSource::Expr(..) | PathSource::Pat | | |
493 | PathSource::Struct | PathSource::TupleStruct | | |
ff7c6d11 | 494 | PathSource::Trait(_) | PathSource::TraitItem(..) => false, |
32a655c1 SL |
495 | } |
496 | } | |
497 | ||
498 | fn defer_to_typeck(self) -> bool { | |
499 | match self { | |
500 | PathSource::Type | PathSource::Expr(..) | PathSource::Pat | | |
501 | PathSource::Struct | PathSource::TupleStruct => true, | |
ff7c6d11 | 502 | PathSource::Trait(_) | PathSource::TraitItem(..) | |
32a655c1 SL |
503 | PathSource::Visibility | PathSource::ImportPrefix => false, |
504 | } | |
505 | } | |
506 | ||
507 | fn descr_expected(self) -> &'static str { | |
508 | match self { | |
509 | PathSource::Type => "type", | |
ff7c6d11 | 510 | PathSource::Trait(_) => "trait", |
32a655c1 SL |
511 | PathSource::Pat => "unit struct/variant or constant", |
512 | PathSource::Struct => "struct, variant or union type", | |
513 | PathSource::TupleStruct => "tuple struct/variant", | |
514 | PathSource::Visibility => "module", | |
515 | PathSource::ImportPrefix => "module or enum", | |
516 | PathSource::TraitItem(ns) => match ns { | |
517 | TypeNS => "associated type", | |
518 | ValueNS => "method or associated constant", | |
519 | MacroNS => bug!("associated macro"), | |
520 | }, | |
8bb4bdeb | 521 | PathSource::Expr(parent) => match parent.map(|p| &p.node) { |
32a655c1 SL |
522 | // "function" here means "anything callable" rather than `Def::Fn`, |
523 | // this is not precise but usually more helpful than just "value". | |
524 | Some(&ExprKind::Call(..)) => "function", | |
525 | _ => "value", | |
526 | }, | |
527 | } | |
528 | } | |
529 | ||
530 | fn is_expected(self, def: Def) -> bool { | |
531 | match self { | |
532 | PathSource::Type => match def { | |
533 | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | | |
534 | Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | | |
abe05a73 XL |
535 | Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) | |
536 | Def::TyForeign(..) => true, | |
32a655c1 SL |
537 | _ => false, |
538 | }, | |
ff7c6d11 | 539 | PathSource::Trait(AliasPossibility::No) => match def { |
32a655c1 SL |
540 | Def::Trait(..) => true, |
541 | _ => false, | |
542 | }, | |
ff7c6d11 XL |
543 | PathSource::Trait(AliasPossibility::Maybe) => match def { |
544 | Def::Trait(..) => true, | |
545 | Def::TraitAlias(..) => true, | |
546 | _ => false, | |
547 | }, | |
32a655c1 SL |
548 | PathSource::Expr(..) => match def { |
549 | Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) | | |
550 | Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) | | |
551 | Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) | | |
552 | Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) => true, | |
553 | _ => false, | |
554 | }, | |
555 | PathSource::Pat => match def { | |
556 | Def::StructCtor(_, CtorKind::Const) | | |
557 | Def::VariantCtor(_, CtorKind::Const) | | |
558 | Def::Const(..) | Def::AssociatedConst(..) => true, | |
559 | _ => false, | |
560 | }, | |
561 | PathSource::TupleStruct => match def { | |
562 | Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => true, | |
563 | _ => false, | |
564 | }, | |
565 | PathSource::Struct => match def { | |
566 | Def::Struct(..) | Def::Union(..) | Def::Variant(..) | | |
567 | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true, | |
568 | _ => false, | |
569 | }, | |
570 | PathSource::TraitItem(ns) => match def { | |
571 | Def::AssociatedConst(..) | Def::Method(..) if ns == ValueNS => true, | |
572 | Def::AssociatedTy(..) if ns == TypeNS => true, | |
573 | _ => false, | |
574 | }, | |
575 | PathSource::ImportPrefix => match def { | |
576 | Def::Mod(..) | Def::Enum(..) => true, | |
577 | _ => false, | |
578 | }, | |
579 | PathSource::Visibility => match def { | |
580 | Def::Mod(..) => true, | |
581 | _ => false, | |
582 | }, | |
583 | } | |
584 | } | |
585 | ||
586 | fn error_code(self, has_unexpected_resolution: bool) -> &'static str { | |
587 | __diagnostic_used!(E0404); | |
588 | __diagnostic_used!(E0405); | |
589 | __diagnostic_used!(E0412); | |
590 | __diagnostic_used!(E0422); | |
591 | __diagnostic_used!(E0423); | |
592 | __diagnostic_used!(E0425); | |
593 | __diagnostic_used!(E0531); | |
594 | __diagnostic_used!(E0532); | |
595 | __diagnostic_used!(E0573); | |
596 | __diagnostic_used!(E0574); | |
597 | __diagnostic_used!(E0575); | |
598 | __diagnostic_used!(E0576); | |
599 | __diagnostic_used!(E0577); | |
600 | __diagnostic_used!(E0578); | |
601 | match (self, has_unexpected_resolution) { | |
ff7c6d11 XL |
602 | (PathSource::Trait(_), true) => "E0404", |
603 | (PathSource::Trait(_), false) => "E0405", | |
32a655c1 SL |
604 | (PathSource::Type, true) => "E0573", |
605 | (PathSource::Type, false) => "E0412", | |
606 | (PathSource::Struct, true) => "E0574", | |
607 | (PathSource::Struct, false) => "E0422", | |
608 | (PathSource::Expr(..), true) => "E0423", | |
609 | (PathSource::Expr(..), false) => "E0425", | |
610 | (PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532", | |
611 | (PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531", | |
612 | (PathSource::TraitItem(..), true) => "E0575", | |
613 | (PathSource::TraitItem(..), false) => "E0576", | |
614 | (PathSource::Visibility, true) | (PathSource::ImportPrefix, true) => "E0577", | |
615 | (PathSource::Visibility, false) | (PathSource::ImportPrefix, false) => "E0578", | |
616 | } | |
617 | } | |
618 | } | |
619 | ||
3b2f2976 XL |
620 | struct UsePlacementFinder { |
621 | target_module: NodeId, | |
622 | span: Option<Span>, | |
623 | found_use: bool, | |
624 | } | |
625 | ||
ff7c6d11 XL |
626 | impl UsePlacementFinder { |
627 | fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, bool) { | |
628 | let mut finder = UsePlacementFinder { | |
629 | target_module, | |
630 | span: None, | |
631 | found_use: false, | |
632 | }; | |
633 | visit::walk_crate(&mut finder, krate); | |
634 | (finder.span, finder.found_use) | |
635 | } | |
636 | } | |
637 | ||
3b2f2976 XL |
638 | impl<'tcx> Visitor<'tcx> for UsePlacementFinder { |
639 | fn visit_mod( | |
640 | &mut self, | |
641 | module: &'tcx ast::Mod, | |
642 | _: Span, | |
643 | _: &[ast::Attribute], | |
644 | node_id: NodeId, | |
645 | ) { | |
646 | if self.span.is_some() { | |
647 | return; | |
648 | } | |
649 | if node_id != self.target_module { | |
650 | visit::walk_mod(self, module); | |
651 | return; | |
652 | } | |
653 | // find a use statement | |
654 | for item in &module.items { | |
655 | match item.node { | |
656 | ItemKind::Use(..) => { | |
657 | // don't suggest placing a use before the prelude | |
658 | // import or other generated ones | |
ea8adc8c | 659 | if item.span.ctxt().outer().expn_info().is_none() { |
0531ce1d | 660 | self.span = Some(item.span.shrink_to_lo()); |
3b2f2976 XL |
661 | self.found_use = true; |
662 | return; | |
663 | } | |
664 | }, | |
665 | // don't place use before extern crate | |
666 | ItemKind::ExternCrate(_) => {} | |
667 | // but place them before the first other item | |
668 | _ => if self.span.map_or(true, |span| item.span < span ) { | |
ea8adc8c | 669 | if item.span.ctxt().outer().expn_info().is_none() { |
3b2f2976 XL |
670 | // don't insert between attributes and an item |
671 | if item.attrs.is_empty() { | |
0531ce1d | 672 | self.span = Some(item.span.shrink_to_lo()); |
3b2f2976 XL |
673 | } else { |
674 | // find the first attribute on the item | |
675 | for attr in &item.attrs { | |
676 | if self.span.map_or(true, |span| attr.span < span) { | |
0531ce1d | 677 | self.span = Some(attr.span.shrink_to_lo()); |
3b2f2976 XL |
678 | } |
679 | } | |
680 | } | |
681 | } | |
682 | }, | |
683 | } | |
684 | } | |
685 | } | |
686 | } | |
687 | ||
0531ce1d | 688 | /// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes. |
476ff2be SL |
689 | impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { |
690 | fn visit_item(&mut self, item: &'tcx Item) { | |
1a4d82fc JJ |
691 | self.resolve_item(item); |
692 | } | |
476ff2be | 693 | fn visit_arm(&mut self, arm: &'tcx Arm) { |
1a4d82fc JJ |
694 | self.resolve_arm(arm); |
695 | } | |
476ff2be | 696 | fn visit_block(&mut self, block: &'tcx Block) { |
1a4d82fc JJ |
697 | self.resolve_block(block); |
698 | } | |
94b46f34 XL |
699 | fn visit_anon_const(&mut self, constant: &'tcx ast::AnonConst) { |
700 | self.with_constant_rib(|this| { | |
701 | visit::walk_anon_const(this, constant); | |
702 | }); | |
703 | } | |
476ff2be | 704 | fn visit_expr(&mut self, expr: &'tcx Expr) { |
a7813a04 | 705 | self.resolve_expr(expr, None); |
1a4d82fc | 706 | } |
476ff2be | 707 | fn visit_local(&mut self, local: &'tcx Local) { |
1a4d82fc JJ |
708 | self.resolve_local(local); |
709 | } | |
476ff2be | 710 | fn visit_ty(&mut self, ty: &'tcx Ty) { |
3b2f2976 XL |
711 | match ty.node { |
712 | TyKind::Path(ref qself, ref path) => { | |
713 | self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); | |
714 | } | |
715 | TyKind::ImplicitSelf => { | |
716 | let self_ty = keywords::SelfType.ident(); | |
717 | let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span) | |
718 | .map_or(Def::Err, |d| d.def()); | |
719 | self.record_def(ty.id, PathResolution::new(def)); | |
720 | } | |
3b2f2976 | 721 | _ => (), |
32a655c1 SL |
722 | } |
723 | visit::walk_ty(self, ty); | |
1a4d82fc | 724 | } |
476ff2be SL |
725 | fn visit_poly_trait_ref(&mut self, |
726 | tref: &'tcx ast::PolyTraitRef, | |
727 | m: &'tcx ast::TraitBoundModifier) { | |
32a655c1 | 728 | self.smart_resolve_path(tref.trait_ref.ref_id, None, |
ff7c6d11 | 729 | &tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe)); |
a7813a04 | 730 | visit::walk_poly_trait_ref(self, tref, m); |
c34b1796 | 731 | } |
476ff2be | 732 | fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) { |
c34b1796 | 733 | let type_parameters = match foreign_item.node { |
a7813a04 | 734 | ForeignItemKind::Fn(_, ref generics) => { |
9e0c209e | 735 | HasTypeParameters(generics, ItemRibKind) |
c34b1796 | 736 | } |
a7813a04 | 737 | ForeignItemKind::Static(..) => NoTypeParameters, |
abe05a73 | 738 | ForeignItemKind::Ty => NoTypeParameters, |
83c7162d | 739 | ForeignItemKind::Macro(..) => NoTypeParameters, |
c34b1796 AL |
740 | }; |
741 | self.with_type_parameter_rib(type_parameters, |this| { | |
a7813a04 | 742 | visit::walk_foreign_item(this, foreign_item); |
c34b1796 AL |
743 | }); |
744 | } | |
745 | fn visit_fn(&mut self, | |
476ff2be SL |
746 | function_kind: FnKind<'tcx>, |
747 | declaration: &'tcx FnDecl, | |
c34b1796 AL |
748 | _: Span, |
749 | node_id: NodeId) { | |
750 | let rib_kind = match function_kind { | |
abe05a73 | 751 | FnKind::ItemFn(..) => { |
c34b1796 AL |
752 | ItemRibKind |
753 | } | |
ff7c6d11 XL |
754 | FnKind::Method(_, _, _, _) => { |
755 | TraitOrImplItemRibKind | |
c34b1796 | 756 | } |
476ff2be | 757 | FnKind::Closure(_) => ClosureRibKind(node_id), |
c34b1796 | 758 | }; |
1a4d82fc | 759 | |
476ff2be SL |
760 | // Create a value rib for the function. |
761 | self.ribs[ValueNS].push(Rib::new(rib_kind)); | |
1a4d82fc | 762 | |
476ff2be SL |
763 | // Create a label rib for the function. |
764 | self.label_ribs.push(Rib::new(rib_kind)); | |
1a4d82fc | 765 | |
476ff2be SL |
766 | // Add each argument to the rib. |
767 | let mut bindings_list = FxHashMap(); | |
768 | for argument in &declaration.inputs { | |
769 | self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); | |
7453a54e | 770 | |
476ff2be SL |
771 | self.visit_ty(&argument.ty); |
772 | ||
773 | debug!("(resolving function) recorded argument"); | |
92a42be0 | 774 | } |
476ff2be SL |
775 | visit::walk_fn_ret_ty(self, &declaration.output); |
776 | ||
777 | // Resolve the function body. | |
778 | match function_kind { | |
779 | FnKind::ItemFn(.., body) | | |
780 | FnKind::Method(.., body) => { | |
781 | self.visit_block(body); | |
782 | } | |
783 | FnKind::Closure(body) => { | |
784 | self.visit_expr(body); | |
785 | } | |
786 | }; | |
787 | ||
788 | debug!("(resolving function) leaving function"); | |
789 | ||
790 | self.label_ribs.pop(); | |
791 | self.ribs[ValueNS].pop(); | |
1a4d82fc | 792 | } |
8bb4bdeb XL |
793 | fn visit_generics(&mut self, generics: &'tcx Generics) { |
794 | // For type parameter defaults, we have to ban access | |
795 | // to following type parameters, as the Substs can only | |
0531ce1d XL |
796 | // provide previous type parameters as they're built. We |
797 | // put all the parameters on the ban list and then remove | |
798 | // them one by one as they are processed and become available. | |
8bb4bdeb | 799 | let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); |
ff7c6d11 XL |
800 | default_ban_rib.bindings.extend(generics.params.iter() |
801 | .filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None }) | |
8bb4bdeb XL |
802 | .skip_while(|p| p.default.is_none()) |
803 | .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err))); | |
804 | ||
ff7c6d11 XL |
805 | for param in &generics.params { |
806 | match *param { | |
807 | GenericParam::Lifetime(_) => self.visit_generic_param(param), | |
808 | GenericParam::Type(ref ty_param) => { | |
809 | for bound in &ty_param.bounds { | |
810 | self.visit_ty_param_bound(bound); | |
811 | } | |
8bb4bdeb | 812 | |
ff7c6d11 XL |
813 | if let Some(ref ty) = ty_param.default { |
814 | self.ribs[TypeNS].push(default_ban_rib); | |
815 | self.visit_ty(ty); | |
816 | default_ban_rib = self.ribs[TypeNS].pop().unwrap(); | |
817 | } | |
8bb4bdeb | 818 | |
ff7c6d11 XL |
819 | // Allow all following defaults to refer to this type parameter. |
820 | default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name)); | |
821 | } | |
822 | } | |
8bb4bdeb | 823 | } |
8bb4bdeb XL |
824 | for p in &generics.where_clause.predicates { self.visit_where_predicate(p); } |
825 | } | |
1a4d82fc JJ |
826 | } |
827 | ||
c34b1796 | 828 | #[derive(Copy, Clone)] |
a7813a04 | 829 | enum TypeParameters<'a, 'b> { |
1a4d82fc | 830 | NoTypeParameters, |
92a42be0 | 831 | HasTypeParameters(// Type parameters. |
a7813a04 | 832 | &'b Generics, |
1a4d82fc | 833 | |
92a42be0 | 834 | // The kind of the rib used for type parameters. |
a7813a04 | 835 | RibKind<'a>), |
1a4d82fc JJ |
836 | } |
837 | ||
83c7162d XL |
838 | /// The rib kind controls the translation of local |
839 | /// definitions (`Def::Local`) to upvars (`Def::Upvar`). | |
c34b1796 | 840 | #[derive(Copy, Clone, Debug)] |
7453a54e | 841 | enum RibKind<'a> { |
83c7162d | 842 | /// No translation needs to be applied. |
1a4d82fc JJ |
843 | NormalRibKind, |
844 | ||
83c7162d XL |
845 | /// We passed through a closure scope at the given node ID. |
846 | /// Translate upvars as appropriate. | |
85aaf69f | 847 | ClosureRibKind(NodeId /* func id */), |
1a4d82fc | 848 | |
83c7162d XL |
849 | /// We passed through an impl or trait and are now in one of its |
850 | /// methods or associated types. Allow references to ty params that impl or trait | |
851 | /// binds. Disallow any other upvars (including other ty params that are | |
852 | /// upvars). | |
ff7c6d11 | 853 | TraitOrImplItemRibKind, |
1a4d82fc | 854 | |
83c7162d | 855 | /// We passed through an item scope. Disallow upvars. |
1a4d82fc JJ |
856 | ItemRibKind, |
857 | ||
83c7162d | 858 | /// We're in a constant item. Can't refer to dynamic stuff. |
92a42be0 | 859 | ConstantItemRibKind, |
7453a54e | 860 | |
83c7162d | 861 | /// We passed through a module. |
7453a54e | 862 | ModuleRibKind(Module<'a>), |
5bcae85e | 863 | |
83c7162d | 864 | /// We passed through a `macro_rules!` statement |
8bb4bdeb XL |
865 | MacroDefinition(DefId), |
866 | ||
83c7162d XL |
867 | /// All bindings in this rib are type parameters that can't be used |
868 | /// from the default of a type parameter because they're not declared | |
869 | /// before said type parameter. Also see the `visit_generics` override. | |
8bb4bdeb | 870 | ForwardTyParamBanRibKind, |
1a4d82fc JJ |
871 | } |
872 | ||
1a4d82fc | 873 | /// One local scope. |
0531ce1d XL |
874 | /// |
875 | /// A rib represents a scope names can live in. Note that these appear in many places, not just | |
876 | /// around braces. At any place where the list of accessible names (of the given namespace) | |
877 | /// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a | |
878 | /// stack. This may be, for example, a `let` statement (because it introduces variables), a macro, | |
879 | /// etc. | |
880 | /// | |
881 | /// Different [rib kinds](enum.RibKind) are transparent for different names. | |
882 | /// | |
883 | /// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When | |
884 | /// resolving, the name is looked up from inside out. | |
85aaf69f | 885 | #[derive(Debug)] |
7453a54e | 886 | struct Rib<'a> { |
476ff2be | 887 | bindings: FxHashMap<Ident, Def>, |
7453a54e | 888 | kind: RibKind<'a>, |
1a4d82fc JJ |
889 | } |
890 | ||
7453a54e SL |
891 | impl<'a> Rib<'a> { |
892 | fn new(kind: RibKind<'a>) -> Rib<'a> { | |
1a4d82fc | 893 | Rib { |
476ff2be | 894 | bindings: FxHashMap(), |
3b2f2976 | 895 | kind, |
92a42be0 SL |
896 | } |
897 | } | |
898 | } | |
899 | ||
0531ce1d XL |
900 | /// An intermediate resolution result. |
901 | /// | |
902 | /// This refers to the thing referred by a name. The difference between `Def` and `Item` is that | |
903 | /// items are visible in their whole block, while defs only from the place they are defined | |
904 | /// forward. | |
54a0048b SL |
905 | enum LexicalScopeBinding<'a> { |
906 | Item(&'a NameBinding<'a>), | |
476ff2be | 907 | Def(Def), |
54a0048b SL |
908 | } |
909 | ||
910 | impl<'a> LexicalScopeBinding<'a> { | |
5bcae85e | 911 | fn item(self) -> Option<&'a NameBinding<'a>> { |
54a0048b | 912 | match self { |
5bcae85e | 913 | LexicalScopeBinding::Item(binding) => Some(binding), |
54a0048b SL |
914 | _ => None, |
915 | } | |
916 | } | |
54a0048b | 917 | |
32a655c1 SL |
918 | fn def(self) -> Def { |
919 | match self { | |
920 | LexicalScopeBinding::Item(binding) => binding.def(), | |
921 | LexicalScopeBinding::Def(def) => def, | |
922 | } | |
923 | } | |
476ff2be SL |
924 | } |
925 | ||
2c00a5a8 | 926 | #[derive(Clone, Debug)] |
476ff2be SL |
927 | enum PathResult<'a> { |
928 | Module(Module<'a>), | |
929 | NonModule(PathResolution), | |
930 | Indeterminate, | |
3b2f2976 | 931 | Failed(Span, String, bool /* is the error from the last segment? */), |
476ff2be SL |
932 | } |
933 | ||
9e0c209e | 934 | enum ModuleKind { |
0531ce1d XL |
935 | /// An anonymous module, eg. just a block. |
936 | /// | |
937 | /// ``` | |
938 | /// fn main() { | |
939 | /// fn f() {} // (1) | |
940 | /// { // This is an anonymous module | |
941 | /// f(); // This resolves to (2) as we are inside the block. | |
942 | /// fn f() {} // (2) | |
943 | /// } | |
944 | /// f(); // Resolves to (1) | |
945 | /// } | |
946 | /// ``` | |
9e0c209e | 947 | Block(NodeId), |
0531ce1d XL |
948 | /// Any module with a name. |
949 | /// | |
950 | /// This could be: | |
951 | /// | |
952 | /// * A normal module ‒ either `mod from_file;` or `mod from_block { }`. | |
953 | /// * A trait or an enum (it implicitly contains associated types, methods and variant | |
954 | /// constructors). | |
9e0c209e | 955 | Def(Def, Name), |
1a4d82fc JJ |
956 | } |
957 | ||
958 | /// One node in the tree of modules. | |
32a655c1 | 959 | pub struct ModuleData<'a> { |
9e0c209e SL |
960 | parent: Option<Module<'a>>, |
961 | kind: ModuleKind, | |
962 | ||
32a655c1 SL |
963 | // The def id of the closest normal module (`mod`) ancestor (including this module). |
964 | normal_ancestor_id: DefId, | |
1a4d82fc | 965 | |
32a655c1 | 966 | resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>, |
94b46f34 | 967 | legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, MacroKind, Option<Def>)>>, |
32a655c1 | 968 | macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>, |
1a4d82fc | 969 | |
476ff2be SL |
970 | // Macro invocations that can expand into items in this module. |
971 | unresolved_invocations: RefCell<FxHashSet<Mark>>, | |
1a4d82fc | 972 | |
9e0c209e | 973 | no_implicit_prelude: bool, |
1a4d82fc | 974 | |
9e0c209e | 975 | glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>, |
54a0048b | 976 | globs: RefCell<Vec<&'a ImportDirective<'a>>>, |
e9174d1e | 977 | |
54a0048b | 978 | // Used to memoize the traits in this module for faster searches through all traits in scope. |
32a655c1 | 979 | traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>, |
e9174d1e | 980 | |
1a4d82fc JJ |
981 | // Whether this module is populated. If not populated, any attempt to |
982 | // access the children must be preceded with a | |
983 | // `populate_module_if_necessary` call. | |
984 | populated: Cell<bool>, | |
7cac9316 XL |
985 | |
986 | /// Span of the module itself. Used for error reporting. | |
987 | span: Span, | |
988 | ||
989 | expansion: Mark, | |
1a4d82fc JJ |
990 | } |
991 | ||
3b2f2976 | 992 | type Module<'a> = &'a ModuleData<'a>; |
9cc50fc6 | 993 | |
32a655c1 | 994 | impl<'a> ModuleData<'a> { |
7cac9316 XL |
995 | fn new(parent: Option<Module<'a>>, |
996 | kind: ModuleKind, | |
997 | normal_ancestor_id: DefId, | |
998 | expansion: Mark, | |
999 | span: Span) -> Self { | |
32a655c1 | 1000 | ModuleData { |
3b2f2976 XL |
1001 | parent, |
1002 | kind, | |
1003 | normal_ancestor_id, | |
476ff2be SL |
1004 | resolutions: RefCell::new(FxHashMap()), |
1005 | legacy_macro_resolutions: RefCell::new(Vec::new()), | |
1006 | macro_resolutions: RefCell::new(Vec::new()), | |
1007 | unresolved_invocations: RefCell::new(FxHashSet()), | |
9e0c209e | 1008 | no_implicit_prelude: false, |
54a0048b | 1009 | glob_importers: RefCell::new(Vec::new()), |
2c00a5a8 | 1010 | globs: RefCell::new(Vec::new()), |
54a0048b | 1011 | traits: RefCell::new(None), |
32a655c1 | 1012 | populated: Cell::new(normal_ancestor_id.is_local()), |
3b2f2976 XL |
1013 | span, |
1014 | expansion, | |
7453a54e SL |
1015 | } |
1016 | } | |
1017 | ||
32a655c1 SL |
1018 | fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) { |
1019 | for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() { | |
1020 | name_resolution.borrow().binding.map(|binding| f(ident, ns, binding)); | |
7453a54e SL |
1021 | } |
1022 | } | |
1023 | ||
3b2f2976 XL |
1024 | fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) { |
1025 | let resolutions = self.resolutions.borrow(); | |
83c7162d | 1026 | let mut resolutions = resolutions.iter().collect::<Vec<_>>(); |
94b46f34 | 1027 | resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns)); |
83c7162d | 1028 | for &(&(ident, ns), &resolution) in resolutions.iter() { |
3b2f2976 XL |
1029 | resolution.borrow().binding.map(|binding| f(ident, ns, binding)); |
1030 | } | |
1031 | } | |
1032 | ||
9e0c209e SL |
1033 | fn def(&self) -> Option<Def> { |
1034 | match self.kind { | |
1035 | ModuleKind::Def(def, _) => Some(def), | |
1036 | _ => None, | |
1037 | } | |
1038 | } | |
1039 | ||
92a42be0 | 1040 | fn def_id(&self) -> Option<DefId> { |
9e0c209e | 1041 | self.def().as_ref().map(Def::def_id) |
92a42be0 SL |
1042 | } |
1043 | ||
a7813a04 | 1044 | // `self` resolves to the first module ancestor that `is_normal`. |
7453a54e | 1045 | fn is_normal(&self) -> bool { |
9e0c209e SL |
1046 | match self.kind { |
1047 | ModuleKind::Def(Def::Mod(_), _) => true, | |
92a42be0 | 1048 | _ => false, |
1a4d82fc JJ |
1049 | } |
1050 | } | |
1051 | ||
7453a54e | 1052 | fn is_trait(&self) -> bool { |
9e0c209e SL |
1053 | match self.kind { |
1054 | ModuleKind::Def(Def::Trait(_), _) => true, | |
7453a54e | 1055 | _ => false, |
e9174d1e SL |
1056 | } |
1057 | } | |
c30ab7b3 SL |
1058 | |
1059 | fn is_local(&self) -> bool { | |
32a655c1 | 1060 | self.normal_ancestor_id.is_local() |
c30ab7b3 | 1061 | } |
8bb4bdeb XL |
1062 | |
1063 | fn nearest_item_scope(&'a self) -> Module<'a> { | |
1064 | if self.is_trait() { self.parent.unwrap() } else { self } | |
1065 | } | |
1a4d82fc JJ |
1066 | } |
1067 | ||
32a655c1 | 1068 | impl<'a> fmt::Debug for ModuleData<'a> { |
1a4d82fc | 1069 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
9e0c209e | 1070 | write!(f, "{:?}", self.def()) |
1a4d82fc JJ |
1071 | } |
1072 | } | |
1073 | ||
83c7162d | 1074 | /// Records a possibly-private value, type, or module definition. |
54a0048b | 1075 | #[derive(Clone, Debug)] |
7453a54e | 1076 | pub struct NameBinding<'a> { |
7453a54e | 1077 | kind: NameBindingKind<'a>, |
476ff2be | 1078 | expansion: Mark, |
a7813a04 XL |
1079 | span: Span, |
1080 | vis: ty::Visibility, | |
1a4d82fc JJ |
1081 | } |
1082 | ||
5bcae85e | 1083 | pub trait ToNameBinding<'a> { |
32a655c1 | 1084 | fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>; |
5bcae85e SL |
1085 | } |
1086 | ||
32a655c1 SL |
1087 | impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { |
1088 | fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { | |
5bcae85e SL |
1089 | self |
1090 | } | |
1091 | } | |
1092 | ||
54a0048b | 1093 | #[derive(Clone, Debug)] |
7453a54e | 1094 | enum NameBindingKind<'a> { |
92a42be0 | 1095 | Def(Def), |
9cc50fc6 | 1096 | Module(Module<'a>), |
7453a54e SL |
1097 | Import { |
1098 | binding: &'a NameBinding<'a>, | |
a7813a04 | 1099 | directive: &'a ImportDirective<'a>, |
9e0c209e | 1100 | used: Cell<bool>, |
7453a54e | 1101 | }, |
9e0c209e SL |
1102 | Ambiguity { |
1103 | b1: &'a NameBinding<'a>, | |
1104 | b2: &'a NameBinding<'a>, | |
1105 | } | |
1a4d82fc JJ |
1106 | } |
1107 | ||
54a0048b SL |
1108 | struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>); |
1109 | ||
3b2f2976 XL |
1110 | struct UseError<'a> { |
1111 | err: DiagnosticBuilder<'a>, | |
1112 | /// Attach `use` statements for these candidates | |
1113 | candidates: Vec<ImportSuggestion>, | |
1114 | /// The node id of the module to place the use statements in | |
1115 | node_id: NodeId, | |
1116 | /// Whether the diagnostic should state that it's "better" | |
1117 | better: bool, | |
1118 | } | |
1119 | ||
9e0c209e SL |
1120 | struct AmbiguityError<'a> { |
1121 | span: Span, | |
1122 | name: Name, | |
476ff2be | 1123 | lexical: bool, |
9e0c209e SL |
1124 | b1: &'a NameBinding<'a>, |
1125 | b2: &'a NameBinding<'a>, | |
1126 | } | |
1127 | ||
7453a54e | 1128 | impl<'a> NameBinding<'a> { |
476ff2be | 1129 | fn module(&self) -> Option<Module<'a>> { |
7453a54e | 1130 | match self.kind { |
476ff2be | 1131 | NameBindingKind::Module(module) => Some(module), |
7453a54e | 1132 | NameBindingKind::Import { binding, .. } => binding.module(), |
476ff2be | 1133 | _ => None, |
1a4d82fc JJ |
1134 | } |
1135 | } | |
1136 | ||
9e0c209e | 1137 | fn def(&self) -> Def { |
7453a54e | 1138 | match self.kind { |
9e0c209e SL |
1139 | NameBindingKind::Def(def) => def, |
1140 | NameBindingKind::Module(module) => module.def().unwrap(), | |
7453a54e | 1141 | NameBindingKind::Import { binding, .. } => binding.def(), |
9e0c209e | 1142 | NameBindingKind::Ambiguity { .. } => Def::Err, |
1a4d82fc JJ |
1143 | } |
1144 | } | |
1a4d82fc | 1145 | |
8bb4bdeb | 1146 | fn def_ignoring_ambiguity(&self) -> Def { |
476ff2be | 1147 | match self.kind { |
8bb4bdeb XL |
1148 | NameBindingKind::Import { binding, .. } => binding.def_ignoring_ambiguity(), |
1149 | NameBindingKind::Ambiguity { b1, .. } => b1.def_ignoring_ambiguity(), | |
1150 | _ => self.def(), | |
476ff2be SL |
1151 | } |
1152 | } | |
1153 | ||
0531ce1d | 1154 | fn get_macro(&self, resolver: &mut Resolver<'a>) -> Lrc<SyntaxExtension> { |
8bb4bdeb XL |
1155 | resolver.get_macro(self.def_ignoring_ambiguity()) |
1156 | } | |
1157 | ||
a7813a04 XL |
1158 | // We sometimes need to treat variants as `pub` for backwards compatibility |
1159 | fn pseudo_vis(&self) -> ty::Visibility { | |
ff7c6d11 XL |
1160 | if self.is_variant() && self.def().def_id().is_local() { |
1161 | ty::Visibility::Public | |
1162 | } else { | |
1163 | self.vis | |
1164 | } | |
1a4d82fc | 1165 | } |
c34b1796 | 1166 | |
a7813a04 XL |
1167 | fn is_variant(&self) -> bool { |
1168 | match self.kind { | |
c30ab7b3 SL |
1169 | NameBindingKind::Def(Def::Variant(..)) | |
1170 | NameBindingKind::Def(Def::VariantCtor(..)) => true, | |
a7813a04 XL |
1171 | _ => false, |
1172 | } | |
92a42be0 SL |
1173 | } |
1174 | ||
7453a54e | 1175 | fn is_extern_crate(&self) -> bool { |
476ff2be SL |
1176 | match self.kind { |
1177 | NameBindingKind::Import { | |
1178 | directive: &ImportDirective { | |
abe05a73 | 1179 | subclass: ImportDirectiveSubclass::ExternCrate(_), .. |
476ff2be SL |
1180 | }, .. |
1181 | } => true, | |
1182 | _ => false, | |
1183 | } | |
92a42be0 | 1184 | } |
92a42be0 | 1185 | |
7453a54e SL |
1186 | fn is_import(&self) -> bool { |
1187 | match self.kind { | |
1188 | NameBindingKind::Import { .. } => true, | |
1189 | _ => false, | |
c34b1796 AL |
1190 | } |
1191 | } | |
a7813a04 | 1192 | |
abe05a73 XL |
1193 | fn is_renamed_extern_crate(&self) -> bool { |
1194 | if let NameBindingKind::Import { directive, ..} = self.kind { | |
1195 | if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass { | |
1196 | return true; | |
1197 | } | |
1198 | } | |
1199 | false | |
1200 | } | |
1201 | ||
a7813a04 XL |
1202 | fn is_glob_import(&self) -> bool { |
1203 | match self.kind { | |
1204 | NameBindingKind::Import { directive, .. } => directive.is_glob(), | |
476ff2be | 1205 | NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(), |
a7813a04 XL |
1206 | _ => false, |
1207 | } | |
1208 | } | |
1209 | ||
1210 | fn is_importable(&self) -> bool { | |
9e0c209e | 1211 | match self.def() { |
a7813a04 XL |
1212 | Def::AssociatedConst(..) | Def::Method(..) | Def::AssociatedTy(..) => false, |
1213 | _ => true, | |
1214 | } | |
1215 | } | |
7cac9316 XL |
1216 | |
1217 | fn is_macro_def(&self) -> bool { | |
1218 | match self.kind { | |
1219 | NameBindingKind::Def(Def::Macro(..)) => true, | |
1220 | _ => false, | |
1221 | } | |
1222 | } | |
1223 | ||
1224 | fn descr(&self) -> &'static str { | |
1225 | if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() } | |
1226 | } | |
1a4d82fc JJ |
1227 | } |
1228 | ||
1229 | /// Interns the names of the primitive types. | |
0531ce1d XL |
1230 | /// |
1231 | /// All other types are defined somewhere and possibly imported, but the primitive ones need | |
1232 | /// special handling, since they have no place of origin. | |
1a4d82fc | 1233 | struct PrimitiveTypeTable { |
476ff2be | 1234 | primitive_types: FxHashMap<Name, PrimTy>, |
1a4d82fc JJ |
1235 | } |
1236 | ||
1237 | impl PrimitiveTypeTable { | |
1238 | fn new() -> PrimitiveTypeTable { | |
476ff2be | 1239 | let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() }; |
92a42be0 SL |
1240 | |
1241 | table.intern("bool", TyBool); | |
1242 | table.intern("char", TyChar); | |
7453a54e SL |
1243 | table.intern("f32", TyFloat(FloatTy::F32)); |
1244 | table.intern("f64", TyFloat(FloatTy::F64)); | |
2c00a5a8 | 1245 | table.intern("isize", TyInt(IntTy::Isize)); |
7453a54e SL |
1246 | table.intern("i8", TyInt(IntTy::I8)); |
1247 | table.intern("i16", TyInt(IntTy::I16)); | |
1248 | table.intern("i32", TyInt(IntTy::I32)); | |
1249 | table.intern("i64", TyInt(IntTy::I64)); | |
32a655c1 | 1250 | table.intern("i128", TyInt(IntTy::I128)); |
92a42be0 | 1251 | table.intern("str", TyStr); |
2c00a5a8 | 1252 | table.intern("usize", TyUint(UintTy::Usize)); |
7453a54e SL |
1253 | table.intern("u8", TyUint(UintTy::U8)); |
1254 | table.intern("u16", TyUint(UintTy::U16)); | |
1255 | table.intern("u32", TyUint(UintTy::U32)); | |
1256 | table.intern("u64", TyUint(UintTy::U64)); | |
32a655c1 | 1257 | table.intern("u128", TyUint(UintTy::U128)); |
1a4d82fc JJ |
1258 | table |
1259 | } | |
1260 | ||
1261 | fn intern(&mut self, string: &str, primitive_type: PrimTy) { | |
476ff2be | 1262 | self.primitive_types.insert(Symbol::intern(string), primitive_type); |
1a4d82fc JJ |
1263 | } |
1264 | } | |
1265 | ||
1266 | /// The main resolver class. | |
0531ce1d XL |
1267 | /// |
1268 | /// This is the visitor that walks the whole crate. | |
a7813a04 | 1269 | pub struct Resolver<'a> { |
1a4d82fc | 1270 | session: &'a Session, |
ea8adc8c | 1271 | cstore: &'a CrateStore, |
1a4d82fc | 1272 | |
3157f602 | 1273 | pub definitions: Definitions, |
1a4d82fc | 1274 | |
9cc50fc6 | 1275 | graph_root: Module<'a>, |
1a4d82fc | 1276 | |
3157f602 | 1277 | prelude: Option<Module<'a>>, |
83c7162d | 1278 | extern_prelude: FxHashSet<Name>, |
3157f602 | 1279 | |
83c7162d | 1280 | /// n.b. This is used only for better diagnostics, not name resolution itself. |
7cac9316 | 1281 | has_self: FxHashSet<DefId>, |
1a4d82fc | 1282 | |
83c7162d XL |
1283 | /// Names of fields of an item `DefId` accessible with dot syntax. |
1284 | /// Used for hints during error reporting. | |
476ff2be | 1285 | field_names: FxHashMap<DefId, Vec<Name>>, |
1a4d82fc | 1286 | |
83c7162d | 1287 | /// All imports known to succeed or fail. |
9e0c209e SL |
1288 | determined_imports: Vec<&'a ImportDirective<'a>>, |
1289 | ||
83c7162d | 1290 | /// All non-determined imports. |
9e0c209e | 1291 | indeterminate_imports: Vec<&'a ImportDirective<'a>>, |
1a4d82fc | 1292 | |
83c7162d | 1293 | /// The module that represents the current item scope. |
9cc50fc6 | 1294 | current_module: Module<'a>, |
1a4d82fc | 1295 | |
83c7162d XL |
1296 | /// The current set of local scopes for types and values. |
1297 | /// FIXME #4948: Reuse ribs to avoid allocation. | |
476ff2be | 1298 | ribs: PerNS<Vec<Rib<'a>>>, |
1a4d82fc | 1299 | |
83c7162d | 1300 | /// The current set of local scopes, for labels. |
7453a54e | 1301 | label_ribs: Vec<Rib<'a>>, |
1a4d82fc | 1302 | |
83c7162d | 1303 | /// The trait that the current context can refer to. |
7cac9316 | 1304 | current_trait_ref: Option<(Module<'a>, TraitRef)>, |
1a4d82fc | 1305 | |
83c7162d | 1306 | /// The current self type if inside an impl (used for better errors). |
1a4d82fc JJ |
1307 | current_self_type: Option<Ty>, |
1308 | ||
83c7162d | 1309 | /// The idents for the primitive types. |
1a4d82fc JJ |
1310 | primitive_type_table: PrimitiveTypeTable, |
1311 | ||
476ff2be | 1312 | def_map: DefMap, |
94b46f34 | 1313 | import_map: ImportMap, |
a7813a04 | 1314 | pub freevars: FreevarMap, |
92a42be0 | 1315 | freevars_seen: NodeMap<NodeMap<usize>>, |
a7813a04 XL |
1316 | pub export_map: ExportMap, |
1317 | pub trait_map: TraitMap, | |
1318 | ||
83c7162d XL |
1319 | /// A map from nodes to anonymous modules. |
1320 | /// Anonymous modules are pseudo-modules that are implicitly created around items | |
1321 | /// contained within blocks. | |
1322 | /// | |
1323 | /// For example, if we have this: | |
1324 | /// | |
1325 | /// fn f() { | |
1326 | /// fn g() { | |
1327 | /// ... | |
1328 | /// } | |
1329 | /// } | |
1330 | /// | |
1331 | /// There will be an anonymous module created around `g` with the ID of the | |
1332 | /// entry block for `f`. | |
32a655c1 SL |
1333 | block_map: NodeMap<Module<'a>>, |
1334 | module_map: FxHashMap<DefId, Module<'a>>, | |
7cac9316 | 1335 | extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, |
1a4d82fc | 1336 | |
a7813a04 | 1337 | pub make_glob_map: bool, |
3b2f2976 XL |
1338 | /// Maps imports to the names of items actually imported (this actually maps |
1339 | /// all imports, but only glob imports are actually interesting). | |
a7813a04 | 1340 | pub glob_map: GlobMap, |
1a4d82fc | 1341 | |
476ff2be | 1342 | used_imports: FxHashSet<(NodeId, Namespace)>, |
a7813a04 | 1343 | pub maybe_unused_trait_imports: NodeSet, |
3b2f2976 | 1344 | pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, |
e9174d1e | 1345 | |
94b46f34 XL |
1346 | /// A list of labels as of yet unused. Labels will be removed from this map when |
1347 | /// they are used (in a `break` or `continue` statement) | |
1348 | pub unused_labels: FxHashMap<NodeId, Span>, | |
1349 | ||
3b2f2976 | 1350 | /// privacy errors are delayed until the end in order to deduplicate them |
54a0048b | 1351 | privacy_errors: Vec<PrivacyError<'a>>, |
3b2f2976 | 1352 | /// ambiguity errors are delayed for deduplication |
9e0c209e | 1353 | ambiguity_errors: Vec<AmbiguityError<'a>>, |
3b2f2976 XL |
1354 | /// `use` injections are delayed for better placement and deduplication |
1355 | use_injections: Vec<UseError<'a>>, | |
ff7c6d11 XL |
1356 | /// `use` injections for proc macros wrongly imported with #[macro_use] |
1357 | proc_mac_errors: Vec<macros::ProcMacError>, | |
3b2f2976 | 1358 | |
cc61c64b | 1359 | gated_errors: FxHashSet<Span>, |
c30ab7b3 | 1360 | disallowed_shadowing: Vec<&'a LegacyBinding<'a>>, |
9cc50fc6 SL |
1361 | |
1362 | arenas: &'a ResolverArenas<'a>, | |
9e0c209e | 1363 | dummy_binding: &'a NameBinding<'a>, |
83c7162d XL |
1364 | /// true if `#![feature(use_extern_macros)]` |
1365 | use_extern_macros: bool, | |
9e0c209e | 1366 | |
9e0c209e | 1367 | crate_loader: &'a mut CrateLoader, |
7cac9316 | 1368 | macro_names: FxHashSet<Ident>, |
cc61c64b | 1369 | global_macros: FxHashMap<Name, &'a NameBinding<'a>>, |
2c00a5a8 | 1370 | pub all_macros: FxHashMap<Name, Def>, |
7cac9316 | 1371 | lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>, |
0531ce1d | 1372 | macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>, |
8bb4bdeb XL |
1373 | macro_defs: FxHashMap<Mark, DefId>, |
1374 | local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>, | |
476ff2be | 1375 | macro_exports: Vec<Export>, |
32a655c1 | 1376 | pub whitelisted_legacy_custom_derives: Vec<Name>, |
8bb4bdeb | 1377 | pub found_unresolved_macro: bool, |
9e0c209e | 1378 | |
83c7162d XL |
1379 | /// List of crate local macros that we need to warn about as being unused. |
1380 | /// Right now this only includes macro_rules! macros, and macros 2.0. | |
7cac9316 XL |
1381 | unused_macros: FxHashSet<DefId>, |
1382 | ||
83c7162d | 1383 | /// Maps the `Mark` of an expansion to its containing module or block. |
476ff2be SL |
1384 | invocations: FxHashMap<Mark, &'a InvocationData<'a>>, |
1385 | ||
83c7162d | 1386 | /// Avoid duplicated errors for "name already defined". |
476ff2be | 1387 | name_already_seen: FxHashMap<Name, Span>, |
32a655c1 | 1388 | |
83c7162d | 1389 | /// If `#![feature(proc_macro)]` is set |
32a655c1 SL |
1390 | proc_macro_enabled: bool, |
1391 | ||
83c7162d | 1392 | /// A set of procedural macros imported by `#[macro_use]` that have already been warned about |
32a655c1 SL |
1393 | warned_proc_macros: FxHashSet<Name>, |
1394 | ||
1395 | potentially_unused_imports: Vec<&'a ImportDirective<'a>>, | |
8bb4bdeb | 1396 | |
83c7162d XL |
1397 | /// This table maps struct IDs into struct constructor IDs, |
1398 | /// it's not used during normal resolution, only for better error reporting. | |
8bb4bdeb | 1399 | struct_constructors: DefIdMap<(Def, ty::Visibility)>, |
3b2f2976 | 1400 | |
83c7162d | 1401 | /// Only used for better errors on `fn(): fn()` |
3b2f2976 | 1402 | current_type_ascription: Vec<Span>, |
ff7c6d11 XL |
1403 | |
1404 | injected_crate: Option<Module<'a>>, | |
94b46f34 XL |
1405 | |
1406 | /// Only supposed to be used by rustdoc, otherwise should be false. | |
1407 | pub ignore_extern_prelude_feature: bool, | |
9cc50fc6 SL |
1408 | } |
1409 | ||
0531ce1d | 1410 | /// Nothing really interesting here, it just provides memory for the rest of the crate. |
3157f602 | 1411 | pub struct ResolverArenas<'a> { |
32a655c1 | 1412 | modules: arena::TypedArena<ModuleData<'a>>, |
a7813a04 | 1413 | local_modules: RefCell<Vec<Module<'a>>>, |
7453a54e | 1414 | name_bindings: arena::TypedArena<NameBinding<'a>>, |
54a0048b SL |
1415 | import_directives: arena::TypedArena<ImportDirective<'a>>, |
1416 | name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>, | |
c30ab7b3 SL |
1417 | invocation_data: arena::TypedArena<InvocationData<'a>>, |
1418 | legacy_bindings: arena::TypedArena<LegacyBinding<'a>>, | |
54a0048b SL |
1419 | } |
1420 | ||
1421 | impl<'a> ResolverArenas<'a> { | |
32a655c1 | 1422 | fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> { |
a7813a04 XL |
1423 | let module = self.modules.alloc(module); |
1424 | if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) { | |
1425 | self.local_modules.borrow_mut().push(module); | |
1426 | } | |
1427 | module | |
1428 | } | |
1429 | fn local_modules(&'a self) -> ::std::cell::Ref<'a, Vec<Module<'a>>> { | |
1430 | self.local_modules.borrow() | |
54a0048b SL |
1431 | } |
1432 | fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { | |
1433 | self.name_bindings.alloc(name_binding) | |
1434 | } | |
1435 | fn alloc_import_directive(&'a self, import_directive: ImportDirective<'a>) | |
1436 | -> &'a ImportDirective { | |
1437 | self.import_directives.alloc(import_directive) | |
1438 | } | |
1439 | fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> { | |
1440 | self.name_resolutions.alloc(Default::default()) | |
1441 | } | |
c30ab7b3 SL |
1442 | fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>) |
1443 | -> &'a InvocationData<'a> { | |
1444 | self.invocation_data.alloc(expansion_data) | |
1445 | } | |
1446 | fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { | |
1447 | self.legacy_bindings.alloc(binding) | |
1448 | } | |
1a4d82fc JJ |
1449 | } |
1450 | ||
32a655c1 SL |
1451 | impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { |
1452 | fn parent(self, id: DefId) -> Option<DefId> { | |
1453 | match id.krate { | |
1454 | LOCAL_CRATE => self.definitions.def_key(id.index).parent, | |
ea8adc8c | 1455 | _ => self.cstore.def_key(id).parent, |
0531ce1d | 1456 | }.map(|index| DefId { index, ..id }) |
a7813a04 | 1457 | } |
1a4d82fc JJ |
1458 | } |
1459 | ||
0531ce1d XL |
1460 | /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that |
1461 | /// the resolver is no longer needed as all the relevant information is inline. | |
a7813a04 | 1462 | impl<'a> hir::lowering::Resolver for Resolver<'a> { |
476ff2be | 1463 | fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { |
2c00a5a8 XL |
1464 | self.resolve_hir_path_cb(path, is_value, |
1465 | |resolver, span, error| resolve_error(resolver, span, error)) | |
1466 | } | |
1467 | ||
1468 | fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>, | |
1469 | components: &[&str], is_value: bool) -> hir::Path { | |
1470 | let mut path = hir::Path { | |
1471 | span, | |
1472 | def: Def::Err, | |
1473 | segments: iter::once(keywords::CrateRoot.name()).chain({ | |
1474 | crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern) | |
1475 | }).map(hir::PathSegment::from_name).collect(), | |
1476 | }; | |
1477 | ||
1478 | self.resolve_hir_path(&mut path, is_value); | |
1479 | path | |
1480 | } | |
1481 | ||
1482 | fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> { | |
1483 | self.def_map.get(&id).cloned() | |
1484 | } | |
1485 | ||
94b46f34 XL |
1486 | fn get_import(&mut self, id: NodeId) -> PerNS<Option<PathResolution>> { |
1487 | self.import_map.get(&id).cloned().unwrap_or_default() | |
1488 | } | |
1489 | ||
2c00a5a8 XL |
1490 | fn definitions(&mut self) -> &mut Definitions { |
1491 | &mut self.definitions | |
1492 | } | |
1493 | } | |
1494 | ||
1495 | impl<'a> Resolver<'a> { | |
1496 | /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a> | |
1497 | /// isn't something that can be returned because it can't be made to live that long, | |
1498 | /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, | |
0531ce1d | 1499 | /// just that an error occurred. |
2c00a5a8 XL |
1500 | pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool) |
1501 | -> Result<hir::Path, ()> { | |
1502 | use std::iter; | |
1503 | let mut errored = false; | |
1504 | ||
1505 | let mut path = if path_str.starts_with("::") { | |
1506 | hir::Path { | |
1507 | span, | |
1508 | def: Def::Err, | |
1509 | segments: iter::once(keywords::CrateRoot.name()).chain({ | |
1510 | path_str.split("::").skip(1).map(Symbol::intern) | |
1511 | }).map(hir::PathSegment::from_name).collect(), | |
1512 | } | |
1513 | } else { | |
1514 | hir::Path { | |
1515 | span, | |
1516 | def: Def::Err, | |
1517 | segments: path_str.split("::").map(Symbol::intern) | |
1518 | .map(hir::PathSegment::from_name).collect(), | |
1519 | } | |
1520 | }; | |
1521 | self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true); | |
1522 | if errored || path.def == Def::Err { | |
1523 | Err(()) | |
1524 | } else { | |
1525 | Ok(path) | |
1526 | } | |
1527 | } | |
1528 | ||
1529 | /// resolve_hir_path, but takes a callback in case there was an error | |
1530 | fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F) | |
1531 | where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>) | |
1532 | { | |
a7813a04 | 1533 | let namespace = if is_value { ValueNS } else { TypeNS }; |
32a655c1 | 1534 | let hir::Path { ref segments, span, ref mut def } = *path; |
83c7162d XL |
1535 | let path: Vec<Ident> = segments.iter() |
1536 | .map(|seg| Ident::new(seg.name, span)) | |
3b2f2976 | 1537 | .collect(); |
83c7162d | 1538 | // FIXME (Manishearth): Intra doc links won't get warned of epoch changes |
94b46f34 | 1539 | match self.resolve_path(&path, Some(namespace), true, span, CrateLint::No) { |
476ff2be | 1540 | PathResult::Module(module) => *def = module.def().unwrap(), |
8bb4bdeb XL |
1541 | PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => |
1542 | *def = path_res.base_def(), | |
94b46f34 XL |
1543 | PathResult::NonModule(..) => match self.resolve_path( |
1544 | &path, | |
1545 | None, | |
1546 | true, | |
1547 | span, | |
1548 | CrateLint::No, | |
1549 | ) { | |
3b2f2976 | 1550 | PathResult::Failed(span, msg, _) => { |
2c00a5a8 | 1551 | error_callback(self, span, ResolutionError::FailedToResolve(&msg)); |
476ff2be SL |
1552 | } |
1553 | _ => {} | |
1554 | }, | |
1555 | PathResult::Indeterminate => unreachable!(), | |
3b2f2976 | 1556 | PathResult::Failed(span, msg, _) => { |
2c00a5a8 | 1557 | error_callback(self, span, ResolutionError::FailedToResolve(&msg)); |
a7813a04 XL |
1558 | } |
1559 | } | |
1560 | } | |
a7813a04 XL |
1561 | } |
1562 | ||
a7813a04 | 1563 | impl<'a> Resolver<'a> { |
9e0c209e | 1564 | pub fn new(session: &'a Session, |
ea8adc8c | 1565 | cstore: &'a CrateStore, |
9e0c209e | 1566 | krate: &Crate, |
cc61c64b | 1567 | crate_name: &str, |
9e0c209e SL |
1568 | make_glob_map: MakeGlobMap, |
1569 | crate_loader: &'a mut CrateLoader, | |
1570 | arenas: &'a ResolverArenas<'a>) | |
3157f602 | 1571 | -> Resolver<'a> { |
32a655c1 SL |
1572 | let root_def_id = DefId::local(CRATE_DEF_INDEX); |
1573 | let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name()); | |
1574 | let graph_root = arenas.alloc_module(ModuleData { | |
9e0c209e | 1575 | no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"), |
7cac9316 | 1576 | ..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span) |
9e0c209e | 1577 | }); |
32a655c1 SL |
1578 | let mut module_map = FxHashMap(); |
1579 | module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root); | |
1a4d82fc | 1580 | |
c30ab7b3 | 1581 | let mut definitions = Definitions::new(); |
7cac9316 | 1582 | DefCollector::new(&mut definitions, Mark::root()) |
abe05a73 | 1583 | .collect_root(crate_name, session.local_crate_disambiguator()); |
c30ab7b3 | 1584 | |
94b46f34 XL |
1585 | let mut extern_prelude: FxHashSet<Name> = |
1586 | session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(); | |
1587 | if !attr::contains_name(&krate.attrs, "no_core") { | |
1588 | if !attr::contains_name(&krate.attrs, "no_std") { | |
1589 | extern_prelude.insert(Symbol::intern("std")); | |
1590 | } else { | |
1591 | extern_prelude.insert(Symbol::intern("core")); | |
1592 | } | |
1593 | } | |
1594 | ||
476ff2be | 1595 | let mut invocations = FxHashMap(); |
c30ab7b3 SL |
1596 | invocations.insert(Mark::root(), |
1597 | arenas.alloc_invocation_data(InvocationData::root(graph_root))); | |
9e0c209e | 1598 | |
0531ce1d | 1599 | let features = session.features_untracked(); |
32a655c1 | 1600 | |
8bb4bdeb XL |
1601 | let mut macro_defs = FxHashMap(); |
1602 | macro_defs.insert(Mark::root(), root_def_id); | |
1603 | ||
1a4d82fc | 1604 | Resolver { |
3b2f2976 | 1605 | session, |
1a4d82fc | 1606 | |
ea8adc8c XL |
1607 | cstore, |
1608 | ||
3b2f2976 | 1609 | definitions, |
1a4d82fc JJ |
1610 | |
1611 | // The outermost module has def ID 0; this is not reflected in the | |
1612 | // AST. | |
3b2f2976 | 1613 | graph_root, |
3157f602 | 1614 | prelude: None, |
94b46f34 | 1615 | extern_prelude, |
1a4d82fc | 1616 | |
7cac9316 | 1617 | has_self: FxHashSet(), |
476ff2be | 1618 | field_names: FxHashMap(), |
1a4d82fc | 1619 | |
9e0c209e SL |
1620 | determined_imports: Vec::new(), |
1621 | indeterminate_imports: Vec::new(), | |
1a4d82fc | 1622 | |
92a42be0 | 1623 | current_module: graph_root, |
476ff2be SL |
1624 | ribs: PerNS { |
1625 | value_ns: vec![Rib::new(ModuleRibKind(graph_root))], | |
1626 | type_ns: vec![Rib::new(ModuleRibKind(graph_root))], | |
83c7162d | 1627 | macro_ns: vec![Rib::new(ModuleRibKind(graph_root))], |
476ff2be | 1628 | }, |
1a4d82fc JJ |
1629 | label_ribs: Vec::new(), |
1630 | ||
1631 | current_trait_ref: None, | |
1632 | current_self_type: None, | |
1633 | ||
1a4d82fc JJ |
1634 | primitive_type_table: PrimitiveTypeTable::new(), |
1635 | ||
a7813a04 | 1636 | def_map: NodeMap(), |
94b46f34 | 1637 | import_map: NodeMap(), |
92a42be0 SL |
1638 | freevars: NodeMap(), |
1639 | freevars_seen: NodeMap(), | |
ea8adc8c | 1640 | export_map: FxHashMap(), |
85aaf69f | 1641 | trait_map: NodeMap(), |
3b2f2976 | 1642 | module_map, |
32a655c1 | 1643 | block_map: NodeMap(), |
7cac9316 | 1644 | extern_module_map: FxHashMap(), |
1a4d82fc | 1645 | |
1a4d82fc | 1646 | make_glob_map: make_glob_map == MakeGlobMap::Yes, |
54a0048b | 1647 | glob_map: NodeMap(), |
e9174d1e | 1648 | |
476ff2be | 1649 | used_imports: FxHashSet(), |
a7813a04 | 1650 | maybe_unused_trait_imports: NodeSet(), |
3b2f2976 | 1651 | maybe_unused_extern_crates: Vec::new(), |
a7813a04 | 1652 | |
94b46f34 XL |
1653 | unused_labels: FxHashMap(), |
1654 | ||
54a0048b | 1655 | privacy_errors: Vec::new(), |
9e0c209e | 1656 | ambiguity_errors: Vec::new(), |
3b2f2976 | 1657 | use_injections: Vec::new(), |
ff7c6d11 | 1658 | proc_mac_errors: Vec::new(), |
cc61c64b | 1659 | gated_errors: FxHashSet(), |
c30ab7b3 | 1660 | disallowed_shadowing: Vec::new(), |
9cc50fc6 | 1661 | |
3b2f2976 | 1662 | arenas, |
9e0c209e SL |
1663 | dummy_binding: arenas.alloc_name_binding(NameBinding { |
1664 | kind: NameBindingKind::Def(Def::Err), | |
476ff2be | 1665 | expansion: Mark::root(), |
9e0c209e SL |
1666 | span: DUMMY_SP, |
1667 | vis: ty::Visibility::Public, | |
1668 | }), | |
32a655c1 | 1669 | |
7cac9316 XL |
1670 | // The `proc_macro` and `decl_macro` features imply `use_extern_macros` |
1671 | use_extern_macros: | |
1672 | features.use_extern_macros || features.proc_macro || features.decl_macro, | |
9e0c209e | 1673 | |
3b2f2976 | 1674 | crate_loader, |
476ff2be | 1675 | macro_names: FxHashSet(), |
cc61c64b | 1676 | global_macros: FxHashMap(), |
2c00a5a8 | 1677 | all_macros: FxHashMap(), |
c30ab7b3 | 1678 | lexical_macro_resolutions: Vec::new(), |
476ff2be SL |
1679 | macro_map: FxHashMap(), |
1680 | macro_exports: Vec::new(), | |
3b2f2976 XL |
1681 | invocations, |
1682 | macro_defs, | |
8bb4bdeb | 1683 | local_macro_def_scopes: FxHashMap(), |
476ff2be | 1684 | name_already_seen: FxHashMap(), |
32a655c1 SL |
1685 | whitelisted_legacy_custom_derives: Vec::new(), |
1686 | proc_macro_enabled: features.proc_macro, | |
1687 | warned_proc_macros: FxHashSet(), | |
1688 | potentially_unused_imports: Vec::new(), | |
8bb4bdeb XL |
1689 | struct_constructors: DefIdMap(), |
1690 | found_unresolved_macro: false, | |
7cac9316 | 1691 | unused_macros: FxHashSet(), |
3b2f2976 | 1692 | current_type_ascription: Vec::new(), |
ff7c6d11 | 1693 | injected_crate: None, |
94b46f34 | 1694 | ignore_extern_prelude_feature: false, |
9cc50fc6 SL |
1695 | } |
1696 | } | |
1697 | ||
3157f602 | 1698 | pub fn arenas() -> ResolverArenas<'a> { |
9cc50fc6 SL |
1699 | ResolverArenas { |
1700 | modules: arena::TypedArena::new(), | |
a7813a04 | 1701 | local_modules: RefCell::new(Vec::new()), |
7453a54e | 1702 | name_bindings: arena::TypedArena::new(), |
54a0048b SL |
1703 | import_directives: arena::TypedArena::new(), |
1704 | name_resolutions: arena::TypedArena::new(), | |
c30ab7b3 SL |
1705 | invocation_data: arena::TypedArena::new(), |
1706 | legacy_bindings: arena::TypedArena::new(), | |
1a4d82fc JJ |
1707 | } |
1708 | } | |
1709 | ||
0531ce1d | 1710 | /// Runs the function on each namespace. |
83c7162d XL |
1711 | fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) { |
1712 | f(self, TypeNS); | |
1713 | f(self, ValueNS); | |
1714 | if self.use_extern_macros { | |
1715 | f(self, MacroNS); | |
c30ab7b3 | 1716 | } |
476ff2be | 1717 | } |
c30ab7b3 | 1718 | |
ff7c6d11 XL |
1719 | fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId { |
1720 | loop { | |
1721 | match self.macro_defs.get(&ctxt.outer()) { | |
1722 | Some(&def_id) => return def_id, | |
1723 | None => ctxt.remove_mark(), | |
1724 | }; | |
1725 | } | |
1726 | } | |
1727 | ||
476ff2be SL |
1728 | /// Entry point to crate resolution. |
1729 | pub fn resolve_crate(&mut self, krate: &Crate) { | |
1730 | ImportResolver { resolver: self }.finalize_imports(); | |
3157f602 | 1731 | self.current_module = self.graph_root; |
476ff2be | 1732 | self.finalize_current_module_macro_resolutions(); |
3b2f2976 | 1733 | |
3157f602 XL |
1734 | visit::walk_crate(self, krate); |
1735 | ||
1736 | check_unused::check_crate(self, krate); | |
3b2f2976 | 1737 | self.report_errors(krate); |
9e0c209e | 1738 | self.crate_loader.postprocess(krate); |
3157f602 XL |
1739 | } |
1740 | ||
7cac9316 XL |
1741 | fn new_module( |
1742 | &self, | |
1743 | parent: Module<'a>, | |
1744 | kind: ModuleKind, | |
1745 | normal_ancestor_id: DefId, | |
1746 | expansion: Mark, | |
1747 | span: Span, | |
1748 | ) -> Module<'a> { | |
1749 | let module = ModuleData::new(Some(parent), kind, normal_ancestor_id, expansion, span); | |
1750 | self.arenas.alloc_module(module) | |
7453a54e SL |
1751 | } |
1752 | ||
32a655c1 | 1753 | fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span) |
9e0c209e | 1754 | -> bool /* true if an error was reported */ { |
9e0c209e | 1755 | match binding.kind { |
94b46f34 | 1756 | NameBindingKind::Import { directive, binding, ref used } |
32a655c1 | 1757 | if !used.get() => { |
9e0c209e | 1758 | used.set(true); |
32a655c1 | 1759 | directive.used.set(true); |
9e0c209e | 1760 | self.used_imports.insert((directive.id, ns)); |
32a655c1 SL |
1761 | self.add_to_glob_map(directive.id, ident); |
1762 | self.record_use(ident, ns, binding, span) | |
9e0c209e SL |
1763 | } |
1764 | NameBindingKind::Import { .. } => false, | |
94b46f34 | 1765 | NameBindingKind::Ambiguity { b1, b2 } => { |
476ff2be | 1766 | self.ambiguity_errors.push(AmbiguityError { |
94b46f34 | 1767 | span, name: ident.name, lexical: false, b1, b2, |
476ff2be | 1768 | }); |
94b46f34 | 1769 | true |
9e0c209e SL |
1770 | } |
1771 | _ => false | |
54a0048b | 1772 | } |
5bcae85e | 1773 | } |
7453a54e | 1774 | |
32a655c1 | 1775 | fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) { |
5bcae85e | 1776 | if self.make_glob_map { |
32a655c1 | 1777 | self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name); |
1a4d82fc | 1778 | } |
1a4d82fc JJ |
1779 | } |
1780 | ||
54a0048b SL |
1781 | /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope. |
1782 | /// More specifically, we proceed up the hierarchy of scopes and return the binding for | |
1783 | /// `ident` in the first scope that defines it (or None if no scopes define it). | |
1784 | /// | |
1785 | /// A block's items are above its local variables in the scope hierarchy, regardless of where | |
1786 | /// the items are defined in the block. For example, | |
1787 | /// ```rust | |
1788 | /// fn f() { | |
1789 | /// g(); // Since there are no local variables in scope yet, this resolves to the item. | |
1790 | /// let g = || {}; | |
1791 | /// fn g() {} | |
1792 | /// g(); // This resolves to the local variable `g` since it shadows the item. | |
1793 | /// } | |
1794 | /// ``` | |
1795 | /// | |
1a4d82fc JJ |
1796 | /// Invariant: This must only be called during main resolution, not during |
1797 | /// import resolution. | |
54a0048b | 1798 | fn resolve_ident_in_lexical_scope(&mut self, |
c30ab7b3 | 1799 | mut ident: Ident, |
54a0048b | 1800 | ns: Namespace, |
7cac9316 XL |
1801 | record_used: bool, |
1802 | path_span: Span) | |
54a0048b | 1803 | -> Option<LexicalScopeBinding<'a>> { |
5bcae85e | 1804 | if ns == TypeNS { |
83c7162d XL |
1805 | ident.span = if ident.name == keywords::SelfType.name() { |
1806 | // FIXME(jseyfried) improve `Self` hygiene | |
1807 | ident.span.with_ctxt(SyntaxContext::empty()) | |
7cac9316 | 1808 | } else { |
83c7162d | 1809 | ident.span.modern() |
7cac9316 | 1810 | } |
5bcae85e | 1811 | } |
54a0048b SL |
1812 | |
1813 | // Walk backwards up the ribs in scope. | |
7cac9316 | 1814 | let mut module = self.graph_root; |
476ff2be SL |
1815 | for i in (0 .. self.ribs[ns].len()).rev() { |
1816 | if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { | |
54a0048b | 1817 | // The ident resolves to a type parameter or local variable. |
32a655c1 | 1818 | return Some(LexicalScopeBinding::Def( |
7cac9316 | 1819 | self.adjust_local_def(ns, i, def, record_used, path_span) |
32a655c1 | 1820 | )); |
54a0048b SL |
1821 | } |
1822 | ||
7cac9316 XL |
1823 | module = match self.ribs[ns][i].kind { |
1824 | ModuleRibKind(module) => module, | |
83c7162d | 1825 | MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { |
7cac9316 XL |
1826 | // If an invocation of this macro created `ident`, give up on `ident` |
1827 | // and switch to `ident`'s source from the macro definition. | |
83c7162d | 1828 | ident.span.remove_mark(); |
7cac9316 | 1829 | continue |
7453a54e | 1830 | } |
7cac9316 XL |
1831 | _ => continue, |
1832 | }; | |
1a4d82fc | 1833 | |
7cac9316 XL |
1834 | let item = self.resolve_ident_in_module_unadjusted( |
1835 | module, ident, ns, false, record_used, path_span, | |
1836 | ); | |
1837 | if let Ok(binding) = item { | |
1838 | // The ident resolves to an item. | |
1839 | return Some(LexicalScopeBinding::Item(binding)); | |
1a4d82fc | 1840 | } |
5bcae85e | 1841 | |
7cac9316 XL |
1842 | match module.kind { |
1843 | ModuleKind::Block(..) => {}, // We can see through blocks | |
1844 | _ => break, | |
1845 | } | |
1846 | } | |
1847 | ||
83c7162d | 1848 | ident.span = ident.span.modern(); |
7cac9316 | 1849 | loop { |
83c7162d | 1850 | module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.span), break); |
7cac9316 XL |
1851 | let orig_current_module = self.current_module; |
1852 | self.current_module = module; // Lexical resolutions can never be a privacy error. | |
1853 | let result = self.resolve_ident_in_module_unadjusted( | |
1854 | module, ident, ns, false, record_used, path_span, | |
1855 | ); | |
1856 | self.current_module = orig_current_module; | |
1857 | ||
1858 | match result { | |
1859 | Ok(binding) => return Some(LexicalScopeBinding::Item(binding)), | |
1860 | Err(Undetermined) => return None, | |
1861 | Err(Determined) => {} | |
1862 | } | |
1863 | } | |
1864 | ||
83c7162d XL |
1865 | if !module.no_implicit_prelude { |
1866 | // `record_used` means that we don't try to load crates during speculative resolution | |
1867 | if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) { | |
94b46f34 XL |
1868 | if !self.session.features_untracked().extern_prelude && |
1869 | !self.ignore_extern_prelude_feature { | |
83c7162d XL |
1870 | feature_err(&self.session.parse_sess, "extern_prelude", |
1871 | ident.span, GateIssue::Language, | |
1872 | "access to extern crates through prelude is experimental").emit(); | |
1873 | } | |
1874 | ||
1875 | let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); | |
1876 | let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); | |
1877 | self.populate_module_if_necessary(crate_root); | |
1878 | ||
1879 | let binding = (crate_root, ty::Visibility::Public, | |
1880 | ident.span, Mark::root()).to_name_binding(self.arenas); | |
1881 | return Some(LexicalScopeBinding::Item(binding)); | |
1882 | } | |
1883 | if let Some(prelude) = self.prelude { | |
1884 | if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns, | |
1885 | false, false, path_span) { | |
1886 | return Some(LexicalScopeBinding::Item(binding)); | |
1887 | } | |
5bcae85e | 1888 | } |
7cac9316 | 1889 | } |
83c7162d XL |
1890 | |
1891 | None | |
7cac9316 XL |
1892 | } |
1893 | ||
83c7162d | 1894 | fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span) |
7cac9316 | 1895 | -> Option<Module<'a>> { |
83c7162d XL |
1896 | if !module.expansion.is_descendant_of(span.ctxt().outer()) { |
1897 | return Some(self.macro_def_scope(span.remove_mark())); | |
7cac9316 XL |
1898 | } |
1899 | ||
1900 | if let ModuleKind::Block(..) = module.kind { | |
1901 | return Some(module.parent.unwrap()); | |
1902 | } | |
1903 | ||
3b2f2976 | 1904 | let mut module_expansion = module.expansion.modern(); // for backward compatibility |
7cac9316 XL |
1905 | while let Some(parent) = module.parent { |
1906 | let parent_expansion = parent.expansion.modern(); | |
1907 | if module_expansion.is_descendant_of(parent_expansion) && | |
1908 | parent_expansion != module_expansion { | |
83c7162d | 1909 | return if parent_expansion.is_descendant_of(span.ctxt().outer()) { |
7cac9316 XL |
1910 | Some(parent) |
1911 | } else { | |
1912 | None | |
1913 | }; | |
1914 | } | |
1915 | module = parent; | |
1916 | module_expansion = parent_expansion; | |
1a4d82fc | 1917 | } |
54a0048b SL |
1918 | |
1919 | None | |
1a4d82fc JJ |
1920 | } |
1921 | ||
7cac9316 XL |
1922 | fn resolve_ident_in_module(&mut self, |
1923 | module: Module<'a>, | |
1924 | mut ident: Ident, | |
1925 | ns: Namespace, | |
1926 | ignore_unresolved_invocations: bool, | |
1927 | record_used: bool, | |
1928 | span: Span) | |
1929 | -> Result<&'a NameBinding<'a>, Determinacy> { | |
83c7162d | 1930 | ident.span = ident.span.modern(); |
7cac9316 | 1931 | let orig_current_module = self.current_module; |
83c7162d | 1932 | if let Some(def) = ident.span.adjust(module.expansion) { |
7cac9316 XL |
1933 | self.current_module = self.macro_def_scope(def); |
1934 | } | |
1935 | let result = self.resolve_ident_in_module_unadjusted( | |
1936 | module, ident, ns, ignore_unresolved_invocations, record_used, span, | |
1937 | ); | |
1938 | self.current_module = orig_current_module; | |
1939 | result | |
1940 | } | |
1941 | ||
2c00a5a8 XL |
1942 | fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext, legacy: bool) -> Module<'a> { |
1943 | let mark = if legacy { | |
1944 | // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, | |
1945 | // we don't want to pretend that the `macro_rules!` definition is in the `macro` | |
1946 | // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks. | |
1947 | ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern) | |
1948 | } else { | |
1949 | ctxt = ctxt.modern(); | |
1950 | ctxt.adjust(Mark::root()) | |
1951 | }; | |
1952 | let module = match mark { | |
7cac9316 XL |
1953 | Some(def) => self.macro_def_scope(def), |
1954 | None => return self.graph_root, | |
1955 | }; | |
1956 | self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id }) | |
1957 | } | |
1958 | ||
1959 | fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { | |
1960 | let mut module = self.get_module(module.normal_ancestor_id); | |
ea8adc8c | 1961 | while module.span.ctxt().modern() != *ctxt { |
7cac9316 XL |
1962 | let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark())); |
1963 | module = self.get_module(parent.normal_ancestor_id); | |
c30ab7b3 | 1964 | } |
7cac9316 | 1965 | module |
c30ab7b3 SL |
1966 | } |
1967 | ||
1a4d82fc JJ |
1968 | // AST resolution |
1969 | // | |
1970 | // We maintain a list of value ribs and type ribs. | |
1971 | // | |
1972 | // Simultaneously, we keep track of the current position in the module | |
1973 | // graph in the `current_module` pointer. When we go to resolve a name in | |
1974 | // the value or type namespaces, we first look through all the ribs and | |
1975 | // then query the module graph. When we resolve a name in the module | |
1976 | // namespace, we can skip all the ribs (since nested modules are not | |
1977 | // allowed within blocks in Rust) and jump straight to the current module | |
1978 | // graph node. | |
1979 | // | |
1980 | // Named implementations are handled separately. When we find a method | |
1981 | // call, we consult the module node to find all of the implementations in | |
92a42be0 SL |
1982 | // scope. This information is lazily cached in the module node. We then |
1983 | // generate a fake "implementation scope" containing all the | |
1984 | // implementations thus found, for compatibility with old resolve pass. | |
1985 | ||
2c00a5a8 XL |
1986 | pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T |
1987 | where F: FnOnce(&mut Resolver) -> T | |
92a42be0 | 1988 | { |
32a655c1 | 1989 | let id = self.definitions.local_def_id(id); |
a7813a04 XL |
1990 | let module = self.module_map.get(&id).cloned(); // clones a reference |
1991 | if let Some(module) = module { | |
7453a54e | 1992 | // Move down in the graph. |
9e0c209e | 1993 | let orig_module = replace(&mut self.current_module, module); |
476ff2be SL |
1994 | self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); |
1995 | self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); | |
92a42be0 | 1996 | |
476ff2be | 1997 | self.finalize_current_module_macro_resolutions(); |
2c00a5a8 | 1998 | let ret = f(self); |
1a4d82fc | 1999 | |
7453a54e | 2000 | self.current_module = orig_module; |
476ff2be SL |
2001 | self.ribs[ValueNS].pop(); |
2002 | self.ribs[TypeNS].pop(); | |
2c00a5a8 | 2003 | ret |
7453a54e | 2004 | } else { |
2c00a5a8 | 2005 | f(self) |
1a4d82fc | 2006 | } |
1a4d82fc JJ |
2007 | } |
2008 | ||
abe05a73 XL |
2009 | /// Searches the current set of local scopes for labels. Returns the first non-None label that |
2010 | /// is returned by the given predicate function | |
2011 | /// | |
1a4d82fc | 2012 | /// Stops after meeting a closure. |
abe05a73 XL |
2013 | fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R> |
2014 | where P: Fn(&Rib, Ident) -> Option<R> | |
2015 | { | |
1a4d82fc JJ |
2016 | for rib in self.label_ribs.iter().rev() { |
2017 | match rib.kind { | |
7cac9316 XL |
2018 | NormalRibKind => {} |
2019 | // If an invocation of this macro created `ident`, give up on `ident` | |
2020 | // and switch to `ident`'s source from the macro definition. | |
8bb4bdeb | 2021 | MacroDefinition(def) => { |
83c7162d XL |
2022 | if def == self.macro_def(ident.span.ctxt()) { |
2023 | ident.span.remove_mark(); | |
5bcae85e SL |
2024 | } |
2025 | } | |
1a4d82fc JJ |
2026 | _ => { |
2027 | // Do not resolve labels across function boundary | |
92a42be0 | 2028 | return None; |
1a4d82fc JJ |
2029 | } |
2030 | } | |
abe05a73 XL |
2031 | let r = pred(rib, ident); |
2032 | if r.is_some() { | |
2033 | return r; | |
1a4d82fc JJ |
2034 | } |
2035 | } | |
2036 | None | |
2037 | } | |
2038 | ||
1a4d82fc | 2039 | fn resolve_item(&mut self, item: &Item) { |
a7813a04 | 2040 | let name = item.ident.name; |
1a4d82fc | 2041 | |
92a42be0 | 2042 | debug!("(resolving item) resolving {}", name); |
1a4d82fc | 2043 | |
32a655c1 SL |
2044 | self.check_proc_macro_attrs(&item.attrs); |
2045 | ||
1a4d82fc | 2046 | match item.node { |
a7813a04 XL |
2047 | ItemKind::Enum(_, ref generics) | |
2048 | ItemKind::Ty(_, ref generics) | | |
9e0c209e SL |
2049 | ItemKind::Struct(_, ref generics) | |
2050 | ItemKind::Union(_, ref generics) | | |
2051 | ItemKind::Fn(.., ref generics, _) => { | |
2052 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), | |
a7813a04 | 2053 | |this| visit::walk_item(this, item)); |
1a4d82fc JJ |
2054 | } |
2055 | ||
9e0c209e | 2056 | ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => |
c34b1796 | 2057 | self.resolve_implementation(generics, |
9346a6ac | 2058 | opt_trait_ref, |
7453a54e | 2059 | &self_type, |
9346a6ac | 2060 | item.id, |
a7813a04 | 2061 | impl_items), |
1a4d82fc | 2062 | |
abe05a73 | 2063 | ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => { |
1a4d82fc | 2064 | // Create a new rib for the trait-wide type parameters. |
9e0c209e | 2065 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { |
a7813a04 | 2066 | let local_def_id = this.definitions.local_def_id(item.id); |
7453a54e | 2067 | this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { |
9346a6ac | 2068 | this.visit_generics(generics); |
b039eaaf | 2069 | walk_list!(this, visit_ty_param_bound, bounds); |
9346a6ac AL |
2070 | |
2071 | for trait_item in trait_items { | |
32a655c1 SL |
2072 | this.check_proc_macro_attrs(&trait_item.attrs); |
2073 | ||
ff7c6d11 XL |
2074 | let type_parameters = HasTypeParameters(&trait_item.generics, |
2075 | TraitOrImplItemRibKind); | |
2076 | this.with_type_parameter_rib(type_parameters, |this| { | |
2077 | match trait_item.node { | |
2078 | TraitItemKind::Const(ref ty, ref default) => { | |
2079 | this.visit_ty(ty); | |
2080 | ||
2081 | // Only impose the restrictions of | |
2082 | // ConstRibKind for an actual constant | |
2083 | // expression in a provided default. | |
2084 | if let Some(ref expr) = *default{ | |
2085 | this.with_constant_rib(|this| { | |
2086 | this.visit_expr(expr); | |
2087 | }); | |
2088 | } | |
d9579d0f | 2089 | } |
ff7c6d11 | 2090 | TraitItemKind::Method(_, _) => { |
a7813a04 | 2091 | visit::walk_trait_item(this, trait_item) |
ff7c6d11 XL |
2092 | } |
2093 | TraitItemKind::Type(..) => { | |
a7813a04 | 2094 | visit::walk_trait_item(this, trait_item) |
ff7c6d11 XL |
2095 | } |
2096 | TraitItemKind::Macro(_) => { | |
2097 | panic!("unexpanded macro in resolve!") | |
2098 | } | |
2099 | }; | |
2100 | }); | |
9346a6ac AL |
2101 | } |
2102 | }); | |
1a4d82fc | 2103 | }); |
1a4d82fc JJ |
2104 | } |
2105 | ||
ff7c6d11 XL |
2106 | ItemKind::TraitAlias(ref generics, ref bounds) => { |
2107 | // Create a new rib for the trait-wide type parameters. | |
2108 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { | |
2109 | let local_def_id = this.definitions.local_def_id(item.id); | |
2110 | this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { | |
2111 | this.visit_generics(generics); | |
2112 | walk_list!(this, visit_ty_param_bound, bounds); | |
2113 | }); | |
2114 | }); | |
2115 | } | |
2116 | ||
a7813a04 | 2117 | ItemKind::Mod(_) | ItemKind::ForeignMod(_) => { |
7453a54e | 2118 | self.with_scope(item.id, |this| { |
a7813a04 | 2119 | visit::walk_item(this, item); |
1a4d82fc JJ |
2120 | }); |
2121 | } | |
2122 | ||
7cac9316 XL |
2123 | ItemKind::Static(ref ty, _, ref expr) | |
2124 | ItemKind::Const(ref ty, ref expr) => { | |
2125 | self.with_item_rib(|this| { | |
2126 | this.visit_ty(ty); | |
2127 | this.with_constant_rib(|this| { | |
2128 | this.visit_expr(expr); | |
2129 | }); | |
1a4d82fc JJ |
2130 | }); |
2131 | } | |
2132 | ||
ff7c6d11 | 2133 | ItemKind::Use(ref use_tree) => { |
0531ce1d | 2134 | // Imports are resolved as global by default, add starting root segment. |
ff7c6d11 | 2135 | let path = Path { |
0531ce1d | 2136 | segments: use_tree.prefix.make_root().into_iter().collect(), |
ff7c6d11 XL |
2137 | span: use_tree.span, |
2138 | }; | |
94b46f34 | 2139 | self.resolve_use_tree(item.id, use_tree.span, item.id, use_tree, &path); |
85aaf69f SL |
2140 | } |
2141 | ||
ff7c6d11 | 2142 | ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_) => { |
1a4d82fc | 2143 | // do nothing, these are just around to be encoded |
85aaf69f | 2144 | } |
a7813a04 XL |
2145 | |
2146 | ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"), | |
1a4d82fc JJ |
2147 | } |
2148 | } | |
2149 | ||
94b46f34 XL |
2150 | /// For the most part, use trees are desugared into `ImportDirective` instances |
2151 | /// when building the reduced graph (see `build_reduced_graph_for_use_tree`). But | |
2152 | /// there is one special case we handle here: an empty nested import like | |
2153 | /// `a::{b::{}}`, which desugares into...no import directives. | |
2154 | fn resolve_use_tree( | |
2155 | &mut self, | |
2156 | root_id: NodeId, | |
2157 | root_span: Span, | |
2158 | id: NodeId, | |
2159 | use_tree: &ast::UseTree, | |
2160 | prefix: &Path, | |
2161 | ) { | |
ff7c6d11 XL |
2162 | match use_tree.kind { |
2163 | ast::UseTreeKind::Nested(ref items) => { | |
2164 | let path = Path { | |
2165 | segments: prefix.segments | |
2166 | .iter() | |
2167 | .chain(use_tree.prefix.segments.iter()) | |
2168 | .cloned() | |
2169 | .collect(), | |
2170 | span: prefix.span.to(use_tree.prefix.span), | |
2171 | }; | |
2172 | ||
2173 | if items.len() == 0 { | |
2174 | // Resolve prefix of an import with empty braces (issue #28388). | |
94b46f34 XL |
2175 | self.smart_resolve_path_with_crate_lint( |
2176 | id, | |
2177 | None, | |
2178 | &path, | |
2179 | PathSource::ImportPrefix, | |
2180 | CrateLint::UsePath { root_id, root_span }, | |
2181 | ); | |
ff7c6d11 | 2182 | } else { |
2c00a5a8 | 2183 | for &(ref tree, nested_id) in items { |
94b46f34 | 2184 | self.resolve_use_tree(root_id, root_span, nested_id, tree, &path); |
ff7c6d11 XL |
2185 | } |
2186 | } | |
2187 | } | |
94b46f34 | 2188 | ast::UseTreeKind::Simple(..) => {}, |
ff7c6d11 XL |
2189 | ast::UseTreeKind::Glob => {}, |
2190 | } | |
2191 | } | |
2192 | ||
7453a54e | 2193 | fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<'a, 'b>, f: F) |
92a42be0 | 2194 | where F: FnOnce(&mut Resolver) |
1a4d82fc JJ |
2195 | { |
2196 | match type_parameters { | |
9e0c209e | 2197 | HasTypeParameters(generics, rib_kind) => { |
1a4d82fc | 2198 | let mut function_type_rib = Rib::new(rib_kind); |
476ff2be | 2199 | let mut seen_bindings = FxHashMap(); |
ff7c6d11 XL |
2200 | for param in &generics.params { |
2201 | if let GenericParam::Type(ref type_parameter) = *param { | |
2202 | let ident = type_parameter.ident.modern(); | |
2203 | debug!("with_type_parameter_rib: {}", type_parameter.id); | |
2204 | ||
2205 | if seen_bindings.contains_key(&ident) { | |
2206 | let span = seen_bindings.get(&ident).unwrap(); | |
2207 | let err = ResolutionError::NameAlreadyUsedInTypeParameterList( | |
2208 | ident.name, | |
2209 | span, | |
2210 | ); | |
83c7162d | 2211 | resolve_error(self, type_parameter.ident.span, err); |
ff7c6d11 | 2212 | } |
83c7162d | 2213 | seen_bindings.entry(ident).or_insert(type_parameter.ident.span); |
1a4d82fc | 2214 | |
ff7c6d11 XL |
2215 | // plain insert (no renaming) |
2216 | let def_id = self.definitions.local_def_id(type_parameter.id); | |
2217 | let def = Def::TyParam(def_id); | |
2218 | function_type_rib.bindings.insert(ident, def); | |
2219 | self.record_def(type_parameter.id, PathResolution::new(def)); | |
2220 | } | |
1a4d82fc | 2221 | } |
476ff2be | 2222 | self.ribs[TypeNS].push(function_type_rib); |
1a4d82fc JJ |
2223 | } |
2224 | ||
2225 | NoTypeParameters => { | |
2226 | // Nothing to do. | |
2227 | } | |
2228 | } | |
2229 | ||
2230 | f(self); | |
2231 | ||
a7813a04 | 2232 | if let HasTypeParameters(..) = type_parameters { |
476ff2be | 2233 | self.ribs[TypeNS].pop(); |
1a4d82fc JJ |
2234 | } |
2235 | } | |
2236 | ||
92a42be0 SL |
2237 | fn with_label_rib<F>(&mut self, f: F) |
2238 | where F: FnOnce(&mut Resolver) | |
1a4d82fc JJ |
2239 | { |
2240 | self.label_ribs.push(Rib::new(NormalRibKind)); | |
c34b1796 | 2241 | f(self); |
a7813a04 | 2242 | self.label_ribs.pop(); |
1a4d82fc JJ |
2243 | } |
2244 | ||
7cac9316 XL |
2245 | fn with_item_rib<F>(&mut self, f: F) |
2246 | where F: FnOnce(&mut Resolver) | |
2247 | { | |
2248 | self.ribs[ValueNS].push(Rib::new(ItemRibKind)); | |
2249 | self.ribs[TypeNS].push(Rib::new(ItemRibKind)); | |
2250 | f(self); | |
2251 | self.ribs[TypeNS].pop(); | |
2252 | self.ribs[ValueNS].pop(); | |
2253 | } | |
2254 | ||
92a42be0 SL |
2255 | fn with_constant_rib<F>(&mut self, f: F) |
2256 | where F: FnOnce(&mut Resolver) | |
c34b1796 | 2257 | { |
476ff2be | 2258 | self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind)); |
c34b1796 | 2259 | f(self); |
476ff2be | 2260 | self.ribs[ValueNS].pop(); |
1a4d82fc JJ |
2261 | } |
2262 | ||
9346a6ac AL |
2263 | fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T |
2264 | where F: FnOnce(&mut Resolver) -> T | |
1a4d82fc JJ |
2265 | { |
2266 | // Handle nested impls (inside fn bodies) | |
2267 | let previous_value = replace(&mut self.current_self_type, Some(self_type.clone())); | |
2268 | let result = f(self); | |
2269 | self.current_self_type = previous_value; | |
2270 | result | |
2271 | } | |
2272 | ||
0531ce1d | 2273 | /// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`) |
32a655c1 | 2274 | fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T |
9346a6ac | 2275 | where F: FnOnce(&mut Resolver, Option<DefId>) -> T |
1a4d82fc | 2276 | { |
c34b1796 | 2277 | let mut new_val = None; |
9346a6ac | 2278 | let mut new_id = None; |
c34b1796 | 2279 | if let Some(trait_ref) = opt_trait_ref { |
3b2f2976 | 2280 | let path: Vec<_> = trait_ref.path.segments.iter() |
83c7162d | 2281 | .map(|seg| seg.ident) |
3b2f2976 | 2282 | .collect(); |
0531ce1d XL |
2283 | let def = self.smart_resolve_path_fragment( |
2284 | trait_ref.ref_id, | |
2285 | None, | |
2286 | &path, | |
2287 | trait_ref.path.span, | |
94b46f34 XL |
2288 | PathSource::Trait(AliasPossibility::No), |
2289 | CrateLint::SimplePath(trait_ref.ref_id), | |
0531ce1d | 2290 | ).base_def(); |
32a655c1 | 2291 | if def != Def::Err { |
32a655c1 | 2292 | new_id = Some(def.def_id()); |
7cac9316 | 2293 | let span = trait_ref.path.span; |
94b46f34 XL |
2294 | if let PathResult::Module(module) = self.resolve_path( |
2295 | &path, | |
2296 | None, | |
2297 | false, | |
2298 | span, | |
2299 | CrateLint::SimplePath(trait_ref.ref_id), | |
2300 | ) { | |
7cac9316 XL |
2301 | new_val = Some((module, trait_ref.clone())); |
2302 | } | |
1a4d82fc | 2303 | } |
c34b1796 | 2304 | } |
1a4d82fc | 2305 | let original_trait_ref = replace(&mut self.current_trait_ref, new_val); |
9346a6ac | 2306 | let result = f(self, new_id); |
1a4d82fc JJ |
2307 | self.current_trait_ref = original_trait_ref; |
2308 | result | |
2309 | } | |
2310 | ||
9346a6ac AL |
2311 | fn with_self_rib<F>(&mut self, self_def: Def, f: F) |
2312 | where F: FnOnce(&mut Resolver) | |
2313 | { | |
2314 | let mut self_type_rib = Rib::new(NormalRibKind); | |
2315 | ||
2316 | // plain insert (no renaming, types are not currently hygienic....) | |
5bcae85e | 2317 | self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def); |
476ff2be | 2318 | self.ribs[TypeNS].push(self_type_rib); |
9346a6ac | 2319 | f(self); |
476ff2be | 2320 | self.ribs[TypeNS].pop(); |
9346a6ac AL |
2321 | } |
2322 | ||
1a4d82fc | 2323 | fn resolve_implementation(&mut self, |
1a4d82fc JJ |
2324 | generics: &Generics, |
2325 | opt_trait_reference: &Option<TraitRef>, | |
2326 | self_type: &Ty, | |
9346a6ac | 2327 | item_id: NodeId, |
92a42be0 | 2328 | impl_items: &[ImplItem]) { |
1a4d82fc | 2329 | // If applicable, create a rib for the type parameters. |
9e0c209e | 2330 | self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { |
32a655c1 SL |
2331 | // Dummy self type for better errors if `Self` is used in the trait path. |
2332 | this.with_self_rib(Def::SelfTy(None, None), |this| { | |
2333 | // Resolve the trait reference, if necessary. | |
2334 | this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { | |
2335 | let item_def_id = this.definitions.local_def_id(item_id); | |
2336 | this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| { | |
2337 | if let Some(trait_ref) = opt_trait_reference.as_ref() { | |
2338 | // Resolve type arguments in trait path | |
2339 | visit::walk_trait_ref(this, trait_ref); | |
2340 | } | |
2341 | // Resolve the self type. | |
2342 | this.visit_ty(self_type); | |
2343 | // Resolve the type parameters. | |
2344 | this.visit_generics(generics); | |
2345 | this.with_current_self_type(self_type, |this| { | |
2346 | for impl_item in impl_items { | |
2347 | this.check_proc_macro_attrs(&impl_item.attrs); | |
2348 | this.resolve_visibility(&impl_item.vis); | |
32a655c1 | 2349 | |
ff7c6d11 XL |
2350 | // We also need a new scope for the impl item type parameters. |
2351 | let type_parameters = HasTypeParameters(&impl_item.generics, | |
2352 | TraitOrImplItemRibKind); | |
2353 | this.with_type_parameter_rib(type_parameters, |this| { | |
2354 | use self::ResolutionError::*; | |
2355 | match impl_item.node { | |
2356 | ImplItemKind::Const(..) => { | |
2357 | // If this is a trait impl, ensure the const | |
2358 | // exists in trait | |
2359 | this.check_trait_item(impl_item.ident, | |
2360 | ValueNS, | |
2361 | impl_item.span, | |
2362 | |n, s| ConstNotMemberOfTrait(n, s)); | |
2363 | this.with_constant_rib(|this| | |
2364 | visit::walk_impl_item(this, impl_item) | |
2365 | ); | |
2366 | } | |
2367 | ImplItemKind::Method(_, _) => { | |
2368 | // If this is a trait impl, ensure the method | |
2369 | // exists in trait | |
2370 | this.check_trait_item(impl_item.ident, | |
2371 | ValueNS, | |
2372 | impl_item.span, | |
2373 | |n, s| MethodNotMemberOfTrait(n, s)); | |
2374 | ||
2375 | visit::walk_impl_item(this, impl_item); | |
2376 | } | |
2377 | ImplItemKind::Type(ref ty) => { | |
2378 | // If this is a trait impl, ensure the type | |
2379 | // exists in trait | |
2380 | this.check_trait_item(impl_item.ident, | |
2381 | TypeNS, | |
2382 | impl_item.span, | |
2383 | |n, s| TypeNotMemberOfTrait(n, s)); | |
2384 | ||
2385 | this.visit_ty(ty); | |
2386 | } | |
2387 | ImplItemKind::Macro(_) => | |
2388 | panic!("unexpanded macro in resolve!"), | |
32a655c1 | 2389 | } |
ff7c6d11 | 2390 | }); |
1a4d82fc | 2391 | } |
32a655c1 | 2392 | }); |
9346a6ac | 2393 | }); |
1a4d82fc | 2394 | }); |
32a655c1 | 2395 | }); |
1a4d82fc | 2396 | }); |
1a4d82fc JJ |
2397 | } |
2398 | ||
7cac9316 | 2399 | fn check_trait_item<F>(&mut self, ident: Ident, ns: Namespace, span: Span, err: F) |
92a42be0 SL |
2400 | where F: FnOnce(Name, &str) -> ResolutionError |
2401 | { | |
2402 | // If there is a TraitRef in scope for an impl, then the method must be in the | |
2403 | // trait. | |
7cac9316 XL |
2404 | if let Some((module, _)) = self.current_trait_ref { |
2405 | if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() { | |
2406 | let path = &self.current_trait_ref.as_ref().unwrap().1.path; | |
2407 | resolve_error(self, span, err(ident.name, &path_names_to_string(path))); | |
1a4d82fc JJ |
2408 | } |
2409 | } | |
2410 | } | |
2411 | ||
1a4d82fc JJ |
2412 | fn resolve_local(&mut self, local: &Local) { |
2413 | // Resolve the type. | |
b039eaaf | 2414 | walk_list!(self, visit_ty, &local.ty); |
1a4d82fc | 2415 | |
c34b1796 | 2416 | // Resolve the initializer. |
b039eaaf | 2417 | walk_list!(self, visit_expr, &local.init); |
1a4d82fc JJ |
2418 | |
2419 | // Resolve the pattern. | |
476ff2be | 2420 | self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap()); |
1a4d82fc JJ |
2421 | } |
2422 | ||
2423 | // build a map from pattern identifiers to binding-info's. | |
2424 | // this is done hygienically. This could arise for a macro | |
2425 | // that expands into an or-pattern where one 'x' was from the | |
2426 | // user and one 'x' came from the macro. | |
2427 | fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { | |
476ff2be | 2428 | let mut binding_map = FxHashMap(); |
a7813a04 XL |
2429 | |
2430 | pat.walk(&mut |pat| { | |
2431 | if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { | |
8bb4bdeb XL |
2432 | if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) { |
2433 | Some(Def::Local(..)) => true, | |
a7813a04 XL |
2434 | _ => false, |
2435 | } { | |
2436 | let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; | |
83c7162d | 2437 | binding_map.insert(ident, binding_info); |
a7813a04 XL |
2438 | } |
2439 | } | |
2440 | true | |
1a4d82fc | 2441 | }); |
a7813a04 XL |
2442 | |
2443 | binding_map | |
1a4d82fc JJ |
2444 | } |
2445 | ||
2446 | // check that all of the arms in an or-pattern have exactly the | |
2447 | // same set of bindings, with the same binding modes for each. | |
0531ce1d XL |
2448 | fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) { |
2449 | if pats.is_empty() { | |
92a42be0 | 2450 | return; |
1a4d82fc | 2451 | } |
8bb4bdeb XL |
2452 | |
2453 | let mut missing_vars = FxHashMap(); | |
2454 | let mut inconsistent_vars = FxHashMap(); | |
0531ce1d | 2455 | for (i, p) in pats.iter().enumerate() { |
7453a54e | 2456 | let map_i = self.binding_mode_map(&p); |
1a4d82fc | 2457 | |
0531ce1d | 2458 | for (j, q) in pats.iter().enumerate() { |
8bb4bdeb XL |
2459 | if i == j { |
2460 | continue; | |
2461 | } | |
2462 | ||
2463 | let map_j = self.binding_mode_map(&q); | |
2464 | for (&key, &binding_i) in &map_i { | |
2465 | if map_j.len() == 0 { // Account for missing bindings when | |
2466 | let binding_error = missing_vars // map_j has none. | |
2467 | .entry(key.name) | |
2468 | .or_insert(BindingError { | |
2469 | name: key.name, | |
2470 | origin: BTreeSet::new(), | |
2471 | target: BTreeSet::new(), | |
2472 | }); | |
2473 | binding_error.origin.insert(binding_i.span); | |
2474 | binding_error.target.insert(q.span); | |
92a42be0 | 2475 | } |
8bb4bdeb XL |
2476 | for (&key_j, &binding_j) in &map_j { |
2477 | match map_i.get(&key_j) { | |
2478 | None => { // missing binding | |
2479 | let binding_error = missing_vars | |
2480 | .entry(key_j.name) | |
2481 | .or_insert(BindingError { | |
2482 | name: key_j.name, | |
2483 | origin: BTreeSet::new(), | |
2484 | target: BTreeSet::new(), | |
2485 | }); | |
2486 | binding_error.origin.insert(binding_j.span); | |
2487 | binding_error.target.insert(p.span); | |
2488 | } | |
2489 | Some(binding_i) => { // check consistent binding | |
2490 | if binding_i.binding_mode != binding_j.binding_mode { | |
2491 | inconsistent_vars | |
2492 | .entry(key.name) | |
2493 | .or_insert((binding_j.span, binding_i.span)); | |
2494 | } | |
2495 | } | |
92a42be0 | 2496 | } |
1a4d82fc | 2497 | } |
1a4d82fc JJ |
2498 | } |
2499 | } | |
8bb4bdeb XL |
2500 | } |
2501 | let mut missing_vars = missing_vars.iter().collect::<Vec<_>>(); | |
2502 | missing_vars.sort(); | |
2503 | for (_, v) in missing_vars { | |
2504 | resolve_error(self, | |
2505 | *v.origin.iter().next().unwrap(), | |
2506 | ResolutionError::VariableNotBoundInPattern(v)); | |
2507 | } | |
2508 | let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>(); | |
2509 | inconsistent_vars.sort(); | |
2510 | for (name, v) in inconsistent_vars { | |
2511 | resolve_error(self, v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1)); | |
1a4d82fc JJ |
2512 | } |
2513 | } | |
2514 | ||
2515 | fn resolve_arm(&mut self, arm: &Arm) { | |
476ff2be | 2516 | self.ribs[ValueNS].push(Rib::new(NormalRibKind)); |
1a4d82fc | 2517 | |
476ff2be | 2518 | let mut bindings_list = FxHashMap(); |
85aaf69f | 2519 | for pattern in &arm.pats { |
3157f602 | 2520 | self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list); |
1a4d82fc JJ |
2521 | } |
2522 | ||
0531ce1d XL |
2523 | // This has to happen *after* we determine which pat_idents are variants |
2524 | self.check_consistent_bindings(&arm.pats); | |
1a4d82fc | 2525 | |
b039eaaf | 2526 | walk_list!(self, visit_expr, &arm.guard); |
7453a54e | 2527 | self.visit_expr(&arm.body); |
1a4d82fc | 2528 | |
476ff2be | 2529 | self.ribs[ValueNS].pop(); |
1a4d82fc JJ |
2530 | } |
2531 | ||
2532 | fn resolve_block(&mut self, block: &Block) { | |
2533 | debug!("(resolving block) entering block"); | |
1a4d82fc | 2534 | // Move down in the graph, if there's an anonymous module rooted here. |
9cc50fc6 | 2535 | let orig_module = self.current_module; |
32a655c1 | 2536 | let anonymous_module = self.block_map.get(&block.id).cloned(); // clones a reference |
7453a54e | 2537 | |
5bcae85e | 2538 | let mut num_macro_definition_ribs = 0; |
7453a54e SL |
2539 | if let Some(anonymous_module) = anonymous_module { |
2540 | debug!("(resolving block) found anonymous module, moving down"); | |
476ff2be SL |
2541 | self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); |
2542 | self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); | |
7453a54e | 2543 | self.current_module = anonymous_module; |
476ff2be | 2544 | self.finalize_current_module_macro_resolutions(); |
7453a54e | 2545 | } else { |
476ff2be | 2546 | self.ribs[ValueNS].push(Rib::new(NormalRibKind)); |
85aaf69f SL |
2547 | } |
2548 | ||
1a4d82fc | 2549 | // Descend into the block. |
5bcae85e | 2550 | for stmt in &block.stmts { |
8bb4bdeb XL |
2551 | if let ast::StmtKind::Item(ref item) = stmt.node { |
2552 | if let ast::ItemKind::MacroDef(..) = item.node { | |
2553 | num_macro_definition_ribs += 1; | |
2554 | let def = self.definitions.local_def_id(item.id); | |
2555 | self.ribs[ValueNS].push(Rib::new(MacroDefinition(def))); | |
2556 | self.label_ribs.push(Rib::new(MacroDefinition(def))); | |
5bcae85e SL |
2557 | } |
2558 | } | |
2559 | ||
2560 | self.visit_stmt(stmt); | |
2561 | } | |
1a4d82fc JJ |
2562 | |
2563 | // Move back up. | |
a7813a04 | 2564 | self.current_module = orig_module; |
5bcae85e | 2565 | for _ in 0 .. num_macro_definition_ribs { |
476ff2be | 2566 | self.ribs[ValueNS].pop(); |
5bcae85e SL |
2567 | self.label_ribs.pop(); |
2568 | } | |
476ff2be | 2569 | self.ribs[ValueNS].pop(); |
a7813a04 | 2570 | if let Some(_) = anonymous_module { |
476ff2be | 2571 | self.ribs[TypeNS].pop(); |
e9174d1e | 2572 | } |
1a4d82fc JJ |
2573 | debug!("(resolving block) leaving block"); |
2574 | } | |
2575 | ||
3157f602 | 2576 | fn fresh_binding(&mut self, |
83c7162d | 2577 | ident: Ident, |
3157f602 XL |
2578 | pat_id: NodeId, |
2579 | outer_pat_id: NodeId, | |
2580 | pat_src: PatternSource, | |
476ff2be | 2581 | bindings: &mut FxHashMap<Ident, NodeId>) |
3157f602 XL |
2582 | -> PathResolution { |
2583 | // Add the binding to the local ribs, if it | |
2584 | // doesn't already exist in the bindings map. (We | |
2585 | // must not add it if it's in the bindings map | |
2586 | // because that breaks the assumptions later | |
2587 | // passes make about or-patterns.) | |
ea8adc8c | 2588 | let mut def = Def::Local(pat_id); |
83c7162d | 2589 | match bindings.get(&ident).cloned() { |
3157f602 XL |
2590 | Some(id) if id == outer_pat_id => { |
2591 | // `Variant(a, a)`, error | |
2592 | resolve_error( | |
2593 | self, | |
2594 | ident.span, | |
2595 | ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( | |
94b46f34 | 2596 | &ident.as_str()) |
3157f602 | 2597 | ); |
3157f602 XL |
2598 | } |
2599 | Some(..) if pat_src == PatternSource::FnParam => { | |
2600 | // `fn f(a: u8, a: u8)`, error | |
2601 | resolve_error( | |
2602 | self, | |
2603 | ident.span, | |
2604 | ResolutionError::IdentifierBoundMoreThanOnceInParameterList( | |
94b46f34 | 2605 | &ident.as_str()) |
3157f602 | 2606 | ); |
3157f602 | 2607 | } |
0531ce1d XL |
2608 | Some(..) if pat_src == PatternSource::Match || |
2609 | pat_src == PatternSource::IfLet || | |
2610 | pat_src == PatternSource::WhileLet => { | |
3157f602 XL |
2611 | // `Variant1(a) | Variant2(a)`, ok |
2612 | // Reuse definition from the first `a`. | |
83c7162d | 2613 | def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident]; |
3157f602 XL |
2614 | } |
2615 | Some(..) => { | |
2616 | span_bug!(ident.span, "two bindings with the same name from \ | |
2617 | unexpected pattern source {:?}", pat_src); | |
2618 | } | |
2619 | None => { | |
5bcae85e | 2620 | // A completely fresh binding, add to the lists if it's valid. |
83c7162d XL |
2621 | if ident.name != keywords::Invalid.name() { |
2622 | bindings.insert(ident, outer_pat_id); | |
2623 | self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, def); | |
1a4d82fc | 2624 | } |
3157f602 | 2625 | } |
5bcae85e | 2626 | } |
1a4d82fc | 2627 | |
3157f602 XL |
2628 | PathResolution::new(def) |
2629 | } | |
a7813a04 | 2630 | |
3157f602 XL |
2631 | fn resolve_pattern(&mut self, |
2632 | pat: &Pat, | |
2633 | pat_src: PatternSource, | |
2634 | // Maps idents to the node ID for the | |
2635 | // outermost pattern that binds them. | |
476ff2be | 2636 | bindings: &mut FxHashMap<Ident, NodeId>) { |
3157f602 XL |
2637 | // Visit all direct subpatterns of this pattern. |
2638 | let outer_pat_id = pat.id; | |
2639 | pat.walk(&mut |pat| { | |
2640 | match pat.node { | |
83c7162d | 2641 | PatKind::Ident(bmode, ident, ref opt_pat) => { |
3157f602 XL |
2642 | // First try to resolve the identifier as some existing |
2643 | // entity, then fall back to a fresh binding. | |
83c7162d | 2644 | let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, |
7cac9316 | 2645 | false, pat.span) |
5bcae85e | 2646 | .and_then(LexicalScopeBinding::item); |
9e0c209e | 2647 | let resolution = binding.map(NameBinding::def).and_then(|def| { |
abe05a73 XL |
2648 | let is_syntactic_ambiguity = opt_pat.is_none() && |
2649 | bmode == BindingMode::ByValue(Mutability::Immutable); | |
3157f602 | 2650 | match def { |
c30ab7b3 SL |
2651 | Def::StructCtor(_, CtorKind::Const) | |
2652 | Def::VariantCtor(_, CtorKind::Const) | | |
abe05a73 XL |
2653 | Def::Const(..) if is_syntactic_ambiguity => { |
2654 | // Disambiguate in favor of a unit struct/variant | |
2655 | // or constant pattern. | |
83c7162d | 2656 | self.record_use(ident, ValueNS, binding.unwrap(), ident.span); |
5bcae85e | 2657 | Some(PathResolution::new(def)) |
d9579d0f | 2658 | } |
c30ab7b3 SL |
2659 | Def::StructCtor(..) | Def::VariantCtor(..) | |
2660 | Def::Const(..) | Def::Static(..) => { | |
abe05a73 XL |
2661 | // This is unambiguously a fresh binding, either syntactically |
2662 | // (e.g. `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves | |
2663 | // to something unusable as a pattern (e.g. constructor function), | |
2664 | // but we still conservatively report an error, see | |
2665 | // issues/33118#issuecomment-233962221 for one reason why. | |
c1a9b12d SL |
2666 | resolve_error( |
2667 | self, | |
3157f602 XL |
2668 | ident.span, |
2669 | ResolutionError::BindingShadowsSomethingUnacceptable( | |
83c7162d | 2670 | pat_src.descr(), ident.name, binding.unwrap()) |
c1a9b12d | 2671 | ); |
5bcae85e | 2672 | None |
3157f602 | 2673 | } |
abe05a73 | 2674 | Def::Fn(..) | Def::Err => { |
3157f602 XL |
2675 | // These entities are explicitly allowed |
2676 | // to be shadowed by fresh bindings. | |
5bcae85e | 2677 | None |
3157f602 XL |
2678 | } |
2679 | def => { | |
2680 | span_bug!(ident.span, "unexpected definition for an \ | |
c30ab7b3 | 2681 | identifier in pattern: {:?}", def); |
c34b1796 | 2682 | } |
1a4d82fc | 2683 | } |
5bcae85e | 2684 | }).unwrap_or_else(|| { |
3157f602 | 2685 | self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings) |
5bcae85e | 2686 | }); |
3157f602 XL |
2687 | |
2688 | self.record_def(pat.id, resolution); | |
1a4d82fc JJ |
2689 | } |
2690 | ||
9e0c209e | 2691 | PatKind::TupleStruct(ref path, ..) => { |
32a655c1 | 2692 | self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct); |
c34b1796 AL |
2693 | } |
2694 | ||
3157f602 | 2695 | PatKind::Path(ref qself, ref path) => { |
32a655c1 | 2696 | self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat); |
1a4d82fc JJ |
2697 | } |
2698 | ||
9e0c209e | 2699 | PatKind::Struct(ref path, ..) => { |
32a655c1 | 2700 | self.smart_resolve_path(pat.id, None, path, PathSource::Struct); |
1a4d82fc | 2701 | } |
3157f602 XL |
2702 | |
2703 | _ => {} | |
1a4d82fc JJ |
2704 | } |
2705 | true | |
2706 | }); | |
a7813a04 | 2707 | |
3157f602 | 2708 | visit::walk_pat(self, pat); |
1a4d82fc JJ |
2709 | } |
2710 | ||
32a655c1 SL |
2711 | // High-level and context dependent path resolution routine. |
2712 | // Resolves the path and records the resolution into definition map. | |
2713 | // If resolution fails tries several techniques to find likely | |
2714 | // resolution candidates, suggest imports or other help, and report | |
2715 | // errors in user friendly way. | |
2716 | fn smart_resolve_path(&mut self, | |
2717 | id: NodeId, | |
2718 | qself: Option<&QSelf>, | |
2719 | path: &Path, | |
2720 | source: PathSource) | |
2721 | -> PathResolution { | |
94b46f34 XL |
2722 | self.smart_resolve_path_with_crate_lint(id, qself, path, source, CrateLint::SimplePath(id)) |
2723 | } | |
2724 | ||
2725 | /// A variant of `smart_resolve_path` where you also specify extra | |
2726 | /// information about where the path came from; this extra info is | |
2727 | /// sometimes needed for the lint that recommends rewriting | |
2728 | /// absoluate paths to `crate`, so that it knows how to frame the | |
2729 | /// suggestion. If you are just resolving a path like `foo::bar` | |
2730 | /// that appears...somewhere, though, then you just want | |
2731 | /// `CrateLint::SimplePath`, which is what `smart_resolve_path` | |
2732 | /// already provides. | |
2733 | fn smart_resolve_path_with_crate_lint( | |
2734 | &mut self, | |
2735 | id: NodeId, | |
2736 | qself: Option<&QSelf>, | |
2737 | path: &Path, | |
2738 | source: PathSource, | |
2739 | crate_lint: CrateLint | |
2740 | ) -> PathResolution { | |
3b2f2976 | 2741 | let segments = &path.segments.iter() |
83c7162d | 2742 | .map(|seg| seg.ident) |
3b2f2976 | 2743 | .collect::<Vec<_>>(); |
94b46f34 | 2744 | self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint) |
32a655c1 SL |
2745 | } |
2746 | ||
2747 | fn smart_resolve_path_fragment(&mut self, | |
d9579d0f | 2748 | id: NodeId, |
32a655c1 | 2749 | qself: Option<&QSelf>, |
83c7162d | 2750 | path: &[Ident], |
32a655c1 | 2751 | span: Span, |
94b46f34 XL |
2752 | source: PathSource, |
2753 | crate_lint: CrateLint) | |
32a655c1 | 2754 | -> PathResolution { |
0531ce1d | 2755 | let ident_span = path.last().map_or(span, |ident| ident.span); |
32a655c1 SL |
2756 | let ns = source.namespace(); |
2757 | let is_expected = &|def| source.is_expected(def); | |
cc61c64b | 2758 | let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; |
32a655c1 SL |
2759 | |
2760 | // Base error is amended with one short label and possibly some longer helps/notes. | |
2761 | let report_errors = |this: &mut Self, def: Option<Def>| { | |
2762 | // Make the base error. | |
2763 | let expected = source.descr_expected(); | |
2764 | let path_str = names_to_string(path); | |
2765 | let code = source.error_code(def.is_some()); | |
8bb4bdeb | 2766 | let (base_msg, fallback_label, base_span) = if let Some(def) = def { |
32a655c1 | 2767 | (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), |
2c00a5a8 XL |
2768 | format!("not a {}", expected), |
2769 | span) | |
32a655c1 | 2770 | } else { |
83c7162d | 2771 | let item_str = path[path.len() - 1]; |
3b2f2976 | 2772 | let item_span = path[path.len() - 1].span; |
32a655c1 SL |
2773 | let (mod_prefix, mod_str) = if path.len() == 1 { |
2774 | (format!(""), format!("this scope")) | |
83c7162d | 2775 | } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { |
32a655c1 SL |
2776 | (format!(""), format!("the crate root")) |
2777 | } else { | |
2778 | let mod_path = &path[..path.len() - 1]; | |
83c7162d | 2779 | let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), |
94b46f34 | 2780 | false, span, CrateLint::No) { |
32a655c1 SL |
2781 | PathResult::Module(module) => module.def(), |
2782 | _ => None, | |
2783 | }.map_or(format!(""), |def| format!("{} ", def.kind_name())); | |
2784 | (mod_prefix, format!("`{}`", names_to_string(mod_path))) | |
2785 | }; | |
2786 | (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), | |
2c00a5a8 XL |
2787 | format!("not found in {}", mod_str), |
2788 | item_span) | |
32a655c1 | 2789 | }; |
abe05a73 | 2790 | let code = DiagnosticId::Error(code.into()); |
8bb4bdeb | 2791 | let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code); |
32a655c1 SL |
2792 | |
2793 | // Emit special messages for unresolved `Self` and `self`. | |
2794 | if is_self_type(path, ns) { | |
2795 | __diagnostic_used!(E0411); | |
abe05a73 | 2796 | err.code(DiagnosticId::Error("E0411".into())); |
7cac9316 | 2797 | err.span_label(span, "`Self` is only available in traits and impls"); |
3b2f2976 | 2798 | return (err, Vec::new()); |
32a655c1 SL |
2799 | } |
2800 | if is_self_value(path, ns) { | |
2801 | __diagnostic_used!(E0424); | |
abe05a73 | 2802 | err.code(DiagnosticId::Error("E0424".into())); |
7cac9316 | 2803 | err.span_label(span, format!("`self` value is only available in \ |
32a655c1 | 2804 | methods with `self` parameter")); |
3b2f2976 | 2805 | return (err, Vec::new()); |
32a655c1 SL |
2806 | } |
2807 | ||
2808 | // Try to lookup the name in more relaxed fashion for better error reporting. | |
7cac9316 | 2809 | let ident = *path.last().unwrap(); |
83c7162d | 2810 | let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); |
3b2f2976 | 2811 | if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { |
7cac9316 | 2812 | let enum_candidates = |
83c7162d | 2813 | this.lookup_import_candidates(ident.name, ns, is_enum_variant); |
cc61c64b XL |
2814 | let mut enum_candidates = enum_candidates.iter() |
2815 | .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>(); | |
2816 | enum_candidates.sort(); | |
2817 | for (sp, variant_path, enum_path) in enum_candidates { | |
cc61c64b | 2818 | if sp == DUMMY_SP { |
041b39d2 XL |
2819 | let msg = format!("there is an enum variant `{}`, \ |
2820 | try using `{}`?", | |
2821 | variant_path, | |
2822 | enum_path); | |
cc61c64b XL |
2823 | err.help(&msg); |
2824 | } else { | |
041b39d2 XL |
2825 | err.span_suggestion(span, "you can try using the variant's enum", |
2826 | enum_path); | |
cc61c64b XL |
2827 | } |
2828 | } | |
32a655c1 | 2829 | } |
7cac9316 | 2830 | if path.len() == 1 && this.self_type_is_available(span) { |
83c7162d XL |
2831 | if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) { |
2832 | let self_is_available = this.self_value_is_available(path[0].span, span); | |
32a655c1 SL |
2833 | match candidate { |
2834 | AssocSuggestion::Field => { | |
041b39d2 XL |
2835 | err.span_suggestion(span, "try", |
2836 | format!("self.{}", path_str)); | |
32a655c1 | 2837 | if !self_is_available { |
7cac9316 | 2838 | err.span_label(span, format!("`self` value is only available in \ |
32a655c1 SL |
2839 | methods with `self` parameter")); |
2840 | } | |
2841 | } | |
2842 | AssocSuggestion::MethodWithSelf if self_is_available => { | |
041b39d2 XL |
2843 | err.span_suggestion(span, "try", |
2844 | format!("self.{}", path_str)); | |
32a655c1 SL |
2845 | } |
2846 | AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => { | |
041b39d2 XL |
2847 | err.span_suggestion(span, "try", |
2848 | format!("Self::{}", path_str)); | |
32a655c1 SL |
2849 | } |
2850 | } | |
3b2f2976 | 2851 | return (err, candidates); |
32a655c1 SL |
2852 | } |
2853 | } | |
2854 | ||
7cac9316 XL |
2855 | let mut levenshtein_worked = false; |
2856 | ||
2857 | // Try Levenshtein. | |
2858 | if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) { | |
2859 | err.span_label(ident_span, format!("did you mean `{}`?", candidate)); | |
2860 | levenshtein_worked = true; | |
2861 | } | |
2862 | ||
32a655c1 SL |
2863 | // Try context dependent help if relaxed lookup didn't work. |
2864 | if let Some(def) = def { | |
2865 | match (def, source) { | |
2866 | (Def::Macro(..), _) => { | |
7cac9316 | 2867 | err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); |
3b2f2976 | 2868 | return (err, candidates); |
32a655c1 | 2869 | } |
ff7c6d11 | 2870 | (Def::TyAlias(..), PathSource::Trait(_)) => { |
7cac9316 | 2871 | err.span_label(span, "type aliases cannot be used for traits"); |
3b2f2976 | 2872 | return (err, candidates); |
32a655c1 | 2873 | } |
8bb4bdeb | 2874 | (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { |
32a655c1 | 2875 | ExprKind::Field(_, ident) => { |
7cac9316 | 2876 | err.span_label(parent.span, format!("did you mean `{}::{}`?", |
83c7162d | 2877 | path_str, ident)); |
3b2f2976 | 2878 | return (err, candidates); |
32a655c1 | 2879 | } |
041b39d2 | 2880 | ExprKind::MethodCall(ref segment, ..) => { |
7cac9316 | 2881 | err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", |
83c7162d | 2882 | path_str, segment.ident)); |
3b2f2976 | 2883 | return (err, candidates); |
32a655c1 SL |
2884 | } |
2885 | _ => {} | |
2886 | }, | |
ff7c6d11 XL |
2887 | (Def::Enum(..), PathSource::TupleStruct) |
2888 | | (Def::Enum(..), PathSource::Expr(..)) => { | |
2889 | if let Some(variants) = this.collect_enum_variants(def) { | |
2890 | err.note(&format!("did you mean to use one \ | |
2891 | of the following variants?\n{}", | |
2892 | variants.iter() | |
2893 | .map(|suggestion| path_names_to_string(suggestion)) | |
2894 | .map(|suggestion| format!("- `{}`", suggestion)) | |
2895 | .collect::<Vec<_>>() | |
2896 | .join("\n"))); | |
2897 | ||
2898 | } else { | |
2899 | err.note("did you mean to use one of the enum's variants?"); | |
2900 | } | |
2901 | return (err, candidates); | |
2902 | }, | |
2c00a5a8 XL |
2903 | (Def::Struct(def_id), _) if ns == ValueNS => { |
2904 | if let Some((ctor_def, ctor_vis)) | |
2905 | = this.struct_constructors.get(&def_id).cloned() { | |
2906 | let accessible_ctor = this.is_accessible(ctor_vis); | |
2907 | if is_expected(ctor_def) && !accessible_ctor { | |
2908 | err.span_label(span, format!("constructor is not visible \ | |
2909 | here due to private fields")); | |
8bb4bdeb | 2910 | } |
2c00a5a8 | 2911 | } else { |
94b46f34 XL |
2912 | // HACK(estebank): find a better way to figure out that this was a |
2913 | // parser issue where a struct literal is being used on an expression | |
2914 | // where a brace being opened means a block is being started. Look | |
2915 | // ahead for the next text to see if `span` is followed by a `{`. | |
2916 | let cm = this.session.codemap(); | |
2917 | let mut sp = span; | |
2918 | loop { | |
2919 | sp = cm.next_point(sp); | |
2920 | match cm.span_to_snippet(sp) { | |
2921 | Ok(ref snippet) => { | |
2922 | if snippet.chars().any(|c| { !c.is_whitespace() }) { | |
2923 | break; | |
2924 | } | |
2925 | } | |
2926 | _ => break, | |
2927 | } | |
2928 | } | |
2929 | let followed_by_brace = match cm.span_to_snippet(sp) { | |
2930 | Ok(ref snippet) if snippet == "{" => true, | |
2931 | _ => false, | |
2932 | }; | |
2933 | if let (PathSource::Expr(None), true) = (source, followed_by_brace) { | |
2934 | err.span_label( | |
2935 | span, | |
2936 | format!("did you mean `({} {{ /* fields */ }})`?", path_str), | |
2937 | ); | |
2938 | } else { | |
2939 | err.span_label( | |
2940 | span, | |
2941 | format!("did you mean `{} {{ /* fields */ }}`?", path_str), | |
2942 | ); | |
2943 | } | |
8bb4bdeb | 2944 | } |
2c00a5a8 XL |
2945 | return (err, candidates); |
2946 | } | |
2947 | (Def::Union(..), _) | | |
2948 | (Def::Variant(..), _) | | |
2949 | (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => { | |
7cac9316 | 2950 | err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", |
abe05a73 | 2951 | path_str)); |
3b2f2976 | 2952 | return (err, candidates); |
32a655c1 | 2953 | } |
2c00a5a8 XL |
2954 | (Def::SelfTy(..), _) if ns == ValueNS => { |
2955 | err.span_label(span, fallback_label); | |
2956 | err.note("can't use `Self` as a constructor, you must use the \ | |
2957 | implemented struct"); | |
2958 | return (err, candidates); | |
2959 | } | |
2960 | (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => { | |
2961 | err.note("can't use a type alias as a constructor"); | |
2962 | return (err, candidates); | |
2963 | } | |
32a655c1 SL |
2964 | _ => {} |
2965 | } | |
2966 | } | |
2967 | ||
32a655c1 | 2968 | // Fallback label. |
7cac9316 XL |
2969 | if !levenshtein_worked { |
2970 | err.span_label(base_span, fallback_label); | |
3b2f2976 | 2971 | this.type_ascription_suggestion(&mut err, base_span); |
7cac9316 | 2972 | } |
3b2f2976 | 2973 | (err, candidates) |
32a655c1 SL |
2974 | }; |
2975 | let report_errors = |this: &mut Self, def: Option<Def>| { | |
3b2f2976 XL |
2976 | let (err, candidates) = report_errors(this, def); |
2977 | let def_id = this.current_module.normal_ancestor_id; | |
2978 | let node_id = this.definitions.as_local_node_id(def_id).unwrap(); | |
2979 | let better = def.is_some(); | |
2980 | this.use_injections.push(UseError { err, candidates, node_id, better }); | |
32a655c1 SL |
2981 | err_path_resolution() |
2982 | }; | |
2983 | ||
94b46f34 XL |
2984 | let resolution = match self.resolve_qpath_anywhere( |
2985 | id, | |
2986 | qself, | |
2987 | path, | |
2988 | ns, | |
2989 | span, | |
2990 | source.defer_to_typeck(), | |
2991 | source.global_by_default(), | |
2992 | crate_lint, | |
2993 | ) { | |
8bb4bdeb XL |
2994 | Some(resolution) if resolution.unresolved_segments() == 0 => { |
2995 | if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err { | |
32a655c1 SL |
2996 | resolution |
2997 | } else { | |
8bb4bdeb XL |
2998 | // Add a temporary hack to smooth the transition to new struct ctor |
2999 | // visibility rules. See #38932 for more details. | |
3000 | let mut res = None; | |
3001 | if let Def::Struct(def_id) = resolution.base_def() { | |
3002 | if let Some((ctor_def, ctor_vis)) | |
3003 | = self.struct_constructors.get(&def_id).cloned() { | |
3004 | if is_expected(ctor_def) && self.is_accessible(ctor_vis) { | |
3005 | let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; | |
3b2f2976 | 3006 | self.session.buffer_lint(lint, id, span, |
8bb4bdeb | 3007 | "private struct constructors are not usable through \ |
2c00a5a8 | 3008 | re-exports in outer modules", |
3b2f2976 | 3009 | ); |
8bb4bdeb XL |
3010 | res = Some(PathResolution::new(ctor_def)); |
3011 | } | |
3012 | } | |
3013 | } | |
3014 | ||
3015 | res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def()))) | |
32a655c1 SL |
3016 | } |
3017 | } | |
3018 | Some(resolution) if source.defer_to_typeck() => { | |
3019 | // Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B` | |
3020 | // or `<T>::A::B`. If `B` should be resolved in value namespace then | |
3021 | // it needs to be added to the trait map. | |
3022 | if ns == ValueNS { | |
83c7162d | 3023 | let item_name = *path.last().unwrap(); |
32a655c1 SL |
3024 | let traits = self.get_traits_containing_item(item_name, ns); |
3025 | self.trait_map.insert(id, traits); | |
3026 | } | |
3027 | resolution | |
3028 | } | |
3029 | _ => report_errors(self, None) | |
3030 | }; | |
3031 | ||
3032 | if let PathSource::TraitItem(..) = source {} else { | |
3033 | // Avoid recording definition of `A::B` in `<T as A>::B::C`. | |
3034 | self.record_def(id, resolution); | |
3035 | } | |
3036 | resolution | |
3037 | } | |
3038 | ||
3b2f2976 XL |
3039 | fn type_ascription_suggestion(&self, |
3040 | err: &mut DiagnosticBuilder, | |
3041 | base_span: Span) { | |
3042 | debug!("type_ascription_suggetion {:?}", base_span); | |
3043 | let cm = self.session.codemap(); | |
3044 | debug!("self.current_type_ascription {:?}", self.current_type_ascription); | |
3045 | if let Some(sp) = self.current_type_ascription.last() { | |
3046 | let mut sp = *sp; | |
3047 | loop { // try to find the `:`, bail on first non-':'/non-whitespace | |
2c00a5a8 XL |
3048 | sp = cm.next_point(sp); |
3049 | if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) { | |
3b2f2976 | 3050 | debug!("snippet {:?}", snippet); |
ea8adc8c XL |
3051 | let line_sp = cm.lookup_char_pos(sp.hi()).line; |
3052 | let line_base_sp = cm.lookup_char_pos(base_span.lo()).line; | |
3b2f2976 XL |
3053 | debug!("{:?} {:?}", line_sp, line_base_sp); |
3054 | if snippet == ":" { | |
3055 | err.span_label(base_span, | |
3056 | "expecting a type here because of type ascription"); | |
3057 | if line_sp != line_base_sp { | |
3058 | err.span_suggestion_short(sp, | |
3059 | "did you mean to use `;` here instead?", | |
3060 | ";".to_string()); | |
3061 | } | |
3062 | break; | |
3063 | } else if snippet.trim().len() != 0 { | |
3064 | debug!("tried to find type ascription `:` token, couldn't find it"); | |
3065 | break; | |
3066 | } | |
3067 | } else { | |
3068 | break; | |
3069 | } | |
3070 | } | |
3071 | } | |
3072 | } | |
3073 | ||
7cac9316 XL |
3074 | fn self_type_is_available(&mut self, span: Span) -> bool { |
3075 | let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(), | |
3076 | TypeNS, false, span); | |
32a655c1 SL |
3077 | if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } |
3078 | } | |
3079 | ||
83c7162d XL |
3080 | fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool { |
3081 | let ident = Ident::new(keywords::SelfValue.name(), self_span); | |
3082 | let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, path_span); | |
32a655c1 SL |
3083 | if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } |
3084 | } | |
3085 | ||
3086 | // Resolve in alternative namespaces if resolution in the primary namespace fails. | |
3087 | fn resolve_qpath_anywhere(&mut self, | |
3088 | id: NodeId, | |
3089 | qself: Option<&QSelf>, | |
83c7162d | 3090 | path: &[Ident], |
32a655c1 SL |
3091 | primary_ns: Namespace, |
3092 | span: Span, | |
3093 | defer_to_typeck: bool, | |
94b46f34 XL |
3094 | global_by_default: bool, |
3095 | crate_lint: CrateLint) | |
32a655c1 SL |
3096 | -> Option<PathResolution> { |
3097 | let mut fin_res = None; | |
3098 | // FIXME: can't resolve paths in macro namespace yet, macros are | |
3099 | // processed by the little special hack below. | |
3100 | for (i, ns) in [primary_ns, TypeNS, ValueNS, /*MacroNS*/].iter().cloned().enumerate() { | |
3101 | if i == 0 || ns != primary_ns { | |
94b46f34 | 3102 | match self.resolve_qpath(id, qself, path, ns, span, global_by_default, crate_lint) { |
32a655c1 SL |
3103 | // If defer_to_typeck, then resolution > no resolution, |
3104 | // otherwise full resolution > partial resolution > no resolution. | |
8bb4bdeb XL |
3105 | Some(res) if res.unresolved_segments() == 0 || defer_to_typeck => |
3106 | return Some(res), | |
32a655c1 SL |
3107 | res => if fin_res.is_none() { fin_res = res }, |
3108 | }; | |
3109 | } | |
3110 | } | |
83c7162d | 3111 | let is_global = self.global_macros.get(&path[0].name).cloned() |
8bb4bdeb | 3112 | .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false); |
3b2f2976 | 3113 | if primary_ns != MacroNS && (is_global || |
83c7162d | 3114 | self.macro_names.contains(&path[0].modern())) { |
32a655c1 | 3115 | // Return some dummy definition, it's enough for error reporting. |
8bb4bdeb XL |
3116 | return Some( |
3117 | PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) | |
3118 | ); | |
32a655c1 SL |
3119 | } |
3120 | fin_res | |
3121 | } | |
3122 | ||
3123 | /// Handles paths that may refer to associated items. | |
3124 | fn resolve_qpath(&mut self, | |
3125 | id: NodeId, | |
3126 | qself: Option<&QSelf>, | |
83c7162d | 3127 | path: &[Ident], |
32a655c1 SL |
3128 | ns: Namespace, |
3129 | span: Span, | |
94b46f34 XL |
3130 | global_by_default: bool, |
3131 | crate_lint: CrateLint) | |
32a655c1 | 3132 | -> Option<PathResolution> { |
94b46f34 XL |
3133 | debug!( |
3134 | "resolve_qpath(id={:?}, qself={:?}, path={:?}, \ | |
3135 | ns={:?}, span={:?}, global_by_default={:?})", | |
3136 | id, | |
3137 | qself, | |
3138 | path, | |
3139 | ns, | |
3140 | span, | |
3141 | global_by_default, | |
3142 | ); | |
3143 | ||
32a655c1 | 3144 | if let Some(qself) = qself { |
476ff2be | 3145 | if qself.position == 0 { |
94b46f34 XL |
3146 | // This is a case like `<T>::B`, where there is no |
3147 | // trait to resolve. In that case, we leave the `B` | |
3148 | // segment to be resolved by type-check. | |
8bb4bdeb XL |
3149 | return Some(PathResolution::with_unresolved_segments( |
3150 | Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len() | |
3151 | )); | |
d9579d0f | 3152 | } |
94b46f34 XL |
3153 | |
3154 | // Make sure `A::B` in `<T as A::B>::C` is a trait item. | |
3155 | // | |
3156 | // Currently, `path` names the full item (`A::B::C`, in | |
3157 | // our example). so we extract the prefix of that that is | |
3158 | // the trait (the slice upto and including | |
3159 | // `qself.position`). And then we recursively resolve that, | |
3160 | // but with `qself` set to `None`. | |
3161 | // | |
3162 | // However, setting `qself` to none (but not changing the | |
3163 | // span) loses the information about where this path | |
3164 | // *actually* appears, so for the purposes of the crate | |
3165 | // lint we pass along information that this is the trait | |
3166 | // name from a fully qualified path, and this also | |
3167 | // contains the full span (the `CrateLint::QPathTrait`). | |
32a655c1 | 3168 | let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; |
94b46f34 XL |
3169 | let res = self.smart_resolve_path_fragment( |
3170 | id, | |
3171 | None, | |
3172 | &path[..qself.position + 1], | |
3173 | span, | |
3174 | PathSource::TraitItem(ns), | |
3175 | CrateLint::QPathTrait { | |
3176 | qpath_id: id, | |
3177 | qpath_span: qself.path_span, | |
3178 | }, | |
3179 | ); | |
3180 | ||
3181 | // The remaining segments (the `C` in our example) will | |
3182 | // have to be resolved by type-check, since that requires doing | |
3183 | // trait resolution. | |
8bb4bdeb XL |
3184 | return Some(PathResolution::with_unresolved_segments( |
3185 | res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 | |
3186 | )); | |
d9579d0f | 3187 | } |
a7813a04 | 3188 | |
94b46f34 XL |
3189 | let result = match self.resolve_path( |
3190 | &path, | |
3191 | Some(ns), | |
3192 | true, | |
3193 | span, | |
3194 | crate_lint, | |
3195 | ) { | |
32a655c1 | 3196 | PathResult::NonModule(path_res) => path_res, |
476ff2be SL |
3197 | PathResult::Module(module) if !module.is_normal() => { |
3198 | PathResolution::new(module.def().unwrap()) | |
54a0048b | 3199 | } |
54a0048b SL |
3200 | // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we |
3201 | // don't report an error right away, but try to fallback to a primitive type. | |
3202 | // So, we are still able to successfully resolve something like | |
3203 | // | |
3204 | // use std::u8; // bring module u8 in scope | |
3205 | // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 | |
3206 | // u8::max_value() // OK, resolves to associated function <u8>::max_value, | |
3207 | // // not to non-existent std::u8::max_value | |
3208 | // } | |
3209 | // | |
3210 | // Such behavior is required for backward compatibility. | |
3211 | // The same fallback is used when `a` resolves to nothing. | |
476ff2be | 3212 | PathResult::Module(..) | PathResult::Failed(..) |
32a655c1 | 3213 | if (ns == TypeNS || path.len() > 1) && |
3b2f2976 | 3214 | self.primitive_type_table.primitive_types |
83c7162d XL |
3215 | .contains_key(&path[0].name) => { |
3216 | let prim = self.primitive_type_table.primitive_types[&path[0].name]; | |
8bb4bdeb | 3217 | PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) |
476ff2be SL |
3218 | } |
3219 | PathResult::Module(module) => PathResolution::new(module.def().unwrap()), | |
3b2f2976 | 3220 | PathResult::Failed(span, msg, false) => { |
476ff2be SL |
3221 | resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); |
3222 | err_path_resolution() | |
3223 | } | |
32a655c1 SL |
3224 | PathResult::Failed(..) => return None, |
3225 | PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), | |
476ff2be SL |
3226 | }; |
3227 | ||
8bb4bdeb | 3228 | if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && |
83c7162d XL |
3229 | path[0].name != keywords::CrateRoot.name() && |
3230 | path[0].name != keywords::DollarCrate.name() { | |
32a655c1 | 3231 | let unqualified_result = { |
94b46f34 XL |
3232 | match self.resolve_path( |
3233 | &[*path.last().unwrap()], | |
3234 | Some(ns), | |
3235 | false, | |
3236 | span, | |
3237 | CrateLint::No, | |
3238 | ) { | |
8bb4bdeb | 3239 | PathResult::NonModule(path_res) => path_res.base_def(), |
32a655c1 SL |
3240 | PathResult::Module(module) => module.def().unwrap(), |
3241 | _ => return Some(result), | |
3242 | } | |
3243 | }; | |
8bb4bdeb | 3244 | if result.base_def() == unqualified_result { |
32a655c1 | 3245 | let lint = lint::builtin::UNUSED_QUALIFICATIONS; |
3b2f2976 | 3246 | self.session.buffer_lint(lint, id, span, "unnecessary qualification") |
c34b1796 | 3247 | } |
1a4d82fc JJ |
3248 | } |
3249 | ||
476ff2be | 3250 | Some(result) |
1a4d82fc JJ |
3251 | } |
3252 | ||
94b46f34 XL |
3253 | fn resolve_path( |
3254 | &mut self, | |
3255 | path: &[Ident], | |
3256 | opt_ns: Option<Namespace>, // `None` indicates a module path | |
3257 | record_used: bool, | |
3258 | path_span: Span, | |
3259 | crate_lint: CrateLint, | |
3260 | ) -> PathResult<'a> { | |
32a655c1 SL |
3261 | let mut module = None; |
3262 | let mut allow_super = true; | |
94b46f34 XL |
3263 | let mut second_binding = None; |
3264 | ||
3265 | debug!( | |
3266 | "resolve_path(path={:?}, opt_ns={:?}, record_used={:?}, \ | |
3267 | path_span={:?}, crate_lint={:?})", | |
3268 | path, | |
3269 | opt_ns, | |
3270 | record_used, | |
3271 | path_span, | |
3272 | crate_lint, | |
3273 | ); | |
476ff2be SL |
3274 | |
3275 | for (i, &ident) in path.iter().enumerate() { | |
3b2f2976 | 3276 | debug!("resolve_path ident {} {:?}", i, ident); |
476ff2be SL |
3277 | let is_last = i == path.len() - 1; |
3278 | let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; | |
83c7162d | 3279 | let name = ident.name; |
476ff2be | 3280 | |
ff7c6d11 | 3281 | if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() { |
83c7162d | 3282 | let mut ctxt = ident.span.ctxt().modern(); |
7cac9316 | 3283 | module = Some(self.resolve_self(&mut ctxt, self.current_module)); |
476ff2be | 3284 | continue |
ff7c6d11 | 3285 | } else if allow_super && ns == TypeNS && name == keywords::Super.name() { |
83c7162d | 3286 | let mut ctxt = ident.span.ctxt().modern(); |
7cac9316 XL |
3287 | let self_module = match i { |
3288 | 0 => self.resolve_self(&mut ctxt, self.current_module), | |
3289 | _ => module.unwrap(), | |
3290 | }; | |
476ff2be | 3291 | if let Some(parent) = self_module.parent { |
7cac9316 | 3292 | module = Some(self.resolve_self(&mut ctxt, parent)); |
476ff2be SL |
3293 | continue |
3294 | } else { | |
3295 | let msg = "There are too many initial `super`s.".to_string(); | |
3b2f2976 | 3296 | return PathResult::Failed(ident.span, msg, false); |
476ff2be | 3297 | } |
2c00a5a8 XL |
3298 | } else if i == 0 && ns == TypeNS && name == keywords::Extern.name() { |
3299 | continue; | |
476ff2be SL |
3300 | } |
3301 | allow_super = false; | |
3302 | ||
ff7c6d11 XL |
3303 | if ns == TypeNS { |
3304 | if (i == 0 && name == keywords::CrateRoot.name()) || | |
83c7162d | 3305 | (i == 0 && name == keywords::Crate.name()) || |
ff7c6d11 | 3306 | (i == 1 && name == keywords::Crate.name() && |
83c7162d | 3307 | path[0].name == keywords::CrateRoot.name()) { |
ff7c6d11 | 3308 | // `::a::b` or `::crate::a::b` |
83c7162d | 3309 | module = Some(self.resolve_crate_root(ident.span.ctxt(), false)); |
ff7c6d11 XL |
3310 | continue |
3311 | } else if i == 0 && name == keywords::DollarCrate.name() { | |
3312 | // `$crate::a::b` | |
83c7162d | 3313 | module = Some(self.resolve_crate_root(ident.span.ctxt(), true)); |
ff7c6d11 | 3314 | continue |
94b46f34 | 3315 | } else if i == 1 && !ident.is_path_segment_keyword() { |
83c7162d | 3316 | let prev_name = path[0].name; |
2c00a5a8 XL |
3317 | if prev_name == keywords::Extern.name() || |
3318 | prev_name == keywords::CrateRoot.name() && | |
83c7162d XL |
3319 | self.session.features_untracked().extern_absolute_paths && |
3320 | self.session.rust_2018() { | |
2c00a5a8 | 3321 | // `::extern_crate::a::b` |
83c7162d | 3322 | let crate_id = self.crate_loader.process_path_extern(name, ident.span); |
2c00a5a8 XL |
3323 | let crate_root = |
3324 | self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); | |
3325 | self.populate_module_if_necessary(crate_root); | |
3326 | module = Some(crate_root); | |
3327 | continue | |
3328 | } | |
ff7c6d11 XL |
3329 | } |
3330 | } | |
3331 | ||
3332 | // Report special messages for path segment keywords in wrong positions. | |
3333 | if name == keywords::CrateRoot.name() && i != 0 || | |
3334 | name == keywords::DollarCrate.name() && i != 0 || | |
3335 | name == keywords::SelfValue.name() && i != 0 || | |
3336 | name == keywords::SelfType.name() && i != 0 || | |
3337 | name == keywords::Super.name() && i != 0 || | |
2c00a5a8 | 3338 | name == keywords::Extern.name() && i != 0 || |
83c7162d XL |
3339 | // we allow crate::foo and ::crate::foo but nothing else |
3340 | name == keywords::Crate.name() && i > 1 && | |
3341 | path[0].name != keywords::CrateRoot.name() || | |
3342 | name == keywords::Crate.name() && path.len() == 1 { | |
ff7c6d11 XL |
3343 | let name_str = if name == keywords::CrateRoot.name() { |
3344 | format!("crate root") | |
3345 | } else { | |
3346 | format!("`{}`", name) | |
3347 | }; | |
83c7162d | 3348 | let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { |
ff7c6d11 | 3349 | format!("global paths cannot start with {}", name_str) |
ff7c6d11 XL |
3350 | } else { |
3351 | format!("{} in paths can only be used in start position", name_str) | |
3352 | }; | |
3353 | return PathResult::Failed(ident.span, msg, false); | |
32a655c1 SL |
3354 | } |
3355 | ||
476ff2be | 3356 | let binding = if let Some(module) = module { |
83c7162d | 3357 | self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span) |
476ff2be | 3358 | } else if opt_ns == Some(MacroNS) { |
83c7162d | 3359 | self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span) |
cc61c64b | 3360 | .map(MacroBinding::binding) |
476ff2be | 3361 | } else { |
83c7162d | 3362 | match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) { |
94b46f34 | 3363 | // we found a locally-imported or available item/module |
476ff2be | 3364 | Some(LexicalScopeBinding::Item(binding)) => Ok(binding), |
94b46f34 | 3365 | // we found a local variable or type param |
476ff2be SL |
3366 | Some(LexicalScopeBinding::Def(def)) |
3367 | if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { | |
8bb4bdeb XL |
3368 | return PathResult::NonModule(PathResolution::with_unresolved_segments( |
3369 | def, path.len() - 1 | |
3370 | )); | |
476ff2be | 3371 | } |
7cac9316 | 3372 | _ => Err(if record_used { Determined } else { Undetermined }), |
476ff2be SL |
3373 | } |
3374 | }; | |
3375 | ||
3376 | match binding { | |
3377 | Ok(binding) => { | |
94b46f34 XL |
3378 | if i == 1 { |
3379 | second_binding = Some(binding); | |
3380 | } | |
32a655c1 SL |
3381 | let def = binding.def(); |
3382 | let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); | |
476ff2be SL |
3383 | if let Some(next_module) = binding.module() { |
3384 | module = Some(next_module); | |
32a655c1 | 3385 | } else if def == Def::Err { |
476ff2be | 3386 | return PathResult::NonModule(err_path_resolution()); |
32a655c1 | 3387 | } else if opt_ns.is_some() && (is_last || maybe_assoc) { |
94b46f34 XL |
3388 | self.lint_if_path_starts_with_module( |
3389 | crate_lint, | |
3390 | path, | |
3391 | path_span, | |
3392 | second_binding, | |
3393 | ); | |
8bb4bdeb XL |
3394 | return PathResult::NonModule(PathResolution::with_unresolved_segments( |
3395 | def, path.len() - i - 1 | |
3396 | )); | |
476ff2be | 3397 | } else { |
3b2f2976 | 3398 | return PathResult::Failed(ident.span, |
83c7162d | 3399 | format!("Not a module `{}`", ident), |
3b2f2976 | 3400 | is_last); |
476ff2be SL |
3401 | } |
3402 | } | |
3403 | Err(Undetermined) => return PathResult::Indeterminate, | |
3404 | Err(Determined) => { | |
3405 | if let Some(module) = module { | |
3406 | if opt_ns.is_some() && !module.is_normal() { | |
8bb4bdeb XL |
3407 | return PathResult::NonModule(PathResolution::with_unresolved_segments( |
3408 | module.def().unwrap(), path.len() - i | |
3409 | )); | |
476ff2be SL |
3410 | } |
3411 | } | |
32a655c1 | 3412 | let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { |
476ff2be SL |
3413 | let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; |
3414 | let mut candidates = | |
ff7c6d11 | 3415 | self.lookup_import_candidates(name, TypeNS, is_mod); |
83c7162d XL |
3416 | candidates.sort_by_cached_key(|c| { |
3417 | (c.path.segments.len(), c.path.to_string()) | |
3418 | }); | |
476ff2be | 3419 | if let Some(candidate) = candidates.get(0) { |
32a655c1 | 3420 | format!("Did you mean `{}`?", candidate.path) |
476ff2be | 3421 | } else { |
83c7162d | 3422 | format!("Maybe a missing `extern crate {};`?", ident) |
476ff2be SL |
3423 | } |
3424 | } else if i == 0 { | |
83c7162d | 3425 | format!("Use of undeclared type or module `{}`", ident) |
476ff2be | 3426 | } else { |
83c7162d | 3427 | format!("Could not find `{}` in `{}`", ident, path[i - 1]) |
476ff2be | 3428 | }; |
3b2f2976 | 3429 | return PathResult::Failed(ident.span, msg, is_last); |
476ff2be SL |
3430 | } |
3431 | } | |
7453a54e SL |
3432 | } |
3433 | ||
94b46f34 XL |
3434 | self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding); |
3435 | ||
32a655c1 | 3436 | PathResult::Module(module.unwrap_or(self.graph_root)) |
1a4d82fc JJ |
3437 | } |
3438 | ||
94b46f34 XL |
3439 | fn lint_if_path_starts_with_module( |
3440 | &self, | |
3441 | crate_lint: CrateLint, | |
3442 | path: &[Ident], | |
3443 | path_span: Span, | |
3444 | second_binding: Option<&NameBinding>, | |
3445 | ) { | |
3446 | let (diag_id, diag_span) = match crate_lint { | |
3447 | CrateLint::No => return, | |
3448 | CrateLint::SimplePath(id) => (id, path_span), | |
3449 | CrateLint::UsePath { root_id, root_span } => (root_id, root_span), | |
3450 | CrateLint::QPathTrait { qpath_id, qpath_span } => (qpath_id, qpath_span), | |
3451 | }; | |
3452 | ||
3453 | let first_name = match path.get(0) { | |
3454 | Some(ident) => ident.name, | |
3455 | None => return, | |
3456 | }; | |
3457 | ||
3458 | // We're only interested in `use` paths which should start with | |
3459 | // `{{root}}` or `extern` currently. | |
3460 | if first_name != keywords::Extern.name() && first_name != keywords::CrateRoot.name() { | |
3461 | return | |
3462 | } | |
3463 | ||
3464 | match path.get(1) { | |
3465 | // If this import looks like `crate::...` it's already good | |
3466 | Some(name) if name.name == keywords::Crate.name() => return, | |
3467 | // Otherwise go below to see if it's an extern crate | |
3468 | Some(_) => {} | |
3469 | // If the path has length one (and it's `CrateRoot` most likely) | |
3470 | // then we don't know whether we're gonna be importing a crate or an | |
3471 | // item in our crate. Defer this lint to elsewhere | |
3472 | None => return, | |
3473 | } | |
3474 | ||
3475 | // If the first element of our path was actually resolved to an | |
3476 | // `ExternCrate` (also used for `crate::...`) then no need to issue a | |
3477 | // warning, this looks all good! | |
3478 | if let Some(binding) = second_binding { | |
3479 | if let NameBindingKind::Import { directive: d, .. } = binding.kind { | |
3480 | // Careful: we still want to rewrite paths from | |
3481 | // renamed extern crates. | |
3482 | if let ImportDirectiveSubclass::ExternCrate(None) = d.subclass { | |
3483 | return | |
3484 | } | |
3485 | } | |
3486 | } | |
3487 | ||
3488 | self.lint_path_starts_with_module(diag_id, diag_span); | |
3489 | } | |
3490 | ||
3491 | fn lint_path_starts_with_module(&self, id: NodeId, span: Span) { | |
3492 | // In the 2018 edition this lint is a hard error, so nothing to do | |
3493 | if self.session.rust_2018() { | |
3494 | return | |
3495 | } | |
3496 | // In the 2015 edition there's no use in emitting lints unless the | |
3497 | // crate's already enabled the feature that we're going to suggest | |
3498 | if !self.session.features_untracked().crate_in_paths { | |
3499 | return | |
3500 | } | |
3501 | let diag = lint::builtin::BuiltinLintDiagnostics | |
3502 | ::AbsPathWithModule(span); | |
3503 | self.session.buffer_lint_with_diagnostic( | |
3504 | lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, | |
3505 | id, span, | |
3506 | "absolute paths must start with `self`, `super`, \ | |
3507 | `crate`, or an external crate name in the 2018 edition", | |
3508 | diag); | |
3509 | } | |
3510 | ||
92a42be0 | 3511 | // Resolve a local definition, potentially adjusting for closures. |
8bb4bdeb XL |
3512 | fn adjust_local_def(&mut self, |
3513 | ns: Namespace, | |
3514 | rib_index: usize, | |
3515 | mut def: Def, | |
7cac9316 XL |
3516 | record_used: bool, |
3517 | span: Span) -> Def { | |
8bb4bdeb XL |
3518 | let ribs = &self.ribs[ns][rib_index + 1..]; |
3519 | ||
3520 | // An invalid forward use of a type parameter from a previous default. | |
3521 | if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind { | |
7cac9316 | 3522 | if record_used { |
3b2f2976 | 3523 | resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam); |
8bb4bdeb XL |
3524 | } |
3525 | assert_eq!(def, Def::Err); | |
3526 | return Def::Err; | |
3527 | } | |
3528 | ||
92a42be0 | 3529 | match def { |
7453a54e | 3530 | Def::Upvar(..) => { |
7cac9316 | 3531 | span_bug!(span, "unexpected {:?} in bindings", def) |
1a4d82fc | 3532 | } |
ea8adc8c | 3533 | Def::Local(node_id) => { |
92a42be0 SL |
3534 | for rib in ribs { |
3535 | match rib.kind { | |
8bb4bdeb XL |
3536 | NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) | |
3537 | ForwardTyParamBanRibKind => { | |
92a42be0 SL |
3538 | // Nothing to do. Continue. |
3539 | } | |
3540 | ClosureRibKind(function_id) => { | |
3541 | let prev_def = def; | |
92a42be0 SL |
3542 | |
3543 | let seen = self.freevars_seen | |
3544 | .entry(function_id) | |
3545 | .or_insert_with(|| NodeMap()); | |
3546 | if let Some(&index) = seen.get(&node_id) { | |
ea8adc8c | 3547 | def = Def::Upvar(node_id, index, function_id); |
92a42be0 | 3548 | continue; |
1a4d82fc | 3549 | } |
92a42be0 SL |
3550 | let vec = self.freevars |
3551 | .entry(function_id) | |
3552 | .or_insert_with(|| vec![]); | |
3553 | let depth = vec.len(); | |
ea8adc8c | 3554 | def = Def::Upvar(node_id, depth, function_id); |
32a655c1 | 3555 | |
7cac9316 | 3556 | if record_used { |
32a655c1 SL |
3557 | vec.push(Freevar { |
3558 | def: prev_def, | |
3b2f2976 | 3559 | span, |
32a655c1 SL |
3560 | }); |
3561 | seen.insert(node_id, depth); | |
3562 | } | |
92a42be0 | 3563 | } |
ff7c6d11 | 3564 | ItemRibKind | TraitOrImplItemRibKind => { |
92a42be0 SL |
3565 | // This was an attempt to access an upvar inside a |
3566 | // named function item. This is not allowed, so we | |
3567 | // report an error. | |
7cac9316 | 3568 | if record_used { |
32a655c1 SL |
3569 | resolve_error(self, span, |
3570 | ResolutionError::CannotCaptureDynamicEnvironmentInFnItem); | |
3571 | } | |
476ff2be | 3572 | return Def::Err; |
1a4d82fc | 3573 | } |
92a42be0 SL |
3574 | ConstantItemRibKind => { |
3575 | // Still doesn't deal with upvars | |
7cac9316 | 3576 | if record_used { |
32a655c1 SL |
3577 | resolve_error(self, span, |
3578 | ResolutionError::AttemptToUseNonConstantValueInConstant); | |
3579 | } | |
476ff2be | 3580 | return Def::Err; |
1a4d82fc JJ |
3581 | } |
3582 | } | |
3583 | } | |
3584 | } | |
7453a54e | 3585 | Def::TyParam(..) | Def::SelfTy(..) => { |
92a42be0 SL |
3586 | for rib in ribs { |
3587 | match rib.kind { | |
ff7c6d11 | 3588 | NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) | |
7cac9316 XL |
3589 | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | |
3590 | ConstantItemRibKind => { | |
92a42be0 SL |
3591 | // Nothing to do. Continue. |
3592 | } | |
3593 | ItemRibKind => { | |
3594 | // This was an attempt to use a type parameter outside | |
3595 | // its scope. | |
7cac9316 | 3596 | if record_used { |
32a655c1 | 3597 | resolve_error(self, span, |
0531ce1d | 3598 | ResolutionError::TypeParametersFromOuterFunction(def)); |
32a655c1 | 3599 | } |
476ff2be | 3600 | return Def::Err; |
92a42be0 | 3601 | } |
92a42be0 | 3602 | } |
1a4d82fc JJ |
3603 | } |
3604 | } | |
92a42be0 | 3605 | _ => {} |
1a4d82fc | 3606 | } |
476ff2be | 3607 | return def; |
1a4d82fc JJ |
3608 | } |
3609 | ||
32a655c1 | 3610 | fn lookup_assoc_candidate<FilterFn>(&mut self, |
7cac9316 | 3611 | ident: Ident, |
32a655c1 SL |
3612 | ns: Namespace, |
3613 | filter_fn: FilterFn) | |
3614 | -> Option<AssocSuggestion> | |
3615 | where FilterFn: Fn(Def) -> bool | |
3616 | { | |
a7813a04 | 3617 | fn extract_node_id(t: &Ty) -> Option<NodeId> { |
1a4d82fc | 3618 | match t.node { |
a7813a04 XL |
3619 | TyKind::Path(None, _) => Some(t.id), |
3620 | TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty), | |
1a4d82fc JJ |
3621 | // This doesn't handle the remaining `Ty` variants as they are not |
3622 | // that commonly the self_type, it might be interesting to provide | |
3623 | // support for those in future. | |
3624 | _ => None, | |
3625 | } | |
3626 | } | |
3627 | ||
32a655c1 | 3628 | // Fields are generally expected in the same contexts as locals. |
ea8adc8c | 3629 | if filter_fn(Def::Local(ast::DUMMY_NODE_ID)) { |
32a655c1 SL |
3630 | if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) { |
3631 | // Look for a field with the same name in the current self_type. | |
3632 | if let Some(resolution) = self.def_map.get(&node_id) { | |
8bb4bdeb XL |
3633 | match resolution.base_def() { |
3634 | Def::Struct(did) | Def::Union(did) | |
3635 | if resolution.unresolved_segments() == 0 => { | |
32a655c1 | 3636 | if let Some(field_names) = self.field_names.get(&did) { |
7cac9316 | 3637 | if field_names.iter().any(|&field_name| ident.name == field_name) { |
32a655c1 SL |
3638 | return Some(AssocSuggestion::Field); |
3639 | } | |
3157f602 | 3640 | } |
1a4d82fc | 3641 | } |
32a655c1 | 3642 | _ => {} |
1a4d82fc | 3643 | } |
3157f602 | 3644 | } |
1a4d82fc JJ |
3645 | } |
3646 | } | |
3647 | ||
32a655c1 | 3648 | // Look for associated items in the current trait. |
7cac9316 XL |
3649 | if let Some((module, _)) = self.current_trait_ref { |
3650 | if let Ok(binding) = | |
3651 | self.resolve_ident_in_module(module, ident, ns, false, false, module.span) { | |
3652 | let def = binding.def(); | |
32a655c1 | 3653 | if filter_fn(def) { |
7cac9316 | 3654 | return Some(if self.has_self.contains(&def.def_id()) { |
32a655c1 SL |
3655 | AssocSuggestion::MethodWithSelf |
3656 | } else { | |
3657 | AssocSuggestion::AssocItem | |
3658 | }); | |
1a4d82fc JJ |
3659 | } |
3660 | } | |
1a4d82fc JJ |
3661 | } |
3662 | ||
32a655c1 | 3663 | None |
1a4d82fc JJ |
3664 | } |
3665 | ||
32a655c1 | 3666 | fn lookup_typo_candidate<FilterFn>(&mut self, |
83c7162d | 3667 | path: &[Ident], |
32a655c1 | 3668 | ns: Namespace, |
7cac9316 XL |
3669 | filter_fn: FilterFn, |
3670 | span: Span) | |
8bb4bdeb | 3671 | -> Option<Symbol> |
32a655c1 SL |
3672 | where FilterFn: Fn(Def) -> bool |
3673 | { | |
3674 | let add_module_candidates = |module: Module, names: &mut Vec<Name>| { | |
3675 | for (&(ident, _), resolution) in module.resolutions.borrow().iter() { | |
3676 | if let Some(binding) = resolution.borrow().binding { | |
3677 | if filter_fn(binding.def()) { | |
3678 | names.push(ident.name); | |
3679 | } | |
3680 | } | |
3681 | } | |
3682 | }; | |
92a42be0 | 3683 | |
32a655c1 | 3684 | let mut names = Vec::new(); |
8bb4bdeb | 3685 | if path.len() == 1 { |
32a655c1 SL |
3686 | // Search in lexical scope. |
3687 | // Walk backwards up the ribs in scope and collect candidates. | |
3688 | for rib in self.ribs[ns].iter().rev() { | |
3689 | // Locals and type parameters | |
3690 | for (ident, def) in &rib.bindings { | |
3691 | if filter_fn(*def) { | |
3692 | names.push(ident.name); | |
3693 | } | |
3694 | } | |
3695 | // Items in scope | |
3696 | if let ModuleRibKind(module) = rib.kind { | |
3697 | // Items from this module | |
3698 | add_module_candidates(module, &mut names); | |
1a4d82fc | 3699 | |
32a655c1 SL |
3700 | if let ModuleKind::Block(..) = module.kind { |
3701 | // We can see through blocks | |
3702 | } else { | |
3703 | // Items from the prelude | |
83c7162d XL |
3704 | if !module.no_implicit_prelude { |
3705 | names.extend(self.extern_prelude.iter().cloned()); | |
3706 | if let Some(prelude) = self.prelude { | |
32a655c1 SL |
3707 | add_module_candidates(prelude, &mut names); |
3708 | } | |
3709 | } | |
3710 | break; | |
3711 | } | |
3712 | } | |
1a4d82fc | 3713 | } |
32a655c1 SL |
3714 | // Add primitive types to the mix |
3715 | if filter_fn(Def::PrimTy(TyBool)) { | |
3716 | for (name, _) in &self.primitive_type_table.primitive_types { | |
3717 | names.push(*name); | |
3718 | } | |
3719 | } | |
32a655c1 SL |
3720 | } else { |
3721 | // Search in module. | |
3722 | let mod_path = &path[..path.len() - 1]; | |
7cac9316 | 3723 | if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), |
94b46f34 | 3724 | false, span, CrateLint::No) { |
32a655c1 SL |
3725 | add_module_candidates(module, &mut names); |
3726 | } | |
8bb4bdeb | 3727 | } |
32a655c1 | 3728 | |
83c7162d | 3729 | let name = path[path.len() - 1].name; |
32a655c1 | 3730 | // Make sure error reporting is deterministic. |
83c7162d | 3731 | names.sort_by_cached_key(|name| name.as_str()); |
32a655c1 | 3732 | match find_best_match_for_name(names.iter(), &name.as_str(), None) { |
8bb4bdeb | 3733 | Some(found) if found != name => Some(found), |
32a655c1 SL |
3734 | _ => None, |
3735 | } | |
1a4d82fc JJ |
3736 | } |
3737 | ||
2c00a5a8 | 3738 | fn with_resolved_label<F>(&mut self, label: Option<Label>, id: NodeId, f: F) |
8bb4bdeb XL |
3739 | where F: FnOnce(&mut Resolver) |
3740 | { | |
a7813a04 | 3741 | if let Some(label) = label { |
94b46f34 | 3742 | self.unused_labels.insert(id, label.ident.span); |
5bcae85e | 3743 | let def = Def::Label(id); |
a7813a04 | 3744 | self.with_label_rib(|this| { |
2c00a5a8 | 3745 | this.label_ribs.last_mut().unwrap().bindings.insert(label.ident, def); |
8bb4bdeb | 3746 | f(this); |
a7813a04 XL |
3747 | }); |
3748 | } else { | |
8bb4bdeb | 3749 | f(self); |
a7813a04 XL |
3750 | } |
3751 | } | |
3752 | ||
2c00a5a8 | 3753 | fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &Block) { |
8bb4bdeb XL |
3754 | self.with_resolved_label(label, id, |this| this.visit_block(block)); |
3755 | } | |
3756 | ||
3757 | fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { | |
1a4d82fc JJ |
3758 | // First, record candidate traits for this expression if it could |
3759 | // result in the invocation of a method call. | |
3760 | ||
3761 | self.record_candidate_traits_for_expr_if_necessary(expr); | |
3762 | ||
3763 | // Next, resolve the node. | |
3764 | match expr.node { | |
32a655c1 SL |
3765 | ExprKind::Path(ref qself, ref path) => { |
3766 | self.smart_resolve_path(expr.id, qself.as_ref(), path, PathSource::Expr(parent)); | |
a7813a04 | 3767 | visit::walk_expr(self, expr); |
1a4d82fc JJ |
3768 | } |
3769 | ||
9e0c209e | 3770 | ExprKind::Struct(ref path, ..) => { |
32a655c1 | 3771 | self.smart_resolve_path(expr.id, None, path, PathSource::Struct); |
a7813a04 | 3772 | visit::walk_expr(self, expr); |
1a4d82fc JJ |
3773 | } |
3774 | ||
476ff2be | 3775 | ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { |
2c00a5a8 | 3776 | match self.search_label(label.ident, |rib, id| rib.bindings.get(&id).cloned()) { |
1a4d82fc | 3777 | None => { |
abe05a73 XL |
3778 | // Search again for close matches... |
3779 | // Picks the first label that is "close enough", which is not necessarily | |
3780 | // the closest match | |
2c00a5a8 | 3781 | let close_match = self.search_label(label.ident, |rib, ident| { |
abe05a73 | 3782 | let names = rib.bindings.iter().map(|(id, _)| &id.name); |
94b46f34 | 3783 | find_best_match_for_name(names, &*ident.as_str(), None) |
abe05a73 | 3784 | }); |
9cc50fc6 | 3785 | self.record_def(expr.id, err_path_resolution()); |
c1a9b12d | 3786 | resolve_error(self, |
83c7162d | 3787 | label.ident.span, |
94b46f34 | 3788 | ResolutionError::UndeclaredLabel(&label.ident.as_str(), |
abe05a73 | 3789 | close_match)); |
1a4d82fc | 3790 | } |
94b46f34 | 3791 | Some(Def::Label(id)) => { |
1a4d82fc | 3792 | // Since this def is a label, it is never read. |
94b46f34 XL |
3793 | self.record_def(expr.id, PathResolution::new(Def::Label(id))); |
3794 | self.unused_labels.remove(&id); | |
1a4d82fc JJ |
3795 | } |
3796 | Some(_) => { | |
476ff2be | 3797 | span_bug!(expr.span, "label wasn't mapped to a label def!"); |
1a4d82fc JJ |
3798 | } |
3799 | } | |
476ff2be SL |
3800 | |
3801 | // visit `break` argument if any | |
3802 | visit::walk_expr(self, expr); | |
1a4d82fc JJ |
3803 | } |
3804 | ||
0531ce1d | 3805 | ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => { |
a7813a04 XL |
3806 | self.visit_expr(subexpression); |
3807 | ||
476ff2be | 3808 | self.ribs[ValueNS].push(Rib::new(NormalRibKind)); |
0531ce1d XL |
3809 | let mut bindings_list = FxHashMap(); |
3810 | for pat in pats { | |
3811 | self.resolve_pattern(pat, PatternSource::IfLet, &mut bindings_list); | |
3812 | } | |
3813 | // This has to happen *after* we determine which pat_idents are variants | |
3814 | self.check_consistent_bindings(pats); | |
a7813a04 | 3815 | self.visit_block(if_block); |
476ff2be | 3816 | self.ribs[ValueNS].pop(); |
a7813a04 XL |
3817 | |
3818 | optional_else.as_ref().map(|expr| self.visit_expr(expr)); | |
3819 | } | |
3820 | ||
9e0c209e SL |
3821 | ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block), |
3822 | ||
3823 | ExprKind::While(ref subexpression, ref block, label) => { | |
8bb4bdeb XL |
3824 | self.with_resolved_label(label, expr.id, |this| { |
3825 | this.visit_expr(subexpression); | |
3826 | this.visit_block(block); | |
3827 | }); | |
9e0c209e SL |
3828 | } |
3829 | ||
0531ce1d | 3830 | ExprKind::WhileLet(ref pats, ref subexpression, ref block, label) => { |
8bb4bdeb XL |
3831 | self.with_resolved_label(label, expr.id, |this| { |
3832 | this.visit_expr(subexpression); | |
3833 | this.ribs[ValueNS].push(Rib::new(NormalRibKind)); | |
0531ce1d XL |
3834 | let mut bindings_list = FxHashMap(); |
3835 | for pat in pats { | |
3836 | this.resolve_pattern(pat, PatternSource::WhileLet, &mut bindings_list); | |
3837 | } | |
3838 | // This has to happen *after* we determine which pat_idents are variants | |
3839 | this.check_consistent_bindings(pats); | |
8bb4bdeb XL |
3840 | this.visit_block(block); |
3841 | this.ribs[ValueNS].pop(); | |
3842 | }); | |
a7813a04 XL |
3843 | } |
3844 | ||
3845 | ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { | |
3846 | self.visit_expr(subexpression); | |
476ff2be SL |
3847 | self.ribs[ValueNS].push(Rib::new(NormalRibKind)); |
3848 | self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap()); | |
a7813a04 | 3849 | |
9e0c209e | 3850 | self.resolve_labeled_block(label, expr.id, block); |
a7813a04 | 3851 | |
476ff2be | 3852 | self.ribs[ValueNS].pop(); |
a7813a04 XL |
3853 | } |
3854 | ||
94b46f34 XL |
3855 | ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block), |
3856 | ||
32a655c1 | 3857 | // Equivalent to `visit::walk_expr` + passing some context to children. |
a7813a04 | 3858 | ExprKind::Field(ref subexpression, _) => { |
8bb4bdeb | 3859 | self.resolve_expr(subexpression, Some(expr)); |
a7813a04 | 3860 | } |
041b39d2 | 3861 | ExprKind::MethodCall(ref segment, ref arguments) => { |
a7813a04 | 3862 | let mut arguments = arguments.iter(); |
8bb4bdeb | 3863 | self.resolve_expr(arguments.next().unwrap(), Some(expr)); |
a7813a04 XL |
3864 | for argument in arguments { |
3865 | self.resolve_expr(argument, None); | |
3866 | } | |
041b39d2 | 3867 | self.visit_path_segment(expr.span, segment); |
a7813a04 XL |
3868 | } |
3869 | ||
32a655c1 | 3870 | ExprKind::Call(ref callee, ref arguments) => { |
8bb4bdeb | 3871 | self.resolve_expr(callee, Some(expr)); |
32a655c1 SL |
3872 | for argument in arguments { |
3873 | self.resolve_expr(argument, None); | |
3874 | } | |
3875 | } | |
3b2f2976 XL |
3876 | ExprKind::Type(ref type_expr, _) => { |
3877 | self.current_type_ascription.push(type_expr.span); | |
3878 | visit::walk_expr(self, expr); | |
3879 | self.current_type_ascription.pop(); | |
3880 | } | |
1a4d82fc | 3881 | _ => { |
a7813a04 | 3882 | visit::walk_expr(self, expr); |
1a4d82fc JJ |
3883 | } |
3884 | } | |
3885 | } | |
3886 | ||
3887 | fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) { | |
3888 | match expr.node { | |
83c7162d | 3889 | ExprKind::Field(_, ident) => { |
1a4d82fc JJ |
3890 | // FIXME(#6890): Even though you can't treat a method like a |
3891 | // field, we need to add any trait methods we find that match | |
3892 | // the field name so that we can do some nice error reporting | |
3893 | // later on in typeck. | |
83c7162d | 3894 | let traits = self.get_traits_containing_item(ident, ValueNS); |
1a4d82fc JJ |
3895 | self.trait_map.insert(expr.id, traits); |
3896 | } | |
041b39d2 | 3897 | ExprKind::MethodCall(ref segment, ..) => { |
92a42be0 | 3898 | debug!("(recording candidate traits for expr) recording traits for {}", |
1a4d82fc | 3899 | expr.id); |
83c7162d | 3900 | let traits = self.get_traits_containing_item(segment.ident, ValueNS); |
1a4d82fc JJ |
3901 | self.trait_map.insert(expr.id, traits); |
3902 | } | |
3903 | _ => { | |
3904 | // Nothing to do. | |
3905 | } | |
3906 | } | |
3907 | } | |
3908 | ||
7cac9316 XL |
3909 | fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace) |
3910 | -> Vec<TraitCandidate> { | |
3911 | debug!("(getting traits containing item) looking for '{}'", ident.name); | |
1a4d82fc | 3912 | |
1a4d82fc | 3913 | let mut found_traits = Vec::new(); |
54a0048b | 3914 | // Look for the current trait. |
7cac9316 XL |
3915 | if let Some((module, _)) = self.current_trait_ref { |
3916 | if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() { | |
3917 | let def_id = module.def_id().unwrap(); | |
3918 | found_traits.push(TraitCandidate { def_id: def_id, import_id: None }); | |
1a4d82fc | 3919 | } |
54a0048b | 3920 | } |
1a4d82fc | 3921 | |
83c7162d | 3922 | ident.span = ident.span.modern(); |
54a0048b SL |
3923 | let mut search_module = self.current_module; |
3924 | loop { | |
7cac9316 XL |
3925 | self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); |
3926 | search_module = | |
83c7162d | 3927 | unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.span), break); |
32a655c1 | 3928 | } |
1a4d82fc | 3929 | |
32a655c1 SL |
3930 | if let Some(prelude) = self.prelude { |
3931 | if !search_module.no_implicit_prelude { | |
7cac9316 | 3932 | self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits); |
1a4d82fc JJ |
3933 | } |
3934 | } | |
3935 | ||
3936 | found_traits | |
3937 | } | |
3938 | ||
32a655c1 | 3939 | fn get_traits_in_module_containing_item(&mut self, |
7cac9316 | 3940 | ident: Ident, |
32a655c1 | 3941 | ns: Namespace, |
7cac9316 | 3942 | module: Module<'a>, |
32a655c1 SL |
3943 | found_traits: &mut Vec<TraitCandidate>) { |
3944 | let mut traits = module.traits.borrow_mut(); | |
3945 | if traits.is_none() { | |
3946 | let mut collected_traits = Vec::new(); | |
3947 | module.for_each_child(|name, ns, binding| { | |
3948 | if ns != TypeNS { return } | |
3949 | if let Def::Trait(_) = binding.def() { | |
3950 | collected_traits.push((name, binding)); | |
3951 | } | |
3952 | }); | |
3953 | *traits = Some(collected_traits.into_boxed_slice()); | |
3954 | } | |
3955 | ||
3956 | for &(trait_name, binding) in traits.as_ref().unwrap().iter() { | |
7cac9316 XL |
3957 | let module = binding.module().unwrap(); |
3958 | let mut ident = ident; | |
83c7162d | 3959 | if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() { |
7cac9316 XL |
3960 | continue |
3961 | } | |
3962 | if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span) | |
3963 | .is_ok() { | |
32a655c1 SL |
3964 | let import_id = match binding.kind { |
3965 | NameBindingKind::Import { directive, .. } => { | |
3966 | self.maybe_unused_trait_imports.insert(directive.id); | |
3967 | self.add_to_glob_map(directive.id, trait_name); | |
3968 | Some(directive.id) | |
3969 | } | |
3970 | _ => None, | |
3971 | }; | |
7cac9316 | 3972 | let trait_def_id = module.def_id().unwrap(); |
32a655c1 SL |
3973 | found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id }); |
3974 | } | |
3975 | } | |
3976 | } | |
3977 | ||
7453a54e SL |
3978 | /// When name resolution fails, this method can be used to look up candidate |
3979 | /// entities with the expected name. It allows filtering them using the | |
3980 | /// supplied predicate (which should be used to only accept the types of | |
3981 | /// definitions expected e.g. traits). The lookup spans across all crates. | |
3982 | /// | |
3983 | /// NOTE: The method does not look into imports, but this is not a problem, | |
3984 | /// since we report the definitions (thus, the de-aliased imports). | |
32a655c1 SL |
3985 | fn lookup_import_candidates<FilterFn>(&mut self, |
3986 | lookup_name: Name, | |
3987 | namespace: Namespace, | |
3988 | filter_fn: FilterFn) | |
3989 | -> Vec<ImportSuggestion> | |
3990 | where FilterFn: Fn(Def) -> bool | |
3991 | { | |
3992 | let mut candidates = Vec::new(); | |
7453a54e | 3993 | let mut worklist = Vec::new(); |
476ff2be | 3994 | let mut seen_modules = FxHashSet(); |
7453a54e SL |
3995 | worklist.push((self.graph_root, Vec::new(), false)); |
3996 | ||
3997 | while let Some((in_module, | |
3998 | path_segments, | |
3999 | in_module_is_extern)) = worklist.pop() { | |
54a0048b | 4000 | self.populate_module_if_necessary(in_module); |
7453a54e | 4001 | |
3b2f2976 XL |
4002 | // We have to visit module children in deterministic order to avoid |
4003 | // instabilities in reported imports (#43552). | |
4004 | in_module.for_each_child_stable(|ident, ns, name_binding| { | |
7453a54e | 4005 | // avoid imports entirely |
476ff2be | 4006 | if name_binding.is_import() && !name_binding.is_extern_crate() { return; } |
32a655c1 SL |
4007 | // avoid non-importable candidates as well |
4008 | if !name_binding.is_importable() { return; } | |
7453a54e SL |
4009 | |
4010 | // collect results based on the filter function | |
32a655c1 | 4011 | if ident.name == lookup_name && ns == namespace { |
9e0c209e | 4012 | if filter_fn(name_binding.def()) { |
7453a54e | 4013 | // create the path |
7453a54e | 4014 | let mut segms = path_segments.clone(); |
83c7162d | 4015 | segms.push(ast::PathSegment::from_ident(ident)); |
7453a54e | 4016 | let path = Path { |
8bb4bdeb | 4017 | span: name_binding.span, |
7453a54e SL |
4018 | segments: segms, |
4019 | }; | |
4020 | // the entity is accessible in the following cases: | |
4021 | // 1. if it's defined in the same crate, it's always | |
4022 | // accessible (since private entities can be made public) | |
4023 | // 2. if it's defined in another crate, it's accessible | |
4024 | // only if both the module is public and the entity is | |
4025 | // declared as public (due to pruning, we don't explore | |
4026 | // outside crate private modules => no need to check this) | |
a7813a04 | 4027 | if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { |
32a655c1 | 4028 | candidates.push(ImportSuggestion { path: path }); |
7453a54e SL |
4029 | } |
4030 | } | |
4031 | } | |
4032 | ||
4033 | // collect submodules to explore | |
476ff2be | 4034 | if let Some(module) = name_binding.module() { |
7453a54e | 4035 | // form the path |
476ff2be | 4036 | let mut path_segments = path_segments.clone(); |
83c7162d | 4037 | path_segments.push(ast::PathSegment::from_ident(ident)); |
7453a54e | 4038 | |
a7813a04 | 4039 | if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { |
7453a54e SL |
4040 | // add the module to the lookup |
4041 | let is_extern = in_module_is_extern || name_binding.is_extern_crate(); | |
476ff2be | 4042 | if seen_modules.insert(module.def_id().unwrap()) { |
3157f602 XL |
4043 | worklist.push((module, path_segments, is_extern)); |
4044 | } | |
7453a54e SL |
4045 | } |
4046 | } | |
4047 | }) | |
4048 | } | |
4049 | ||
32a655c1 | 4050 | candidates |
7453a54e SL |
4051 | } |
4052 | ||
ff7c6d11 XL |
4053 | fn find_module(&mut self, |
4054 | module_def: Def) | |
4055 | -> Option<(Module<'a>, ImportSuggestion)> | |
4056 | { | |
4057 | let mut result = None; | |
4058 | let mut worklist = Vec::new(); | |
4059 | let mut seen_modules = FxHashSet(); | |
4060 | worklist.push((self.graph_root, Vec::new())); | |
4061 | ||
4062 | while let Some((in_module, path_segments)) = worklist.pop() { | |
4063 | // abort if the module is already found | |
4064 | if let Some(_) = result { break; } | |
4065 | ||
4066 | self.populate_module_if_necessary(in_module); | |
4067 | ||
4068 | in_module.for_each_child_stable(|ident, _, name_binding| { | |
4069 | // abort if the module is already found or if name_binding is private external | |
4070 | if result.is_some() || !name_binding.vis.is_visible_locally() { | |
4071 | return | |
4072 | } | |
4073 | if let Some(module) = name_binding.module() { | |
4074 | // form the path | |
4075 | let mut path_segments = path_segments.clone(); | |
83c7162d | 4076 | path_segments.push(ast::PathSegment::from_ident(ident)); |
ff7c6d11 XL |
4077 | if module.def() == Some(module_def) { |
4078 | let path = Path { | |
4079 | span: name_binding.span, | |
4080 | segments: path_segments, | |
4081 | }; | |
4082 | result = Some((module, ImportSuggestion { path: path })); | |
4083 | } else { | |
4084 | // add the module to the lookup | |
4085 | if seen_modules.insert(module.def_id().unwrap()) { | |
4086 | worklist.push((module, path_segments)); | |
4087 | } | |
4088 | } | |
4089 | } | |
4090 | }); | |
4091 | } | |
4092 | ||
4093 | result | |
4094 | } | |
4095 | ||
4096 | fn collect_enum_variants(&mut self, enum_def: Def) -> Option<Vec<Path>> { | |
4097 | if let Def::Enum(..) = enum_def {} else { | |
4098 | panic!("Non-enum def passed to collect_enum_variants: {:?}", enum_def) | |
4099 | } | |
4100 | ||
4101 | self.find_module(enum_def).map(|(enum_module, enum_import_suggestion)| { | |
4102 | self.populate_module_if_necessary(enum_module); | |
4103 | ||
4104 | let mut variants = Vec::new(); | |
4105 | enum_module.for_each_child_stable(|ident, _, name_binding| { | |
4106 | if let Def::Variant(..) = name_binding.def() { | |
4107 | let mut segms = enum_import_suggestion.path.segments.clone(); | |
83c7162d | 4108 | segms.push(ast::PathSegment::from_ident(ident)); |
ff7c6d11 XL |
4109 | variants.push(Path { |
4110 | span: name_binding.span, | |
4111 | segments: segms, | |
4112 | }); | |
4113 | } | |
4114 | }); | |
4115 | variants | |
4116 | }) | |
4117 | } | |
4118 | ||
c34b1796 AL |
4119 | fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { |
4120 | debug!("(recording def) recording {:?} for {}", resolution, node_id); | |
a7813a04 XL |
4121 | if let Some(prev_res) = self.def_map.insert(node_id, resolution) { |
4122 | panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution); | |
1a4d82fc JJ |
4123 | } |
4124 | } | |
4125 | ||
a7813a04 | 4126 | fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { |
0531ce1d XL |
4127 | match vis.node { |
4128 | ast::VisibilityKind::Public => ty::Visibility::Public, | |
4129 | ast::VisibilityKind::Crate(..) => { | |
4130 | ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)) | |
4131 | } | |
4132 | ast::VisibilityKind::Inherited => { | |
32a655c1 | 4133 | ty::Visibility::Restricted(self.current_module.normal_ancestor_id) |
a7813a04 | 4134 | } |
0531ce1d XL |
4135 | ast::VisibilityKind::Restricted { ref path, id, .. } => { |
4136 | // Visibilities are resolved as global by default, add starting root segment. | |
4137 | let segments = path.make_root().iter().chain(path.segments.iter()) | |
83c7162d | 4138 | .map(|seg| seg.ident) |
0531ce1d | 4139 | .collect::<Vec<_>>(); |
94b46f34 XL |
4140 | let def = self.smart_resolve_path_fragment( |
4141 | id, | |
4142 | None, | |
4143 | &segments, | |
4144 | path.span, | |
4145 | PathSource::Visibility, | |
4146 | CrateLint::SimplePath(id), | |
4147 | ).base_def(); | |
32a655c1 SL |
4148 | if def == Def::Err { |
4149 | ty::Visibility::Public | |
4150 | } else { | |
4151 | let vis = ty::Visibility::Restricted(def.def_id()); | |
4152 | if self.is_accessible(vis) { | |
4153 | vis | |
4154 | } else { | |
4155 | self.session.span_err(path.span, "visibilities can only be restricted \ | |
4156 | to ancestor modules"); | |
4157 | ty::Visibility::Public | |
4158 | } | |
4159 | } | |
a7813a04 | 4160 | } |
a7813a04 | 4161 | } |
54a0048b SL |
4162 | } |
4163 | ||
a7813a04 | 4164 | fn is_accessible(&self, vis: ty::Visibility) -> bool { |
32a655c1 | 4165 | vis.is_accessible_from(self.current_module.normal_ancestor_id, self) |
a7813a04 XL |
4166 | } |
4167 | ||
9e0c209e | 4168 | fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool { |
32a655c1 | 4169 | vis.is_accessible_from(module.normal_ancestor_id, self) |
54a0048b SL |
4170 | } |
4171 | ||
3b2f2976 | 4172 | fn report_errors(&mut self, krate: &Crate) { |
c30ab7b3 | 4173 | self.report_shadowing_errors(); |
3b2f2976 | 4174 | self.report_with_use_injections(krate); |
ff7c6d11 | 4175 | self.report_proc_macro_import(krate); |
476ff2be | 4176 | let mut reported_spans = FxHashSet(); |
9e0c209e | 4177 | |
94b46f34 | 4178 | for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors { |
9e0c209e | 4179 | if !reported_spans.insert(span) { continue } |
476ff2be SL |
4180 | let participle = |binding: &NameBinding| { |
4181 | if binding.is_import() { "imported" } else { "defined" } | |
4182 | }; | |
32a655c1 SL |
4183 | let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1)); |
4184 | let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2)); | |
cc61c64b | 4185 | let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() { |
476ff2be SL |
4186 | format!("consider adding an explicit import of `{}` to disambiguate", name) |
4187 | } else if let Def::Macro(..) = b1.def() { | |
4188 | format!("macro-expanded {} do not shadow", | |
4189 | if b1.is_import() { "macro imports" } else { "macros" }) | |
4190 | } else { | |
4191 | format!("macro-expanded {} do not shadow when used in a macro invocation path", | |
4192 | if b1.is_import() { "imports" } else { "items" }) | |
4193 | }; | |
94b46f34 XL |
4194 | |
4195 | let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name); | |
4196 | err.span_note(b1.span, &msg1); | |
4197 | match b2.def() { | |
4198 | Def::Macro(..) if b2.span == DUMMY_SP => | |
4199 | err.note(&format!("`{}` is also a builtin macro", name)), | |
4200 | _ => err.span_note(b2.span, &msg2), | |
4201 | }; | |
4202 | err.note(¬e).emit(); | |
9e0c209e SL |
4203 | } |
4204 | ||
54a0048b SL |
4205 | for &PrivacyError(span, name, binding) in &self.privacy_errors { |
4206 | if !reported_spans.insert(span) { continue } | |
7cac9316 | 4207 | span_err!(self.session, span, E0603, "{} `{}` is private", binding.descr(), name); |
54a0048b SL |
4208 | } |
4209 | } | |
4210 | ||
3b2f2976 XL |
4211 | fn report_with_use_injections(&mut self, krate: &Crate) { |
4212 | for UseError { mut err, candidates, node_id, better } in self.use_injections.drain(..) { | |
ff7c6d11 | 4213 | let (span, found_use) = UsePlacementFinder::check(krate, node_id); |
3b2f2976 | 4214 | if !candidates.is_empty() { |
ff7c6d11 | 4215 | show_candidates(&mut err, span, &candidates, better, found_use); |
3b2f2976 XL |
4216 | } |
4217 | err.emit(); | |
4218 | } | |
4219 | } | |
4220 | ||
c30ab7b3 | 4221 | fn report_shadowing_errors(&mut self) { |
7cac9316 XL |
4222 | for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { |
4223 | self.resolve_legacy_scope(scope, ident, true); | |
c30ab7b3 SL |
4224 | } |
4225 | ||
476ff2be | 4226 | let mut reported_errors = FxHashSet(); |
c30ab7b3 | 4227 | for binding in replace(&mut self.disallowed_shadowing, Vec::new()) { |
7cac9316 XL |
4228 | if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() && |
4229 | reported_errors.insert((binding.ident, binding.span)) { | |
4230 | let msg = format!("`{}` is already in scope", binding.ident); | |
c30ab7b3 SL |
4231 | self.session.struct_span_err(binding.span, &msg) |
4232 | .note("macro-expanded `macro_rules!`s may not shadow \ | |
4233 | existing macros (see RFC 1560)") | |
4234 | .emit(); | |
4235 | } | |
4236 | } | |
4237 | } | |
4238 | ||
abe05a73 | 4239 | fn report_conflict<'b>(&mut self, |
54a0048b | 4240 | parent: Module, |
32a655c1 | 4241 | ident: Ident, |
54a0048b | 4242 | ns: Namespace, |
abe05a73 XL |
4243 | new_binding: &NameBinding<'b>, |
4244 | old_binding: &NameBinding<'b>) { | |
54a0048b | 4245 | // Error on the second of two conflicting names |
ea8adc8c | 4246 | if old_binding.span.lo() > new_binding.span.lo() { |
041b39d2 | 4247 | return self.report_conflict(parent, ident, ns, old_binding, new_binding); |
54a0048b SL |
4248 | } |
4249 | ||
9e0c209e SL |
4250 | let container = match parent.kind { |
4251 | ModuleKind::Def(Def::Mod(_), _) => "module", | |
4252 | ModuleKind::Def(Def::Trait(_), _) => "trait", | |
4253 | ModuleKind::Block(..) => "block", | |
54a0048b SL |
4254 | _ => "enum", |
4255 | }; | |
4256 | ||
041b39d2 XL |
4257 | let old_noun = match old_binding.is_import() { |
4258 | true => "import", | |
4259 | false => "definition", | |
54a0048b SL |
4260 | }; |
4261 | ||
041b39d2 XL |
4262 | let new_participle = match new_binding.is_import() { |
4263 | true => "imported", | |
4264 | false => "defined", | |
4265 | }; | |
4266 | ||
ff7c6d11 | 4267 | let (name, span) = (ident.name, self.session.codemap().def_span(new_binding.span)); |
476ff2be SL |
4268 | |
4269 | if let Some(s) = self.name_already_seen.get(&name) { | |
4270 | if s == &span { | |
4271 | return; | |
4272 | } | |
4273 | } | |
4274 | ||
041b39d2 XL |
4275 | let old_kind = match (ns, old_binding.module()) { |
4276 | (ValueNS, _) => "value", | |
4277 | (MacroNS, _) => "macro", | |
4278 | (TypeNS, _) if old_binding.is_extern_crate() => "extern crate", | |
4279 | (TypeNS, Some(module)) if module.is_normal() => "module", | |
4280 | (TypeNS, Some(module)) if module.is_trait() => "trait", | |
4281 | (TypeNS, _) => "type", | |
54a0048b SL |
4282 | }; |
4283 | ||
041b39d2 XL |
4284 | let namespace = match ns { |
4285 | ValueNS => "value", | |
4286 | MacroNS => "macro", | |
4287 | TypeNS => "type", | |
4288 | }; | |
4289 | ||
4290 | let msg = format!("the name `{}` is defined multiple times", name); | |
4291 | ||
4292 | let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) { | |
32a655c1 | 4293 | (true, true) => struct_span_err!(self.session, span, E0259, "{}", msg), |
041b39d2 | 4294 | (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() { |
32a655c1 SL |
4295 | true => struct_span_err!(self.session, span, E0254, "{}", msg), |
4296 | false => struct_span_err!(self.session, span, E0260, "{}", msg), | |
9e0c209e | 4297 | }, |
041b39d2 | 4298 | _ => match (old_binding.is_import(), new_binding.is_import()) { |
32a655c1 SL |
4299 | (false, false) => struct_span_err!(self.session, span, E0428, "{}", msg), |
4300 | (true, true) => struct_span_err!(self.session, span, E0252, "{}", msg), | |
4301 | _ => struct_span_err!(self.session, span, E0255, "{}", msg), | |
54a0048b SL |
4302 | }, |
4303 | }; | |
4304 | ||
041b39d2 XL |
4305 | err.note(&format!("`{}` must be defined only once in the {} namespace of this {}", |
4306 | name, | |
4307 | namespace, | |
4308 | container)); | |
4309 | ||
4310 | err.span_label(span, format!("`{}` re{} here", name, new_participle)); | |
2c00a5a8 | 4311 | if old_binding.span != DUMMY_SP { |
ff7c6d11 XL |
4312 | err.span_label(self.session.codemap().def_span(old_binding.span), |
4313 | format!("previous {} of the {} `{}` here", old_noun, old_kind, name)); | |
54a0048b | 4314 | } |
041b39d2 | 4315 | |
abe05a73 XL |
4316 | // See https://github.com/rust-lang/rust/issues/32354 |
4317 | if old_binding.is_import() || new_binding.is_import() { | |
2c00a5a8 | 4318 | let binding = if new_binding.is_import() && new_binding.span != DUMMY_SP { |
abe05a73 XL |
4319 | new_binding |
4320 | } else { | |
4321 | old_binding | |
4322 | }; | |
4323 | ||
4324 | let cm = self.session.codemap(); | |
4325 | let rename_msg = "You can use `as` to change the binding name of the import"; | |
4326 | ||
4327 | if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span), | |
4328 | binding.is_renamed_extern_crate()) { | |
2c00a5a8 XL |
4329 | let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { |
4330 | format!("Other{}", name) | |
4331 | } else { | |
4332 | format!("other_{}", name) | |
4333 | }; | |
4334 | ||
abe05a73 XL |
4335 | err.span_suggestion(binding.span, |
4336 | rename_msg, | |
2c00a5a8 XL |
4337 | if snippet.ends_with(';') { |
4338 | format!("{} as {};", | |
4339 | &snippet[..snippet.len()-1], | |
4340 | suggested_name) | |
4341 | } else { | |
4342 | format!("{} as {}", snippet, suggested_name) | |
4343 | }); | |
abe05a73 XL |
4344 | } else { |
4345 | err.span_label(binding.span, rename_msg); | |
4346 | } | |
4347 | } | |
4348 | ||
54a0048b | 4349 | err.emit(); |
476ff2be | 4350 | self.name_already_seen.insert(name, span); |
54a0048b | 4351 | } |
32a655c1 | 4352 | |
32a655c1 SL |
4353 | fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) { |
4354 | if self.proc_macro_enabled { return; } | |
4355 | ||
4356 | for attr in attrs { | |
cc61c64b XL |
4357 | if attr.path.segments.len() > 1 { |
4358 | continue | |
4359 | } | |
83c7162d | 4360 | let ident = attr.path.segments[0].ident; |
7cac9316 XL |
4361 | let result = self.resolve_lexical_macro_path_segment(ident, |
4362 | MacroNS, | |
4363 | false, | |
4364 | attr.path.span); | |
cc61c64b XL |
4365 | if let Ok(binding) = result { |
4366 | if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) { | |
32a655c1 SL |
4367 | attr::mark_known(attr); |
4368 | ||
4369 | let msg = "attribute procedural macros are experimental"; | |
4370 | let feature = "proc_macro"; | |
4371 | ||
4372 | feature_err(&self.session.parse_sess, feature, | |
4373 | attr.span, GateIssue::Language, msg) | |
ff7c6d11 | 4374 | .span_label(binding.span(), "procedural macro imported here") |
32a655c1 SL |
4375 | .emit(); |
4376 | } | |
4377 | } | |
4378 | } | |
4379 | } | |
54a0048b | 4380 | } |
c34b1796 | 4381 | |
83c7162d XL |
4382 | fn is_self_type(path: &[Ident], namespace: Namespace) -> bool { |
4383 | namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name() | |
32a655c1 SL |
4384 | } |
4385 | ||
83c7162d XL |
4386 | fn is_self_value(path: &[Ident], namespace: Namespace) -> bool { |
4387 | namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name() | |
32a655c1 SL |
4388 | } |
4389 | ||
83c7162d | 4390 | fn names_to_string(idents: &[Ident]) -> String { |
c34b1796 | 4391 | let mut result = String::new(); |
3b2f2976 | 4392 | for (i, ident) in idents.iter() |
83c7162d | 4393 | .filter(|ident| ident.name != keywords::CrateRoot.name()) |
3b2f2976 | 4394 | .enumerate() { |
32a655c1 SL |
4395 | if i > 0 { |
4396 | result.push_str("::"); | |
c34b1796 | 4397 | } |
94b46f34 | 4398 | result.push_str(&ident.as_str()); |
92a42be0 | 4399 | } |
c34b1796 AL |
4400 | result |
4401 | } | |
4402 | ||
32a655c1 | 4403 | fn path_names_to_string(path: &Path) -> String { |
3b2f2976 | 4404 | names_to_string(&path.segments.iter() |
83c7162d | 4405 | .map(|seg| seg.ident) |
3b2f2976 | 4406 | .collect::<Vec<_>>()) |
c34b1796 AL |
4407 | } |
4408 | ||
cc61c64b XL |
4409 | /// Get the path for an enum and the variant from an `ImportSuggestion` for an enum variant. |
4410 | fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, String) { | |
4411 | let variant_path = &suggestion.path; | |
4412 | let variant_path_string = path_names_to_string(variant_path); | |
4413 | ||
4414 | let path_len = suggestion.path.segments.len(); | |
4415 | let enum_path = ast::Path { | |
4416 | span: suggestion.path.span, | |
4417 | segments: suggestion.path.segments[0..path_len - 1].to_vec(), | |
4418 | }; | |
4419 | let enum_path_string = path_names_to_string(&enum_path); | |
4420 | ||
4421 | (suggestion.path.span, variant_path_string, enum_path_string) | |
4422 | } | |
4423 | ||
4424 | ||
7453a54e SL |
4425 | /// When an entity with a given name is not available in scope, we search for |
4426 | /// entities with that name in all crates. This method allows outputting the | |
4427 | /// results of this search in a programmer-friendly way | |
7cac9316 | 4428 | fn show_candidates(err: &mut DiagnosticBuilder, |
3b2f2976 XL |
4429 | // This is `None` if all placement locations are inside expansions |
4430 | span: Option<Span>, | |
32a655c1 | 4431 | candidates: &[ImportSuggestion], |
3b2f2976 XL |
4432 | better: bool, |
4433 | found_use: bool) { | |
32a655c1 SL |
4434 | |
4435 | // we want consistent results across executions, but candidates are produced | |
4436 | // by iterating through a hash map, so make sure they are ordered: | |
4437 | let mut path_strings: Vec<_> = | |
4438 | candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect(); | |
4439 | path_strings.sort(); | |
4440 | ||
4441 | let better = if better { "better " } else { "" }; | |
4442 | let msg_diff = match path_strings.len() { | |
4443 | 1 => " is found in another module, you can import it", | |
4444 | _ => "s are found in other modules, you can import them", | |
7453a54e | 4445 | }; |
7cac9316 XL |
4446 | let msg = format!("possible {}candidate{} into scope", better, msg_diff); |
4447 | ||
3b2f2976 XL |
4448 | if let Some(span) = span { |
4449 | for candidate in &mut path_strings { | |
4450 | // produce an additional newline to separate the new use statement | |
4451 | // from the directly following item. | |
4452 | let additional_newline = if found_use { | |
4453 | "" | |
4454 | } else { | |
4455 | "\n" | |
4456 | }; | |
4457 | *candidate = format!("use {};\n{}", candidate, additional_newline); | |
4458 | } | |
32a655c1 | 4459 | |
3b2f2976 XL |
4460 | err.span_suggestions(span, &msg, path_strings); |
4461 | } else { | |
4462 | let mut msg = msg; | |
4463 | msg.push(':'); | |
4464 | for candidate in path_strings { | |
4465 | msg.push('\n'); | |
4466 | msg.push_str(&candidate); | |
4467 | } | |
4468 | } | |
7453a54e SL |
4469 | } |
4470 | ||
c34b1796 | 4471 | /// A somewhat inefficient routine to obtain the name of a module. |
2c00a5a8 | 4472 | fn module_to_string(module: Module) -> Option<String> { |
c34b1796 AL |
4473 | let mut names = Vec::new(); |
4474 | ||
c30ab7b3 | 4475 | fn collect_mod(names: &mut Vec<Ident>, module: Module) { |
9e0c209e SL |
4476 | if let ModuleKind::Def(_, name) = module.kind { |
4477 | if let Some(parent) = module.parent { | |
c30ab7b3 | 4478 | names.push(Ident::with_empty_ctxt(name)); |
9e0c209e | 4479 | collect_mod(names, parent); |
c34b1796 | 4480 | } |
9e0c209e SL |
4481 | } else { |
4482 | // danger, shouldn't be ident? | |
476ff2be | 4483 | names.push(Ident::from_str("<opaque>")); |
c30ab7b3 | 4484 | collect_mod(names, module.parent.unwrap()); |
c34b1796 AL |
4485 | } |
4486 | } | |
4487 | collect_mod(&mut names, module); | |
4488 | ||
9346a6ac | 4489 | if names.is_empty() { |
2c00a5a8 | 4490 | return None; |
c34b1796 | 4491 | } |
2c00a5a8 | 4492 | Some(names_to_string(&names.into_iter() |
3b2f2976 | 4493 | .rev() |
2c00a5a8 | 4494 | .collect::<Vec<_>>())) |
c34b1796 AL |
4495 | } |
4496 | ||
9cc50fc6 | 4497 | fn err_path_resolution() -> PathResolution { |
3157f602 | 4498 | PathResolution::new(Def::Err) |
9cc50fc6 SL |
4499 | } |
4500 | ||
c34b1796 | 4501 | #[derive(PartialEq,Copy, Clone)] |
1a4d82fc JJ |
4502 | pub enum MakeGlobMap { |
4503 | Yes, | |
92a42be0 | 4504 | No, |
1a4d82fc JJ |
4505 | } |
4506 | ||
94b46f34 XL |
4507 | #[derive(Copy, Clone, Debug)] |
4508 | enum CrateLint { | |
4509 | /// Do not issue the lint | |
4510 | No, | |
4511 | ||
4512 | /// This lint applies to some random path like `impl ::foo::Bar` | |
4513 | /// or whatever. In this case, we can take the span of that path. | |
4514 | SimplePath(NodeId), | |
4515 | ||
4516 | /// This lint comes from a `use` statement. In this case, what we | |
4517 | /// care about really is the *root* `use` statement; e.g., if we | |
4518 | /// have nested things like `use a::{b, c}`, we care about the | |
4519 | /// `use a` part. | |
4520 | UsePath { root_id: NodeId, root_span: Span }, | |
4521 | ||
4522 | /// This is the "trait item" from a fully qualified path. For example, | |
4523 | /// we might be resolving `X::Y::Z` from a path like `<T as X::Y>::Z`. | |
4524 | /// The `path_span` is the span of the to the trait itself (`X::Y`). | |
4525 | QPathTrait { qpath_id: NodeId, qpath_span: Span }, | |
4526 | } | |
4527 | ||
d9579d0f | 4528 | __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } |