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