2015-03-15 21:44:19 +00:00
|
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
2012-12-04 00:48:01 +00:00
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
2015-08-09 21:15:05 +00:00
|
|
|
|
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
2015-05-15 23:04:01 +00:00
|
|
|
|
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
2015-08-09 21:15:05 +00:00
|
|
|
|
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
2014-12-18 22:46:26 +00:00
|
|
|
|
|
2018-05-22 15:10:17 +00:00
|
|
|
|
#![feature(crate_visibility_modifier)]
|
2015-01-30 20:26:44 +00:00
|
|
|
|
#![feature(rustc_diagnostic_macros)]
|
2018-03-30 09:23:27 +00:00
|
|
|
|
#![feature(slice_sort_by_cached_key)]
|
2017-05-08 21:36:44 +00:00
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
|
#[macro_use]
|
|
|
|
|
extern crate log;
|
|
|
|
|
#[macro_use]
|
|
|
|
|
extern crate syntax;
|
2016-06-21 22:08:13 +00:00
|
|
|
|
extern crate syntax_pos;
|
|
|
|
|
extern crate rustc_errors as errors;
|
2016-01-11 21:19:29 +00:00
|
|
|
|
extern crate arena;
|
2015-10-26 19:31:11 +00:00
|
|
|
|
#[macro_use]
|
2014-12-18 22:46:26 +00:00
|
|
|
|
extern crate rustc;
|
2017-11-04 20:48:05 +00:00
|
|
|
|
extern crate rustc_data_structures;
|
2014-12-18 22:46:26 +00:00
|
|
|
|
|
2014-11-06 08:05:53 +00:00
|
|
|
|
use self::Namespace::*;
|
|
|
|
|
use self::TypeParameters::*;
|
|
|
|
|
use self::RibKind::*;
|
|
|
|
|
|
2016-09-14 09:55:20 +00:00
|
|
|
|
use rustc::hir::map::{Definitions, DefCollector};
|
2016-05-02 23:26:18 +00:00
|
|
|
|
use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
|
2017-09-05 14:48:24 +00:00
|
|
|
|
use rustc::middle::cstore::{CrateStore, CrateLoader};
|
2014-12-18 22:46:26 +00:00
|
|
|
|
use rustc::session::Session;
|
|
|
|
|
use rustc::lint;
|
2016-03-29 09:54:26 +00:00
|
|
|
|
use rustc::hir::def::*;
|
2017-08-13 02:58:17 +00:00
|
|
|
|
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
2016-04-09 23:19:53 +00:00
|
|
|
|
use rustc::ty;
|
2016-04-19 13:43:10 +00:00
|
|
|
|
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
|
2017-01-20 15:53:49 +00:00
|
|
|
|
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
|
2012-12-23 22:41:37 +00:00
|
|
|
|
|
2018-03-18 13:47:09 +00:00
|
|
|
|
use syntax::codemap::{BytePos, CodeMap};
|
2017-11-29 09:05:31 +00:00
|
|
|
|
use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
|
2018-03-18 13:47:09 +00:00
|
|
|
|
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
|
2016-10-06 08:04:30 +00:00
|
|
|
|
use syntax::ext::base::SyntaxExtension;
|
2017-03-22 08:39:51 +00:00
|
|
|
|
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
2017-02-06 11:44:38 +00:00
|
|
|
|
use syntax::ext::base::MacroKind;
|
2016-11-16 10:52:37 +00:00
|
|
|
|
use syntax::symbol::{Symbol, keywords};
|
2015-12-14 17:06:31 +00:00
|
|
|
|
use syntax::util::lev_distance::find_best_match_for_name;
|
2015-07-31 07:04:06 +00:00
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
|
use syntax::visit::{self, FnKind, Visitor};
|
2016-09-19 05:25:17 +00:00
|
|
|
|
use syntax::attr;
|
2016-04-24 03:26:10 +00:00
|
|
|
|
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
2017-10-16 19:07:26 +00:00
|
|
|
|
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
|
2016-04-24 03:26:10 +00:00
|
|
|
|
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
2018-01-15 22:44:32 +00:00
|
|
|
|
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
|
2016-12-10 06:45:58 +00:00
|
|
|
|
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
2018-03-17 01:38:59 +00:00
|
|
|
|
use syntax::feature_gate::{feature_err, GateIssue};
|
2018-02-24 00:12:35 +00:00
|
|
|
|
use syntax::ptr::P;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-12-09 11:08:39 +00:00
|
|
|
|
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
2017-10-27 06:21:22 +00:00
|
|
|
|
use errors::{DiagnosticBuilder, DiagnosticId};
|
2016-06-21 22:08:13 +00:00
|
|
|
|
|
2013-12-21 05:14:25 +00:00
|
|
|
|
use std::cell::{Cell, RefCell};
|
2017-01-19 00:33:25 +00:00
|
|
|
|
use std::cmp;
|
2017-03-05 23:19:05 +00:00
|
|
|
|
use std::collections::BTreeSet;
|
2014-11-28 02:41:16 +00:00
|
|
|
|
use std::fmt;
|
2018-01-22 09:59:34 +00:00
|
|
|
|
use std::iter;
|
2014-01-31 20:35:36 +00:00
|
|
|
|
use std::mem::replace;
|
2018-02-27 16:11:14 +00:00
|
|
|
|
use rustc_data_structures::sync::Lrc;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-11-10 10:11:25 +00:00
|
|
|
|
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
|
2017-03-11 10:58:19 +00:00
|
|
|
|
use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding};
|
2015-03-15 21:44:19 +00:00
|
|
|
|
|
2015-01-16 23:54:58 +00:00
|
|
|
|
// NB: This module needs to be declared first so diagnostics are
|
|
|
|
|
// registered before they are used.
|
2016-03-17 01:05:29 +00:00
|
|
|
|
mod diagnostics;
|
2015-01-16 23:54:58 +00:00
|
|
|
|
|
2016-09-07 23:21:59 +00:00
|
|
|
|
mod macros;
|
2014-12-11 03:46:38 +00:00
|
|
|
|
mod check_unused;
|
2014-12-30 18:16:42 +00:00
|
|
|
|
mod build_reduced_graph;
|
2015-03-15 21:44:19 +00:00
|
|
|
|
mod resolve_imports;
|
2014-12-19 07:13:54 +00:00
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
/// A free importable items suggested in case of resolution failure.
|
|
|
|
|
struct ImportSuggestion {
|
|
|
|
|
path: Path,
|
2015-11-21 09:37:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
/// A field or associated item from self type suggested in case of resolution failure.
|
|
|
|
|
enum AssocSuggestion {
|
|
|
|
|
Field,
|
|
|
|
|
MethodWithSelf,
|
|
|
|
|
AssocItem,
|
2016-02-14 01:47:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
#[derive(Eq)]
|
|
|
|
|
struct BindingError {
|
|
|
|
|
name: Name,
|
2017-03-05 23:19:05 +00:00
|
|
|
|
origin: BTreeSet<Span>,
|
|
|
|
|
target: BTreeSet<Span>,
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PartialOrd for BindingError {
|
|
|
|
|
fn partial_cmp(&self, other: &BindingError) -> Option<cmp::Ordering> {
|
|
|
|
|
Some(self.cmp(other))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PartialEq for BindingError {
|
|
|
|
|
fn eq(&self, other: &BindingError) -> bool {
|
|
|
|
|
self.name == other.name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Ord for BindingError {
|
|
|
|
|
fn cmp(&self, other: &BindingError) -> cmp::Ordering {
|
|
|
|
|
self.name.cmp(&other.name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-17 01:05:29 +00:00
|
|
|
|
enum ResolutionError<'a> {
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0401: can't use type parameters from outer function
|
2018-02-07 10:50:11 +00:00
|
|
|
|
TypeParametersFromOuterFunction(Def),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0403: the name is already used for a type parameter in this type parameter list
|
2016-08-17 01:47:45 +00:00
|
|
|
|
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0407: method is not a member of trait
|
2015-07-14 17:42:38 +00:00
|
|
|
|
MethodNotMemberOfTrait(Name, &'a str),
|
2015-07-18 23:56:15 +00:00
|
|
|
|
/// error E0437: type is not a member of trait
|
|
|
|
|
TypeNotMemberOfTrait(Name, &'a str),
|
|
|
|
|
/// error E0438: const is not a member of trait
|
|
|
|
|
ConstNotMemberOfTrait(Name, &'a str),
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
/// error E0408: variable `{}` is not bound in all patterns
|
|
|
|
|
VariableNotBoundInPattern(&'a BindingError),
|
|
|
|
|
/// error E0409: variable `{}` is bound in inconsistent ways within the same match arm
|
|
|
|
|
VariableBoundWithDifferentMode(Name, Span),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0415: identifier is bound more than once in this parameter list
|
2015-07-14 17:42:38 +00:00
|
|
|
|
IdentifierBoundMoreThanOnceInParameterList(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0416: identifier is bound more than once in the same pattern
|
2015-07-14 17:42:38 +00:00
|
|
|
|
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0426: use of undeclared label
|
2017-10-09 22:21:09 +00:00
|
|
|
|
UndeclaredLabel(&'a str, Option<Name>),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0429: `self` imports are only allowed within a { } list
|
2015-07-14 14:32:43 +00:00
|
|
|
|
SelfImportsOnlyAllowedWithin,
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0430: `self` import can only appear once in the list
|
2015-07-14 14:32:43 +00:00
|
|
|
|
SelfImportCanOnlyAppearOnceInTheList,
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0431: `self` import can only appear in an import list with a non-empty prefix
|
2015-07-14 14:32:43 +00:00
|
|
|
|
SelfImportOnlyInImportListWithNonEmptyPrefix,
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0432: unresolved import
|
2017-07-23 22:15:45 +00:00
|
|
|
|
UnresolvedImport(Option<(Span, &'a str, &'a str)>),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0433: failed to resolve
|
2015-07-14 17:42:38 +00:00
|
|
|
|
FailedToResolve(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0434: can't capture dynamic environment in a fn item
|
2015-07-14 14:32:43 +00:00
|
|
|
|
CannotCaptureDynamicEnvironmentInFnItem,
|
2015-07-14 13:37:52 +00:00
|
|
|
|
/// error E0435: attempt to use a non-constant value in a constant
|
2015-07-14 14:32:43 +00:00
|
|
|
|
AttemptToUseNonConstantValueInConstant,
|
2016-06-03 20:15:00 +00:00
|
|
|
|
/// error E0530: X bindings cannot shadow Ys
|
2016-07-29 15:19:29 +00:00
|
|
|
|
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
|
2017-01-25 20:01:11 +00:00
|
|
|
|
/// error E0128: type parameters with a default cannot use forward declared identifiers
|
|
|
|
|
ForwardDeclaredTyParam,
|
2015-12-10 23:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// Combines an error with provided span and emits it
|
|
|
|
|
///
|
|
|
|
|
/// This takes the error provided, combines it with the span and any additional spans inside the
|
|
|
|
|
/// error and emits it.
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn resolve_error<'sess, 'a>(resolver: &'sess Resolver,
|
|
|
|
|
span: Span,
|
|
|
|
|
resolution_error: ResolutionError<'a>) {
|
2015-12-23 06:27:20 +00:00
|
|
|
|
resolve_struct_error(resolver, span, resolution_error).emit();
|
2015-12-20 21:00:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
|
|
|
|
|
span: Span,
|
|
|
|
|
resolution_error: ResolutionError<'a>)
|
|
|
|
|
-> DiagnosticBuilder<'sess> {
|
2015-12-23 06:27:20 +00:00
|
|
|
|
match resolution_error {
|
2018-02-07 10:50:11 +00:00
|
|
|
|
ResolutionError::TypeParametersFromOuterFunction(outer_def) => {
|
2016-05-11 21:42:18 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
|
|
|
|
E0401,
|
2018-02-07 10:50:11 +00:00
|
|
|
|
"can't use type parameters from outer function");
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "use of type variable from outer function");
|
2018-03-14 05:58:45 +00:00
|
|
|
|
|
|
|
|
|
let cm = resolver.session.codemap();
|
2018-02-07 10:50:11 +00:00
|
|
|
|
match outer_def {
|
|
|
|
|
Def::SelfTy(_, maybe_impl_defid) => {
|
|
|
|
|
if let Some(impl_span) = maybe_impl_defid.map_or(None,
|
|
|
|
|
|def_id| resolver.definitions.opt_span(def_id)) {
|
|
|
|
|
err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span),
|
|
|
|
|
"`Self` type implicitely declared here, on the `impl`");
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Def::TyParam(typaram_defid) => {
|
|
|
|
|
if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) {
|
|
|
|
|
err.span_label(typaram_span, "type variable from outer function");
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) |
|
|
|
|
|
Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) |
|
|
|
|
|
Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) |
|
|
|
|
|
Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) |
|
|
|
|
|
Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) |
|
|
|
|
|
Def::Macro(..) | Def::GlobalAsm(..) | Def::Err =>
|
|
|
|
|
bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
|
|
|
|
|
Def::TyParam")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try to retrieve the span of the function signature and generate a new message with
|
|
|
|
|
// a local type parameter
|
|
|
|
|
let sugg_msg = "try using a local type parameter instead";
|
2018-03-14 05:58:45 +00:00
|
|
|
|
if let Some((sugg_span, new_snippet)) = generate_local_type_param_snippet(cm, span) {
|
2018-02-07 10:50:11 +00:00
|
|
|
|
// Suggest the modification to the user
|
|
|
|
|
err.span_suggestion(sugg_span,
|
|
|
|
|
sugg_msg,
|
|
|
|
|
new_snippet);
|
2018-03-14 05:58:45 +00:00
|
|
|
|
} else if let Some(sp) = generate_fn_name_span(cm, span) {
|
|
|
|
|
err.span_label(sp, "try adding a local type parameter in this method instead");
|
2018-02-07 10:50:11 +00:00
|
|
|
|
} else {
|
|
|
|
|
err.help("try using a local type parameter instead");
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-11 21:42:18 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2016-08-17 01:47:45 +00:00
|
|
|
|
ResolutionError::NameAlreadyUsedInTypeParameterList(name, first_use_span) => {
|
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
|
|
|
|
E0403,
|
|
|
|
|
"the name `{}` is already used for a type parameter \
|
|
|
|
|
in this type parameter list",
|
|
|
|
|
name);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "already used");
|
|
|
|
|
err.span_label(first_use_span.clone(), format!("first use of `{}`", name));
|
2016-08-17 01:47:45 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
|
2016-08-16 22:03:53 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
|
|
|
|
E0407,
|
|
|
|
|
"method `{}` is not a member of trait `{}`",
|
|
|
|
|
method,
|
|
|
|
|
trait_);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
2016-08-16 22:03:53 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-18 23:56:15 +00:00
|
|
|
|
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
|
2016-08-21 13:13:58 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-20 21:00:43 +00:00
|
|
|
|
span,
|
|
|
|
|
E0437,
|
|
|
|
|
"type `{}` is not a member of trait `{}`",
|
|
|
|
|
type_,
|
2016-08-21 13:13:58 +00:00
|
|
|
|
trait_);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
2016-08-21 13:13:58 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-18 23:56:15 +00:00
|
|
|
|
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
|
2016-08-21 13:13:58 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-20 21:00:43 +00:00
|
|
|
|
span,
|
|
|
|
|
E0438,
|
|
|
|
|
"const `{}` is not a member of trait `{}`",
|
|
|
|
|
const_,
|
2016-08-21 13:13:58 +00:00
|
|
|
|
trait_);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("not a member of trait `{}`", trait_));
|
2016-08-21 13:13:58 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
ResolutionError::VariableNotBoundInPattern(binding_error) => {
|
2017-03-05 23:19:05 +00:00
|
|
|
|
let target_sp = binding_error.target.iter().map(|x| *x).collect::<Vec<_>>();
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
let msp = MultiSpan::from_spans(target_sp.clone());
|
|
|
|
|
let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
|
2017-10-27 06:21:22 +00:00
|
|
|
|
let mut err = resolver.session.struct_span_err_with_code(
|
|
|
|
|
msp,
|
|
|
|
|
&msg,
|
|
|
|
|
DiagnosticId::Error("E0408".into()),
|
|
|
|
|
);
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
for sp in target_sp {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
}
|
2017-03-05 23:19:05 +00:00
|
|
|
|
let origin_sp = binding_error.origin.iter().map(|x| *x).collect::<Vec<_>>();
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
for sp in origin_sp {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(sp, "variable not in all patterns");
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
}
|
2016-09-06 21:00:35 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2016-08-16 19:13:09 +00:00
|
|
|
|
ResolutionError::VariableBoundWithDifferentMode(variable_name,
|
|
|
|
|
first_binding_span) => {
|
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-20 21:00:43 +00:00
|
|
|
|
span,
|
|
|
|
|
E0409,
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
"variable `{}` is bound in inconsistent \
|
|
|
|
|
ways within the same match arm",
|
|
|
|
|
variable_name);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "bound in different ways");
|
|
|
|
|
err.span_label(first_binding_span, "first binding");
|
2016-08-16 19:13:09 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
2016-05-11 21:42:18 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-20 21:00:43 +00:00
|
|
|
|
span,
|
|
|
|
|
E0415,
|
|
|
|
|
"identifier `{}` is bound more than once in this parameter list",
|
2016-05-11 21:42:18 +00:00
|
|
|
|
identifier);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "used as parameter more than once");
|
2016-05-11 21:42:18 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
|
2016-05-11 21:42:18 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-20 21:00:43 +00:00
|
|
|
|
span,
|
|
|
|
|
E0416,
|
|
|
|
|
"identifier `{}` is bound more than once in the same pattern",
|
2016-05-11 21:42:18 +00:00
|
|
|
|
identifier);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "used in a pattern more than once");
|
2016-05-11 21:42:18 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2017-10-09 22:21:09 +00:00
|
|
|
|
ResolutionError::UndeclaredLabel(name, lev_candidate) => {
|
2016-08-19 20:31:31 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
|
|
|
|
E0426,
|
|
|
|
|
"use of undeclared label `{}`",
|
|
|
|
|
name);
|
2017-10-09 22:21:09 +00:00
|
|
|
|
if let Some(lev_candidate) = lev_candidate {
|
|
|
|
|
err.span_label(span, format!("did you mean `{}`?", lev_candidate));
|
|
|
|
|
} else {
|
|
|
|
|
err.span_label(span, format!("undeclared label `{}`", name));
|
|
|
|
|
}
|
2016-08-19 20:31:31 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
2015-12-20 21:00:43 +00:00
|
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
|
|
|
|
E0429,
|
|
|
|
|
"{}",
|
|
|
|
|
"`self` imports are only allowed within a { } list")
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
|
2017-12-20 03:53:39 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0430,
|
|
|
|
|
"`self` import can only appear once in an import list");
|
|
|
|
|
err.span_label(span, "can only appear once in an import list");
|
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
|
2017-12-20 03:53:39 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0431,
|
|
|
|
|
"`self` import can only appear in an import list with \
|
|
|
|
|
a non-empty prefix");
|
|
|
|
|
err.span_label(span, "can only appear in an import list with a non-empty prefix");
|
|
|
|
|
err
|
2015-07-14 13:37:52 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::UnresolvedImport(name) => {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
let (span, msg) = match name {
|
|
|
|
|
Some((sp, n, _)) => (sp, format!("unresolved import `{}`", n)),
|
|
|
|
|
None => (span, "unresolved import".to_owned()),
|
2015-07-14 13:37:52 +00:00
|
|
|
|
};
|
2016-08-22 05:57:10 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg);
|
2017-07-23 22:15:45 +00:00
|
|
|
|
if let Some((_, _, p)) = name {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, p);
|
2016-08-22 05:57:10 +00:00
|
|
|
|
}
|
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::FailedToResolve(msg) => {
|
2016-08-11 17:17:12 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0433,
|
|
|
|
|
"failed to resolve. {}", msg);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, msg);
|
2016-08-08 22:26:43 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
|
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
2017-12-20 03:53:39 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
|
|
|
|
E0434,
|
|
|
|
|
"{}",
|
|
|
|
|
"can't capture dynamic environment in a fn item");
|
|
|
|
|
err.help("use the `|| { ... }` closure form instead");
|
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
|
|
|
|
ResolutionError::AttemptToUseNonConstantValueInConstant => {
|
2017-12-20 03:53:39 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0435,
|
|
|
|
|
"attempt to use a non-constant value in a constant");
|
2017-06-22 19:10:56 +00:00
|
|
|
|
err.span_label(span, "non-constant value");
|
2016-08-21 13:13:58 +00:00
|
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2016-07-29 15:19:29 +00:00
|
|
|
|
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
|
2016-08-20 07:26:26 +00:00
|
|
|
|
let shadows_what = PathResolution::new(binding.def()).kind_name();
|
2016-06-03 20:15:00 +00:00
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
|
span,
|
2016-06-03 20:15:00 +00:00
|
|
|
|
E0530,
|
2016-06-03 20:15:00 +00:00
|
|
|
|
"{}s cannot shadow {}s", what_binding, shadows_what);
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("cannot be named the same as a {}", shadows_what));
|
2016-07-29 15:19:29 +00:00
|
|
|
|
let participle = if binding.is_import() { "imported" } else { "defined" };
|
2017-05-04 12:17:23 +00:00
|
|
|
|
let msg = format!("a {} `{}` is {} here", shadows_what, name, participle);
|
2016-07-29 15:19:29 +00:00
|
|
|
|
err.span_label(binding.span, msg);
|
2016-06-03 20:15:00 +00:00
|
|
|
|
err
|
|
|
|
|
}
|
2017-01-25 20:01:11 +00:00
|
|
|
|
ResolutionError::ForwardDeclaredTyParam => {
|
|
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0128,
|
|
|
|
|
"type parameters with a default cannot use \
|
|
|
|
|
forward declared identifiers");
|
2017-12-20 03:53:39 +00:00
|
|
|
|
err.span_label(span, format!("defaulted type parameters cannot be forward declared"));
|
2017-01-25 20:01:11 +00:00
|
|
|
|
err
|
|
|
|
|
}
|
2015-12-23 06:27:20 +00:00
|
|
|
|
}
|
2015-07-13 00:05:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-07 10:50:11 +00:00
|
|
|
|
/// Adjust the impl span so that just the `impl` keyword is taken by removing
|
|
|
|
|
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
|
|
|
|
|
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`)
|
|
|
|
|
///
|
|
|
|
|
/// Attention: The method used is very fragile since it essentially duplicates the work of the
|
|
|
|
|
/// parser. If you need to use this function or something similar, please consider updating the
|
|
|
|
|
/// codemap functions and this function to something more robust.
|
|
|
|
|
fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
|
|
|
|
|
let impl_span = cm.span_until_char(impl_span, '<');
|
|
|
|
|
let impl_span = cm.span_until_whitespace(impl_span);
|
|
|
|
|
impl_span
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-14 05:58:45 +00:00
|
|
|
|
fn generate_fn_name_span(cm: &CodeMap, span: Span) -> Option<Span> {
|
|
|
|
|
let prev_span = cm.span_extend_to_prev_str(span, "fn", true);
|
|
|
|
|
cm.span_to_snippet(prev_span).map(|snippet| {
|
|
|
|
|
let len = snippet.find(|c: char| !c.is_alphanumeric() && c != '_')
|
|
|
|
|
.expect("no label after fn");
|
|
|
|
|
prev_span.with_hi(BytePos(prev_span.lo().0 + len as u32))
|
|
|
|
|
}).ok()
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-07 10:50:11 +00:00
|
|
|
|
/// Take the span of a type parameter in a function signature and try to generate a span for the
|
|
|
|
|
/// function name (with generics) and a new snippet for this span with the pointed type parameter as
|
|
|
|
|
/// a new local type parameter.
|
|
|
|
|
///
|
|
|
|
|
/// For instance:
|
2018-04-04 15:09:58 +00:00
|
|
|
|
/// ```rust,ignore (pseudo-Rust)
|
2018-02-07 10:50:11 +00:00
|
|
|
|
/// // Given span
|
|
|
|
|
/// fn my_function(param: T)
|
2018-04-04 15:09:58 +00:00
|
|
|
|
/// // ^ Original span
|
2018-02-07 10:50:11 +00:00
|
|
|
|
///
|
|
|
|
|
/// // Result
|
|
|
|
|
/// fn my_function(param: T)
|
2018-04-04 15:09:58 +00:00
|
|
|
|
/// // ^^^^^^^^^^^ Generated span with snippet `my_function<T>`
|
2018-02-07 10:50:11 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Attention: The method used is very fragile since it essentially duplicates the work of the
|
|
|
|
|
/// parser. If you need to use this function or something similar, please consider updating the
|
|
|
|
|
/// codemap functions and this function to something more robust.
|
|
|
|
|
fn generate_local_type_param_snippet(cm: &CodeMap, span: Span) -> Option<(Span, String)> {
|
|
|
|
|
// Try to extend the span to the previous "fn" keyword to retrieve the function
|
|
|
|
|
// signature
|
2018-03-14 05:58:45 +00:00
|
|
|
|
let sugg_span = cm.span_extend_to_prev_str(span, "fn", false);
|
2018-02-07 10:50:11 +00:00
|
|
|
|
if sugg_span != span {
|
|
|
|
|
if let Ok(snippet) = cm.span_to_snippet(sugg_span) {
|
|
|
|
|
// Consume the function name
|
2018-03-14 05:58:45 +00:00
|
|
|
|
let mut offset = snippet.find(|c: char| !c.is_alphanumeric() && c != '_')
|
|
|
|
|
.expect("no label after fn");
|
2018-02-07 10:50:11 +00:00
|
|
|
|
|
|
|
|
|
// Consume the generics part of the function signature
|
|
|
|
|
let mut bracket_counter = 0;
|
|
|
|
|
let mut last_char = None;
|
|
|
|
|
for c in snippet[offset..].chars() {
|
|
|
|
|
match c {
|
|
|
|
|
'<' => bracket_counter += 1,
|
|
|
|
|
'>' => bracket_counter -= 1,
|
|
|
|
|
'(' => if bracket_counter == 0 { break; }
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
offset += c.len_utf8();
|
|
|
|
|
last_char = Some(c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adjust the suggestion span to encompass the function name with its generics
|
|
|
|
|
let sugg_span = sugg_span.with_hi(BytePos(sugg_span.lo().0 + offset as u32));
|
|
|
|
|
|
|
|
|
|
// Prepare the new suggested snippet to append the type parameter that triggered
|
|
|
|
|
// the error in the generics of the function signature
|
|
|
|
|
let mut new_snippet = if last_char == Some('>') {
|
|
|
|
|
format!("{}, ", &snippet[..(offset - '>'.len_utf8())])
|
|
|
|
|
} else {
|
|
|
|
|
format!("{}<", &snippet[..offset])
|
|
|
|
|
};
|
|
|
|
|
new_snippet.push_str(&cm.span_to_snippet(span).unwrap_or("T".to_string()));
|
|
|
|
|
new_snippet.push('>');
|
|
|
|
|
|
|
|
|
|
return Some((sugg_span, new_snippet));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
2014-12-18 17:17:41 +00:00
|
|
|
|
struct BindingInfo {
|
2013-08-31 16:13:04 +00:00
|
|
|
|
span: Span,
|
2013-09-02 01:45:37 +00:00
|
|
|
|
binding_mode: BindingMode,
|
2012-08-06 14:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// Map from the name in a pattern to its binding mode.
|
2016-11-08 03:02:55 +00:00
|
|
|
|
type BindingMap = FxHashMap<Ident, BindingInfo>;
|
2012-08-06 14:20:23 +00:00
|
|
|
|
|
2016-06-03 20:15:00 +00:00
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
|
enum PatternSource {
|
|
|
|
|
Match,
|
|
|
|
|
IfLet,
|
|
|
|
|
WhileLet,
|
|
|
|
|
Let,
|
|
|
|
|
For,
|
|
|
|
|
FnParam,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PatternSource {
|
|
|
|
|
fn descr(self) -> &'static str {
|
|
|
|
|
match self {
|
|
|
|
|
PatternSource::Match => "match binding",
|
|
|
|
|
PatternSource::IfLet => "if let binding",
|
|
|
|
|
PatternSource::WhileLet => "while let binding",
|
|
|
|
|
PatternSource::Let => "let binding",
|
|
|
|
|
PatternSource::For => "for binding",
|
|
|
|
|
PatternSource::FnParam => "function parameter",
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 06:56:22 +00:00
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
|
enum AliasPossibility {
|
|
|
|
|
No,
|
|
|
|
|
Maybe,
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
|
enum PathSource<'a> {
|
|
|
|
|
// Type paths `Path`.
|
|
|
|
|
Type,
|
|
|
|
|
// Trait paths in bounds or impls.
|
2017-12-13 06:56:22 +00:00
|
|
|
|
Trait(AliasPossibility),
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Expression paths `path`, with optional parent context.
|
2017-03-08 19:15:12 +00:00
|
|
|
|
Expr(Option<&'a Expr>),
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Paths in path patterns `Path`.
|
|
|
|
|
Pat,
|
|
|
|
|
// Paths in struct expressions and patterns `Path { .. }`.
|
|
|
|
|
Struct,
|
|
|
|
|
// Paths in tuple struct patterns `Path(..)`.
|
|
|
|
|
TupleStruct,
|
|
|
|
|
// `m::A::B` in `<T as m::A>::B::C`.
|
|
|
|
|
TraitItem(Namespace),
|
|
|
|
|
// Path in `pub(path)`
|
|
|
|
|
Visibility,
|
|
|
|
|
// Path in `use a::b::{...};`
|
|
|
|
|
ImportPrefix,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> PathSource<'a> {
|
|
|
|
|
fn namespace(self) -> Namespace {
|
|
|
|
|
match self {
|
2017-12-13 06:56:22 +00:00
|
|
|
|
PathSource::Type | PathSource::Trait(_) | PathSource::Struct |
|
2016-11-30 22:35:25 +00:00
|
|
|
|
PathSource::Visibility | PathSource::ImportPrefix => TypeNS,
|
|
|
|
|
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
|
|
|
|
|
PathSource::TraitItem(ns) => ns,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn global_by_default(self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
PathSource::Visibility | PathSource::ImportPrefix => true,
|
|
|
|
|
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
|
|
|
|
|
PathSource::Struct | PathSource::TupleStruct |
|
2017-12-13 06:56:22 +00:00
|
|
|
|
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn defer_to_typeck(self) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
|
|
|
|
|
PathSource::Struct | PathSource::TupleStruct => true,
|
2017-12-13 06:56:22 +00:00
|
|
|
|
PathSource::Trait(_) | PathSource::TraitItem(..) |
|
2016-11-30 22:35:25 +00:00
|
|
|
|
PathSource::Visibility | PathSource::ImportPrefix => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn descr_expected(self) -> &'static str {
|
|
|
|
|
match self {
|
|
|
|
|
PathSource::Type => "type",
|
2017-12-13 06:56:22 +00:00
|
|
|
|
PathSource::Trait(_) => "trait",
|
2016-11-30 22:35:25 +00:00
|
|
|
|
PathSource::Pat => "unit struct/variant or constant",
|
|
|
|
|
PathSource::Struct => "struct, variant or union type",
|
|
|
|
|
PathSource::TupleStruct => "tuple struct/variant",
|
|
|
|
|
PathSource::Visibility => "module",
|
|
|
|
|
PathSource::ImportPrefix => "module or enum",
|
|
|
|
|
PathSource::TraitItem(ns) => match ns {
|
|
|
|
|
TypeNS => "associated type",
|
|
|
|
|
ValueNS => "method or associated constant",
|
|
|
|
|
MacroNS => bug!("associated macro"),
|
|
|
|
|
},
|
2017-03-08 19:15:12 +00:00
|
|
|
|
PathSource::Expr(parent) => match parent.map(|p| &p.node) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// "function" here means "anything callable" rather than `Def::Fn`,
|
|
|
|
|
// this is not precise but usually more helpful than just "value".
|
|
|
|
|
Some(&ExprKind::Call(..)) => "function",
|
|
|
|
|
_ => "value",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_expected(self, def: Def) -> bool {
|
|
|
|
|
match self {
|
|
|
|
|
PathSource::Type => match def {
|
|
|
|
|
Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
|
|
|
|
|
Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
|
2017-09-03 18:53:58 +00:00
|
|
|
|
Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
|
|
|
|
|
Def::TyForeign(..) => true,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
_ => false,
|
|
|
|
|
},
|
2017-12-13 06:56:22 +00:00
|
|
|
|
PathSource::Trait(AliasPossibility::No) => match def {
|
|
|
|
|
Def::Trait(..) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::Trait(AliasPossibility::Maybe) => match def {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
Def::Trait(..) => true,
|
2017-10-02 13:48:57 +00:00
|
|
|
|
Def::TraitAlias(..) => true,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::Expr(..) => match def {
|
|
|
|
|
Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
|
|
|
|
|
Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
|
|
|
|
|
Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
|
|
|
|
|
Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::Pat => match def {
|
|
|
|
|
Def::StructCtor(_, CtorKind::Const) |
|
|
|
|
|
Def::VariantCtor(_, CtorKind::Const) |
|
|
|
|
|
Def::Const(..) | Def::AssociatedConst(..) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::TupleStruct => match def {
|
|
|
|
|
Def::StructCtor(_, CtorKind::Fn) | Def::VariantCtor(_, CtorKind::Fn) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::Struct => match def {
|
|
|
|
|
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
|
|
|
|
|
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::TraitItem(ns) => match def {
|
|
|
|
|
Def::AssociatedConst(..) | Def::Method(..) if ns == ValueNS => true,
|
|
|
|
|
Def::AssociatedTy(..) if ns == TypeNS => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::ImportPrefix => match def {
|
|
|
|
|
Def::Mod(..) | Def::Enum(..) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
PathSource::Visibility => match def {
|
|
|
|
|
Def::Mod(..) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
|
|
|
|
|
__diagnostic_used!(E0404);
|
|
|
|
|
__diagnostic_used!(E0405);
|
|
|
|
|
__diagnostic_used!(E0412);
|
|
|
|
|
__diagnostic_used!(E0422);
|
|
|
|
|
__diagnostic_used!(E0423);
|
|
|
|
|
__diagnostic_used!(E0425);
|
|
|
|
|
__diagnostic_used!(E0531);
|
|
|
|
|
__diagnostic_used!(E0532);
|
|
|
|
|
__diagnostic_used!(E0573);
|
|
|
|
|
__diagnostic_used!(E0574);
|
|
|
|
|
__diagnostic_used!(E0575);
|
|
|
|
|
__diagnostic_used!(E0576);
|
|
|
|
|
__diagnostic_used!(E0577);
|
|
|
|
|
__diagnostic_used!(E0578);
|
|
|
|
|
match (self, has_unexpected_resolution) {
|
2017-12-13 06:56:22 +00:00
|
|
|
|
(PathSource::Trait(_), true) => "E0404",
|
|
|
|
|
(PathSource::Trait(_), false) => "E0405",
|
2016-11-30 22:35:25 +00:00
|
|
|
|
(PathSource::Type, true) => "E0573",
|
|
|
|
|
(PathSource::Type, false) => "E0412",
|
|
|
|
|
(PathSource::Struct, true) => "E0574",
|
|
|
|
|
(PathSource::Struct, false) => "E0422",
|
|
|
|
|
(PathSource::Expr(..), true) => "E0423",
|
|
|
|
|
(PathSource::Expr(..), false) => "E0425",
|
|
|
|
|
(PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
|
|
|
|
|
(PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
|
|
|
|
|
(PathSource::TraitItem(..), true) => "E0575",
|
|
|
|
|
(PathSource::TraitItem(..), false) => "E0576",
|
|
|
|
|
(PathSource::Visibility, true) | (PathSource::ImportPrefix, true) => "E0577",
|
|
|
|
|
(PathSource::Visibility, false) | (PathSource::ImportPrefix, false) => "E0578",
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// Different kinds of symbols don't influence each other.
|
|
|
|
|
///
|
|
|
|
|
/// Therefore, they have a separate universe (namespace).
|
2017-07-29 23:28:30 +00:00
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
2015-05-14 11:40:16 +00:00
|
|
|
|
pub enum Namespace {
|
2012-05-22 17:54:12 +00:00
|
|
|
|
TypeNS,
|
2015-10-26 19:31:11 +00:00
|
|
|
|
ValueNS,
|
2016-10-25 22:05:02 +00:00
|
|
|
|
MacroNS,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// Just a helper ‒ separate structure for each namespace.
|
2016-11-10 06:19:54 +00:00
|
|
|
|
#[derive(Clone, Default, Debug)]
|
|
|
|
|
pub struct PerNS<T> {
|
|
|
|
|
value_ns: T,
|
|
|
|
|
type_ns: T,
|
2018-04-29 23:20:14 +00:00
|
|
|
|
macro_ns: T,
|
2016-11-10 06:19:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
|
|
|
|
|
type Output = T;
|
|
|
|
|
fn index(&self, ns: Namespace) -> &T {
|
|
|
|
|
match ns {
|
|
|
|
|
ValueNS => &self.value_ns,
|
|
|
|
|
TypeNS => &self.type_ns,
|
2018-04-29 23:20:14 +00:00
|
|
|
|
MacroNS => &self.macro_ns,
|
2016-11-10 06:19:54 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
|
|
|
|
|
fn index_mut(&mut self, ns: Namespace) -> &mut T {
|
|
|
|
|
match ns {
|
|
|
|
|
ValueNS => &mut self.value_ns,
|
|
|
|
|
TypeNS => &mut self.type_ns,
|
2018-04-29 23:20:14 +00:00
|
|
|
|
MacroNS => &mut self.macro_ns,
|
2016-11-10 06:19:54 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-17 09:03:59 +00:00
|
|
|
|
struct UsePlacementFinder {
|
|
|
|
|
target_module: NodeId,
|
|
|
|
|
span: Option<Span>,
|
2017-08-18 10:46:28 +00:00
|
|
|
|
found_use: bool,
|
2017-08-17 09:03:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-16 12:14:22 +00:00
|
|
|
|
impl UsePlacementFinder {
|
|
|
|
|
fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, bool) {
|
|
|
|
|
let mut finder = UsePlacementFinder {
|
|
|
|
|
target_module,
|
|
|
|
|
span: None,
|
|
|
|
|
found_use: false,
|
|
|
|
|
};
|
|
|
|
|
visit::walk_crate(&mut finder, krate);
|
|
|
|
|
(finder.span, finder.found_use)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-17 09:03:59 +00:00
|
|
|
|
impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
|
|
|
|
|
fn visit_mod(
|
|
|
|
|
&mut self,
|
|
|
|
|
module: &'tcx ast::Mod,
|
|
|
|
|
_: Span,
|
|
|
|
|
_: &[ast::Attribute],
|
|
|
|
|
node_id: NodeId,
|
|
|
|
|
) {
|
|
|
|
|
if self.span.is_some() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if node_id != self.target_module {
|
|
|
|
|
visit::walk_mod(self, module);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// find a use statement
|
|
|
|
|
for item in &module.items {
|
|
|
|
|
match item.node {
|
|
|
|
|
ItemKind::Use(..) => {
|
|
|
|
|
// don't suggest placing a use before the prelude
|
|
|
|
|
// import or other generated ones
|
2017-08-31 13:45:16 +00:00
|
|
|
|
if item.span.ctxt().outer().expn_info().is_none() {
|
2018-03-10 14:45:47 +00:00
|
|
|
|
self.span = Some(item.span.shrink_to_lo());
|
2017-08-18 10:46:28 +00:00
|
|
|
|
self.found_use = true;
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// don't place use before extern crate
|
|
|
|
|
ItemKind::ExternCrate(_) => {}
|
|
|
|
|
// but place them before the first other item
|
|
|
|
|
_ => if self.span.map_or(true, |span| item.span < span ) {
|
2017-08-31 13:45:16 +00:00
|
|
|
|
if item.span.ctxt().outer().expn_info().is_none() {
|
|
|
|
|
// don't insert between attributes and an item
|
|
|
|
|
if item.attrs.is_empty() {
|
2018-03-10 14:45:47 +00:00
|
|
|
|
self.span = Some(item.span.shrink_to_lo());
|
2017-08-31 13:45:16 +00:00
|
|
|
|
} else {
|
|
|
|
|
// find the first attribute on the item
|
|
|
|
|
for attr in &item.attrs {
|
|
|
|
|
if self.span.map_or(true, |span| attr.span < span) {
|
2018-03-10 14:45:47 +00:00
|
|
|
|
self.span = Some(attr.span.shrink_to_lo());
|
2017-08-31 13:45:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-17 09:03:59 +00:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes.
|
2016-12-06 10:26:52 +00:00
|
|
|
|
impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
|
|
|
|
fn visit_item(&mut self, item: &'tcx Item) {
|
2013-09-27 02:10:16 +00:00
|
|
|
|
self.resolve_item(item);
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_arm(&mut self, arm: &'tcx Arm) {
|
2013-09-27 02:10:16 +00:00
|
|
|
|
self.resolve_arm(arm);
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_block(&mut self, block: &'tcx Block) {
|
2013-09-27 02:10:16 +00:00
|
|
|
|
self.resolve_block(block);
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2018-05-17 18:28:50 +00:00
|
|
|
|
fn visit_anon_const(&mut self, constant: &'tcx ast::AnonConst) {
|
|
|
|
|
self.with_constant_rib(|this| {
|
|
|
|
|
visit::walk_anon_const(this, constant);
|
|
|
|
|
});
|
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
2016-04-24 21:10:54 +00:00
|
|
|
|
self.resolve_expr(expr, None);
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_local(&mut self, local: &'tcx Local) {
|
2013-09-27 02:10:16 +00:00
|
|
|
|
self.resolve_local(local);
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_ty(&mut self, ty: &'tcx Ty) {
|
2017-07-18 18:41:21 +00:00
|
|
|
|
match ty.node {
|
|
|
|
|
TyKind::Path(ref qself, ref path) => {
|
|
|
|
|
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
|
|
|
|
|
}
|
|
|
|
|
TyKind::ImplicitSelf => {
|
|
|
|
|
let self_ty = keywords::SelfType.ident();
|
|
|
|
|
let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, true, ty.span)
|
|
|
|
|
.map_or(Def::Err, |d| d.def());
|
|
|
|
|
self.record_def(ty.id, PathResolution::new(def));
|
|
|
|
|
}
|
|
|
|
|
_ => (),
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
visit::walk_ty(self, ty);
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_poly_trait_ref(&mut self,
|
|
|
|
|
tref: &'tcx ast::PolyTraitRef,
|
|
|
|
|
m: &'tcx ast::TraitBoundModifier) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
self.smart_resolve_path(tref.trait_ref.ref_id, None,
|
2017-12-13 06:56:22 +00:00
|
|
|
|
&tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_poly_trait_ref(self, tref, m);
|
2015-02-05 07:19:07 +00:00
|
|
|
|
}
|
2016-12-06 10:26:52 +00:00
|
|
|
|
fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
|
2015-02-05 07:19:07 +00:00
|
|
|
|
let type_parameters = match foreign_item.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
ForeignItemKind::Fn(_, ref generics) => {
|
2016-08-14 22:07:09 +00:00
|
|
|
|
HasTypeParameters(generics, ItemRibKind)
|
2015-02-05 07:19:07 +00:00
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
|
ForeignItemKind::Static(..) => NoTypeParameters,
|
2017-09-03 18:53:58 +00:00
|
|
|
|
ForeignItemKind::Ty => NoTypeParameters,
|
2018-03-11 02:16:26 +00:00
|
|
|
|
ForeignItemKind::Macro(..) => NoTypeParameters,
|
2015-02-05 07:19:07 +00:00
|
|
|
|
};
|
|
|
|
|
self.with_type_parameter_rib(type_parameters, |this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_foreign_item(this, foreign_item);
|
2015-02-05 07:19:07 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
fn visit_fn(&mut self,
|
2016-12-06 10:26:52 +00:00
|
|
|
|
function_kind: FnKind<'tcx>,
|
|
|
|
|
declaration: &'tcx FnDecl,
|
2015-02-05 07:19:07 +00:00
|
|
|
|
_: Span,
|
|
|
|
|
node_id: NodeId) {
|
|
|
|
|
let rib_kind = match function_kind {
|
2017-10-10 21:56:24 +00:00
|
|
|
|
FnKind::ItemFn(..) => {
|
2015-02-05 07:19:07 +00:00
|
|
|
|
ItemRibKind
|
|
|
|
|
}
|
2017-11-22 18:15:05 +00:00
|
|
|
|
FnKind::Method(_, _, _, _) => {
|
|
|
|
|
TraitOrImplItemRibKind
|
2015-02-05 07:19:07 +00:00
|
|
|
|
}
|
2016-10-25 23:17:29 +00:00
|
|
|
|
FnKind::Closure(_) => ClosureRibKind(node_id),
|
2015-02-05 07:19:07 +00:00
|
|
|
|
};
|
2016-10-25 23:17:29 +00:00
|
|
|
|
|
|
|
|
|
// Create a value rib for the function.
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(rib_kind));
|
2016-10-25 23:17:29 +00:00
|
|
|
|
|
|
|
|
|
// Create a label rib for the function.
|
|
|
|
|
self.label_ribs.push(Rib::new(rib_kind));
|
|
|
|
|
|
|
|
|
|
// Add each argument to the rib.
|
|
|
|
|
let mut bindings_list = FxHashMap();
|
|
|
|
|
for argument in &declaration.inputs {
|
|
|
|
|
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
|
|
|
|
|
|
|
|
|
|
self.visit_ty(&argument.ty);
|
|
|
|
|
|
|
|
|
|
debug!("(resolving function) recorded argument");
|
|
|
|
|
}
|
|
|
|
|
visit::walk_fn_ret_ty(self, &declaration.output);
|
|
|
|
|
|
|
|
|
|
// Resolve the function body.
|
|
|
|
|
match function_kind {
|
|
|
|
|
FnKind::ItemFn(.., body) |
|
|
|
|
|
FnKind::Method(.., body) => {
|
|
|
|
|
self.visit_block(body);
|
|
|
|
|
}
|
|
|
|
|
FnKind::Closure(body) => {
|
|
|
|
|
self.visit_expr(body);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
debug!("(resolving function) leaving function");
|
|
|
|
|
|
|
|
|
|
self.label_ribs.pop();
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2015-02-05 07:19:07 +00:00
|
|
|
|
}
|
2017-01-25 20:01:11 +00:00
|
|
|
|
fn visit_generics(&mut self, generics: &'tcx Generics) {
|
|
|
|
|
// For type parameter defaults, we have to ban access
|
|
|
|
|
// to following type parameters, as the Substs can only
|
2018-02-18 17:01:33 +00:00
|
|
|
|
// provide previous type parameters as they're built. We
|
|
|
|
|
// put all the parameters on the ban list and then remove
|
|
|
|
|
// them one by one as they are processed and become available.
|
2017-01-25 20:01:11 +00:00
|
|
|
|
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
|
2017-10-16 19:07:26 +00:00
|
|
|
|
default_ban_rib.bindings.extend(generics.params.iter()
|
|
|
|
|
.filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None })
|
2017-01-25 20:01:11 +00:00
|
|
|
|
.skip_while(|p| p.default.is_none())
|
|
|
|
|
.map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
|
|
|
|
|
|
2017-10-16 19:07:26 +00:00
|
|
|
|
for param in &generics.params {
|
|
|
|
|
match *param {
|
|
|
|
|
GenericParam::Lifetime(_) => self.visit_generic_param(param),
|
|
|
|
|
GenericParam::Type(ref ty_param) => {
|
|
|
|
|
for bound in &ty_param.bounds {
|
|
|
|
|
self.visit_ty_param_bound(bound);
|
|
|
|
|
}
|
2017-01-25 20:01:11 +00:00
|
|
|
|
|
2017-10-16 19:07:26 +00:00
|
|
|
|
if let Some(ref ty) = ty_param.default {
|
|
|
|
|
self.ribs[TypeNS].push(default_ban_rib);
|
|
|
|
|
self.visit_ty(ty);
|
|
|
|
|
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
|
|
|
|
|
}
|
2017-01-25 20:01:11 +00:00
|
|
|
|
|
2017-10-16 19:07:26 +00:00
|
|
|
|
// Allow all following defaults to refer to this type parameter.
|
|
|
|
|
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name));
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-01-25 20:01:11 +00:00
|
|
|
|
}
|
|
|
|
|
for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
|
|
|
|
|
}
|
2013-08-13 16:52:41 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
|
#[derive(Copy, Clone)]
|
2016-04-24 03:26:10 +00:00
|
|
|
|
enum TypeParameters<'a, 'b> {
|
2014-05-31 22:53:13 +00:00
|
|
|
|
NoTypeParameters,
|
2015-10-26 19:31:11 +00:00
|
|
|
|
HasTypeParameters(// Type parameters.
|
2016-04-24 03:26:10 +00:00
|
|
|
|
&'b Generics,
|
2014-05-31 22:53:13 +00:00
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
|
// The kind of the rib used for type parameters.
|
2016-04-24 03:26:10 +00:00
|
|
|
|
RibKind<'a>),
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The rib kind controls the translation of local
|
|
|
|
|
/// definitions (`Def::Local`) to upvars (`Def::Upvar`).
|
2015-03-30 13:38:44 +00:00
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
2016-01-22 09:55:29 +00:00
|
|
|
|
enum RibKind<'a> {
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// No translation needs to be applied.
|
2012-05-22 17:54:12 +00:00
|
|
|
|
NormalRibKind,
|
2012-07-07 02:06:58 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// We passed through a closure scope at the given node ID.
|
|
|
|
|
/// Translate upvars as appropriate.
|
2015-01-24 20:04:41 +00:00
|
|
|
|
ClosureRibKind(NodeId /* func id */),
|
2012-07-07 02:06:58 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// We passed through an impl or trait and are now in one of its
|
|
|
|
|
/// methods or associated types. Allow references to ty params that impl or trait
|
|
|
|
|
/// binds. Disallow any other upvars (including other ty params that are
|
|
|
|
|
/// upvars).
|
2017-11-22 18:15:05 +00:00
|
|
|
|
TraitOrImplItemRibKind,
|
2012-07-26 21:04:03 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// We passed through an item scope. Disallow upvars.
|
2014-05-31 05:54:04 +00:00
|
|
|
|
ItemRibKind,
|
2012-10-15 19:27:09 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// We're in a constant item. Can't refer to dynamic stuff.
|
2015-10-26 19:31:11 +00:00
|
|
|
|
ConstantItemRibKind,
|
2016-01-22 09:55:29 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// We passed through a module.
|
2016-02-24 04:48:31 +00:00
|
|
|
|
ModuleRibKind(Module<'a>),
|
2016-06-26 03:32:45 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// We passed through a `macro_rules!` statement
|
2017-03-01 23:48:16 +00:00
|
|
|
|
MacroDefinition(DefId),
|
2017-01-25 20:01:11 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// All bindings in this rib are type parameters that can't be used
|
|
|
|
|
/// from the default of a type parameter because they're not declared
|
|
|
|
|
/// before said type parameter. Also see the `visit_generics` override.
|
2017-01-25 20:01:11 +00:00
|
|
|
|
ForwardTyParamBanRibKind,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-15 02:20:56 +00:00
|
|
|
|
/// One local scope.
|
2018-02-18 17:01:33 +00:00
|
|
|
|
///
|
|
|
|
|
/// A rib represents a scope names can live in. Note that these appear in many places, not just
|
|
|
|
|
/// around braces. At any place where the list of accessible names (of the given namespace)
|
2018-03-24 16:07:58 +00:00
|
|
|
|
/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
|
|
|
|
|
/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
|
|
|
|
|
/// etc.
|
2018-02-18 17:01:33 +00:00
|
|
|
|
///
|
|
|
|
|
/// Different [rib kinds](enum.RibKind) are transparent for different names.
|
|
|
|
|
///
|
|
|
|
|
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
|
|
|
|
|
/// resolving, the name is looked up from inside out.
|
2015-01-28 13:34:18 +00:00
|
|
|
|
#[derive(Debug)]
|
2016-01-22 09:55:29 +00:00
|
|
|
|
struct Rib<'a> {
|
2016-11-08 03:02:55 +00:00
|
|
|
|
bindings: FxHashMap<Ident, Def>,
|
2016-01-22 09:55:29 +00:00
|
|
|
|
kind: RibKind<'a>,
|
2012-09-05 22:58:43 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
|
impl<'a> Rib<'a> {
|
|
|
|
|
fn new(kind: RibKind<'a>) -> Rib<'a> {
|
2013-08-31 16:13:04 +00:00
|
|
|
|
Rib {
|
2016-11-08 03:02:55 +00:00
|
|
|
|
bindings: FxHashMap(),
|
2017-08-07 05:54:09 +00:00
|
|
|
|
kind,
|
2013-08-31 16:13:04 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// An intermediate resolution result.
|
|
|
|
|
///
|
|
|
|
|
/// This refers to the thing referred by a name. The difference between `Def` and `Item` is that
|
|
|
|
|
/// items are visible in their whole block, while defs only from the place they are defined
|
|
|
|
|
/// forward.
|
2016-03-12 08:03:13 +00:00
|
|
|
|
enum LexicalScopeBinding<'a> {
|
|
|
|
|
Item(&'a NameBinding<'a>),
|
2016-11-25 06:07:21 +00:00
|
|
|
|
Def(Def),
|
2016-03-12 08:03:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-12 08:17:56 +00:00
|
|
|
|
impl<'a> LexicalScopeBinding<'a> {
|
2016-07-29 15:19:29 +00:00
|
|
|
|
fn item(self) -> Option<&'a NameBinding<'a>> {
|
2016-03-12 08:17:56 +00:00
|
|
|
|
match self {
|
2016-07-29 15:19:29 +00:00
|
|
|
|
LexicalScopeBinding::Item(binding) => Some(binding),
|
2016-03-12 08:17:56 +00:00
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-04 01:18:11 +00:00
|
|
|
|
|
|
|
|
|
fn def(self) -> Def {
|
|
|
|
|
match self {
|
|
|
|
|
LexicalScopeBinding::Item(binding) => binding.def(),
|
|
|
|
|
LexicalScopeBinding::Def(def) => def,
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-12 08:17:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-02 05:21:11 +00:00
|
|
|
|
#[derive(Clone, Debug)]
|
2016-11-25 06:07:21 +00:00
|
|
|
|
enum PathResult<'a> {
|
|
|
|
|
Module(Module<'a>),
|
|
|
|
|
NonModule(PathResolution),
|
|
|
|
|
Indeterminate,
|
2017-07-23 22:15:45 +00:00
|
|
|
|
Failed(Span, String, bool /* is the error from the last segment? */),
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-18 09:45:06 +00:00
|
|
|
|
enum ModuleKind {
|
2018-03-24 16:07:58 +00:00
|
|
|
|
/// An anonymous module, eg. just a block.
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// fn main() {
|
|
|
|
|
/// fn f() {} // (1)
|
|
|
|
|
/// { // This is an anonymous module
|
|
|
|
|
/// f(); // This resolves to (2) as we are inside the block.
|
|
|
|
|
/// fn f() {} // (2)
|
|
|
|
|
/// }
|
|
|
|
|
/// f(); // Resolves to (1)
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2016-09-18 09:45:06 +00:00
|
|
|
|
Block(NodeId),
|
2018-03-24 16:07:58 +00:00
|
|
|
|
/// Any module with a name.
|
|
|
|
|
///
|
|
|
|
|
/// This could be:
|
2018-02-18 17:01:33 +00:00
|
|
|
|
///
|
2018-03-24 16:07:58 +00:00
|
|
|
|
/// * A normal module ‒ either `mod from_file;` or `mod from_block { }`.
|
|
|
|
|
/// * A trait or an enum (it implicitly contains associated types, methods and variant
|
|
|
|
|
/// constructors).
|
2016-09-18 09:45:06 +00:00
|
|
|
|
Def(Def, Name),
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
|
/// One node in the tree of modules.
|
2016-11-26 12:47:52 +00:00
|
|
|
|
pub struct ModuleData<'a> {
|
2016-09-18 09:45:06 +00:00
|
|
|
|
parent: Option<Module<'a>>,
|
|
|
|
|
kind: ModuleKind,
|
2016-02-02 20:21:24 +00:00
|
|
|
|
|
2016-12-20 08:32:15 +00:00
|
|
|
|
// The def id of the closest normal module (`mod`) ancestor (including this module).
|
|
|
|
|
normal_ancestor_id: DefId,
|
2016-08-22 00:24:11 +00:00
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
|
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
2017-02-06 11:44:38 +00:00
|
|
|
|
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span, MacroKind)>>,
|
2016-12-05 03:51:11 +00:00
|
|
|
|
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-11-11 10:51:15 +00:00
|
|
|
|
// Macro invocations that can expand into items in this module.
|
|
|
|
|
unresolved_invocations: RefCell<FxHashSet<Mark>>,
|
|
|
|
|
|
2016-09-19 05:25:17 +00:00
|
|
|
|
no_implicit_prelude: bool,
|
2016-02-06 23:43:04 +00:00
|
|
|
|
|
2016-08-17 00:42:14 +00:00
|
|
|
|
glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>,
|
2016-03-17 11:05:09 +00:00
|
|
|
|
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
|
2015-08-05 19:47:01 +00:00
|
|
|
|
|
2016-04-18 00:00:18 +00:00
|
|
|
|
// Used to memoize the traits in this module for faster searches through all traits in scope.
|
2016-11-29 02:07:12 +00:00
|
|
|
|
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
|
2016-04-18 00:00:18 +00:00
|
|
|
|
|
2013-08-22 01:39:30 +00:00
|
|
|
|
// Whether this module is populated. If not populated, any attempt to
|
|
|
|
|
// access the children must be preceded with a
|
|
|
|
|
// `populate_module_if_necessary` call.
|
2013-12-20 02:53:59 +00:00
|
|
|
|
populated: Cell<bool>,
|
2017-05-10 11:19:29 +00:00
|
|
|
|
|
|
|
|
|
/// Span of the module itself. Used for error reporting.
|
|
|
|
|
span: Span,
|
2017-03-22 08:39:51 +00:00
|
|
|
|
|
|
|
|
|
expansion: Mark,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-19 00:09:55 +00:00
|
|
|
|
type Module<'a> = &'a ModuleData<'a>;
|
2016-01-11 21:19:29 +00:00
|
|
|
|
|
2016-11-26 12:47:52 +00:00
|
|
|
|
impl<'a> ModuleData<'a> {
|
2017-05-10 11:58:41 +00:00
|
|
|
|
fn new(parent: Option<Module<'a>>,
|
|
|
|
|
kind: ModuleKind,
|
|
|
|
|
normal_ancestor_id: DefId,
|
2017-03-22 08:39:51 +00:00
|
|
|
|
expansion: Mark,
|
2017-05-10 11:58:41 +00:00
|
|
|
|
span: Span) -> Self {
|
2016-11-26 12:47:52 +00:00
|
|
|
|
ModuleData {
|
2017-08-07 05:54:09 +00:00
|
|
|
|
parent,
|
|
|
|
|
kind,
|
|
|
|
|
normal_ancestor_id,
|
2016-11-08 03:02:55 +00:00
|
|
|
|
resolutions: RefCell::new(FxHashMap()),
|
2016-11-10 10:29:36 +00:00
|
|
|
|
legacy_macro_resolutions: RefCell::new(Vec::new()),
|
2016-11-27 10:58:46 +00:00
|
|
|
|
macro_resolutions: RefCell::new(Vec::new()),
|
2016-11-11 10:51:15 +00:00
|
|
|
|
unresolved_invocations: RefCell::new(FxHashSet()),
|
2016-09-19 05:25:17 +00:00
|
|
|
|
no_implicit_prelude: false,
|
2016-02-16 03:54:14 +00:00
|
|
|
|
glob_importers: RefCell::new(Vec::new()),
|
2017-12-24 03:28:33 +00:00
|
|
|
|
globs: RefCell::new(Vec::new()),
|
2016-04-18 00:00:18 +00:00
|
|
|
|
traits: RefCell::new(None),
|
2016-12-20 08:32:15 +00:00
|
|
|
|
populated: Cell::new(normal_ancestor_id.is_local()),
|
2017-08-07 05:54:09 +00:00
|
|
|
|
span,
|
|
|
|
|
expansion,
|
2016-01-11 21:19:29 +00:00
|
|
|
|
}
|
2012-09-05 22:58:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
|
fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
|
|
|
|
|
for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() {
|
|
|
|
|
name_resolution.borrow().binding.map(|binding| f(ident, ns, binding));
|
2016-02-07 23:58:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-29 23:28:30 +00:00
|
|
|
|
fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
|
|
|
|
|
let resolutions = self.resolutions.borrow();
|
2018-03-30 09:40:25 +00:00
|
|
|
|
let mut resolutions = resolutions.iter().collect::<Vec<_>>();
|
|
|
|
|
resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.name.as_str(), ns));
|
|
|
|
|
for &(&(ident, ns), &resolution) in resolutions.iter() {
|
2017-07-29 23:28:30 +00:00
|
|
|
|
resolution.borrow().binding.map(|binding| f(ident, ns, binding));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-18 09:45:06 +00:00
|
|
|
|
fn def(&self) -> Option<Def> {
|
|
|
|
|
match self.kind {
|
|
|
|
|
ModuleKind::Def(def, _) => Some(def),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-16 07:59:50 +00:00
|
|
|
|
fn def_id(&self) -> Option<DefId> {
|
2016-09-18 09:45:06 +00:00
|
|
|
|
self.def().as_ref().map(Def::def_id)
|
2015-11-16 07:59:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-09 23:19:53 +00:00
|
|
|
|
// `self` resolves to the first module ancestor that `is_normal`.
|
2015-11-16 07:59:50 +00:00
|
|
|
|
fn is_normal(&self) -> bool {
|
2016-09-18 09:45:06 +00:00
|
|
|
|
match self.kind {
|
|
|
|
|
ModuleKind::Def(Def::Mod(_), _) => true,
|
2015-11-16 07:59:50 +00:00
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_trait(&self) -> bool {
|
2016-09-18 09:45:06 +00:00
|
|
|
|
match self.kind {
|
|
|
|
|
ModuleKind::Def(Def::Trait(_), _) => true,
|
2015-11-16 07:59:50 +00:00
|
|
|
|
_ => false,
|
2013-08-31 16:13:04 +00:00
|
|
|
|
}
|
2012-09-05 22:58:43 +00:00
|
|
|
|
}
|
2016-10-22 22:08:08 +00:00
|
|
|
|
|
|
|
|
|
fn is_local(&self) -> bool {
|
2016-12-20 08:32:15 +00:00
|
|
|
|
self.normal_ancestor_id.is_local()
|
2016-10-22 22:08:08 +00:00
|
|
|
|
}
|
2017-03-27 05:22:18 +00:00
|
|
|
|
|
|
|
|
|
fn nearest_item_scope(&'a self) -> Module<'a> {
|
|
|
|
|
if self.is_trait() { self.parent.unwrap() } else { self }
|
|
|
|
|
}
|
2015-08-06 10:47:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-26 12:47:52 +00:00
|
|
|
|
impl<'a> fmt::Debug for ModuleData<'a> {
|
2014-11-28 02:41:16 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2016-09-18 09:45:06 +00:00
|
|
|
|
write!(f, "{:?}", self.def())
|
2014-11-28 02:41:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// Records a possibly-private value, type, or module definition.
|
2016-02-15 05:18:55 +00:00
|
|
|
|
#[derive(Clone, Debug)]
|
2016-01-14 01:42:45 +00:00
|
|
|
|
pub struct NameBinding<'a> {
|
2016-02-07 21:34:23 +00:00
|
|
|
|
kind: NameBindingKind<'a>,
|
2016-11-07 22:23:26 +00:00
|
|
|
|
expansion: Mark,
|
2016-04-27 01:13:15 +00:00
|
|
|
|
span: Span,
|
2016-04-09 23:19:53 +00:00
|
|
|
|
vis: ty::Visibility,
|
2012-08-18 00:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 02:34:01 +00:00
|
|
|
|
pub trait ToNameBinding<'a> {
|
2016-11-29 02:53:00 +00:00
|
|
|
|
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>;
|
2016-07-28 02:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-29 02:53:00 +00:00
|
|
|
|
impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
|
|
|
|
|
fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
2016-07-28 02:34:01 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 05:18:55 +00:00
|
|
|
|
#[derive(Clone, Debug)]
|
2016-02-07 21:34:23 +00:00
|
|
|
|
enum NameBindingKind<'a> {
|
2015-11-17 09:10:41 +00:00
|
|
|
|
Def(Def),
|
2016-01-11 21:19:29 +00:00
|
|
|
|
Module(Module<'a>),
|
2016-02-07 21:34:23 +00:00
|
|
|
|
Import {
|
|
|
|
|
binding: &'a NameBinding<'a>,
|
2016-04-17 01:57:09 +00:00
|
|
|
|
directive: &'a ImportDirective<'a>,
|
2016-09-05 05:27:58 +00:00
|
|
|
|
used: Cell<bool>,
|
2016-02-07 21:34:23 +00:00
|
|
|
|
},
|
2016-08-20 05:23:19 +00:00
|
|
|
|
Ambiguity {
|
|
|
|
|
b1: &'a NameBinding<'a>,
|
|
|
|
|
b2: &'a NameBinding<'a>,
|
|
|
|
|
}
|
2012-09-08 02:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-25 04:40:46 +00:00
|
|
|
|
struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
|
|
|
|
|
|
2017-08-17 09:03:59 +00:00
|
|
|
|
struct UseError<'a> {
|
|
|
|
|
err: DiagnosticBuilder<'a>,
|
|
|
|
|
/// Attach `use` statements for these candidates
|
|
|
|
|
candidates: Vec<ImportSuggestion>,
|
|
|
|
|
/// The node id of the module to place the use statements in
|
|
|
|
|
node_id: NodeId,
|
|
|
|
|
/// Whether the diagnostic should state that it's "better"
|
|
|
|
|
better: bool,
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 03:47:11 +00:00
|
|
|
|
struct AmbiguityError<'a> {
|
|
|
|
|
span: Span,
|
|
|
|
|
name: Name,
|
2016-11-10 10:29:36 +00:00
|
|
|
|
lexical: bool,
|
2016-09-06 03:47:11 +00:00
|
|
|
|
b1: &'a NameBinding<'a>,
|
|
|
|
|
b2: &'a NameBinding<'a>,
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
|
impl<'a> NameBinding<'a> {
|
2016-11-27 00:23:54 +00:00
|
|
|
|
fn module(&self) -> Option<Module<'a>> {
|
2016-02-07 21:34:23 +00:00
|
|
|
|
match self.kind {
|
2016-11-27 00:23:54 +00:00
|
|
|
|
NameBindingKind::Module(module) => Some(module),
|
2016-02-07 21:34:23 +00:00
|
|
|
|
NameBindingKind::Import { binding, .. } => binding.module(),
|
2016-11-27 00:23:54 +00:00
|
|
|
|
_ => None,
|
2013-05-13 23:13:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 07:26:26 +00:00
|
|
|
|
fn def(&self) -> Def {
|
2016-02-07 21:34:23 +00:00
|
|
|
|
match self.kind {
|
2016-08-20 07:26:26 +00:00
|
|
|
|
NameBindingKind::Def(def) => def,
|
2016-09-18 09:45:06 +00:00
|
|
|
|
NameBindingKind::Module(module) => module.def().unwrap(),
|
2016-02-07 21:34:23 +00:00
|
|
|
|
NameBindingKind::Import { binding, .. } => binding.def(),
|
2016-08-20 05:23:19 +00:00
|
|
|
|
NameBindingKind::Ambiguity { .. } => Def::Err,
|
2012-10-16 01:04:15 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2012-10-15 21:56:42 +00:00
|
|
|
|
|
2017-03-01 23:48:16 +00:00
|
|
|
|
fn def_ignoring_ambiguity(&self) -> Def {
|
2016-11-27 10:27:41 +00:00
|
|
|
|
match self.kind {
|
2017-03-01 23:48:16 +00:00
|
|
|
|
NameBindingKind::Import { binding, .. } => binding.def_ignoring_ambiguity(),
|
|
|
|
|
NameBindingKind::Ambiguity { b1, .. } => b1.def_ignoring_ambiguity(),
|
|
|
|
|
_ => self.def(),
|
2016-11-27 10:27:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-27 16:11:14 +00:00
|
|
|
|
fn get_macro(&self, resolver: &mut Resolver<'a>) -> Lrc<SyntaxExtension> {
|
2017-03-01 23:48:16 +00:00
|
|
|
|
resolver.get_macro(self.def_ignoring_ambiguity())
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-11 05:35:18 +00:00
|
|
|
|
// We sometimes need to treat variants as `pub` for backwards compatibility
|
|
|
|
|
fn pseudo_vis(&self) -> ty::Visibility {
|
2017-11-29 19:20:49 +00:00
|
|
|
|
if self.is_variant() && self.def().def_id().is_local() {
|
|
|
|
|
ty::Visibility::Public
|
|
|
|
|
} else {
|
|
|
|
|
self.vis
|
|
|
|
|
}
|
2016-04-11 05:35:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_variant(&self) -> bool {
|
|
|
|
|
match self.kind {
|
2016-09-14 21:51:46 +00:00
|
|
|
|
NameBindingKind::Def(Def::Variant(..)) |
|
|
|
|
|
NameBindingKind::Def(Def::VariantCtor(..)) => true,
|
2016-04-11 05:35:18 +00:00
|
|
|
|
_ => false,
|
|
|
|
|
}
|
2015-11-16 02:10:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-29 22:21:36 +00:00
|
|
|
|
fn is_extern_crate(&self) -> bool {
|
2016-10-28 03:40:58 +00:00
|
|
|
|
match self.kind {
|
|
|
|
|
NameBindingKind::Import {
|
|
|
|
|
directive: &ImportDirective {
|
2017-11-08 02:01:35 +00:00
|
|
|
|
subclass: ImportDirectiveSubclass::ExternCrate(_), ..
|
2016-10-28 03:40:58 +00:00
|
|
|
|
}, ..
|
|
|
|
|
} => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
2016-01-29 22:21:36 +00:00
|
|
|
|
}
|
2016-02-07 21:34:23 +00:00
|
|
|
|
|
|
|
|
|
fn is_import(&self) -> bool {
|
|
|
|
|
match self.kind {
|
|
|
|
|
NameBindingKind::Import { .. } => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-17 01:57:09 +00:00
|
|
|
|
|
2017-11-08 02:01:35 +00:00
|
|
|
|
fn is_renamed_extern_crate(&self) -> bool {
|
|
|
|
|
if let NameBindingKind::Import { directive, ..} = self.kind {
|
|
|
|
|
if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-17 01:57:09 +00:00
|
|
|
|
fn is_glob_import(&self) -> bool {
|
|
|
|
|
match self.kind {
|
|
|
|
|
NameBindingKind::Import { directive, .. } => directive.is_glob(),
|
2016-11-10 10:29:36 +00:00
|
|
|
|
NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(),
|
2016-04-17 01:57:09 +00:00
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_importable(&self) -> bool {
|
2016-08-20 07:26:26 +00:00
|
|
|
|
match self.def() {
|
2016-04-17 01:57:09 +00:00
|
|
|
|
Def::AssociatedConst(..) | Def::Method(..) | Def::AssociatedTy(..) => false,
|
|
|
|
|
_ => true,
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-18 01:55:51 +00:00
|
|
|
|
|
|
|
|
|
fn is_macro_def(&self) -> bool {
|
|
|
|
|
match self.kind {
|
|
|
|
|
NameBindingKind::Def(Def::Macro(..)) => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-21 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
fn descr(&self) -> &'static str {
|
|
|
|
|
if self.is_extern_crate() { "extern crate" } else { self.def().kind_name() }
|
|
|
|
|
}
|
2012-08-18 00:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
|
/// Interns the names of the primitive types.
|
2018-02-18 17:01:33 +00:00
|
|
|
|
///
|
|
|
|
|
/// All other types are defined somewhere and possibly imported, but the primitive ones need
|
|
|
|
|
/// special handling, since they have no place of origin.
|
2013-10-02 12:33:01 +00:00
|
|
|
|
struct PrimitiveTypeTable {
|
2016-11-08 03:02:55 +00:00
|
|
|
|
primitive_types: FxHashMap<Name, PrimTy>,
|
2012-09-08 02:04:40 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2013-05-31 22:17:22 +00:00
|
|
|
|
impl PrimitiveTypeTable {
|
2014-05-28 19:36:05 +00:00
|
|
|
|
fn new() -> PrimitiveTypeTable {
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() };
|
2015-10-26 19:31:11 +00:00
|
|
|
|
|
|
|
|
|
table.intern("bool", TyBool);
|
|
|
|
|
table.intern("char", TyChar);
|
2016-02-08 15:09:01 +00:00
|
|
|
|
table.intern("f32", TyFloat(FloatTy::F32));
|
|
|
|
|
table.intern("f64", TyFloat(FloatTy::F64));
|
2018-01-04 01:12:04 +00:00
|
|
|
|
table.intern("isize", TyInt(IntTy::Isize));
|
2016-02-08 15:20:57 +00:00
|
|
|
|
table.intern("i8", TyInt(IntTy::I8));
|
|
|
|
|
table.intern("i16", TyInt(IntTy::I16));
|
|
|
|
|
table.intern("i32", TyInt(IntTy::I32));
|
|
|
|
|
table.intern("i64", TyInt(IntTy::I64));
|
2016-08-23 00:56:52 +00:00
|
|
|
|
table.intern("i128", TyInt(IntTy::I128));
|
2015-10-26 19:31:11 +00:00
|
|
|
|
table.intern("str", TyStr);
|
2018-01-04 01:12:04 +00:00
|
|
|
|
table.intern("usize", TyUint(UintTy::Usize));
|
2016-02-08 15:20:57 +00:00
|
|
|
|
table.intern("u8", TyUint(UintTy::U8));
|
|
|
|
|
table.intern("u16", TyUint(UintTy::U16));
|
|
|
|
|
table.intern("u32", TyUint(UintTy::U32));
|
|
|
|
|
table.intern("u64", TyUint(UintTy::U64));
|
2016-08-23 00:56:52 +00:00
|
|
|
|
table.intern("u128", TyUint(UintTy::U128));
|
2014-05-28 19:36:05 +00:00
|
|
|
|
table
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-09 13:05:33 +00:00
|
|
|
|
fn intern(&mut self, string: &str, primitive_type: PrimTy) {
|
2016-11-16 08:21:52 +00:00
|
|
|
|
self.primitive_types.insert(Symbol::intern(string), primitive_type);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
|
/// The main resolver class.
|
2018-02-18 17:01:33 +00:00
|
|
|
|
///
|
|
|
|
|
/// This is the visitor that walks the whole crate.
|
2016-04-24 03:26:10 +00:00
|
|
|
|
pub struct Resolver<'a> {
|
2014-03-05 14:36:01 +00:00
|
|
|
|
session: &'a Session,
|
2017-09-05 14:48:24 +00:00
|
|
|
|
cstore: &'a CrateStore,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-06-22 01:54:34 +00:00
|
|
|
|
pub definitions: Definitions,
|
2014-11-23 09:29:41 +00:00
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
|
graph_root: Module<'a>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-06-05 09:56:05 +00:00
|
|
|
|
prelude: Option<Module<'a>>,
|
2018-04-08 12:34:35 +00:00
|
|
|
|
extern_prelude: FxHashSet<Name>,
|
2016-06-05 09:56:05 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// n.b. This is used only for better diagnostics, not name resolution itself.
|
2017-03-18 02:10:13 +00:00
|
|
|
|
has_self: FxHashSet<DefId>,
|
2014-05-06 23:37:32 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// Names of fields of an item `DefId` accessible with dot syntax.
|
|
|
|
|
/// Used for hints during error reporting.
|
2016-11-08 03:02:55 +00:00
|
|
|
|
field_names: FxHashMap<DefId, Vec<Name>>,
|
2012-07-11 22:00:40 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// All imports known to succeed or fail.
|
2016-08-15 08:19:09 +00:00
|
|
|
|
determined_imports: Vec<&'a ImportDirective<'a>>,
|
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// All non-determined imports.
|
2016-08-17 00:52:18 +00:00
|
|
|
|
indeterminate_imports: Vec<&'a ImportDirective<'a>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The module that represents the current item scope.
|
2016-01-11 21:19:29 +00:00
|
|
|
|
current_module: Module<'a>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The current set of local scopes for types and values.
|
|
|
|
|
/// FIXME #4948: Reuse ribs to avoid allocation.
|
2016-11-10 06:19:54 +00:00
|
|
|
|
ribs: PerNS<Vec<Rib<'a>>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The current set of local scopes, for labels.
|
2016-01-22 09:55:29 +00:00
|
|
|
|
label_ribs: Vec<Rib<'a>>,
|
2012-08-15 02:20:56 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The trait that the current context can refer to.
|
2017-03-18 02:10:13 +00:00
|
|
|
|
current_trait_ref: Option<(Module<'a>, TraitRef)>,
|
2014-05-08 21:35:09 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The current self type if inside an impl (used for better errors).
|
2014-05-08 21:35:09 +00:00
|
|
|
|
current_self_type: Option<Ty>,
|
2012-07-11 22:00:40 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// The idents for the primitive types.
|
2014-04-14 08:30:59 +00:00
|
|
|
|
primitive_type_table: PrimitiveTypeTable,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-11-29 00:33:59 +00:00
|
|
|
|
def_map: DefMap,
|
2016-05-04 06:00:27 +00:00
|
|
|
|
pub freevars: FreevarMap,
|
2015-11-04 05:12:37 +00:00
|
|
|
|
freevars_seen: NodeMap<NodeMap<usize>>,
|
2016-05-04 06:00:27 +00:00
|
|
|
|
pub export_map: ExportMap,
|
|
|
|
|
pub trait_map: TraitMap,
|
2013-04-30 05:15:17 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// A map from nodes to anonymous modules.
|
|
|
|
|
/// Anonymous modules are pseudo-modules that are implicitly created around items
|
|
|
|
|
/// contained within blocks.
|
|
|
|
|
///
|
|
|
|
|
/// For example, if we have this:
|
|
|
|
|
///
|
|
|
|
|
/// fn f() {
|
|
|
|
|
/// fn g() {
|
|
|
|
|
/// ...
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// There will be an anonymous module created around `g` with the ID of the
|
|
|
|
|
/// entry block for `f`.
|
2016-12-20 08:32:15 +00:00
|
|
|
|
block_map: NodeMap<Module<'a>>,
|
|
|
|
|
module_map: FxHashMap<DefId, Module<'a>>,
|
2017-03-22 08:39:51 +00:00
|
|
|
|
extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
|
2016-04-17 20:41:57 +00:00
|
|
|
|
|
2016-05-04 06:00:27 +00:00
|
|
|
|
pub make_glob_map: bool,
|
2017-08-17 09:03:59 +00:00
|
|
|
|
/// Maps imports to the names of items actually imported (this actually maps
|
|
|
|
|
/// all imports, but only glob imports are actually interesting).
|
2016-05-04 06:00:27 +00:00
|
|
|
|
pub glob_map: GlobMap,
|
2014-11-23 09:29:41 +00:00
|
|
|
|
|
2016-11-08 03:02:55 +00:00
|
|
|
|
used_imports: FxHashSet<(NodeId, Namespace)>,
|
2016-05-04 06:00:27 +00:00
|
|
|
|
pub maybe_unused_trait_imports: NodeSet,
|
2017-08-13 02:58:17 +00:00
|
|
|
|
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
|
2015-05-14 11:40:16 +00:00
|
|
|
|
|
2018-05-18 00:20:30 +00:00
|
|
|
|
/// A list of labels as of yet unused. Labels will be removed from this map when
|
|
|
|
|
/// they are used (in a `break` or `continue` statement)
|
|
|
|
|
pub unused_labels: FxHashMap<NodeId, Span>,
|
|
|
|
|
|
2017-08-17 09:03:59 +00:00
|
|
|
|
/// privacy errors are delayed until the end in order to deduplicate them
|
2016-02-25 04:40:46 +00:00
|
|
|
|
privacy_errors: Vec<PrivacyError<'a>>,
|
2017-08-17 09:03:59 +00:00
|
|
|
|
/// ambiguity errors are delayed for deduplication
|
2016-09-06 03:47:11 +00:00
|
|
|
|
ambiguity_errors: Vec<AmbiguityError<'a>>,
|
2017-08-17 09:03:59 +00:00
|
|
|
|
/// `use` injections are delayed for better placement and deduplication
|
|
|
|
|
use_injections: Vec<UseError<'a>>,
|
2017-11-16 14:03:25 +00:00
|
|
|
|
/// `use` injections for proc macros wrongly imported with #[macro_use]
|
|
|
|
|
proc_mac_errors: Vec<macros::ProcMacError>,
|
2017-08-17 09:03:59 +00:00
|
|
|
|
|
2017-03-08 23:13:35 +00:00
|
|
|
|
gated_errors: FxHashSet<Span>,
|
2016-10-31 06:48:59 +00:00
|
|
|
|
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
|
2016-01-11 21:19:29 +00:00
|
|
|
|
|
|
|
|
|
arenas: &'a ResolverArenas<'a>,
|
2016-08-22 04:05:49 +00:00
|
|
|
|
dummy_binding: &'a NameBinding<'a>,
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// true if `#![feature(use_extern_macros)]`
|
|
|
|
|
use_extern_macros: bool,
|
2016-09-05 03:46:05 +00:00
|
|
|
|
|
2016-09-16 02:52:09 +00:00
|
|
|
|
crate_loader: &'a mut CrateLoader,
|
2017-03-22 08:39:51 +00:00
|
|
|
|
macro_names: FxHashSet<Ident>,
|
2017-03-16 01:39:47 +00:00
|
|
|
|
global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
|
2018-01-06 11:53:33 +00:00
|
|
|
|
pub all_macros: FxHashMap<Name, Def>,
|
2017-03-22 08:39:51 +00:00
|
|
|
|
lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
|
2018-02-27 16:11:14 +00:00
|
|
|
|
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
|
2017-03-01 23:48:16 +00:00
|
|
|
|
macro_defs: FxHashMap<Mark, DefId>,
|
|
|
|
|
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
|
2016-10-28 06:52:45 +00:00
|
|
|
|
macro_exports: Vec<Export>,
|
2016-12-22 06:03:19 +00:00
|
|
|
|
pub whitelisted_legacy_custom_derives: Vec<Name>,
|
2017-02-06 11:44:38 +00:00
|
|
|
|
pub found_unresolved_macro: bool,
|
2016-09-07 23:21:59 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// List of crate local macros that we need to warn about as being unused.
|
|
|
|
|
/// Right now this only includes macro_rules! macros, and macros 2.0.
|
2017-05-15 05:35:19 +00:00
|
|
|
|
unused_macros: FxHashSet<DefId>,
|
2017-05-11 08:26:07 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// Maps the `Mark` of an expansion to its containing module or block.
|
2016-11-08 03:02:55 +00:00
|
|
|
|
invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
|
2016-10-28 07:30:23 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// Avoid duplicated errors for "name already defined".
|
2016-10-28 07:30:23 +00:00
|
|
|
|
name_already_seen: FxHashMap<Name, Span>,
|
2017-01-09 09:31:14 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// If `#![feature(proc_macro)]` is set
|
2017-01-09 09:31:14 +00:00
|
|
|
|
proc_macro_enabled: bool,
|
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// A set of procedural macros imported by `#[macro_use]` that have already been warned about
|
2017-01-09 09:31:14 +00:00
|
|
|
|
warned_proc_macros: FxHashSet<Name>,
|
2017-01-14 07:35:54 +00:00
|
|
|
|
|
|
|
|
|
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
|
2017-01-20 15:53:49 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// This table maps struct IDs into struct constructor IDs,
|
|
|
|
|
/// it's not used during normal resolution, only for better error reporting.
|
2017-01-28 23:56:52 +00:00
|
|
|
|
struct_constructors: DefIdMap<(Def, ty::Visibility)>,
|
2017-07-18 18:41:21 +00:00
|
|
|
|
|
2018-04-14 01:05:01 +00:00
|
|
|
|
/// Only used for better errors on `fn(): fn()`
|
2017-07-18 18:41:21 +00:00
|
|
|
|
current_type_ascription: Vec<Span>,
|
2017-12-06 18:50:55 +00:00
|
|
|
|
|
|
|
|
|
injected_crate: Option<Module<'a>>,
|
2016-01-11 21:19:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// Nothing really interesting here, it just provides memory for the rest of the crate.
|
2016-06-22 01:54:34 +00:00
|
|
|
|
pub struct ResolverArenas<'a> {
|
2016-11-26 12:47:52 +00:00
|
|
|
|
modules: arena::TypedArena<ModuleData<'a>>,
|
2016-04-17 20:23:10 +00:00
|
|
|
|
local_modules: RefCell<Vec<Module<'a>>>,
|
2016-02-07 21:23:58 +00:00
|
|
|
|
name_bindings: arena::TypedArena<NameBinding<'a>>,
|
2016-03-17 01:13:31 +00:00
|
|
|
|
import_directives: arena::TypedArena<ImportDirective<'a>>,
|
2016-03-30 22:21:56 +00:00
|
|
|
|
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
|
2016-10-03 23:48:19 +00:00
|
|
|
|
invocation_data: arena::TypedArena<InvocationData<'a>>,
|
2016-10-06 08:04:30 +00:00
|
|
|
|
legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
|
2016-02-15 02:22:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> ResolverArenas<'a> {
|
2016-11-26 12:47:52 +00:00
|
|
|
|
fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> {
|
2016-04-17 20:23:10 +00:00
|
|
|
|
let module = self.modules.alloc(module);
|
|
|
|
|
if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) {
|
|
|
|
|
self.local_modules.borrow_mut().push(module);
|
|
|
|
|
}
|
|
|
|
|
module
|
|
|
|
|
}
|
|
|
|
|
fn local_modules(&'a self) -> ::std::cell::Ref<'a, Vec<Module<'a>>> {
|
|
|
|
|
self.local_modules.borrow()
|
2016-02-15 05:18:55 +00:00
|
|
|
|
}
|
|
|
|
|
fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
|
|
|
|
|
self.name_bindings.alloc(name_binding)
|
|
|
|
|
}
|
2016-03-17 01:13:31 +00:00
|
|
|
|
fn alloc_import_directive(&'a self, import_directive: ImportDirective<'a>)
|
|
|
|
|
-> &'a ImportDirective {
|
2016-02-15 02:22:59 +00:00
|
|
|
|
self.import_directives.alloc(import_directive)
|
|
|
|
|
}
|
2016-03-30 22:21:56 +00:00
|
|
|
|
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
|
|
|
|
|
self.name_resolutions.alloc(Default::default())
|
|
|
|
|
}
|
2016-10-03 23:48:19 +00:00
|
|
|
|
fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>)
|
|
|
|
|
-> &'a InvocationData<'a> {
|
|
|
|
|
self.invocation_data.alloc(expansion_data)
|
2016-09-16 08:50:34 +00:00
|
|
|
|
}
|
2016-10-06 08:04:30 +00:00
|
|
|
|
fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
|
|
|
|
|
self.legacy_bindings.alloc(binding)
|
|
|
|
|
}
|
2012-09-08 02:04:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-20 08:32:15 +00:00
|
|
|
|
impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> {
|
|
|
|
|
fn parent(self, id: DefId) -> Option<DefId> {
|
|
|
|
|
match id.krate {
|
|
|
|
|
LOCAL_CRATE => self.definitions.def_key(id.index).parent,
|
2017-09-05 14:48:24 +00:00
|
|
|
|
_ => self.cstore.def_key(id).parent,
|
2018-02-18 17:01:33 +00:00
|
|
|
|
}.map(|index| DefId { index, ..id })
|
2016-04-27 02:29:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-24 16:07:58 +00:00
|
|
|
|
/// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that
|
|
|
|
|
/// the resolver is no longer needed as all the relevant information is inline.
|
2016-05-02 23:26:18 +00:00
|
|
|
|
impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
|
2017-12-29 08:06:32 +00:00
|
|
|
|
self.resolve_hir_path_cb(path, is_value,
|
|
|
|
|
|resolver, span, error| resolve_error(resolver, span, error))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
|
2018-01-22 09:59:34 +00:00
|
|
|
|
components: &[&str], is_value: bool) -> hir::Path {
|
2017-12-29 08:06:32 +00:00
|
|
|
|
let mut path = hir::Path {
|
|
|
|
|
span,
|
|
|
|
|
def: Def::Err,
|
|
|
|
|
segments: iter::once(keywords::CrateRoot.name()).chain({
|
|
|
|
|
crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
|
|
|
|
|
}).map(hir::PathSegment::from_name).collect(),
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-01 07:31:19 +00:00
|
|
|
|
self.resolve_hir_path(&mut path, is_value);
|
2017-12-29 08:06:32 +00:00
|
|
|
|
path
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-01 07:31:19 +00:00
|
|
|
|
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
|
|
|
|
|
self.def_map.get(&id).cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn definitions(&mut self) -> &mut Definitions {
|
|
|
|
|
&mut self.definitions
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> Resolver<'a> {
|
2017-12-29 08:06:32 +00:00
|
|
|
|
/// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
|
|
|
|
|
/// isn't something that can be returned because it can't be made to live that long,
|
|
|
|
|
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
|
2018-02-16 14:56:50 +00:00
|
|
|
|
/// just that an error occurred.
|
2018-01-03 06:03:04 +00:00
|
|
|
|
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
|
|
|
|
|
-> Result<hir::Path, ()> {
|
2018-01-01 07:31:19 +00:00
|
|
|
|
use std::iter;
|
2017-12-29 08:06:32 +00:00
|
|
|
|
let mut errored = false;
|
2018-01-01 07:31:19 +00:00
|
|
|
|
|
|
|
|
|
let mut path = if path_str.starts_with("::") {
|
|
|
|
|
hir::Path {
|
|
|
|
|
span,
|
|
|
|
|
def: Def::Err,
|
|
|
|
|
segments: iter::once(keywords::CrateRoot.name()).chain({
|
|
|
|
|
path_str.split("::").skip(1).map(Symbol::intern)
|
|
|
|
|
}).map(hir::PathSegment::from_name).collect(),
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
hir::Path {
|
|
|
|
|
span,
|
|
|
|
|
def: Def::Err,
|
|
|
|
|
segments: path_str.split("::").map(Symbol::intern)
|
|
|
|
|
.map(hir::PathSegment::from_name).collect(),
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true);
|
2017-12-29 08:06:32 +00:00
|
|
|
|
if errored || path.def == Def::Err {
|
|
|
|
|
Err(())
|
|
|
|
|
} else {
|
|
|
|
|
Ok(path)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// resolve_hir_path, but takes a callback in case there was an error
|
|
|
|
|
fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F)
|
|
|
|
|
where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
|
|
|
|
|
{
|
2016-05-02 23:26:18 +00:00
|
|
|
|
let namespace = if is_value { ValueNS } else { TypeNS };
|
2016-12-05 03:51:11 +00:00
|
|
|
|
let hir::Path { ref segments, span, ref mut def } = *path;
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let path: Vec<Ident> = segments.iter()
|
|
|
|
|
.map(|seg| Ident::new(seg.name, span))
|
2017-07-23 22:15:45 +00:00
|
|
|
|
.collect();
|
2018-04-20 00:27:31 +00:00
|
|
|
|
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes
|
2018-05-22 15:10:17 +00:00
|
|
|
|
match self.resolve_path(&path, Some(namespace), true, span, CrateLint::No) {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
PathResult::Module(module) => *def = module.def().unwrap(),
|
2017-02-18 19:11:42 +00:00
|
|
|
|
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
|
|
|
|
|
*def = path_res.base_def(),
|
2018-05-22 15:45:36 +00:00
|
|
|
|
PathResult::NonModule(..) => match self.resolve_path(
|
|
|
|
|
&path,
|
|
|
|
|
None,
|
|
|
|
|
true,
|
|
|
|
|
span,
|
|
|
|
|
CrateLint::No,
|
|
|
|
|
) {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
PathResult::Failed(span, msg, _) => {
|
2017-12-29 08:06:32 +00:00
|
|
|
|
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
},
|
|
|
|
|
PathResult::Indeterminate => unreachable!(),
|
2017-07-23 22:15:45 +00:00
|
|
|
|
PathResult::Failed(span, msg, _) => {
|
2017-12-29 08:06:32 +00:00
|
|
|
|
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
|
2016-05-02 23:26:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
|
impl<'a> Resolver<'a> {
|
2016-09-05 03:46:05 +00:00
|
|
|
|
pub fn new(session: &'a Session,
|
2017-09-05 14:48:24 +00:00
|
|
|
|
cstore: &'a CrateStore,
|
2016-09-19 05:25:17 +00:00
|
|
|
|
krate: &Crate,
|
2017-04-03 17:20:26 +00:00
|
|
|
|
crate_name: &str,
|
2016-09-05 03:46:05 +00:00
|
|
|
|
make_glob_map: MakeGlobMap,
|
2016-09-16 02:52:09 +00:00
|
|
|
|
crate_loader: &'a mut CrateLoader,
|
2016-09-05 03:46:05 +00:00
|
|
|
|
arenas: &'a ResolverArenas<'a>)
|
2016-06-22 01:54:34 +00:00
|
|
|
|
-> Resolver<'a> {
|
2016-12-20 08:32:15 +00:00
|
|
|
|
let root_def_id = DefId::local(CRATE_DEF_INDEX);
|
|
|
|
|
let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
|
2016-11-26 12:47:52 +00:00
|
|
|
|
let graph_root = arenas.alloc_module(ModuleData {
|
2016-09-19 05:25:17 +00:00
|
|
|
|
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
|
2017-03-22 08:39:51 +00:00
|
|
|
|
..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span)
|
2016-09-19 05:25:17 +00:00
|
|
|
|
});
|
2016-12-20 08:32:15 +00:00
|
|
|
|
let mut module_map = FxHashMap();
|
|
|
|
|
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
2016-09-14 09:55:20 +00:00
|
|
|
|
let mut definitions = Definitions::new();
|
2017-03-24 23:03:15 +00:00
|
|
|
|
DefCollector::new(&mut definitions, Mark::root())
|
2017-10-24 15:49:58 +00:00
|
|
|
|
.collect_root(crate_name, session.local_crate_disambiguator());
|
2016-09-14 09:55:20 +00:00
|
|
|
|
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut invocations = FxHashMap();
|
2016-10-03 23:48:19 +00:00
|
|
|
|
invocations.insert(Mark::root(),
|
|
|
|
|
arenas.alloc_invocation_data(InvocationData::root(graph_root)));
|
2016-09-19 07:27:20 +00:00
|
|
|
|
|
2018-02-14 15:11:02 +00:00
|
|
|
|
let features = session.features_untracked();
|
2017-01-09 09:31:14 +00:00
|
|
|
|
|
2017-03-01 23:48:16 +00:00
|
|
|
|
let mut macro_defs = FxHashMap();
|
|
|
|
|
macro_defs.insert(Mark::root(), root_def_id);
|
|
|
|
|
|
2014-05-28 19:36:05 +00:00
|
|
|
|
Resolver {
|
2017-08-07 05:54:09 +00:00
|
|
|
|
session,
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
2017-09-05 14:48:24 +00:00
|
|
|
|
cstore,
|
|
|
|
|
|
2017-08-07 05:54:09 +00:00
|
|
|
|
definitions,
|
2014-11-23 09:29:41 +00:00
|
|
|
|
|
2014-05-28 19:36:05 +00:00
|
|
|
|
// The outermost module has def ID 0; this is not reflected in the
|
|
|
|
|
// AST.
|
2017-08-07 05:54:09 +00:00
|
|
|
|
graph_root,
|
2016-06-05 09:56:05 +00:00
|
|
|
|
prelude: None,
|
2018-04-08 12:34:35 +00:00
|
|
|
|
extern_prelude: session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
2017-03-18 02:10:13 +00:00
|
|
|
|
has_self: FxHashSet(),
|
2016-11-08 03:02:55 +00:00
|
|
|
|
field_names: FxHashMap(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
2016-08-15 08:19:09 +00:00
|
|
|
|
determined_imports: Vec::new(),
|
2016-08-17 00:52:18 +00:00
|
|
|
|
indeterminate_imports: Vec::new(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
2015-11-18 01:22:32 +00:00
|
|
|
|
current_module: graph_root,
|
2016-11-10 06:19:54 +00:00
|
|
|
|
ribs: PerNS {
|
|
|
|
|
value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
|
|
|
|
|
type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
|
2018-04-29 23:20:14 +00:00
|
|
|
|
macro_ns: vec![Rib::new(ModuleRibKind(graph_root))],
|
2016-11-10 06:19:54 +00:00
|
|
|
|
},
|
2014-09-29 23:06:13 +00:00
|
|
|
|
label_ribs: Vec::new(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
|
|
|
|
current_trait_ref: None,
|
|
|
|
|
current_self_type: None,
|
|
|
|
|
|
|
|
|
|
primitive_type_table: PrimitiveTypeTable::new(),
|
|
|
|
|
|
2016-05-03 20:44:27 +00:00
|
|
|
|
def_map: NodeMap(),
|
2015-11-04 05:12:37 +00:00
|
|
|
|
freevars: NodeMap(),
|
|
|
|
|
freevars_seen: NodeMap(),
|
2017-09-08 20:51:57 +00:00
|
|
|
|
export_map: FxHashMap(),
|
2015-01-16 22:27:43 +00:00
|
|
|
|
trait_map: NodeMap(),
|
2017-08-07 05:54:09 +00:00
|
|
|
|
module_map,
|
2016-12-20 08:32:15 +00:00
|
|
|
|
block_map: NodeMap(),
|
2017-03-22 08:39:51 +00:00
|
|
|
|
extern_module_map: FxHashMap(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
2014-11-23 09:29:41 +00:00
|
|
|
|
make_glob_map: make_glob_map == MakeGlobMap::Yes,
|
2016-03-29 10:14:01 +00:00
|
|
|
|
glob_map: NodeMap(),
|
2015-05-14 11:40:16 +00:00
|
|
|
|
|
2016-11-08 03:02:55 +00:00
|
|
|
|
used_imports: FxHashSet(),
|
2016-04-19 13:43:10 +00:00
|
|
|
|
maybe_unused_trait_imports: NodeSet(),
|
2017-06-24 08:48:27 +00:00
|
|
|
|
maybe_unused_extern_crates: Vec::new(),
|
2016-04-19 13:43:10 +00:00
|
|
|
|
|
2018-05-18 00:20:30 +00:00
|
|
|
|
unused_labels: FxHashMap(),
|
|
|
|
|
|
2016-02-25 04:40:46 +00:00
|
|
|
|
privacy_errors: Vec::new(),
|
2016-08-22 08:30:07 +00:00
|
|
|
|
ambiguity_errors: Vec::new(),
|
2017-08-17 09:03:59 +00:00
|
|
|
|
use_injections: Vec::new(),
|
2017-11-16 14:03:25 +00:00
|
|
|
|
proc_mac_errors: Vec::new(),
|
2017-03-08 23:13:35 +00:00
|
|
|
|
gated_errors: FxHashSet(),
|
2016-10-11 03:21:40 +00:00
|
|
|
|
disallowed_shadowing: Vec::new(),
|
2016-01-11 21:19:29 +00:00
|
|
|
|
|
2017-08-07 05:54:09 +00:00
|
|
|
|
arenas,
|
2016-08-22 04:05:49 +00:00
|
|
|
|
dummy_binding: arenas.alloc_name_binding(NameBinding {
|
|
|
|
|
kind: NameBindingKind::Def(Def::Err),
|
2016-11-07 22:23:26 +00:00
|
|
|
|
expansion: Mark::root(),
|
2016-08-22 04:05:49 +00:00
|
|
|
|
span: DUMMY_SP,
|
|
|
|
|
vis: ty::Visibility::Public,
|
|
|
|
|
}),
|
2017-01-09 09:31:14 +00:00
|
|
|
|
|
2017-03-18 01:55:51 +00:00
|
|
|
|
// The `proc_macro` and `decl_macro` features imply `use_extern_macros`
|
|
|
|
|
use_extern_macros:
|
|
|
|
|
features.use_extern_macros || features.proc_macro || features.decl_macro,
|
2016-09-05 03:46:05 +00:00
|
|
|
|
|
2017-08-07 05:54:09 +00:00
|
|
|
|
crate_loader,
|
2016-11-08 03:02:55 +00:00
|
|
|
|
macro_names: FxHashSet(),
|
2017-03-16 01:39:47 +00:00
|
|
|
|
global_macros: FxHashMap(),
|
2018-01-06 11:53:33 +00:00
|
|
|
|
all_macros: FxHashMap(),
|
2016-10-31 22:17:15 +00:00
|
|
|
|
lexical_macro_resolutions: Vec::new(),
|
2016-10-28 06:52:45 +00:00
|
|
|
|
macro_map: FxHashMap(),
|
|
|
|
|
macro_exports: Vec::new(),
|
2017-08-07 05:54:09 +00:00
|
|
|
|
invocations,
|
|
|
|
|
macro_defs,
|
2017-03-01 23:48:16 +00:00
|
|
|
|
local_macro_def_scopes: FxHashMap(),
|
2016-10-28 07:30:23 +00:00
|
|
|
|
name_already_seen: FxHashMap(),
|
2016-12-22 06:03:19 +00:00
|
|
|
|
whitelisted_legacy_custom_derives: Vec::new(),
|
2017-01-09 09:31:14 +00:00
|
|
|
|
proc_macro_enabled: features.proc_macro,
|
|
|
|
|
warned_proc_macros: FxHashSet(),
|
2017-01-14 07:35:54 +00:00
|
|
|
|
potentially_unused_imports: Vec::new(),
|
2017-01-28 23:56:52 +00:00
|
|
|
|
struct_constructors: DefIdMap(),
|
2017-02-06 11:44:38 +00:00
|
|
|
|
found_unresolved_macro: false,
|
2017-05-15 05:35:19 +00:00
|
|
|
|
unused_macros: FxHashSet(),
|
2017-07-18 18:41:21 +00:00
|
|
|
|
current_type_ascription: Vec::new(),
|
2017-12-06 18:50:55 +00:00
|
|
|
|
injected_crate: None,
|
2016-01-11 21:19:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-22 01:54:34 +00:00
|
|
|
|
pub fn arenas() -> ResolverArenas<'a> {
|
2016-01-11 21:19:29 +00:00
|
|
|
|
ResolverArenas {
|
|
|
|
|
modules: arena::TypedArena::new(),
|
2016-04-17 20:23:10 +00:00
|
|
|
|
local_modules: RefCell::new(Vec::new()),
|
2016-02-07 21:23:58 +00:00
|
|
|
|
name_bindings: arena::TypedArena::new(),
|
2016-02-15 02:22:59 +00:00
|
|
|
|
import_directives: arena::TypedArena::new(),
|
2016-03-30 22:21:56 +00:00
|
|
|
|
name_resolutions: arena::TypedArena::new(),
|
2016-10-03 23:48:19 +00:00
|
|
|
|
invocation_data: arena::TypedArena::new(),
|
2016-10-06 08:04:30 +00:00
|
|
|
|
legacy_bindings: arena::TypedArena::new(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2018-02-18 17:01:33 +00:00
|
|
|
|
/// Runs the function on each namespace.
|
2018-04-29 23:20:14 +00:00
|
|
|
|
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
|
|
|
|
|
f(self, TypeNS);
|
|
|
|
|
f(self, ValueNS);
|
|
|
|
|
if self.use_extern_macros {
|
|
|
|
|
f(self, MacroNS);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-28 07:07:44 +00:00
|
|
|
|
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
|
|
|
|
|
loop {
|
|
|
|
|
match self.macro_defs.get(&ctxt.outer()) {
|
|
|
|
|
Some(&def_id) => return def_id,
|
|
|
|
|
None => ctxt.remove_mark(),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-22 01:54:34 +00:00
|
|
|
|
/// Entry point to crate resolution.
|
|
|
|
|
pub fn resolve_crate(&mut self, krate: &Crate) {
|
2016-11-10 10:11:25 +00:00
|
|
|
|
ImportResolver { resolver: self }.finalize_imports();
|
2016-06-22 01:54:34 +00:00
|
|
|
|
self.current_module = self.graph_root;
|
2016-11-27 10:58:46 +00:00
|
|
|
|
self.finalize_current_module_macro_resolutions();
|
2017-08-17 09:03:59 +00:00
|
|
|
|
|
2016-06-22 01:54:34 +00:00
|
|
|
|
visit::walk_crate(self, krate);
|
|
|
|
|
|
|
|
|
|
check_unused::check_crate(self, krate);
|
2017-08-17 09:03:59 +00:00
|
|
|
|
self.report_errors(krate);
|
2016-09-16 02:52:09 +00:00
|
|
|
|
self.crate_loader.postprocess(krate);
|
2016-06-22 01:54:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-10 11:58:41 +00:00
|
|
|
|
fn new_module(
|
|
|
|
|
&self,
|
|
|
|
|
parent: Module<'a>,
|
|
|
|
|
kind: ModuleKind,
|
|
|
|
|
normal_ancestor_id: DefId,
|
2017-03-22 08:39:51 +00:00
|
|
|
|
expansion: Mark,
|
2017-05-10 11:58:41 +00:00
|
|
|
|
span: Span,
|
|
|
|
|
) -> Module<'a> {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let module = ModuleData::new(Some(parent), kind, normal_ancestor_id, expansion, span);
|
|
|
|
|
self.arenas.alloc_module(module)
|
2016-01-29 22:21:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
|
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
2016-08-20 05:23:19 +00:00
|
|
|
|
-> bool /* true if an error was reported */ {
|
2016-09-05 05:27:58 +00:00
|
|
|
|
match binding.kind {
|
2018-05-14 22:24:34 +00:00
|
|
|
|
NameBindingKind::Import { directive, binding, ref used }
|
2017-01-10 05:15:02 +00:00
|
|
|
|
if !used.get() => {
|
2016-09-05 05:27:58 +00:00
|
|
|
|
used.set(true);
|
2017-01-14 07:35:54 +00:00
|
|
|
|
directive.used.set(true);
|
2016-09-05 05:27:58 +00:00
|
|
|
|
self.used_imports.insert((directive.id, ns));
|
2016-11-29 02:07:12 +00:00
|
|
|
|
self.add_to_glob_map(directive.id, ident);
|
|
|
|
|
self.record_use(ident, ns, binding, span)
|
2016-09-05 05:27:58 +00:00
|
|
|
|
}
|
|
|
|
|
NameBindingKind::Import { .. } => false,
|
2018-05-14 22:24:34 +00:00
|
|
|
|
NameBindingKind::Ambiguity { b1, b2 } => {
|
2016-11-10 10:29:36 +00:00
|
|
|
|
self.ambiguity_errors.push(AmbiguityError {
|
2018-05-14 22:24:34 +00:00
|
|
|
|
span, name: ident.name, lexical: false, b1, b2,
|
2016-11-10 10:29:36 +00:00
|
|
|
|
});
|
2018-05-14 22:24:34 +00:00
|
|
|
|
true
|
2016-09-05 05:27:58 +00:00
|
|
|
|
}
|
|
|
|
|
_ => false
|
2016-09-05 04:55:12 +00:00
|
|
|
|
}
|
2016-07-29 16:04:45 +00:00
|
|
|
|
}
|
2014-11-23 09:29:41 +00:00
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
|
fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) {
|
2016-07-29 16:04:45 +00:00
|
|
|
|
if self.make_glob_map {
|
2016-11-29 02:07:12 +00:00
|
|
|
|
self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name);
|
2016-07-29 16:04:45 +00:00
|
|
|
|
}
|
2014-11-23 09:29:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-12 08:03:13 +00:00
|
|
|
|
/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
|
|
|
|
|
/// More specifically, we proceed up the hierarchy of scopes and return the binding for
|
|
|
|
|
/// `ident` in the first scope that defines it (or None if no scopes define it).
|
|
|
|
|
///
|
|
|
|
|
/// A block's items are above its local variables in the scope hierarchy, regardless of where
|
|
|
|
|
/// the items are defined in the block. For example,
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// fn f() {
|
|
|
|
|
/// g(); // Since there are no local variables in scope yet, this resolves to the item.
|
|
|
|
|
/// let g = || {};
|
|
|
|
|
/// fn g() {}
|
|
|
|
|
/// g(); // This resolves to the local variable `g` since it shadows the item.
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2016-03-11 23:28:22 +00:00
|
|
|
|
///
|
2013-03-01 18:44:43 +00:00
|
|
|
|
/// Invariant: This must only be called during main resolution, not during
|
|
|
|
|
/// import resolution.
|
2016-03-12 08:03:13 +00:00
|
|
|
|
fn resolve_ident_in_lexical_scope(&mut self,
|
2016-10-16 02:38:08 +00:00
|
|
|
|
mut ident: Ident,
|
2016-03-12 08:03:13 +00:00
|
|
|
|
ns: Namespace,
|
2017-05-12 09:21:11 +00:00
|
|
|
|
record_used: bool,
|
|
|
|
|
path_span: Span)
|
2016-03-12 08:03:13 +00:00
|
|
|
|
-> Option<LexicalScopeBinding<'a>> {
|
2016-06-22 02:50:05 +00:00
|
|
|
|
if ns == TypeNS {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
ident.span = if ident.name == keywords::SelfType.name() {
|
|
|
|
|
// FIXME(jseyfried) improve `Self` hygiene
|
|
|
|
|
ident.span.with_ctxt(SyntaxContext::empty())
|
2017-05-21 22:35:39 +00:00
|
|
|
|
} else {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
ident.span.modern()
|
2017-05-21 22:35:39 +00:00
|
|
|
|
}
|
2016-06-22 02:50:05 +00:00
|
|
|
|
}
|
2016-03-12 08:03:13 +00:00
|
|
|
|
|
2016-03-11 23:28:22 +00:00
|
|
|
|
// Walk backwards up the ribs in scope.
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let mut module = self.graph_root;
|
2016-11-10 06:19:54 +00:00
|
|
|
|
for i in (0 .. self.ribs[ns].len()).rev() {
|
|
|
|
|
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
|
2016-03-12 08:03:13 +00:00
|
|
|
|
// The ident resolves to a type parameter or local variable.
|
2016-11-30 22:35:25 +00:00
|
|
|
|
return Some(LexicalScopeBinding::Def(
|
2017-05-12 09:21:11 +00:00
|
|
|
|
self.adjust_local_def(ns, i, def, record_used, path_span)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-22 08:39:51 +00:00
|
|
|
|
module = match self.ribs[ns][i].kind {
|
|
|
|
|
ModuleRibKind(module) => module,
|
2018-03-17 23:57:23 +00:00
|
|
|
|
MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
// If an invocation of this macro created `ident`, give up on `ident`
|
|
|
|
|
// and switch to `ident`'s source from the macro definition.
|
2018-03-17 23:57:23 +00:00
|
|
|
|
ident.span.remove_mark();
|
2017-03-22 08:39:51 +00:00
|
|
|
|
continue
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2017-03-22 08:39:51 +00:00
|
|
|
|
_ => continue,
|
|
|
|
|
};
|
2016-03-12 08:03:13 +00:00
|
|
|
|
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let item = self.resolve_ident_in_module_unadjusted(
|
|
|
|
|
module, ident, ns, false, record_used, path_span,
|
|
|
|
|
);
|
|
|
|
|
if let Ok(binding) = item {
|
|
|
|
|
// The ident resolves to an item.
|
|
|
|
|
return Some(LexicalScopeBinding::Item(binding));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2016-06-26 03:32:45 +00:00
|
|
|
|
|
2017-03-22 08:39:51 +00:00
|
|
|
|
match module.kind {
|
|
|
|
|
ModuleKind::Block(..) => {}, // We can see through blocks
|
|
|
|
|
_ => break,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-17 23:57:23 +00:00
|
|
|
|
ident.span = ident.span.modern();
|
2017-03-22 08:39:51 +00:00
|
|
|
|
loop {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.span), break);
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let orig_current_module = self.current_module;
|
|
|
|
|
self.current_module = module; // Lexical resolutions can never be a privacy error.
|
|
|
|
|
let result = self.resolve_ident_in_module_unadjusted(
|
|
|
|
|
module, ident, ns, false, record_used, path_span,
|
|
|
|
|
);
|
|
|
|
|
self.current_module = orig_current_module;
|
|
|
|
|
|
|
|
|
|
match result {
|
|
|
|
|
Ok(binding) => return Some(LexicalScopeBinding::Item(binding)),
|
|
|
|
|
Err(Undetermined) => return None,
|
|
|
|
|
Err(Determined) => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-08 12:34:35 +00:00
|
|
|
|
if !module.no_implicit_prelude {
|
|
|
|
|
// `record_used` means that we don't try to load crates during speculative resolution
|
|
|
|
|
if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
|
|
|
|
|
if !self.session.features_untracked().extern_prelude {
|
|
|
|
|
feature_err(&self.session.parse_sess, "extern_prelude",
|
|
|
|
|
ident.span, GateIssue::Language,
|
|
|
|
|
"access to extern crates through prelude is experimental").emit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
|
|
|
|
|
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
|
|
|
|
self.populate_module_if_necessary(crate_root);
|
|
|
|
|
|
|
|
|
|
let binding = (crate_root, ty::Visibility::Public,
|
|
|
|
|
ident.span, Mark::root()).to_name_binding(self.arenas);
|
|
|
|
|
return Some(LexicalScopeBinding::Item(binding));
|
|
|
|
|
}
|
|
|
|
|
if let Some(prelude) = self.prelude {
|
|
|
|
|
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
|
|
|
|
|
false, false, path_span) {
|
|
|
|
|
return Some(LexicalScopeBinding::Item(binding));
|
|
|
|
|
}
|
2017-03-22 08:39:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-04-08 12:34:35 +00:00
|
|
|
|
|
|
|
|
|
None
|
2017-03-22 08:39:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-17 23:57:23 +00:00
|
|
|
|
fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
|
2017-03-22 08:39:51 +00:00
|
|
|
|
-> Option<Module<'a>> {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
if !module.expansion.is_descendant_of(span.ctxt().outer()) {
|
|
|
|
|
return Some(self.macro_def_scope(span.remove_mark()));
|
2017-03-22 08:39:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let ModuleKind::Block(..) = module.kind {
|
|
|
|
|
return Some(module.parent.unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-11 18:34:14 +00:00
|
|
|
|
let mut module_expansion = module.expansion.modern(); // for backward compatibility
|
2017-03-22 08:39:51 +00:00
|
|
|
|
while let Some(parent) = module.parent {
|
|
|
|
|
let parent_expansion = parent.expansion.modern();
|
|
|
|
|
if module_expansion.is_descendant_of(parent_expansion) &&
|
|
|
|
|
parent_expansion != module_expansion {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
return if parent_expansion.is_descendant_of(span.ctxt().outer()) {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
Some(parent)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
2016-06-26 03:32:45 +00:00
|
|
|
|
}
|
2017-03-22 08:39:51 +00:00
|
|
|
|
module = parent;
|
|
|
|
|
module_expansion = parent_expansion;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2016-03-08 21:44:19 +00:00
|
|
|
|
|
2016-03-12 08:03:13 +00:00
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-22 08:39:51 +00:00
|
|
|
|
fn resolve_ident_in_module(&mut self,
|
|
|
|
|
module: Module<'a>,
|
|
|
|
|
mut ident: Ident,
|
|
|
|
|
ns: Namespace,
|
|
|
|
|
ignore_unresolved_invocations: bool,
|
|
|
|
|
record_used: bool,
|
|
|
|
|
span: Span)
|
|
|
|
|
-> Result<&'a NameBinding<'a>, Determinacy> {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
ident.span = ident.span.modern();
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let orig_current_module = self.current_module;
|
2018-03-17 23:57:23 +00:00
|
|
|
|
if let Some(def) = ident.span.adjust(module.expansion) {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
self.current_module = self.macro_def_scope(def);
|
|
|
|
|
}
|
|
|
|
|
let result = self.resolve_ident_in_module_unadjusted(
|
|
|
|
|
module, ident, ns, ignore_unresolved_invocations, record_used, span,
|
|
|
|
|
);
|
|
|
|
|
self.current_module = orig_current_module;
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-29 09:05:31 +00:00
|
|
|
|
fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext, legacy: bool) -> Module<'a> {
|
|
|
|
|
let mark = if legacy {
|
|
|
|
|
// When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
|
|
|
|
|
// we don't want to pretend that the `macro_rules!` definition is in the `macro`
|
|
|
|
|
// as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
|
|
|
|
|
ctxt.marks().into_iter().find(|&mark| mark.kind() != MarkKind::Modern)
|
|
|
|
|
} else {
|
|
|
|
|
ctxt = ctxt.modern();
|
|
|
|
|
ctxt.adjust(Mark::root())
|
|
|
|
|
};
|
|
|
|
|
let module = match mark {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
Some(def) => self.macro_def_scope(def),
|
|
|
|
|
None => return self.graph_root,
|
|
|
|
|
};
|
|
|
|
|
self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
|
|
|
|
|
let mut module = self.get_module(module.normal_ancestor_id);
|
2017-07-31 20:04:34 +00:00
|
|
|
|
while module.span.ctxt().modern() != *ctxt {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
|
|
|
|
|
module = self.get_module(parent.normal_ancestor_id);
|
2016-10-23 02:44:36 +00:00
|
|
|
|
}
|
2017-03-22 08:39:51 +00:00
|
|
|
|
module
|
2016-10-23 02:44:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
|
// AST resolution
|
|
|
|
|
//
|
2012-07-07 02:06:58 +00:00
|
|
|
|
// We maintain a list of value ribs and type ribs.
|
2012-05-22 17:54:12 +00:00
|
|
|
|
//
|
|
|
|
|
// Simultaneously, we keep track of the current position in the module
|
|
|
|
|
// graph in the `current_module` pointer. When we go to resolve a name in
|
|
|
|
|
// the value or type namespaces, we first look through all the ribs and
|
|
|
|
|
// then query the module graph. When we resolve a name in the module
|
|
|
|
|
// namespace, we can skip all the ribs (since nested modules are not
|
|
|
|
|
// allowed within blocks in Rust) and jump straight to the current module
|
|
|
|
|
// graph node.
|
|
|
|
|
//
|
|
|
|
|
// Named implementations are handled separately. When we find a method
|
|
|
|
|
// call, we consult the module node to find all of the implementations in
|
|
|
|
|
// scope. This information is lazily cached in the module node. We then
|
|
|
|
|
// generate a fake "implementation scope" containing all the
|
|
|
|
|
// implementations thus found, for compatibility with old resolve pass.
|
|
|
|
|
|
2018-01-01 07:31:19 +00:00
|
|
|
|
pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
|
|
|
|
|
where F: FnOnce(&mut Resolver) -> T
|
2014-12-09 01:26:43 +00:00
|
|
|
|
{
|
2016-12-20 08:32:15 +00:00
|
|
|
|
let id = self.definitions.local_def_id(id);
|
2016-04-17 20:41:57 +00:00
|
|
|
|
let module = self.module_map.get(&id).cloned(); // clones a reference
|
|
|
|
|
if let Some(module) = module {
|
2016-02-24 04:48:31 +00:00
|
|
|
|
// Move down in the graph.
|
2016-08-14 23:42:05 +00:00
|
|
|
|
let orig_module = replace(&mut self.current_module, module);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
|
|
|
|
|
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-11-10 10:29:36 +00:00
|
|
|
|
self.finalize_current_module_macro_resolutions();
|
2018-01-01 07:31:19 +00:00
|
|
|
|
let ret = f(self);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-02-24 04:48:31 +00:00
|
|
|
|
self.current_module = orig_module;
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
|
|
|
|
self.ribs[TypeNS].pop();
|
2018-01-01 07:31:19 +00:00
|
|
|
|
ret
|
2016-02-24 04:48:31 +00:00
|
|
|
|
} else {
|
2018-01-01 07:31:19 +00:00
|
|
|
|
f(self)
|
2016-02-24 04:48:31 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 22:21:09 +00:00
|
|
|
|
/// Searches the current set of local scopes for labels. Returns the first non-None label that
|
|
|
|
|
/// is returned by the given predicate function
|
|
|
|
|
///
|
2014-12-27 12:47:42 +00:00
|
|
|
|
/// Stops after meeting a closure.
|
2017-10-09 22:21:09 +00:00
|
|
|
|
fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
|
|
|
|
|
where P: Fn(&Rib, Ident) -> Option<R>
|
|
|
|
|
{
|
2014-12-26 11:08:00 +00:00
|
|
|
|
for rib in self.label_ribs.iter().rev() {
|
|
|
|
|
match rib.kind {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
NormalRibKind => {}
|
|
|
|
|
// If an invocation of this macro created `ident`, give up on `ident`
|
|
|
|
|
// and switch to `ident`'s source from the macro definition.
|
2017-03-01 23:48:16 +00:00
|
|
|
|
MacroDefinition(def) => {
|
2018-03-17 23:57:23 +00:00
|
|
|
|
if def == self.macro_def(ident.span.ctxt()) {
|
|
|
|
|
ident.span.remove_mark();
|
2016-07-15 05:14:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-26 11:08:00 +00:00
|
|
|
|
_ => {
|
|
|
|
|
// Do not resolve labels across function boundary
|
2015-10-26 19:31:11 +00:00
|
|
|
|
return None;
|
2014-12-26 11:08:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-09 22:21:09 +00:00
|
|
|
|
let r = pred(rib, ident);
|
|
|
|
|
if r.is_some() {
|
|
|
|
|
return r;
|
2014-12-26 11:08:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-09 13:05:33 +00:00
|
|
|
|
fn resolve_item(&mut self, item: &Item) {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
let name = item.ident.name;
|
2014-10-01 00:11:34 +00:00
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
|
debug!("(resolving item) resolving {}", name);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2017-01-09 09:31:14 +00:00
|
|
|
|
self.check_proc_macro_attrs(&item.attrs);
|
|
|
|
|
|
2013-03-20 05:17:42 +00:00
|
|
|
|
match item.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
ItemKind::Enum(_, ref generics) |
|
|
|
|
|
ItemKind::Ty(_, ref generics) |
|
2016-08-14 22:07:09 +00:00
|
|
|
|
ItemKind::Struct(_, ref generics) |
|
2016-08-29 05:04:31 +00:00
|
|
|
|
ItemKind::Union(_, ref generics) |
|
2016-08-26 16:23:42 +00:00
|
|
|
|
ItemKind::Fn(.., ref generics, _) => {
|
2016-08-14 22:07:09 +00:00
|
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|this| visit::walk_item(this, item));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-26 16:23:42 +00:00
|
|
|
|
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
|
2015-02-05 07:19:07 +00:00
|
|
|
|
self.resolve_implementation(generics,
|
2015-04-03 04:13:52 +00:00
|
|
|
|
opt_trait_ref,
|
2016-02-09 20:27:42 +00:00
|
|
|
|
&self_type,
|
2015-04-03 04:13:52 +00:00
|
|
|
|
item.id,
|
2016-04-24 03:26:10 +00:00
|
|
|
|
impl_items),
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2017-10-12 12:51:31 +00:00
|
|
|
|
ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
|
2015-04-07 05:59:10 +00:00
|
|
|
|
// Create a new rib for the trait-wide type parameters.
|
2016-08-14 22:07:09 +00:00
|
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
let local_def_id = this.definitions.local_def_id(item.id);
|
2016-01-20 19:31:10 +00:00
|
|
|
|
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
|
2015-04-03 04:13:52 +00:00
|
|
|
|
this.visit_generics(generics);
|
2015-09-28 21:23:54 +00:00
|
|
|
|
walk_list!(this, visit_ty_param_bound, bounds);
|
2015-04-03 04:13:52 +00:00
|
|
|
|
|
|
|
|
|
for trait_item in trait_items {
|
2017-01-09 09:31:14 +00:00
|
|
|
|
this.check_proc_macro_attrs(&trait_item.attrs);
|
|
|
|
|
|
2017-11-22 18:15:05 +00:00
|
|
|
|
let type_parameters = HasTypeParameters(&trait_item.generics,
|
|
|
|
|
TraitOrImplItemRibKind);
|
|
|
|
|
this.with_type_parameter_rib(type_parameters, |this| {
|
|
|
|
|
match trait_item.node {
|
|
|
|
|
TraitItemKind::Const(ref ty, ref default) => {
|
|
|
|
|
this.visit_ty(ty);
|
|
|
|
|
|
|
|
|
|
// Only impose the restrictions of
|
|
|
|
|
// ConstRibKind for an actual constant
|
|
|
|
|
// expression in a provided default.
|
|
|
|
|
if let Some(ref expr) = *default{
|
|
|
|
|
this.with_constant_rib(|this| {
|
|
|
|
|
this.visit_expr(expr);
|
|
|
|
|
});
|
|
|
|
|
}
|
2015-03-16 01:35:25 +00:00
|
|
|
|
}
|
2017-11-22 18:15:05 +00:00
|
|
|
|
TraitItemKind::Method(_, _) => {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_trait_item(this, trait_item)
|
2017-11-22 18:15:05 +00:00
|
|
|
|
}
|
|
|
|
|
TraitItemKind::Type(..) => {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_trait_item(this, trait_item)
|
2017-11-22 18:15:05 +00:00
|
|
|
|
}
|
|
|
|
|
TraitItemKind::Macro(_) => {
|
|
|
|
|
panic!("unexpanded macro in resolve!")
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
2015-04-03 04:13:52 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
2013-11-21 23:42:55 +00:00
|
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-02 13:48:57 +00:00
|
|
|
|
ItemKind::TraitAlias(ref generics, ref bounds) => {
|
|
|
|
|
// Create a new rib for the trait-wide type parameters.
|
|
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
|
|
|
|
let local_def_id = this.definitions.local_def_id(item.id);
|
|
|
|
|
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
|
|
|
|
|
this.visit_generics(generics);
|
|
|
|
|
walk_list!(this, visit_ty_param_bound, bounds);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
|
ItemKind::Mod(_) | ItemKind::ForeignMod(_) => {
|
2016-02-13 23:39:51 +00:00
|
|
|
|
self.with_scope(item.id, |this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_item(this, item);
|
2013-11-21 23:42:55 +00:00
|
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-21 14:10:22 +00:00
|
|
|
|
ItemKind::Static(ref ty, _, ref expr) |
|
|
|
|
|
ItemKind::Const(ref ty, ref expr) => {
|
|
|
|
|
self.with_item_rib(|this| {
|
|
|
|
|
this.visit_ty(ty);
|
|
|
|
|
this.with_constant_rib(|this| {
|
|
|
|
|
this.visit_expr(expr);
|
|
|
|
|
});
|
2012-10-15 19:27:09 +00:00
|
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2012-07-05 19:10:33 +00:00
|
|
|
|
|
2017-09-26 21:04:00 +00:00
|
|
|
|
ItemKind::Use(ref use_tree) => {
|
2018-03-09 23:02:39 +00:00
|
|
|
|
// Imports are resolved as global by default, add starting root segment.
|
2017-09-26 21:04:00 +00:00
|
|
|
|
let path = Path {
|
2018-03-09 23:02:39 +00:00
|
|
|
|
segments: use_tree.prefix.make_root().into_iter().collect(),
|
2017-09-26 21:04:00 +00:00
|
|
|
|
span: use_tree.span,
|
|
|
|
|
};
|
2018-01-24 12:13:39 +00:00
|
|
|
|
self.resolve_use_tree(item.id, use_tree, &path);
|
2015-02-08 16:29:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-21 16:03:02 +00:00
|
|
|
|
ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_) => {
|
2013-12-25 18:10:33 +00:00
|
|
|
|
// do nothing, these are just around to be encoded
|
2014-12-23 19:34:36 +00:00
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
|
|
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-24 12:13:39 +00:00
|
|
|
|
fn resolve_use_tree(&mut self, id: NodeId, use_tree: &ast::UseTree, prefix: &Path) {
|
2017-09-26 21:04:00 +00:00
|
|
|
|
match use_tree.kind {
|
|
|
|
|
ast::UseTreeKind::Nested(ref items) => {
|
|
|
|
|
let path = Path {
|
|
|
|
|
segments: prefix.segments
|
|
|
|
|
.iter()
|
|
|
|
|
.chain(use_tree.prefix.segments.iter())
|
|
|
|
|
.cloned()
|
|
|
|
|
.collect(),
|
|
|
|
|
span: prefix.span.to(use_tree.prefix.span),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if items.len() == 0 {
|
|
|
|
|
// Resolve prefix of an import with empty braces (issue #28388).
|
2018-05-22 22:43:02 +00:00
|
|
|
|
self.smart_resolve_path_with_crate_lint(
|
|
|
|
|
id,
|
|
|
|
|
None,
|
|
|
|
|
&path,
|
|
|
|
|
PathSource::ImportPrefix,
|
|
|
|
|
CrateLint::SimplePath(id), // TODO seems wrong
|
|
|
|
|
);
|
2017-09-26 21:04:00 +00:00
|
|
|
|
} else {
|
2018-01-24 12:13:39 +00:00
|
|
|
|
for &(ref tree, nested_id) in items {
|
|
|
|
|
self.resolve_use_tree(nested_id, tree, &path);
|
2017-09-26 21:04:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast::UseTreeKind::Simple(_) => {},
|
|
|
|
|
ast::UseTreeKind::Glob => {},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
|
fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<'a, 'b>, f: F)
|
2015-10-26 19:31:11 +00:00
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
|
{
|
2012-08-06 19:34:08 +00:00
|
|
|
|
match type_parameters {
|
2016-08-14 22:07:09 +00:00
|
|
|
|
HasTypeParameters(generics, rib_kind) => {
|
2014-09-29 23:06:13 +00:00
|
|
|
|
let mut function_type_rib = Rib::new(rib_kind);
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut seen_bindings = FxHashMap();
|
2017-10-16 19:07:26 +00:00
|
|
|
|
for param in &generics.params {
|
|
|
|
|
if let GenericParam::Type(ref type_parameter) = *param {
|
|
|
|
|
let ident = type_parameter.ident.modern();
|
|
|
|
|
debug!("with_type_parameter_rib: {}", type_parameter.id);
|
|
|
|
|
|
|
|
|
|
if seen_bindings.contains_key(&ident) {
|
|
|
|
|
let span = seen_bindings.get(&ident).unwrap();
|
|
|
|
|
let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
|
|
|
|
|
ident.name,
|
|
|
|
|
span,
|
|
|
|
|
);
|
2018-03-19 00:54:56 +00:00
|
|
|
|
resolve_error(self, type_parameter.ident.span, err);
|
2017-10-16 19:07:26 +00:00
|
|
|
|
}
|
2018-03-19 00:54:56 +00:00
|
|
|
|
seen_bindings.entry(ident).or_insert(type_parameter.ident.span);
|
2014-10-09 04:28:50 +00:00
|
|
|
|
|
2017-10-16 19:07:26 +00:00
|
|
|
|
// plain insert (no renaming)
|
|
|
|
|
let def_id = self.definitions.local_def_id(type_parameter.id);
|
|
|
|
|
let def = Def::TyParam(def_id);
|
|
|
|
|
function_type_rib.bindings.insert(ident, def);
|
|
|
|
|
self.record_def(type_parameter.id, PathResolution::new(def));
|
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[TypeNS].push(function_type_rib);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-04 02:59:04 +00:00
|
|
|
|
NoTypeParameters => {
|
2012-05-22 17:54:12 +00:00
|
|
|
|
// Nothing to do.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-27 02:10:16 +00:00
|
|
|
|
f(self);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-04-23 21:20:17 +00:00
|
|
|
|
if let HasTypeParameters(..) = type_parameters {
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[TypeNS].pop();
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
|
fn with_label_rib<F>(&mut self, f: F)
|
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
|
{
|
2014-09-29 23:06:13 +00:00
|
|
|
|
self.label_ribs.push(Rib::new(NormalRibKind));
|
2013-09-27 02:10:16 +00:00
|
|
|
|
f(self);
|
2016-04-23 21:20:17 +00:00
|
|
|
|
self.label_ribs.pop();
|
2012-08-15 02:20:56 +00:00
|
|
|
|
}
|
2013-02-21 19:08:50 +00:00
|
|
|
|
|
2017-04-21 14:10:22 +00:00
|
|
|
|
fn with_item_rib<F>(&mut self, f: F)
|
|
|
|
|
where F: FnOnce(&mut Resolver)
|
|
|
|
|
{
|
|
|
|
|
self.ribs[ValueNS].push(Rib::new(ItemRibKind));
|
|
|
|
|
self.ribs[TypeNS].push(Rib::new(ItemRibKind));
|
|
|
|
|
f(self);
|
|
|
|
|
self.ribs[TypeNS].pop();
|
|
|
|
|
self.ribs[ValueNS].pop();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
|
fn with_constant_rib<F>(&mut self, f: F)
|
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
|
{
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
|
2013-09-27 02:10:16 +00:00
|
|
|
|
f(self);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2012-10-15 19:27:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-03 04:13:52 +00:00
|
|
|
|
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
|
|
|
|
|
where F: FnOnce(&mut Resolver) -> T
|
2014-12-09 01:26:43 +00:00
|
|
|
|
{
|
2014-05-08 21:35:09 +00:00
|
|
|
|
// Handle nested impls (inside fn bodies)
|
|
|
|
|
let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
|
|
|
|
|
let result = f(self);
|
|
|
|
|
self.current_self_type = previous_value;
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 23:50:06 +00:00
|
|
|
|
/// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
|
2015-04-03 04:13:52 +00:00
|
|
|
|
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
2014-12-09 01:26:43 +00:00
|
|
|
|
{
|
2015-02-05 07:19:07 +00:00
|
|
|
|
let mut new_val = None;
|
2015-04-03 04:13:52 +00:00
|
|
|
|
let mut new_id = None;
|
2015-02-24 06:28:11 +00:00
|
|
|
|
if let Some(trait_ref) = opt_trait_ref {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
let path: Vec<_> = trait_ref.path.segments.iter()
|
2018-03-18 13:47:09 +00:00
|
|
|
|
.map(|seg| seg.ident)
|
2017-07-23 22:15:45 +00:00
|
|
|
|
.collect();
|
2018-02-22 23:50:06 +00:00
|
|
|
|
let def = self.smart_resolve_path_fragment(
|
|
|
|
|
trait_ref.ref_id,
|
|
|
|
|
None,
|
|
|
|
|
&path,
|
|
|
|
|
trait_ref.path.span,
|
2018-05-22 22:43:02 +00:00
|
|
|
|
PathSource::Trait(AliasPossibility::No),
|
|
|
|
|
CrateLint::SimplePath(trait_ref.ref_id),
|
2018-02-22 23:50:06 +00:00
|
|
|
|
).base_def();
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if def != Def::Err {
|
|
|
|
|
new_id = Some(def.def_id());
|
2017-03-18 02:10:13 +00:00
|
|
|
|
let span = trait_ref.path.span;
|
2018-05-22 15:10:17 +00:00
|
|
|
|
if let PathResult::Module(module) = self.resolve_path(
|
|
|
|
|
&path,
|
|
|
|
|
None,
|
|
|
|
|
false,
|
|
|
|
|
span,
|
|
|
|
|
CrateLint::SimplePath(trait_ref.ref_id),
|
|
|
|
|
) {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
new_val = Some((module, trait_ref.clone()));
|
|
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
|
}
|
2015-02-05 07:19:07 +00:00
|
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
|
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
|
2015-04-03 04:13:52 +00:00
|
|
|
|
let result = f(self, new_id);
|
2014-05-08 21:35:09 +00:00
|
|
|
|
self.current_trait_ref = original_trait_ref;
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-03 04:13:52 +00:00
|
|
|
|
fn with_self_rib<F>(&mut self, self_def: Def, f: F)
|
|
|
|
|
where F: FnOnce(&mut Resolver)
|
|
|
|
|
{
|
|
|
|
|
let mut self_type_rib = Rib::new(NormalRibKind);
|
|
|
|
|
|
|
|
|
|
// plain insert (no renaming, types are not currently hygienic....)
|
2016-06-22 02:50:05 +00:00
|
|
|
|
self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[TypeNS].push(self_type_rib);
|
2015-04-03 04:13:52 +00:00
|
|
|
|
f(self);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[TypeNS].pop();
|
2015-04-03 04:13:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
|
fn resolve_implementation(&mut self,
|
2014-05-31 22:53:13 +00:00
|
|
|
|
generics: &Generics,
|
|
|
|
|
opt_trait_reference: &Option<TraitRef>,
|
|
|
|
|
self_type: &Ty,
|
2015-04-03 04:13:52 +00:00
|
|
|
|
item_id: NodeId,
|
2015-12-07 14:17:41 +00:00
|
|
|
|
impl_items: &[ImplItem]) {
|
2012-05-22 17:54:12 +00:00
|
|
|
|
// If applicable, create a rib for the type parameters.
|
2016-08-14 22:07:09 +00:00
|
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
2017-01-08 11:06:44 +00:00
|
|
|
|
// Dummy self type for better errors if `Self` is used in the trait path.
|
|
|
|
|
this.with_self_rib(Def::SelfTy(None, None), |this| {
|
|
|
|
|
// Resolve the trait reference, if necessary.
|
|
|
|
|
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
|
|
|
|
let item_def_id = this.definitions.local_def_id(item_id);
|
|
|
|
|
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
|
|
|
|
|
if let Some(trait_ref) = opt_trait_reference.as_ref() {
|
|
|
|
|
// Resolve type arguments in trait path
|
|
|
|
|
visit::walk_trait_ref(this, trait_ref);
|
|
|
|
|
}
|
|
|
|
|
// Resolve the self type.
|
|
|
|
|
this.visit_ty(self_type);
|
|
|
|
|
// Resolve the type parameters.
|
|
|
|
|
this.visit_generics(generics);
|
|
|
|
|
this.with_current_self_type(self_type, |this| {
|
|
|
|
|
for impl_item in impl_items {
|
|
|
|
|
this.check_proc_macro_attrs(&impl_item.attrs);
|
|
|
|
|
this.resolve_visibility(&impl_item.vis);
|
|
|
|
|
|
2017-11-22 18:15:05 +00:00
|
|
|
|
// We also need a new scope for the impl item type parameters.
|
|
|
|
|
let type_parameters = HasTypeParameters(&impl_item.generics,
|
|
|
|
|
TraitOrImplItemRibKind);
|
|
|
|
|
this.with_type_parameter_rib(type_parameters, |this| {
|
|
|
|
|
use self::ResolutionError::*;
|
|
|
|
|
match impl_item.node {
|
|
|
|
|
ImplItemKind::Const(..) => {
|
|
|
|
|
// If this is a trait impl, ensure the const
|
|
|
|
|
// exists in trait
|
|
|
|
|
this.check_trait_item(impl_item.ident,
|
|
|
|
|
ValueNS,
|
|
|
|
|
impl_item.span,
|
|
|
|
|
|n, s| ConstNotMemberOfTrait(n, s));
|
|
|
|
|
this.with_constant_rib(|this|
|
|
|
|
|
visit::walk_impl_item(this, impl_item)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
ImplItemKind::Method(_, _) => {
|
|
|
|
|
// If this is a trait impl, ensure the method
|
|
|
|
|
// exists in trait
|
|
|
|
|
this.check_trait_item(impl_item.ident,
|
|
|
|
|
ValueNS,
|
|
|
|
|
impl_item.span,
|
|
|
|
|
|n, s| MethodNotMemberOfTrait(n, s));
|
|
|
|
|
|
2017-01-08 11:06:44 +00:00
|
|
|
|
visit::walk_impl_item(this, impl_item);
|
2017-11-22 18:15:05 +00:00
|
|
|
|
}
|
|
|
|
|
ImplItemKind::Type(ref ty) => {
|
|
|
|
|
// If this is a trait impl, ensure the type
|
|
|
|
|
// exists in trait
|
|
|
|
|
this.check_trait_item(impl_item.ident,
|
|
|
|
|
TypeNS,
|
|
|
|
|
impl_item.span,
|
|
|
|
|
|n, s| TypeNotMemberOfTrait(n, s));
|
|
|
|
|
|
2017-11-21 06:46:55 +00:00
|
|
|
|
this.visit_ty(ty);
|
2017-11-22 18:15:05 +00:00
|
|
|
|
}
|
|
|
|
|
ImplItemKind::Macro(_) =>
|
|
|
|
|
panic!("unexpanded macro in resolve!"),
|
2017-01-08 11:06:44 +00:00
|
|
|
|
}
|
2017-11-22 18:15:05 +00:00
|
|
|
|
});
|
2014-08-06 02:44:21 +00:00
|
|
|
|
}
|
2017-01-08 11:06:44 +00:00
|
|
|
|
});
|
2015-04-03 04:13:52 +00:00
|
|
|
|
});
|
2014-05-08 21:35:09 +00:00
|
|
|
|
});
|
2016-11-30 22:35:25 +00:00
|
|
|
|
});
|
2013-11-21 23:42:55 +00:00
|
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 02:10:13 +00:00
|
|
|
|
fn check_trait_item<F>(&mut self, ident: Ident, ns: Namespace, span: Span, err: F)
|
2015-10-26 19:31:11 +00:00
|
|
|
|
where F: FnOnce(Name, &str) -> ResolutionError
|
|
|
|
|
{
|
|
|
|
|
// If there is a TraitRef in scope for an impl, then the method must be in the
|
|
|
|
|
// trait.
|
2017-03-18 02:10:13 +00:00
|
|
|
|
if let Some((module, _)) = self.current_trait_ref {
|
|
|
|
|
if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() {
|
|
|
|
|
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
|
|
|
|
|
resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
|
2014-06-18 13:16:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
|
fn resolve_local(&mut self, local: &Local) {
|
2012-05-22 17:54:12 +00:00
|
|
|
|
// Resolve the type.
|
2015-09-28 21:23:54 +00:00
|
|
|
|
walk_list!(self, visit_ty, &local.ty);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
|
// Resolve the initializer.
|
2015-09-28 21:23:54 +00:00
|
|
|
|
walk_list!(self, visit_expr, &local.init);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
|
|
// Resolve the pattern.
|
2016-11-08 03:02:55 +00:00
|
|
|
|
self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap());
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-05 21:15:00 +00:00
|
|
|
|
// build a map from pattern identifiers to binding-info's.
|
|
|
|
|
// this is done hygienically. This could arise for a macro
|
|
|
|
|
// that expands into an or-pattern where one 'x' was from the
|
|
|
|
|
// user and one 'x' came from the macro.
|
2014-04-14 08:30:59 +00:00
|
|
|
|
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut binding_map = FxHashMap();
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
|
|
pat.walk(&mut |pat| {
|
|
|
|
|
if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
|
2017-02-18 19:11:42 +00:00
|
|
|
|
if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) {
|
|
|
|
|
Some(Def::Local(..)) => true,
|
2016-04-24 03:26:10 +00:00
|
|
|
|
_ => false,
|
|
|
|
|
} {
|
|
|
|
|
let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
|
2018-03-18 13:47:09 +00:00
|
|
|
|
binding_map.insert(ident, binding_info);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
true
|
2013-11-21 23:42:55 +00:00
|
|
|
|
});
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
|
|
binding_map
|
2012-07-11 01:24:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-05 21:15:00 +00:00
|
|
|
|
// check that all of the arms in an or-pattern have exactly the
|
|
|
|
|
// same set of bindings, with the same binding modes for each.
|
2018-02-24 00:12:35 +00:00
|
|
|
|
fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) {
|
|
|
|
|
if pats.is_empty() {
|
2015-10-26 19:31:11 +00:00
|
|
|
|
return;
|
2014-02-28 23:25:15 +00:00
|
|
|
|
}
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
|
|
|
|
|
let mut missing_vars = FxHashMap();
|
|
|
|
|
let mut inconsistent_vars = FxHashMap();
|
2018-02-24 00:12:35 +00:00
|
|
|
|
for (i, p) in pats.iter().enumerate() {
|
2016-02-09 20:27:42 +00:00
|
|
|
|
let map_i = self.binding_mode_map(&p);
|
2012-08-06 14:20:23 +00:00
|
|
|
|
|
2018-02-24 00:12:35 +00:00
|
|
|
|
for (j, q) in pats.iter().enumerate() {
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
if i == j {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let map_j = self.binding_mode_map(&q);
|
|
|
|
|
for (&key, &binding_i) in &map_i {
|
|
|
|
|
if map_j.len() == 0 { // Account for missing bindings when
|
|
|
|
|
let binding_error = missing_vars // map_j has none.
|
|
|
|
|
.entry(key.name)
|
|
|
|
|
.or_insert(BindingError {
|
|
|
|
|
name: key.name,
|
2017-03-05 23:19:05 +00:00
|
|
|
|
origin: BTreeSet::new(),
|
|
|
|
|
target: BTreeSet::new(),
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
});
|
|
|
|
|
binding_error.origin.insert(binding_i.span);
|
|
|
|
|
binding_error.target.insert(q.span);
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
for (&key_j, &binding_j) in &map_j {
|
|
|
|
|
match map_i.get(&key_j) {
|
|
|
|
|
None => { // missing binding
|
|
|
|
|
let binding_error = missing_vars
|
|
|
|
|
.entry(key_j.name)
|
|
|
|
|
.or_insert(BindingError {
|
|
|
|
|
name: key_j.name,
|
2017-03-05 23:19:05 +00:00
|
|
|
|
origin: BTreeSet::new(),
|
|
|
|
|
target: BTreeSet::new(),
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
});
|
|
|
|
|
binding_error.origin.insert(binding_j.span);
|
|
|
|
|
binding_error.target.insert(p.span);
|
|
|
|
|
}
|
|
|
|
|
Some(binding_i) => { // check consistent binding
|
|
|
|
|
if binding_i.binding_mode != binding_j.binding_mode {
|
|
|
|
|
inconsistent_vars
|
|
|
|
|
.entry(key.name)
|
|
|
|
|
.or_insert((binding_j.span, binding_i.span));
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2014-05-28 16:24:28 +00:00
|
|
|
|
}
|
2012-08-06 14:20:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
Clean up "pattern doesn't bind x" messages
Group "missing variable bind" spans in `or` matches and clarify wording
for the two possible cases: when a variable from the first pattern is
not in any of the subsequent patterns, and when a variable in any of the
other patterns is not in the first one.
Before:
```
error[E0408]: variable `a` from pattern #1 is not bound in pattern #2
--> file.rs:10:23
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `b` from pattern #2 is not bound in pattern #1
--> file.rs:10:32
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `b`
error[E0408]: variable `a` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `a`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #3
--> file.rs:10:37
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error[E0408]: variable `c` from pattern #3 is not bound in pattern #1
--> file.rs:10:43
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^ pattern doesn't bind `c`
error[E0408]: variable `d` from pattern #1 is not bound in pattern #4
--> file.rs:10:48
|
10 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
| ^^^^^^^^ pattern doesn't bind `d`
error: aborting due to 6 previous errors
```
After:
```
error[E0408]: variable `a` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - ^^^^^^^^^^^ ^^^^^^^^ - variable
t in all patterns
| | | |
| | | pattern doesn't bind `a`
| | pattern doesn't bind `a`
| variable not in all patterns
error[E0408]: variable `d` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| - - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `d`
| | | |
| | | pattern doesn't bind `d`
| | variable not in all patterns
| variable not in all patterns
error[E0408]: variable `b` is not bound in all patterns
--> file.rs:20:37
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern
esn't bind `b`
| | | |
| | | pattern doesn't bind `b`
| | variable not in all patterns
| pattern doesn't bind `b`
error[E0408]: variable `c` is not bound in all patterns
--> file.rs:20:48
|
20 | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => {
intln!("{:?}", a); }
| ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern
esn't bind `c`
| | | |
| | | variable not in all
tterns
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
error: aborting due to 4 previous errors
```
* Have only one presentation for binding consistency errors
* Point to same binding in multiple patterns when possible
* Check inconsistent bindings in all arms
* Simplify wording of diagnostic message
* Sort emition and spans of binding errors for deterministic output
2017-02-10 01:54:56 +00:00
|
|
|
|
}
|
|
|
|
|
let mut missing_vars = missing_vars.iter().collect::<Vec<_>>();
|
|
|
|
|
missing_vars.sort();
|
|
|
|
|
for (_, v) in missing_vars {
|
|
|
|
|
resolve_error(self,
|
|
|
|
|
*v.origin.iter().next().unwrap(),
|
|
|
|
|
ResolutionError::VariableNotBoundInPattern(v));
|
|
|
|
|
}
|
|
|
|
|
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
|
|
|
|
|
inconsistent_vars.sort();
|
|
|
|
|
for (name, v) in inconsistent_vars {
|
|
|
|
|
resolve_error(self, v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
|
2012-08-06 14:20:23 +00:00
|
|
|
|
}
|
2012-07-11 01:24:41 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
|
fn resolve_arm(&mut self, arm: &Arm) {
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut bindings_list = FxHashMap();
|
2015-01-31 17:20:46 +00:00
|
|
|
|
for pattern in &arm.pats {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-24 00:12:35 +00:00
|
|
|
|
// This has to happen *after* we determine which pat_idents are variants
|
|
|
|
|
self.check_consistent_bindings(&arm.pats);
|
2012-07-11 01:24:41 +00:00
|
|
|
|
|
2015-09-28 21:23:54 +00:00
|
|
|
|
walk_list!(self, visit_expr, &arm.guard);
|
2016-02-09 20:27:42 +00:00
|
|
|
|
self.visit_expr(&arm.body);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
|
fn resolve_block(&mut self, block: &Block) {
|
2013-10-21 20:08:31 +00:00
|
|
|
|
debug!("(resolving block) entering block");
|
2012-05-22 17:54:12 +00:00
|
|
|
|
// Move down in the graph, if there's an anonymous module rooted here.
|
2016-01-11 21:19:29 +00:00
|
|
|
|
let orig_module = self.current_module;
|
2016-12-20 08:32:15 +00:00
|
|
|
|
let anonymous_module = self.block_map.get(&block.id).cloned(); // clones a reference
|
2016-01-22 09:55:29 +00:00
|
|
|
|
|
2016-07-15 05:14:48 +00:00
|
|
|
|
let mut num_macro_definition_ribs = 0;
|
2016-01-22 09:55:29 +00:00
|
|
|
|
if let Some(anonymous_module) = anonymous_module {
|
|
|
|
|
debug!("(resolving block) found anonymous module, moving down");
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
|
|
|
|
|
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
|
2016-01-22 09:55:29 +00:00
|
|
|
|
self.current_module = anonymous_module;
|
2016-11-10 10:29:36 +00:00
|
|
|
|
self.finalize_current_module_macro_resolutions();
|
2016-01-22 09:55:29 +00:00
|
|
|
|
} else {
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Descend into the block.
|
2016-06-26 03:32:45 +00:00
|
|
|
|
for stmt in &block.stmts {
|
2017-03-05 05:15:58 +00:00
|
|
|
|
if let ast::StmtKind::Item(ref item) = stmt.node {
|
2017-03-01 23:48:16 +00:00
|
|
|
|
if let ast::ItemKind::MacroDef(..) = item.node {
|
2017-03-05 05:15:58 +00:00
|
|
|
|
num_macro_definition_ribs += 1;
|
2017-03-01 23:48:16 +00:00
|
|
|
|
let def = self.definitions.local_def_id(item.id);
|
|
|
|
|
self.ribs[ValueNS].push(Rib::new(MacroDefinition(def)));
|
|
|
|
|
self.label_ribs.push(Rib::new(MacroDefinition(def)));
|
2016-06-26 03:32:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.visit_stmt(stmt);
|
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
|
|
// Move back up.
|
2016-04-23 21:20:17 +00:00
|
|
|
|
self.current_module = orig_module;
|
2016-07-15 05:14:48 +00:00
|
|
|
|
for _ in 0 .. num_macro_definition_ribs {
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2016-07-15 05:14:48 +00:00
|
|
|
|
self.label_ribs.pop();
|
2016-06-26 03:32:45 +00:00
|
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2016-04-23 21:20:17 +00:00
|
|
|
|
if let Some(_) = anonymous_module {
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[TypeNS].pop();
|
2015-05-14 11:40:16 +00:00
|
|
|
|
}
|
2013-10-21 20:08:31 +00:00
|
|
|
|
debug!("(resolving block) leaving block");
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-03 20:15:00 +00:00
|
|
|
|
fn fresh_binding(&mut self,
|
2018-03-18 13:47:09 +00:00
|
|
|
|
ident: Ident,
|
2016-06-03 20:15:00 +00:00
|
|
|
|
pat_id: NodeId,
|
|
|
|
|
outer_pat_id: NodeId,
|
|
|
|
|
pat_src: PatternSource,
|
2016-11-08 03:02:55 +00:00
|
|
|
|
bindings: &mut FxHashMap<Ident, NodeId>)
|
2016-06-03 20:15:00 +00:00
|
|
|
|
-> PathResolution {
|
|
|
|
|
// Add the binding to the local ribs, if it
|
2016-06-03 20:15:00 +00:00
|
|
|
|
// doesn't already exist in the bindings map. (We
|
|
|
|
|
// must not add it if it's in the bindings map
|
2016-06-03 20:15:00 +00:00
|
|
|
|
// because that breaks the assumptions later
|
|
|
|
|
// passes make about or-patterns.)
|
2017-04-29 11:39:47 +00:00
|
|
|
|
let mut def = Def::Local(pat_id);
|
2018-03-18 13:47:09 +00:00
|
|
|
|
match bindings.get(&ident).cloned() {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
Some(id) if id == outer_pat_id => {
|
|
|
|
|
// `Variant(a, a)`, error
|
|
|
|
|
resolve_error(
|
|
|
|
|
self,
|
|
|
|
|
ident.span,
|
|
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
|
2018-03-18 13:47:09 +00:00
|
|
|
|
&ident.name.as_str())
|
2016-06-03 20:15:00 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
Some(..) if pat_src == PatternSource::FnParam => {
|
|
|
|
|
// `fn f(a: u8, a: u8)`, error
|
|
|
|
|
resolve_error(
|
|
|
|
|
self,
|
|
|
|
|
ident.span,
|
|
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
|
2018-03-18 13:47:09 +00:00
|
|
|
|
&ident.name.as_str())
|
2016-06-03 20:15:00 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
2018-02-24 00:12:35 +00:00
|
|
|
|
Some(..) if pat_src == PatternSource::Match ||
|
|
|
|
|
pat_src == PatternSource::IfLet ||
|
|
|
|
|
pat_src == PatternSource::WhileLet => {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
// `Variant1(a) | Variant2(a)`, ok
|
|
|
|
|
// Reuse definition from the first `a`.
|
2018-03-18 13:47:09 +00:00
|
|
|
|
def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident];
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
|
|
|
|
Some(..) => {
|
|
|
|
|
span_bug!(ident.span, "two bindings with the same name from \
|
|
|
|
|
unexpected pattern source {:?}", pat_src);
|
|
|
|
|
}
|
|
|
|
|
None => {
|
2016-06-11 15:47:47 +00:00
|
|
|
|
// A completely fresh binding, add to the lists if it's valid.
|
2018-03-18 13:47:09 +00:00
|
|
|
|
if ident.name != keywords::Invalid.name() {
|
|
|
|
|
bindings.insert(ident, outer_pat_id);
|
|
|
|
|
self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, def);
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
2016-06-11 15:47:47 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2016-06-03 20:15:00 +00:00
|
|
|
|
PathResolution::new(def)
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
2016-05-05 20:20:23 +00:00
|
|
|
|
|
2016-06-03 20:15:00 +00:00
|
|
|
|
fn resolve_pattern(&mut self,
|
|
|
|
|
pat: &Pat,
|
|
|
|
|
pat_src: PatternSource,
|
|
|
|
|
// Maps idents to the node ID for the
|
|
|
|
|
// outermost pattern that binds them.
|
2016-11-08 03:02:55 +00:00
|
|
|
|
bindings: &mut FxHashMap<Ident, NodeId>) {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
// Visit all direct subpatterns of this pattern.
|
2016-06-03 20:15:00 +00:00
|
|
|
|
let outer_pat_id = pat.id;
|
|
|
|
|
pat.walk(&mut |pat| {
|
|
|
|
|
match pat.node {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
PatKind::Ident(bmode, ident, ref opt_pat) => {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
// First try to resolve the identifier as some existing
|
|
|
|
|
// entity, then fall back to a fresh binding.
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS,
|
2017-05-12 09:21:11 +00:00
|
|
|
|
false, pat.span)
|
2016-07-29 15:19:29 +00:00
|
|
|
|
.and_then(LexicalScopeBinding::item);
|
2016-08-20 07:26:26 +00:00
|
|
|
|
let resolution = binding.map(NameBinding::def).and_then(|def| {
|
2017-10-05 19:54:34 +00:00
|
|
|
|
let is_syntactic_ambiguity = opt_pat.is_none() &&
|
|
|
|
|
bmode == BindingMode::ByValue(Mutability::Immutable);
|
2016-07-29 15:19:29 +00:00
|
|
|
|
match def {
|
2016-09-14 21:51:46 +00:00
|
|
|
|
Def::StructCtor(_, CtorKind::Const) |
|
|
|
|
|
Def::VariantCtor(_, CtorKind::Const) |
|
2017-10-05 19:54:34 +00:00
|
|
|
|
Def::Const(..) if is_syntactic_ambiguity => {
|
|
|
|
|
// Disambiguate in favor of a unit struct/variant
|
|
|
|
|
// or constant pattern.
|
2018-03-18 13:47:09 +00:00
|
|
|
|
self.record_use(ident, ValueNS, binding.unwrap(), ident.span);
|
2016-07-29 15:19:29 +00:00
|
|
|
|
Some(PathResolution::new(def))
|
2015-03-25 16:53:28 +00:00
|
|
|
|
}
|
2016-09-14 21:51:46 +00:00
|
|
|
|
Def::StructCtor(..) | Def::VariantCtor(..) |
|
2016-09-14 21:51:46 +00:00
|
|
|
|
Def::Const(..) | Def::Static(..) => {
|
2017-10-05 19:54:34 +00:00
|
|
|
|
// This is unambiguously a fresh binding, either syntactically
|
|
|
|
|
// (e.g. `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
|
|
|
|
|
// to something unusable as a pattern (e.g. constructor function),
|
|
|
|
|
// but we still conservatively report an error, see
|
|
|
|
|
// issues/33118#issuecomment-233962221 for one reason why.
|
2015-07-14 13:37:52 +00:00
|
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
|
self,
|
2016-06-03 20:15:00 +00:00
|
|
|
|
ident.span,
|
|
|
|
|
ResolutionError::BindingShadowsSomethingUnacceptable(
|
2018-03-18 13:47:09 +00:00
|
|
|
|
pat_src.descr(), ident.name, binding.unwrap())
|
2015-07-14 13:37:52 +00:00
|
|
|
|
);
|
2016-06-11 15:47:47 +00:00
|
|
|
|
None
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
2017-10-05 19:54:34 +00:00
|
|
|
|
Def::Fn(..) | Def::Err => {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
// These entities are explicitly allowed
|
|
|
|
|
// to be shadowed by fresh bindings.
|
2016-06-11 15:47:47 +00:00
|
|
|
|
None
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
|
|
|
|
def => {
|
|
|
|
|
span_bug!(ident.span, "unexpected definition for an \
|
2016-09-14 21:51:46 +00:00
|
|
|
|
identifier in pattern: {:?}", def);
|
2015-02-17 04:44:23 +00:00
|
|
|
|
}
|
2013-03-13 05:39:32 +00:00
|
|
|
|
}
|
2016-06-11 15:47:47 +00:00
|
|
|
|
}).unwrap_or_else(|| {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
|
2016-06-11 15:47:47 +00:00
|
|
|
|
});
|
2016-06-03 20:15:00 +00:00
|
|
|
|
|
|
|
|
|
self.record_def(pat.id, resolution);
|
2012-07-10 19:29:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-14 21:51:46 +00:00
|
|
|
|
PatKind::TupleStruct(ref path, ..) => {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-11 15:47:47 +00:00
|
|
|
|
PatKind::Path(ref qself, ref path) => {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
|
2015-02-05 07:19:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-26 16:23:42 +00:00
|
|
|
|
PatKind::Struct(ref path, ..) => {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2016-06-03 20:15:00 +00:00
|
|
|
|
|
|
|
|
|
_ => {}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2013-08-02 06:17:20 +00:00
|
|
|
|
true
|
2013-11-21 23:42:55 +00:00
|
|
|
|
});
|
2016-05-05 20:20:23 +00:00
|
|
|
|
|
2016-06-03 20:15:00 +00:00
|
|
|
|
visit::walk_pat(self, pat);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// High-level and context dependent path resolution routine.
|
|
|
|
|
// Resolves the path and records the resolution into definition map.
|
|
|
|
|
// If resolution fails tries several techniques to find likely
|
|
|
|
|
// resolution candidates, suggest imports or other help, and report
|
|
|
|
|
// errors in user friendly way.
|
|
|
|
|
fn smart_resolve_path(&mut self,
|
|
|
|
|
id: NodeId,
|
|
|
|
|
qself: Option<&QSelf>,
|
|
|
|
|
path: &Path,
|
|
|
|
|
source: PathSource)
|
|
|
|
|
-> PathResolution {
|
2018-05-22 22:43:02 +00:00
|
|
|
|
self.smart_resolve_path_with_crate_lint(id, qself, path, source, CrateLint::SimplePath(id))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A variant of `smart_resolve_path` where you also specify extra
|
|
|
|
|
/// information about where the path came from; this extra info is
|
|
|
|
|
/// sometimes needed for the lint that recommends rewriting
|
|
|
|
|
/// absoluate paths to `crate`, so that it knows how to frame the
|
|
|
|
|
/// suggestion. If you are just resolving a path like `foo::bar`
|
|
|
|
|
/// that appears...somewhere, though, then you just want
|
|
|
|
|
/// `CrateLint::SimplePath`, which is what `smart_resolve_path`
|
|
|
|
|
/// already provides.
|
|
|
|
|
fn smart_resolve_path_with_crate_lint(
|
|
|
|
|
&mut self,
|
|
|
|
|
id: NodeId,
|
|
|
|
|
qself: Option<&QSelf>,
|
|
|
|
|
path: &Path,
|
|
|
|
|
source: PathSource,
|
|
|
|
|
crate_lint: CrateLint
|
|
|
|
|
) -> PathResolution {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
let segments = &path.segments.iter()
|
2018-03-18 13:47:09 +00:00
|
|
|
|
.map(|seg| seg.ident)
|
2017-07-23 22:15:45 +00:00
|
|
|
|
.collect::<Vec<_>>();
|
2018-05-22 22:43:02 +00:00
|
|
|
|
self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn smart_resolve_path_fragment(&mut self,
|
2015-03-25 16:53:28 +00:00
|
|
|
|
id: NodeId,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
qself: Option<&QSelf>,
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path: &[Ident],
|
2016-11-30 22:35:25 +00:00
|
|
|
|
span: Span,
|
2018-05-22 22:43:02 +00:00
|
|
|
|
source: PathSource,
|
|
|
|
|
crate_lint: CrateLint)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
-> PathResolution {
|
2018-03-09 23:02:39 +00:00
|
|
|
|
let ident_span = path.last().map_or(span, |ident| ident.span);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
let ns = source.namespace();
|
|
|
|
|
let is_expected = &|def| source.is_expected(def);
|
2017-03-23 22:14:45 +00:00
|
|
|
|
let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
|
2016-11-30 22:35:25 +00:00
|
|
|
|
|
|
|
|
|
// Base error is amended with one short label and possibly some longer helps/notes.
|
|
|
|
|
let report_errors = |this: &mut Self, def: Option<Def>| {
|
|
|
|
|
// Make the base error.
|
|
|
|
|
let expected = source.descr_expected();
|
|
|
|
|
let path_str = names_to_string(path);
|
|
|
|
|
let code = source.error_code(def.is_some());
|
2017-03-08 19:15:12 +00:00
|
|
|
|
let (base_msg, fallback_label, base_span) = if let Some(def) = def {
|
2017-01-11 22:18:08 +00:00
|
|
|
|
(format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
|
2018-01-01 00:35:52 +00:00
|
|
|
|
format!("not a {}", expected),
|
|
|
|
|
span)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
} else {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let item_str = path[path.len() - 1];
|
2017-07-23 22:15:45 +00:00
|
|
|
|
let item_span = path[path.len() - 1].span;
|
2017-01-11 22:18:08 +00:00
|
|
|
|
let (mod_prefix, mod_str) = if path.len() == 1 {
|
|
|
|
|
(format!(""), format!("this scope"))
|
2018-03-18 13:47:09 +00:00
|
|
|
|
} else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() {
|
2017-01-11 22:18:08 +00:00
|
|
|
|
(format!(""), format!("the crate root"))
|
|
|
|
|
} else {
|
|
|
|
|
let mod_path = &path[..path.len() - 1];
|
2018-04-20 00:27:31 +00:00
|
|
|
|
let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS),
|
2018-05-22 15:10:17 +00:00
|
|
|
|
false, span, CrateLint::No) {
|
2017-01-11 22:18:08 +00:00
|
|
|
|
PathResult::Module(module) => module.def(),
|
|
|
|
|
_ => None,
|
|
|
|
|
}.map_or(format!(""), |def| format!("{} ", def.kind_name()));
|
|
|
|
|
(mod_prefix, format!("`{}`", names_to_string(mod_path)))
|
|
|
|
|
};
|
|
|
|
|
(format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
|
2018-01-01 00:35:52 +00:00
|
|
|
|
format!("not found in {}", mod_str),
|
|
|
|
|
item_span)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
};
|
2017-10-27 06:21:22 +00:00
|
|
|
|
let code = DiagnosticId::Error(code.into());
|
2017-03-08 19:15:12 +00:00
|
|
|
|
let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
|
|
|
|
|
// Emit special messages for unresolved `Self` and `self`.
|
|
|
|
|
if is_self_type(path, ns) {
|
|
|
|
|
__diagnostic_used!(E0411);
|
2017-10-27 06:21:22 +00:00
|
|
|
|
err.code(DiagnosticId::Error("E0411".into()));
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "`Self` is only available in traits and impls");
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, Vec::new());
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
if is_self_value(path, ns) {
|
|
|
|
|
__diagnostic_used!(E0424);
|
2017-10-27 06:21:22 +00:00
|
|
|
|
err.code(DiagnosticId::Error("E0424".into()));
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("`self` value is only available in \
|
2016-11-30 22:35:25 +00:00
|
|
|
|
methods with `self` parameter"));
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, Vec::new());
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Try to lookup the name in more relaxed fashion for better error reporting.
|
2017-03-18 02:10:13 +00:00
|
|
|
|
let ident = *path.last().unwrap();
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
|
2017-08-17 09:03:59 +00:00
|
|
|
|
if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
let enum_candidates =
|
2018-03-18 13:47:09 +00:00
|
|
|
|
this.lookup_import_candidates(ident.name, ns, is_enum_variant);
|
2017-04-03 14:46:35 +00:00
|
|
|
|
let mut enum_candidates = enum_candidates.iter()
|
|
|
|
|
.map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>();
|
|
|
|
|
enum_candidates.sort();
|
|
|
|
|
for (sp, variant_path, enum_path) in enum_candidates {
|
|
|
|
|
if sp == DUMMY_SP {
|
2017-05-16 13:12:24 +00:00
|
|
|
|
let msg = format!("there is an enum variant `{}`, \
|
|
|
|
|
try using `{}`?",
|
|
|
|
|
variant_path,
|
|
|
|
|
enum_path);
|
2017-03-23 22:14:45 +00:00
|
|
|
|
err.help(&msg);
|
|
|
|
|
} else {
|
2017-05-16 13:12:24 +00:00
|
|
|
|
err.span_suggestion(span, "you can try using the variant's enum",
|
|
|
|
|
enum_path);
|
2017-03-23 22:14:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if path.len() == 1 && this.self_type_is_available(span) {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) {
|
|
|
|
|
let self_is_available = this.self_value_is_available(path[0].span, span);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
match candidate {
|
|
|
|
|
AssocSuggestion::Field => {
|
2017-05-16 13:12:24 +00:00
|
|
|
|
err.span_suggestion(span, "try",
|
|
|
|
|
format!("self.{}", path_str));
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if !self_is_available {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("`self` value is only available in \
|
2016-11-30 22:35:25 +00:00
|
|
|
|
methods with `self` parameter"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AssocSuggestion::MethodWithSelf if self_is_available => {
|
2017-05-16 13:12:24 +00:00
|
|
|
|
err.span_suggestion(span, "try",
|
|
|
|
|
format!("self.{}", path_str));
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
|
2017-05-16 13:12:24 +00:00
|
|
|
|
err.span_suggestion(span, "try",
|
|
|
|
|
format!("Self::{}", path_str));
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 11:28:05 +00:00
|
|
|
|
let mut levenshtein_worked = false;
|
|
|
|
|
|
|
|
|
|
// Try Levenshtein.
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected, span) {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(ident_span, format!("did you mean `{}`?", candidate));
|
2017-04-18 11:28:05 +00:00
|
|
|
|
levenshtein_worked = true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Try context dependent help if relaxed lookup didn't work.
|
|
|
|
|
if let Some(def) = def {
|
|
|
|
|
match (def, source) {
|
|
|
|
|
(Def::Macro(..), _) => {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2017-12-13 06:56:22 +00:00
|
|
|
|
(Def::TyAlias(..), PathSource::Trait(_)) => {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, "type aliases cannot be used for traits");
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2017-03-08 19:15:12 +00:00
|
|
|
|
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ExprKind::Field(_, ident) => {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(parent.span, format!("did you mean `{}::{}`?",
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path_str, ident));
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2017-07-06 23:39:55 +00:00
|
|
|
|
ExprKind::MethodCall(ref segment, ..) => {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
|
2018-03-18 00:53:41 +00:00
|
|
|
|
path_str, segment.ident));
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
},
|
2017-11-23 13:10:23 +00:00
|
|
|
|
(Def::Enum(..), PathSource::TupleStruct)
|
|
|
|
|
| (Def::Enum(..), PathSource::Expr(..)) => {
|
2017-09-30 08:27:02 +00:00
|
|
|
|
if let Some(variants) = this.collect_enum_variants(def) {
|
|
|
|
|
err.note(&format!("did you mean to use one \
|
|
|
|
|
of the following variants?\n{}",
|
|
|
|
|
variants.iter()
|
2017-11-23 13:10:23 +00:00
|
|
|
|
.map(|suggestion| path_names_to_string(suggestion))
|
|
|
|
|
.map(|suggestion| format!("- `{}`", suggestion))
|
2017-09-30 08:27:02 +00:00
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
|
.join("\n")));
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
err.note("did you mean to use one of the enum's variants?");
|
|
|
|
|
}
|
|
|
|
|
return (err, candidates);
|
|
|
|
|
},
|
2018-01-15 10:00:56 +00:00
|
|
|
|
(Def::Struct(def_id), _) if ns == ValueNS => {
|
2018-01-01 23:29:50 +00:00
|
|
|
|
if let Some((ctor_def, ctor_vis))
|
|
|
|
|
= this.struct_constructors.get(&def_id).cloned() {
|
|
|
|
|
let accessible_ctor = this.is_accessible(ctor_vis);
|
|
|
|
|
if is_expected(ctor_def) && !accessible_ctor {
|
|
|
|
|
err.span_label(span, format!("constructor is not visible \
|
|
|
|
|
here due to private fields"));
|
2017-01-28 23:56:52 +00:00
|
|
|
|
}
|
2018-01-01 23:29:50 +00:00
|
|
|
|
} else {
|
2018-01-01 00:35:52 +00:00
|
|
|
|
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
|
|
|
|
|
path_str));
|
2017-01-28 23:56:52 +00:00
|
|
|
|
}
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2018-01-20 20:02:40 +00:00
|
|
|
|
(Def::Union(..), _) |
|
|
|
|
|
(Def::Variant(..), _) |
|
|
|
|
|
(Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
|
2017-10-22 16:19:30 +00:00
|
|
|
|
path_str));
|
2017-08-17 09:03:59 +00:00
|
|
|
|
return (err, candidates);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2018-01-15 13:18:06 +00:00
|
|
|
|
(Def::SelfTy(..), _) if ns == ValueNS => {
|
2018-01-20 20:02:40 +00:00
|
|
|
|
err.span_label(span, fallback_label);
|
2018-01-15 10:00:56 +00:00
|
|
|
|
err.note("can't use `Self` as a constructor, you must use the \
|
|
|
|
|
implemented struct");
|
2018-01-15 23:02:53 +00:00
|
|
|
|
return (err, candidates);
|
2018-01-02 05:21:11 +00:00
|
|
|
|
}
|
2018-01-20 20:02:40 +00:00
|
|
|
|
(Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
|
2018-01-15 13:18:06 +00:00
|
|
|
|
err.note("can't use a type alias as a constructor");
|
2018-01-15 23:02:53 +00:00
|
|
|
|
return (err, candidates);
|
2018-01-15 13:18:06 +00:00
|
|
|
|
}
|
2016-11-30 22:35:25 +00:00
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-11 22:18:08 +00:00
|
|
|
|
// Fallback label.
|
2017-04-18 11:28:05 +00:00
|
|
|
|
if !levenshtein_worked {
|
2017-05-04 12:17:23 +00:00
|
|
|
|
err.span_label(base_span, fallback_label);
|
2017-07-18 18:41:21 +00:00
|
|
|
|
this.type_ascription_suggestion(&mut err, base_span);
|
2017-04-18 11:28:05 +00:00
|
|
|
|
}
|
2017-08-17 09:03:59 +00:00
|
|
|
|
(err, candidates)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
};
|
|
|
|
|
let report_errors = |this: &mut Self, def: Option<Def>| {
|
2017-08-17 09:03:59 +00:00
|
|
|
|
let (err, candidates) = report_errors(this, def);
|
|
|
|
|
let def_id = this.current_module.normal_ancestor_id;
|
|
|
|
|
let node_id = this.definitions.as_local_node_id(def_id).unwrap();
|
|
|
|
|
let better = def.is_some();
|
|
|
|
|
this.use_injections.push(UseError { err, candidates, node_id, better });
|
2016-11-30 22:35:25 +00:00
|
|
|
|
err_path_resolution()
|
|
|
|
|
};
|
|
|
|
|
|
2018-05-22 22:43:02 +00:00
|
|
|
|
let resolution = match self.resolve_qpath_anywhere(
|
|
|
|
|
id,
|
|
|
|
|
qself,
|
|
|
|
|
path,
|
|
|
|
|
ns,
|
|
|
|
|
span,
|
|
|
|
|
source.defer_to_typeck(),
|
|
|
|
|
source.global_by_default(),
|
|
|
|
|
crate_lint,
|
|
|
|
|
) {
|
2017-02-18 19:11:42 +00:00
|
|
|
|
Some(resolution) if resolution.unresolved_segments() == 0 => {
|
|
|
|
|
if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
resolution
|
|
|
|
|
} else {
|
2017-01-20 15:53:49 +00:00
|
|
|
|
// Add a temporary hack to smooth the transition to new struct ctor
|
|
|
|
|
// visibility rules. See #38932 for more details.
|
|
|
|
|
let mut res = None;
|
2017-02-18 19:11:42 +00:00
|
|
|
|
if let Def::Struct(def_id) = resolution.base_def() {
|
2017-01-20 15:53:49 +00:00
|
|
|
|
if let Some((ctor_def, ctor_vis))
|
2017-01-28 23:56:52 +00:00
|
|
|
|
= self.struct_constructors.get(&def_id).cloned() {
|
2017-01-20 15:53:49 +00:00
|
|
|
|
if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
|
|
|
|
|
let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
|
2017-07-27 04:51:09 +00:00
|
|
|
|
self.session.buffer_lint(lint, id, span,
|
2017-01-20 15:53:49 +00:00
|
|
|
|
"private struct constructors are not usable through \
|
2018-01-12 21:41:45 +00:00
|
|
|
|
re-exports in outer modules",
|
2017-07-27 04:51:09 +00:00
|
|
|
|
);
|
2017-01-20 15:53:49 +00:00
|
|
|
|
res = Some(PathResolution::new(ctor_def));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-18 19:11:42 +00:00
|
|
|
|
res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def())))
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Some(resolution) if source.defer_to_typeck() => {
|
|
|
|
|
// Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B`
|
|
|
|
|
// or `<T>::A::B`. If `B` should be resolved in value namespace then
|
|
|
|
|
// it needs to be added to the trait map.
|
|
|
|
|
if ns == ValueNS {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let item_name = *path.last().unwrap();
|
2016-11-30 22:35:25 +00:00
|
|
|
|
let traits = self.get_traits_containing_item(item_name, ns);
|
|
|
|
|
self.trait_map.insert(id, traits);
|
|
|
|
|
}
|
|
|
|
|
resolution
|
|
|
|
|
}
|
|
|
|
|
_ => report_errors(self, None)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if let PathSource::TraitItem(..) = source {} else {
|
|
|
|
|
// Avoid recording definition of `A::B` in `<T as A>::B::C`.
|
|
|
|
|
self.record_def(id, resolution);
|
|
|
|
|
}
|
|
|
|
|
resolution
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-18 18:41:21 +00:00
|
|
|
|
fn type_ascription_suggestion(&self,
|
|
|
|
|
err: &mut DiagnosticBuilder,
|
|
|
|
|
base_span: Span) {
|
|
|
|
|
debug!("type_ascription_suggetion {:?}", base_span);
|
|
|
|
|
let cm = self.session.codemap();
|
|
|
|
|
debug!("self.current_type_ascription {:?}", self.current_type_ascription);
|
|
|
|
|
if let Some(sp) = self.current_type_ascription.last() {
|
|
|
|
|
let mut sp = *sp;
|
|
|
|
|
loop { // try to find the `:`, bail on first non-':'/non-whitespace
|
2018-01-14 17:29:07 +00:00
|
|
|
|
sp = cm.next_point(sp);
|
|
|
|
|
if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
|
2017-07-18 18:41:21 +00:00
|
|
|
|
debug!("snippet {:?}", snippet);
|
2017-07-31 20:04:34 +00:00
|
|
|
|
let line_sp = cm.lookup_char_pos(sp.hi()).line;
|
|
|
|
|
let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;
|
2017-07-18 18:41:21 +00:00
|
|
|
|
debug!("{:?} {:?}", line_sp, line_base_sp);
|
|
|
|
|
if snippet == ":" {
|
|
|
|
|
err.span_label(base_span,
|
|
|
|
|
"expecting a type here because of type ascription");
|
|
|
|
|
if line_sp != line_base_sp {
|
|
|
|
|
err.span_suggestion_short(sp,
|
|
|
|
|
"did you mean to use `;` here instead?",
|
|
|
|
|
";".to_string());
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
} else if snippet.trim().len() != 0 {
|
|
|
|
|
debug!("tried to find type ascription `:` token, couldn't find it");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-12 09:21:11 +00:00
|
|
|
|
fn self_type_is_available(&mut self, span: Span) -> bool {
|
|
|
|
|
let binding = self.resolve_ident_in_lexical_scope(keywords::SelfType.ident(),
|
|
|
|
|
TypeNS, false, span);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-17 23:57:23 +00:00
|
|
|
|
fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool {
|
|
|
|
|
let ident = Ident::new(keywords::SelfValue.name(), self_span);
|
|
|
|
|
let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, path_span);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Resolve in alternative namespaces if resolution in the primary namespace fails.
|
|
|
|
|
fn resolve_qpath_anywhere(&mut self,
|
|
|
|
|
id: NodeId,
|
|
|
|
|
qself: Option<&QSelf>,
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path: &[Ident],
|
2016-11-30 22:35:25 +00:00
|
|
|
|
primary_ns: Namespace,
|
|
|
|
|
span: Span,
|
|
|
|
|
defer_to_typeck: bool,
|
2018-05-22 22:43:02 +00:00
|
|
|
|
global_by_default: bool,
|
|
|
|
|
crate_lint: CrateLint)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
-> Option<PathResolution> {
|
|
|
|
|
let mut fin_res = None;
|
|
|
|
|
// FIXME: can't resolve paths in macro namespace yet, macros are
|
|
|
|
|
// processed by the little special hack below.
|
|
|
|
|
for (i, ns) in [primary_ns, TypeNS, ValueNS, /*MacroNS*/].iter().cloned().enumerate() {
|
|
|
|
|
if i == 0 || ns != primary_ns {
|
2018-05-22 22:43:02 +00:00
|
|
|
|
match self.resolve_qpath(id, qself, path, ns, span, global_by_default, crate_lint) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// If defer_to_typeck, then resolution > no resolution,
|
|
|
|
|
// otherwise full resolution > partial resolution > no resolution.
|
2017-02-18 19:11:42 +00:00
|
|
|
|
Some(res) if res.unresolved_segments() == 0 || defer_to_typeck =>
|
|
|
|
|
return Some(res),
|
2016-11-30 22:35:25 +00:00
|
|
|
|
res => if fin_res.is_none() { fin_res = res },
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let is_global = self.global_macros.get(&path[0].name).cloned()
|
2017-02-23 09:48:20 +00:00
|
|
|
|
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
|
2017-07-23 22:15:45 +00:00
|
|
|
|
if primary_ns != MacroNS && (is_global ||
|
2018-03-18 13:47:09 +00:00
|
|
|
|
self.macro_names.contains(&path[0].modern())) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Return some dummy definition, it's enough for error reporting.
|
2017-02-23 09:42:33 +00:00
|
|
|
|
return Some(
|
|
|
|
|
PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
|
|
|
|
|
);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
fin_res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Handles paths that may refer to associated items.
|
|
|
|
|
fn resolve_qpath(&mut self,
|
|
|
|
|
id: NodeId,
|
|
|
|
|
qself: Option<&QSelf>,
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path: &[Ident],
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ns: Namespace,
|
|
|
|
|
span: Span,
|
2018-05-22 22:43:02 +00:00
|
|
|
|
global_by_default: bool,
|
|
|
|
|
crate_lint: CrateLint)
|
2016-11-30 22:35:25 +00:00
|
|
|
|
-> Option<PathResolution> {
|
2018-05-22 19:26:35 +00:00
|
|
|
|
debug!(
|
|
|
|
|
"resolve_qpath(id={:?}, qself={:?}, path={:?}, \
|
|
|
|
|
ns={:?}, span={:?}, global_by_default={:?})",
|
|
|
|
|
id,
|
|
|
|
|
qself,
|
|
|
|
|
path,
|
|
|
|
|
ns,
|
|
|
|
|
span,
|
|
|
|
|
global_by_default,
|
|
|
|
|
);
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if let Some(qself) = qself {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
if qself.position == 0 {
|
|
|
|
|
// FIXME: Create some fake resolution that can't possibly be a type.
|
2017-02-18 19:11:42 +00:00
|
|
|
|
return Some(PathResolution::with_unresolved_segments(
|
|
|
|
|
Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len()
|
|
|
|
|
));
|
2015-05-07 07:52:38 +00:00
|
|
|
|
}
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
|
|
|
|
|
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
|
2018-05-22 22:43:02 +00:00
|
|
|
|
let res = self.smart_resolve_path_fragment(
|
|
|
|
|
id,
|
|
|
|
|
None,
|
|
|
|
|
&path[..qself.position + 1],
|
|
|
|
|
span,
|
|
|
|
|
PathSource::TraitItem(ns),
|
|
|
|
|
crate_lint, // TODO wrong
|
|
|
|
|
);
|
2017-02-18 19:11:42 +00:00
|
|
|
|
return Some(PathResolution::with_unresolved_segments(
|
|
|
|
|
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
|
|
|
|
|
));
|
2015-03-25 16:53:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 15:45:36 +00:00
|
|
|
|
let result = match self.resolve_path(
|
|
|
|
|
&path,
|
|
|
|
|
Some(ns),
|
|
|
|
|
true,
|
|
|
|
|
span,
|
|
|
|
|
CrateLint::SimplePath(id),
|
|
|
|
|
) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
PathResult::NonModule(path_res) => path_res,
|
2016-11-25 06:07:21 +00:00
|
|
|
|
PathResult::Module(module) if !module.is_normal() => {
|
|
|
|
|
PathResolution::new(module.def().unwrap())
|
2016-03-10 19:01:38 +00:00
|
|
|
|
}
|
2016-03-08 18:40:13 +00:00
|
|
|
|
// In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
|
|
|
|
|
// don't report an error right away, but try to fallback to a primitive type.
|
|
|
|
|
// So, we are still able to successfully resolve something like
|
|
|
|
|
//
|
|
|
|
|
// use std::u8; // bring module u8 in scope
|
|
|
|
|
// fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8
|
2016-03-10 19:01:38 +00:00
|
|
|
|
// u8::max_value() // OK, resolves to associated function <u8>::max_value,
|
|
|
|
|
// // not to non-existent std::u8::max_value
|
2016-03-08 18:40:13 +00:00
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// Such behavior is required for backward compatibility.
|
|
|
|
|
// The same fallback is used when `a` resolves to nothing.
|
2016-12-14 23:12:08 +00:00
|
|
|
|
PathResult::Module(..) | PathResult::Failed(..)
|
2016-12-05 03:51:11 +00:00
|
|
|
|
if (ns == TypeNS || path.len() > 1) &&
|
2017-07-23 22:15:45 +00:00
|
|
|
|
self.primitive_type_table.primitive_types
|
2018-03-18 13:47:09 +00:00
|
|
|
|
.contains_key(&path[0].name) => {
|
|
|
|
|
let prim = self.primitive_type_table.primitive_types[&path[0].name];
|
2017-02-18 19:11:42 +00:00
|
|
|
|
PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
|
2017-07-23 22:15:45 +00:00
|
|
|
|
PathResult::Failed(span, msg, false) => {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
|
|
|
|
err_path_resolution()
|
|
|
|
|
}
|
2016-11-30 22:35:25 +00:00
|
|
|
|
PathResult::Failed(..) => return None,
|
|
|
|
|
PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
|
2016-11-25 06:07:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-02-18 19:11:42 +00:00
|
|
|
|
if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path[0].name != keywords::CrateRoot.name() &&
|
|
|
|
|
path[0].name != keywords::DollarCrate.name() {
|
2017-01-03 02:47:18 +00:00
|
|
|
|
let unqualified_result = {
|
2018-05-22 15:45:36 +00:00
|
|
|
|
match self.resolve_path(
|
|
|
|
|
&[*path.last().unwrap()],
|
|
|
|
|
Some(ns),
|
|
|
|
|
false,
|
|
|
|
|
span,
|
|
|
|
|
CrateLint::No,
|
|
|
|
|
) {
|
2017-02-18 19:11:42 +00:00
|
|
|
|
PathResult::NonModule(path_res) => path_res.base_def(),
|
2017-01-03 02:47:18 +00:00
|
|
|
|
PathResult::Module(module) => module.def().unwrap(),
|
|
|
|
|
_ => return Some(result),
|
|
|
|
|
}
|
|
|
|
|
};
|
2017-02-18 19:11:42 +00:00
|
|
|
|
if result.base_def() == unqualified_result {
|
2017-01-03 02:47:18 +00:00
|
|
|
|
let lint = lint::builtin::UNUSED_QUALIFICATIONS;
|
2017-07-27 04:51:09 +00:00
|
|
|
|
self.session.buffer_lint(lint, id, span, "unnecessary qualification")
|
2015-03-29 23:21:20 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
2015-03-29 23:21:20 +00:00
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
|
Some(result)
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 15:10:17 +00:00
|
|
|
|
fn resolve_path(
|
|
|
|
|
&mut self,
|
|
|
|
|
path: &[Ident],
|
|
|
|
|
opt_ns: Option<Namespace>, // `None` indicates a module path
|
|
|
|
|
record_used: bool,
|
|
|
|
|
path_span: Span,
|
|
|
|
|
crate_lint: CrateLint,
|
|
|
|
|
) -> PathResult<'a> {
|
2016-12-05 03:51:11 +00:00
|
|
|
|
let mut module = None;
|
|
|
|
|
let mut allow_super = true;
|
2018-05-11 17:02:17 +00:00
|
|
|
|
let mut second_binding = None;
|
2016-11-25 06:07:21 +00:00
|
|
|
|
|
2018-05-22 19:26:35 +00:00
|
|
|
|
debug!(
|
|
|
|
|
"resolve_path(path={:?}, opt_ns={:?}, record_used={:?}, path_span={:?}, crate_lint={:?})",
|
|
|
|
|
path,
|
|
|
|
|
opt_ns,
|
|
|
|
|
record_used,
|
|
|
|
|
path_span,
|
|
|
|
|
crate_lint,
|
|
|
|
|
);
|
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
|
for (i, &ident) in path.iter().enumerate() {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
debug!("resolve_path ident {} {:?}", i, ident);
|
2016-11-25 06:07:21 +00:00
|
|
|
|
let is_last = i == path.len() - 1;
|
|
|
|
|
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let name = ident.name;
|
2016-11-25 06:07:21 +00:00
|
|
|
|
|
2017-11-19 14:05:29 +00:00
|
|
|
|
if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let mut ctxt = ident.span.ctxt().modern();
|
2017-03-22 08:39:51 +00:00
|
|
|
|
module = Some(self.resolve_self(&mut ctxt, self.current_module));
|
2016-11-25 06:07:21 +00:00
|
|
|
|
continue
|
2017-11-19 14:05:29 +00:00
|
|
|
|
} else if allow_super && ns == TypeNS && name == keywords::Super.name() {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let mut ctxt = ident.span.ctxt().modern();
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let self_module = match i {
|
|
|
|
|
0 => self.resolve_self(&mut ctxt, self.current_module),
|
|
|
|
|
_ => module.unwrap(),
|
|
|
|
|
};
|
2016-11-25 06:07:21 +00:00
|
|
|
|
if let Some(parent) = self_module.parent {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
module = Some(self.resolve_self(&mut ctxt, parent));
|
2016-11-25 06:07:21 +00:00
|
|
|
|
continue
|
|
|
|
|
} else {
|
|
|
|
|
let msg = "There are too many initial `super`s.".to_string();
|
2017-07-23 22:15:45 +00:00
|
|
|
|
return PathResult::Failed(ident.span, msg, false);
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
2018-01-01 14:42:32 +00:00
|
|
|
|
} else if i == 0 && ns == TypeNS && name == keywords::Extern.name() {
|
|
|
|
|
continue;
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
allow_super = false;
|
|
|
|
|
|
2017-11-04 20:56:45 +00:00
|
|
|
|
if ns == TypeNS {
|
2017-11-19 14:05:29 +00:00
|
|
|
|
if (i == 0 && name == keywords::CrateRoot.name()) ||
|
2018-04-21 00:04:29 +00:00
|
|
|
|
(i == 0 && name == keywords::Crate.name()) ||
|
2017-11-19 14:05:29 +00:00
|
|
|
|
(i == 1 && name == keywords::Crate.name() &&
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path[0].name == keywords::CrateRoot.name()) {
|
2017-11-04 20:56:45 +00:00
|
|
|
|
// `::a::b` or `::crate::a::b`
|
2018-03-18 13:47:09 +00:00
|
|
|
|
module = Some(self.resolve_crate_root(ident.span.ctxt(), false));
|
2017-11-04 20:56:45 +00:00
|
|
|
|
continue
|
2017-11-19 14:05:29 +00:00
|
|
|
|
} else if i == 0 && name == keywords::DollarCrate.name() {
|
2017-11-04 20:56:45 +00:00
|
|
|
|
// `$crate::a::b`
|
2018-03-18 13:47:09 +00:00
|
|
|
|
module = Some(self.resolve_crate_root(ident.span.ctxt(), true));
|
2017-11-04 20:56:45 +00:00
|
|
|
|
continue
|
2018-05-13 13:14:43 +00:00
|
|
|
|
} else if i == 1 && !ident.is_path_segment_keyword() {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let prev_name = path[0].name;
|
2018-01-01 14:42:32 +00:00
|
|
|
|
if prev_name == keywords::Extern.name() ||
|
|
|
|
|
prev_name == keywords::CrateRoot.name() &&
|
2018-05-04 18:37:27 +00:00
|
|
|
|
self.session.features_untracked().extern_absolute_paths &&
|
|
|
|
|
self.session.rust_2018() {
|
2018-01-01 14:42:32 +00:00
|
|
|
|
// `::extern_crate::a::b`
|
2018-04-10 14:01:24 +00:00
|
|
|
|
let crate_id = self.crate_loader.process_path_extern(name, ident.span);
|
2018-01-01 14:42:32 +00:00
|
|
|
|
let crate_root =
|
|
|
|
|
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
|
|
|
|
self.populate_module_if_necessary(crate_root);
|
|
|
|
|
module = Some(crate_root);
|
|
|
|
|
continue
|
|
|
|
|
}
|
2017-11-04 20:56:45 +00:00
|
|
|
|
}
|
2016-12-05 03:51:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-19 14:05:29 +00:00
|
|
|
|
// Report special messages for path segment keywords in wrong positions.
|
|
|
|
|
if name == keywords::CrateRoot.name() && i != 0 ||
|
|
|
|
|
name == keywords::DollarCrate.name() && i != 0 ||
|
|
|
|
|
name == keywords::SelfValue.name() && i != 0 ||
|
|
|
|
|
name == keywords::SelfType.name() && i != 0 ||
|
|
|
|
|
name == keywords::Super.name() && i != 0 ||
|
2018-01-01 14:42:32 +00:00
|
|
|
|
name == keywords::Extern.name() && i != 0 ||
|
2018-04-21 00:04:29 +00:00
|
|
|
|
// we allow crate::foo and ::crate::foo but nothing else
|
|
|
|
|
name == keywords::Crate.name() && i > 1 &&
|
|
|
|
|
path[0].name != keywords::CrateRoot.name() ||
|
|
|
|
|
name == keywords::Crate.name() && path.len() == 1 {
|
2017-11-19 14:05:29 +00:00
|
|
|
|
let name_str = if name == keywords::CrateRoot.name() {
|
|
|
|
|
format!("crate root")
|
|
|
|
|
} else {
|
|
|
|
|
format!("`{}`", name)
|
|
|
|
|
};
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() {
|
2017-11-19 14:05:29 +00:00
|
|
|
|
format!("global paths cannot start with {}", name_str)
|
|
|
|
|
} else {
|
|
|
|
|
format!("{} in paths can only be used in start position", name_str)
|
|
|
|
|
};
|
|
|
|
|
return PathResult::Failed(ident.span, msg, false);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
|
let binding = if let Some(module) = module {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
|
2016-11-27 10:58:46 +00:00
|
|
|
|
} else if opt_ns == Some(MacroNS) {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
|
2017-03-11 10:58:19 +00:00
|
|
|
|
.map(MacroBinding::binding)
|
2016-11-25 06:07:21 +00:00
|
|
|
|
} else {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) {
|
2018-05-11 17:02:17 +00:00
|
|
|
|
// we found a locally-imported or available item/module
|
2016-11-25 06:07:21 +00:00
|
|
|
|
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
2018-05-11 17:02:17 +00:00
|
|
|
|
// we found a local variable or type param
|
2016-11-27 10:58:46 +00:00
|
|
|
|
Some(LexicalScopeBinding::Def(def))
|
|
|
|
|
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
|
2017-02-18 19:11:42 +00:00
|
|
|
|
return PathResult::NonModule(PathResolution::with_unresolved_segments(
|
|
|
|
|
def, path.len() - 1
|
|
|
|
|
));
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
2017-05-12 09:21:11 +00:00
|
|
|
|
_ => Err(if record_used { Determined } else { Undetermined }),
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match binding {
|
|
|
|
|
Ok(binding) => {
|
2018-05-11 17:02:17 +00:00
|
|
|
|
if i == 1 {
|
|
|
|
|
second_binding = Some(binding);
|
|
|
|
|
}
|
2017-01-08 13:38:40 +00:00
|
|
|
|
let def = binding.def();
|
|
|
|
|
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
|
2016-11-27 00:23:54 +00:00
|
|
|
|
if let Some(next_module) = binding.module() {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
module = Some(next_module);
|
2017-01-08 13:38:40 +00:00
|
|
|
|
} else if def == Def::Err {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
return PathResult::NonModule(err_path_resolution());
|
2017-01-08 13:38:40 +00:00
|
|
|
|
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
|
2018-05-11 17:02:17 +00:00
|
|
|
|
self.lint_if_path_starts_with_module(
|
2018-05-22 15:10:17 +00:00
|
|
|
|
crate_lint,
|
2018-05-11 17:02:17 +00:00
|
|
|
|
path,
|
|
|
|
|
path_span,
|
|
|
|
|
second_binding,
|
|
|
|
|
);
|
2017-02-18 19:11:42 +00:00
|
|
|
|
return PathResult::NonModule(PathResolution::with_unresolved_segments(
|
|
|
|
|
def, path.len() - i - 1
|
|
|
|
|
));
|
2016-11-25 06:07:21 +00:00
|
|
|
|
} else {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
return PathResult::Failed(ident.span,
|
2018-03-18 13:47:09 +00:00
|
|
|
|
format!("Not a module `{}`", ident),
|
2017-07-23 22:15:45 +00:00
|
|
|
|
is_last);
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(Undetermined) => return PathResult::Indeterminate,
|
|
|
|
|
Err(Determined) => {
|
|
|
|
|
if let Some(module) = module {
|
|
|
|
|
if opt_ns.is_some() && !module.is_normal() {
|
2017-02-18 19:11:42 +00:00
|
|
|
|
return PathResult::NonModule(PathResolution::with_unresolved_segments(
|
|
|
|
|
module.def().unwrap(), path.len() - i
|
|
|
|
|
));
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-26 12:47:52 +00:00
|
|
|
|
let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
|
2016-11-25 06:07:21 +00:00
|
|
|
|
let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
|
|
|
|
|
let mut candidates =
|
2017-11-19 14:05:29 +00:00
|
|
|
|
self.lookup_import_candidates(name, TypeNS, is_mod);
|
2018-03-30 09:23:27 +00:00
|
|
|
|
candidates.sort_by_cached_key(|c| {
|
|
|
|
|
(c.path.segments.len(), c.path.to_string())
|
|
|
|
|
});
|
2016-11-25 06:07:21 +00:00
|
|
|
|
if let Some(candidate) = candidates.get(0) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
format!("Did you mean `{}`?", candidate.path)
|
2016-11-25 06:07:21 +00:00
|
|
|
|
} else {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
format!("Maybe a missing `extern crate {};`?", ident)
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
} else if i == 0 {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
format!("Use of undeclared type or module `{}`", ident)
|
2016-11-25 06:07:21 +00:00
|
|
|
|
} else {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
format!("Could not find `{}` in `{}`", ident, path[i - 1])
|
2016-11-25 06:07:21 +00:00
|
|
|
|
};
|
2017-07-23 22:15:45 +00:00
|
|
|
|
return PathResult::Failed(ident.span, msg, is_last);
|
2016-11-25 06:07:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-20 09:29:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 15:10:17 +00:00
|
|
|
|
self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding);
|
2018-05-11 17:02:17 +00:00
|
|
|
|
|
2016-12-05 03:51:11 +00:00
|
|
|
|
PathResult::Module(module.unwrap_or(self.graph_root))
|
2015-11-03 18:44:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 15:10:17 +00:00
|
|
|
|
fn lint_if_path_starts_with_module(
|
|
|
|
|
&self,
|
|
|
|
|
crate_lint: CrateLint,
|
|
|
|
|
path: &[Ident],
|
|
|
|
|
path_span: Span,
|
|
|
|
|
second_binding: Option<&NameBinding>,
|
|
|
|
|
) {
|
|
|
|
|
let (diag_id, diag_span) = match crate_lint {
|
|
|
|
|
CrateLint::No => return,
|
|
|
|
|
CrateLint::SimplePath(id) => (id, path_span),
|
|
|
|
|
CrateLint::UsePath { root_id, root_span } => (root_id, root_span),
|
2018-05-11 17:02:17 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let first_name = match path.get(0) {
|
|
|
|
|
Some(ident) => ident.name,
|
|
|
|
|
None => return,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// We're only interested in `use` paths which should start with
|
|
|
|
|
// `{{root}}` or `extern` currently.
|
|
|
|
|
if first_name != keywords::Extern.name() && first_name != keywords::CrateRoot.name() {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match path.get(1) {
|
|
|
|
|
// If this import looks like `crate::...` it's already good
|
|
|
|
|
Some(name) if name.name == keywords::Crate.name() => return,
|
|
|
|
|
// Otherwise go below to see if it's an extern crate
|
|
|
|
|
Some(_) => {}
|
|
|
|
|
// If the path has length one (and it's `CrateRoot` most likely)
|
|
|
|
|
// then we don't know whether we're gonna be importing a crate or an
|
|
|
|
|
// item in our crate. Defer this lint to elsewhere
|
|
|
|
|
None => return,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the first element of our path was actually resolved to an
|
|
|
|
|
// `ExternCrate` (also used for `crate::...`) then no need to issue a
|
|
|
|
|
// warning, this looks all good!
|
|
|
|
|
if let Some(binding) = second_binding {
|
|
|
|
|
if let NameBindingKind::Import { directive: d, .. } = binding.kind {
|
|
|
|
|
if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 15:10:17 +00:00
|
|
|
|
self.lint_path_starts_with_module(diag_id, diag_span);
|
2018-05-11 17:02:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn lint_path_starts_with_module(&self, id: NodeId, span: Span) {
|
|
|
|
|
// In the 2018 edition this lint is a hard error, so nothing to do
|
|
|
|
|
if self.session.rust_2018() {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// In the 2015 edition there's no use in emitting lints unless the
|
|
|
|
|
// crate's already enabled the feature that we're going to suggest
|
|
|
|
|
if !self.session.features_untracked().crate_in_paths {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
let diag = lint::builtin::BuiltinLintDiagnostics
|
|
|
|
|
::AbsPathWithModule(span);
|
|
|
|
|
self.session.buffer_lint_with_diagnostic(
|
|
|
|
|
lint::builtin::ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
|
|
|
|
|
id, span,
|
|
|
|
|
"absolute paths must start with `self`, `super`, \
|
|
|
|
|
`crate`, or an external crate name in the 2018 edition",
|
|
|
|
|
diag);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-03 18:44:23 +00:00
|
|
|
|
// Resolve a local definition, potentially adjusting for closures.
|
2017-01-25 20:01:11 +00:00
|
|
|
|
fn adjust_local_def(&mut self,
|
|
|
|
|
ns: Namespace,
|
|
|
|
|
rib_index: usize,
|
|
|
|
|
mut def: Def,
|
2017-05-12 09:21:11 +00:00
|
|
|
|
record_used: bool,
|
|
|
|
|
span: Span) -> Def {
|
2017-01-25 20:01:11 +00:00
|
|
|
|
let ribs = &self.ribs[ns][rib_index + 1..];
|
|
|
|
|
|
|
|
|
|
// An invalid forward use of a type parameter from a previous default.
|
|
|
|
|
if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if record_used {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
resolve_error(self, span, ResolutionError::ForwardDeclaredTyParam);
|
2017-01-25 20:01:11 +00:00
|
|
|
|
}
|
|
|
|
|
assert_eq!(def, Def::Err);
|
|
|
|
|
return Def::Err;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-03 18:44:23 +00:00
|
|
|
|
match def {
|
2016-01-20 19:31:10 +00:00
|
|
|
|
Def::Upvar(..) => {
|
2017-05-12 09:21:11 +00:00
|
|
|
|
span_bug!(span, "unexpected {:?} in bindings", def)
|
2015-11-03 18:44:23 +00:00
|
|
|
|
}
|
2017-04-29 11:39:47 +00:00
|
|
|
|
Def::Local(node_id) => {
|
2015-11-03 18:44:23 +00:00
|
|
|
|
for rib in ribs {
|
|
|
|
|
match rib.kind {
|
2017-01-25 20:01:11 +00:00
|
|
|
|
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
|
|
|
|
|
ForwardTyParamBanRibKind => {
|
2015-11-03 18:44:23 +00:00
|
|
|
|
// Nothing to do. Continue.
|
|
|
|
|
}
|
|
|
|
|
ClosureRibKind(function_id) => {
|
|
|
|
|
let prev_def = def;
|
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
|
let seen = self.freevars_seen
|
|
|
|
|
.entry(function_id)
|
|
|
|
|
.or_insert_with(|| NodeMap());
|
2015-11-03 18:44:23 +00:00
|
|
|
|
if let Some(&index) = seen.get(&node_id) {
|
2017-04-29 11:39:47 +00:00
|
|
|
|
def = Def::Upvar(node_id, index, function_id);
|
2015-11-03 18:44:23 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
|
let vec = self.freevars
|
|
|
|
|
.entry(function_id)
|
|
|
|
|
.or_insert_with(|| vec![]);
|
2015-11-03 18:44:23 +00:00
|
|
|
|
let depth = vec.len();
|
2017-04-29 11:39:47 +00:00
|
|
|
|
def = Def::Upvar(node_id, depth, function_id);
|
2016-11-30 22:35:25 +00:00
|
|
|
|
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if record_used {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
vec.push(Freevar {
|
|
|
|
|
def: prev_def,
|
2017-08-07 05:54:09 +00:00
|
|
|
|
span,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
});
|
|
|
|
|
seen.insert(node_id, depth);
|
|
|
|
|
}
|
2015-11-03 18:44:23 +00:00
|
|
|
|
}
|
2017-11-22 18:15:05 +00:00
|
|
|
|
ItemRibKind | TraitOrImplItemRibKind => {
|
2015-11-03 18:44:23 +00:00
|
|
|
|
// This was an attempt to access an upvar inside a
|
|
|
|
|
// named function item. This is not allowed, so we
|
|
|
|
|
// report an error.
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if record_used {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
resolve_error(self, span,
|
|
|
|
|
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
|
|
|
|
|
}
|
2016-11-22 11:32:52 +00:00
|
|
|
|
return Def::Err;
|
2015-11-03 18:44:23 +00:00
|
|
|
|
}
|
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
|
// Still doesn't deal with upvars
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if record_used {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
resolve_error(self, span,
|
|
|
|
|
ResolutionError::AttemptToUseNonConstantValueInConstant);
|
|
|
|
|
}
|
2016-11-22 11:32:52 +00:00
|
|
|
|
return Def::Err;
|
2015-11-03 18:44:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
|
Def::TyParam(..) | Def::SelfTy(..) => {
|
2015-11-03 18:44:23 +00:00
|
|
|
|
for rib in ribs {
|
|
|
|
|
match rib.kind {
|
2017-11-22 18:15:05 +00:00
|
|
|
|
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
|
2017-04-21 14:10:22 +00:00
|
|
|
|
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
|
|
|
|
|
ConstantItemRibKind => {
|
2015-11-03 18:44:23 +00:00
|
|
|
|
// Nothing to do. Continue.
|
|
|
|
|
}
|
|
|
|
|
ItemRibKind => {
|
|
|
|
|
// This was an attempt to use a type parameter outside
|
|
|
|
|
// its scope.
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if record_used {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
resolve_error(self, span,
|
2018-02-07 10:50:11 +00:00
|
|
|
|
ResolutionError::TypeParametersFromOuterFunction(def));
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
2016-11-22 11:32:52 +00:00
|
|
|
|
return Def::Err;
|
2015-11-03 18:44:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
2016-11-22 11:32:52 +00:00
|
|
|
|
return def;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn lookup_assoc_candidate<FilterFn>(&mut self,
|
2017-03-18 02:10:13 +00:00
|
|
|
|
ident: Ident,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ns: Namespace,
|
|
|
|
|
filter_fn: FilterFn)
|
|
|
|
|
-> Option<AssocSuggestion>
|
|
|
|
|
where FilterFn: Fn(Def) -> bool
|
|
|
|
|
{
|
2016-04-26 07:58:58 +00:00
|
|
|
|
fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
2014-05-19 21:27:03 +00:00
|
|
|
|
match t.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
TyKind::Path(None, _) => Some(t.id),
|
|
|
|
|
TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
|
2014-05-19 21:27:03 +00:00
|
|
|
|
// This doesn't handle the remaining `Ty` variants as they are not
|
|
|
|
|
// that commonly the self_type, it might be interesting to provide
|
|
|
|
|
// support for those in future.
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Fields are generally expected in the same contexts as locals.
|
2017-04-29 11:39:47 +00:00
|
|
|
|
if filter_fn(Def::Local(ast::DUMMY_NODE_ID)) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
|
|
|
|
|
// Look for a field with the same name in the current self_type.
|
|
|
|
|
if let Some(resolution) = self.def_map.get(&node_id) {
|
2017-02-18 19:11:42 +00:00
|
|
|
|
match resolution.base_def() {
|
|
|
|
|
Def::Struct(did) | Def::Union(did)
|
|
|
|
|
if resolution.unresolved_segments() == 0 => {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if let Some(field_names) = self.field_names.get(&did) {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
if field_names.iter().any(|&field_name| ident.name == field_name) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
return Some(AssocSuggestion::Field);
|
|
|
|
|
}
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
2014-05-19 21:27:03 +00:00
|
|
|
|
}
|
2016-11-30 22:35:25 +00:00
|
|
|
|
_ => {}
|
2014-05-08 21:35:09 +00:00
|
|
|
|
}
|
2016-06-03 20:15:00 +00:00
|
|
|
|
}
|
2014-05-19 21:27:03 +00:00
|
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Look for associated items in the current trait.
|
2017-03-18 02:10:13 +00:00
|
|
|
|
if let Some((module, _)) = self.current_trait_ref {
|
|
|
|
|
if let Ok(binding) =
|
|
|
|
|
self.resolve_ident_in_module(module, ident, ns, false, false, module.span) {
|
|
|
|
|
let def = binding.def();
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if filter_fn(def) {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
return Some(if self.has_self.contains(&def.def_id()) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
AssocSuggestion::MethodWithSelf
|
|
|
|
|
} else {
|
|
|
|
|
AssocSuggestion::AssocItem
|
|
|
|
|
});
|
2014-05-08 21:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
None
|
2014-05-08 21:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn lookup_typo_candidate<FilterFn>(&mut self,
|
2018-03-18 13:47:09 +00:00
|
|
|
|
path: &[Ident],
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ns: Namespace,
|
2017-05-12 09:21:11 +00:00
|
|
|
|
filter_fn: FilterFn,
|
|
|
|
|
span: Span)
|
2017-03-08 19:15:12 +00:00
|
|
|
|
-> Option<Symbol>
|
2016-11-30 22:35:25 +00:00
|
|
|
|
where FilterFn: Fn(Def) -> bool
|
|
|
|
|
{
|
2017-01-08 16:47:06 +00:00
|
|
|
|
let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
|
|
|
|
|
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
|
|
|
|
|
if let Some(binding) = resolution.borrow().binding {
|
|
|
|
|
if filter_fn(binding.def()) {
|
|
|
|
|
names.push(ident.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut names = Vec::new();
|
2017-03-08 19:15:12 +00:00
|
|
|
|
if path.len() == 1 {
|
2017-01-08 16:47:06 +00:00
|
|
|
|
// Search in lexical scope.
|
|
|
|
|
// Walk backwards up the ribs in scope and collect candidates.
|
|
|
|
|
for rib in self.ribs[ns].iter().rev() {
|
|
|
|
|
// Locals and type parameters
|
|
|
|
|
for (ident, def) in &rib.bindings {
|
|
|
|
|
if filter_fn(*def) {
|
|
|
|
|
names.push(ident.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Items in scope
|
|
|
|
|
if let ModuleRibKind(module) = rib.kind {
|
|
|
|
|
// Items from this module
|
|
|
|
|
add_module_candidates(module, &mut names);
|
|
|
|
|
|
|
|
|
|
if let ModuleKind::Block(..) = module.kind {
|
|
|
|
|
// We can see through blocks
|
|
|
|
|
} else {
|
|
|
|
|
// Items from the prelude
|
2018-04-08 12:34:35 +00:00
|
|
|
|
if !module.no_implicit_prelude {
|
|
|
|
|
names.extend(self.extern_prelude.iter().cloned());
|
|
|
|
|
if let Some(prelude) = self.prelude {
|
2017-01-08 16:47:06 +00:00
|
|
|
|
add_module_candidates(prelude, &mut names);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Add primitive types to the mix
|
|
|
|
|
if filter_fn(Def::PrimTy(TyBool)) {
|
|
|
|
|
for (name, _) in &self.primitive_type_table.primitive_types {
|
|
|
|
|
names.push(*name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Search in module.
|
|
|
|
|
let mod_path = &path[..path.len() - 1];
|
2017-05-12 09:21:11 +00:00
|
|
|
|
if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
|
2018-05-22 15:10:17 +00:00
|
|
|
|
false, span, CrateLint::No) {
|
2017-01-08 16:47:06 +00:00
|
|
|
|
add_module_candidates(module, &mut names);
|
|
|
|
|
}
|
2017-03-08 19:15:12 +00:00
|
|
|
|
}
|
2017-01-08 16:47:06 +00:00
|
|
|
|
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let name = path[path.len() - 1].name;
|
2017-01-08 16:47:06 +00:00
|
|
|
|
// Make sure error reporting is deterministic.
|
2018-03-30 09:23:27 +00:00
|
|
|
|
names.sort_by_cached_key(|name| name.as_str());
|
2017-01-08 16:47:06 +00:00
|
|
|
|
match find_best_match_for_name(names.iter(), &name.as_str(), None) {
|
2017-03-08 19:15:12 +00:00
|
|
|
|
Some(found) if found != name => Some(found),
|
2016-11-30 22:35:25 +00:00
|
|
|
|
_ => None,
|
2015-11-21 09:37:50 +00:00
|
|
|
|
}
|
2013-02-23 08:22:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-15 22:44:32 +00:00
|
|
|
|
fn with_resolved_label<F>(&mut self, label: Option<Label>, id: NodeId, f: F)
|
2017-02-16 07:28:59 +00:00
|
|
|
|
where F: FnOnce(&mut Resolver)
|
|
|
|
|
{
|
2016-04-24 03:26:10 +00:00
|
|
|
|
if let Some(label) = label {
|
2018-05-18 00:20:30 +00:00
|
|
|
|
self.unused_labels.insert(id, label.ident.span);
|
2016-06-22 02:50:05 +00:00
|
|
|
|
let def = Def::Label(id);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
self.with_label_rib(|this| {
|
2018-01-15 22:44:32 +00:00
|
|
|
|
this.label_ribs.last_mut().unwrap().bindings.insert(label.ident, def);
|
2017-02-16 07:28:59 +00:00
|
|
|
|
f(this);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
});
|
|
|
|
|
} else {
|
2017-02-16 07:28:59 +00:00
|
|
|
|
f(self);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-15 22:44:32 +00:00
|
|
|
|
fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &Block) {
|
2017-02-16 07:28:59 +00:00
|
|
|
|
self.with_resolved_label(label, id, |this| this.visit_block(block));
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 19:15:12 +00:00
|
|
|
|
fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
|
2012-08-17 23:53:07 +00:00
|
|
|
|
// First, record candidate traits for this expression if it could
|
|
|
|
|
// result in the invocation of a method call.
|
2012-07-11 22:00:40 +00:00
|
|
|
|
|
|
|
|
|
self.record_candidate_traits_for_expr_if_necessary(expr);
|
|
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
|
// Next, resolve the node.
|
2012-08-06 19:34:08 +00:00
|
|
|
|
match expr.node {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ExprKind::Path(ref qself, ref path) => {
|
|
|
|
|
self.smart_resolve_path(expr.id, qself.as_ref(), path, PathSource::Expr(parent));
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_expr(self, expr);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-26 16:23:42 +00:00
|
|
|
|
ExprKind::Struct(ref path, ..) => {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
self.smart_resolve_path(expr.id, None, path, PathSource::Struct);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_expr(self, expr);
|
2012-07-24 01:44:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
|
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
2018-01-15 22:44:32 +00:00
|
|
|
|
match self.search_label(label.ident, |rib, id| rib.bindings.get(&id).cloned()) {
|
2014-05-16 17:45:16 +00:00
|
|
|
|
None => {
|
2017-10-09 22:21:09 +00:00
|
|
|
|
// Search again for close matches...
|
|
|
|
|
// Picks the first label that is "close enough", which is not necessarily
|
|
|
|
|
// the closest match
|
2018-01-15 22:44:32 +00:00
|
|
|
|
let close_match = self.search_label(label.ident, |rib, ident| {
|
2017-10-09 22:21:09 +00:00
|
|
|
|
let names = rib.bindings.iter().map(|(id, _)| &id.name);
|
|
|
|
|
find_best_match_for_name(names, &*ident.name.as_str(), None)
|
|
|
|
|
});
|
2015-12-11 07:59:11 +00:00
|
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-07-14 14:32:43 +00:00
|
|
|
|
resolve_error(self,
|
2018-03-19 00:54:56 +00:00
|
|
|
|
label.ident.span,
|
2018-01-15 22:44:32 +00:00
|
|
|
|
ResolutionError::UndeclaredLabel(&label.ident.name.as_str(),
|
2017-10-09 22:21:09 +00:00
|
|
|
|
close_match));
|
2014-05-16 17:45:16 +00:00
|
|
|
|
}
|
2018-05-18 00:20:30 +00:00
|
|
|
|
Some(Def::Label(id)) => {
|
2014-02-11 19:19:18 +00:00
|
|
|
|
// Since this def is a label, it is never read.
|
2018-05-18 00:20:30 +00:00
|
|
|
|
self.record_def(expr.id, PathResolution::new(Def::Label(id)));
|
|
|
|
|
self.unused_labels.remove(&id);
|
2013-05-10 22:15:06 +00:00
|
|
|
|
}
|
|
|
|
|
Some(_) => {
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
|
span_bug!(expr.span, "label wasn't mapped to a label def!");
|
2013-05-10 22:15:06 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
Implement the `loop_break_value` feature.
This implements RFC 1624, tracking issue #37339.
- `FnCtxt` (in typeck) gets a stack of `LoopCtxt`s, which store the
currently deduced type of that loop, the desired type, and a list of
break expressions currently seen. `loop` loops get a fresh type
variable as their initial type (this logic is stolen from that for
arrays). `while` loops get `()`.
- `break {expr}` looks up the broken loop, and unifies the type of
`expr` with the type of the loop.
- `break` with no expr unifies the loop's type with `()`.
- When building MIR, `loop` loops no longer construct a `()` value at
termination of the loop; rather, the `break` expression assigns the
result of the loop. `while` loops are unchanged.
- `break` respects contexts in which expressions may not end with braced
blocks. That is, `while break { break-value } { while-body }` is
illegal; this preserves backwards compatibility.
- The RFC did not make it clear, but I chose to make `break ()` inside
of a `while` loop illegal, just in case we wanted to do anything with
that design space in the future.
This is my first time dealing with this part of rustc so I'm sure
there's plenty of problems to pick on here ^_^
2016-10-29 22:15:06 +00:00
|
|
|
|
|
|
|
|
|
// visit `break` argument if any
|
|
|
|
|
visit::walk_expr(self, expr);
|
2013-05-10 22:15:06 +00:00
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
2018-02-24 00:12:35 +00:00
|
|
|
|
ExprKind::IfLet(ref pats, ref subexpression, ref if_block, ref optional_else) => {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
self.visit_expr(subexpression);
|
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
|
2018-02-24 00:12:35 +00:00
|
|
|
|
let mut bindings_list = FxHashMap();
|
|
|
|
|
for pat in pats {
|
|
|
|
|
self.resolve_pattern(pat, PatternSource::IfLet, &mut bindings_list);
|
|
|
|
|
}
|
|
|
|
|
// This has to happen *after* we determine which pat_idents are variants
|
|
|
|
|
self.check_consistent_bindings(pats);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
self.visit_block(if_block);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
|
|
optional_else.as_ref().map(|expr| self.visit_expr(expr));
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-22 23:34:18 +00:00
|
|
|
|
ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block),
|
|
|
|
|
|
|
|
|
|
ExprKind::While(ref subexpression, ref block, label) => {
|
2017-02-16 07:28:59 +00:00
|
|
|
|
self.with_resolved_label(label, expr.id, |this| {
|
|
|
|
|
this.visit_expr(subexpression);
|
|
|
|
|
this.visit_block(block);
|
|
|
|
|
});
|
2016-10-22 23:34:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-24 00:12:35 +00:00
|
|
|
|
ExprKind::WhileLet(ref pats, ref subexpression, ref block, label) => {
|
2017-02-16 07:28:59 +00:00
|
|
|
|
self.with_resolved_label(label, expr.id, |this| {
|
|
|
|
|
this.visit_expr(subexpression);
|
2017-03-03 17:40:44 +00:00
|
|
|
|
this.ribs[ValueNS].push(Rib::new(NormalRibKind));
|
2018-02-24 00:12:35 +00:00
|
|
|
|
let mut bindings_list = FxHashMap();
|
|
|
|
|
for pat in pats {
|
|
|
|
|
this.resolve_pattern(pat, PatternSource::WhileLet, &mut bindings_list);
|
|
|
|
|
}
|
|
|
|
|
// This has to happen *after* we determine which pat_idents are variants
|
|
|
|
|
this.check_consistent_bindings(pats);
|
2017-02-16 07:28:59 +00:00
|
|
|
|
this.visit_block(block);
|
2017-03-03 17:40:44 +00:00
|
|
|
|
this.ribs[ValueNS].pop();
|
2017-02-16 07:28:59 +00:00
|
|
|
|
});
|
2016-04-24 03:26:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
|
|
|
|
|
self.visit_expr(subexpression);
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
|
2016-11-08 03:02:55 +00:00
|
|
|
|
self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap());
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
2016-10-22 23:34:18 +00:00
|
|
|
|
self.resolve_labeled_block(label, expr.id, block);
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
|
self.ribs[ValueNS].pop();
|
2016-04-24 03:26:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-25 17:28:04 +00:00
|
|
|
|
ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block),
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// Equivalent to `visit::walk_expr` + passing some context to children.
|
2016-04-24 03:26:10 +00:00
|
|
|
|
ExprKind::Field(ref subexpression, _) => {
|
2017-03-08 19:15:12 +00:00
|
|
|
|
self.resolve_expr(subexpression, Some(expr));
|
2016-04-24 21:10:54 +00:00
|
|
|
|
}
|
2017-07-06 23:39:55 +00:00
|
|
|
|
ExprKind::MethodCall(ref segment, ref arguments) => {
|
2016-04-24 21:10:54 +00:00
|
|
|
|
let mut arguments = arguments.iter();
|
2017-03-08 19:15:12 +00:00
|
|
|
|
self.resolve_expr(arguments.next().unwrap(), Some(expr));
|
2016-04-24 21:10:54 +00:00
|
|
|
|
for argument in arguments {
|
|
|
|
|
self.resolve_expr(argument, None);
|
|
|
|
|
}
|
2017-07-06 23:39:55 +00:00
|
|
|
|
self.visit_path_segment(expr.span, segment);
|
2016-04-24 21:10:54 +00:00
|
|
|
|
}
|
2016-12-21 10:32:59 +00:00
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ExprKind::Call(ref callee, ref arguments) => {
|
2017-03-08 19:15:12 +00:00
|
|
|
|
self.resolve_expr(callee, Some(expr));
|
2016-11-30 22:35:25 +00:00
|
|
|
|
for argument in arguments {
|
|
|
|
|
self.resolve_expr(argument, None);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-07-18 18:41:21 +00:00
|
|
|
|
ExprKind::Type(ref type_expr, _) => {
|
|
|
|
|
self.current_type_ascription.push(type_expr.span);
|
|
|
|
|
visit::walk_expr(self, expr);
|
|
|
|
|
self.current_type_ascription.pop();
|
|
|
|
|
}
|
2012-08-04 02:59:04 +00:00
|
|
|
|
_ => {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
visit::walk_expr(self, expr);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
|
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
|
2012-08-06 19:34:08 +00:00
|
|
|
|
match expr.node {
|
2018-03-18 13:47:09 +00:00
|
|
|
|
ExprKind::Field(_, ident) => {
|
2013-06-01 22:31:56 +00:00
|
|
|
|
// FIXME(#6890): Even though you can't treat a method like a
|
|
|
|
|
// field, we need to add any trait methods we find that match
|
|
|
|
|
// the field name so that we can do some nice error reporting
|
|
|
|
|
// later on in typeck.
|
2018-03-18 13:47:09 +00:00
|
|
|
|
let traits = self.get_traits_containing_item(ident, ValueNS);
|
2014-02-24 08:36:24 +00:00
|
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-07-11 22:00:40 +00:00
|
|
|
|
}
|
2017-07-06 23:39:55 +00:00
|
|
|
|
ExprKind::MethodCall(ref segment, ..) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
|
debug!("(recording candidate traits for expr) recording traits for {}",
|
2013-06-18 16:39:16 +00:00
|
|
|
|
expr.id);
|
2018-03-18 00:53:41 +00:00
|
|
|
|
let traits = self.get_traits_containing_item(segment.ident, ValueNS);
|
2014-02-24 08:36:24 +00:00
|
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-11-30 19:18:25 +00:00
|
|
|
|
}
|
2012-07-28 02:32:42 +00:00
|
|
|
|
_ => {
|
2012-07-11 22:00:40 +00:00
|
|
|
|
// Nothing to do.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-22 08:39:51 +00:00
|
|
|
|
fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace)
|
|
|
|
|
-> Vec<TraitCandidate> {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
debug!("(getting traits containing item) looking for '{}'", ident.name);
|
2014-04-22 16:06:43 +00:00
|
|
|
|
|
2014-03-04 18:02:49 +00:00
|
|
|
|
let mut found_traits = Vec::new();
|
2016-03-07 23:10:53 +00:00
|
|
|
|
// Look for the current trait.
|
2017-03-18 02:10:13 +00:00
|
|
|
|
if let Some((module, _)) = self.current_trait_ref {
|
|
|
|
|
if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() {
|
|
|
|
|
let def_id = module.def_id().unwrap();
|
|
|
|
|
found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
|
2014-04-22 16:06:43 +00:00
|
|
|
|
}
|
2016-03-07 23:10:53 +00:00
|
|
|
|
}
|
2012-07-11 22:00:40 +00:00
|
|
|
|
|
2018-03-17 23:57:23 +00:00
|
|
|
|
ident.span = ident.span.modern();
|
2016-03-07 23:10:53 +00:00
|
|
|
|
let mut search_module = self.current_module;
|
|
|
|
|
loop {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
|
2017-03-22 08:39:51 +00:00
|
|
|
|
search_module =
|
2018-03-17 23:57:23 +00:00
|
|
|
|
unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.span), break);
|
2016-12-14 09:59:41 +00:00
|
|
|
|
}
|
2016-02-06 23:43:04 +00:00
|
|
|
|
|
2016-12-14 09:59:41 +00:00
|
|
|
|
if let Some(prelude) = self.prelude {
|
|
|
|
|
if !search_module.no_implicit_prelude {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits);
|
2014-04-22 16:06:43 +00:00
|
|
|
|
}
|
2012-07-11 22:00:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-04-22 16:06:43 +00:00
|
|
|
|
found_traits
|
2012-07-11 22:00:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-14 09:59:41 +00:00
|
|
|
|
fn get_traits_in_module_containing_item(&mut self,
|
2017-03-18 02:10:13 +00:00
|
|
|
|
ident: Ident,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ns: Namespace,
|
2017-03-18 02:10:13 +00:00
|
|
|
|
module: Module<'a>,
|
2016-12-14 09:59:41 +00:00
|
|
|
|
found_traits: &mut Vec<TraitCandidate>) {
|
|
|
|
|
let mut traits = module.traits.borrow_mut();
|
|
|
|
|
if traits.is_none() {
|
|
|
|
|
let mut collected_traits = Vec::new();
|
|
|
|
|
module.for_each_child(|name, ns, binding| {
|
|
|
|
|
if ns != TypeNS { return }
|
|
|
|
|
if let Def::Trait(_) = binding.def() {
|
|
|
|
|
collected_traits.push((name, binding));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
*traits = Some(collected_traits.into_boxed_slice());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
|
2017-03-18 02:10:13 +00:00
|
|
|
|
let module = binding.module().unwrap();
|
2017-03-22 08:39:51 +00:00
|
|
|
|
let mut ident = ident;
|
2018-03-17 23:57:23 +00:00
|
|
|
|
if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span)
|
|
|
|
|
.is_ok() {
|
2016-12-14 09:59:41 +00:00
|
|
|
|
let import_id = match binding.kind {
|
|
|
|
|
NameBindingKind::Import { directive, .. } => {
|
|
|
|
|
self.maybe_unused_trait_imports.insert(directive.id);
|
|
|
|
|
self.add_to_glob_map(directive.id, trait_name);
|
|
|
|
|
Some(directive.id)
|
|
|
|
|
}
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
2017-03-18 02:10:13 +00:00
|
|
|
|
let trait_def_id = module.def_id().unwrap();
|
2016-12-14 09:59:41 +00:00
|
|
|
|
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-14 01:47:27 +00:00
|
|
|
|
/// When name resolution fails, this method can be used to look up candidate
|
|
|
|
|
/// entities with the expected name. It allows filtering them using the
|
|
|
|
|
/// supplied predicate (which should be used to only accept the types of
|
|
|
|
|
/// definitions expected e.g. traits). The lookup spans across all crates.
|
|
|
|
|
///
|
|
|
|
|
/// NOTE: The method does not look into imports, but this is not a problem,
|
|
|
|
|
/// since we report the definitions (thus, the de-aliased imports).
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn lookup_import_candidates<FilterFn>(&mut self,
|
|
|
|
|
lookup_name: Name,
|
|
|
|
|
namespace: Namespace,
|
|
|
|
|
filter_fn: FilterFn)
|
|
|
|
|
-> Vec<ImportSuggestion>
|
|
|
|
|
where FilterFn: Fn(Def) -> bool
|
|
|
|
|
{
|
|
|
|
|
let mut candidates = Vec::new();
|
2016-02-14 01:47:27 +00:00
|
|
|
|
let mut worklist = Vec::new();
|
2016-12-22 08:27:26 +00:00
|
|
|
|
let mut seen_modules = FxHashSet();
|
2016-02-14 01:47:27 +00:00
|
|
|
|
worklist.push((self.graph_root, Vec::new(), false));
|
|
|
|
|
|
|
|
|
|
while let Some((in_module,
|
|
|
|
|
path_segments,
|
|
|
|
|
in_module_is_extern)) = worklist.pop() {
|
2016-03-02 09:18:47 +00:00
|
|
|
|
self.populate_module_if_necessary(in_module);
|
2016-02-14 01:47:27 +00:00
|
|
|
|
|
2017-07-29 23:28:30 +00:00
|
|
|
|
// We have to visit module children in deterministic order to avoid
|
|
|
|
|
// instabilities in reported imports (#43552).
|
|
|
|
|
in_module.for_each_child_stable(|ident, ns, name_binding| {
|
2016-02-14 01:47:27 +00:00
|
|
|
|
// avoid imports entirely
|
2016-10-28 03:40:58 +00:00
|
|
|
|
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
|
2016-11-30 22:35:25 +00:00
|
|
|
|
// avoid non-importable candidates as well
|
|
|
|
|
if !name_binding.is_importable() { return; }
|
2016-02-14 01:47:27 +00:00
|
|
|
|
|
|
|
|
|
// collect results based on the filter function
|
2016-11-29 02:07:12 +00:00
|
|
|
|
if ident.name == lookup_name && ns == namespace {
|
2016-08-20 07:26:26 +00:00
|
|
|
|
if filter_fn(name_binding.def()) {
|
2016-02-14 01:47:27 +00:00
|
|
|
|
// create the path
|
|
|
|
|
let mut segms = path_segments.clone();
|
2018-03-19 00:54:56 +00:00
|
|
|
|
segms.push(ast::PathSegment::from_ident(ident));
|
2016-02-14 01:47:27 +00:00
|
|
|
|
let path = Path {
|
2017-03-08 17:30:06 +00:00
|
|
|
|
span: name_binding.span,
|
2016-02-14 01:47:27 +00:00
|
|
|
|
segments: segms,
|
|
|
|
|
};
|
|
|
|
|
// the entity is accessible in the following cases:
|
|
|
|
|
// 1. if it's defined in the same crate, it's always
|
|
|
|
|
// accessible (since private entities can be made public)
|
|
|
|
|
// 2. if it's defined in another crate, it's accessible
|
|
|
|
|
// only if both the module is public and the entity is
|
|
|
|
|
// declared as public (due to pruning, we don't explore
|
|
|
|
|
// outside crate private modules => no need to check this)
|
2016-04-11 05:35:18 +00:00
|
|
|
|
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
candidates.push(ImportSuggestion { path: path });
|
2016-02-14 01:47:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// collect submodules to explore
|
2016-11-27 00:23:54 +00:00
|
|
|
|
if let Some(module) = name_binding.module() {
|
2016-02-14 01:47:27 +00:00
|
|
|
|
// form the path
|
2016-10-28 03:40:58 +00:00
|
|
|
|
let mut path_segments = path_segments.clone();
|
2018-03-19 00:54:56 +00:00
|
|
|
|
path_segments.push(ast::PathSegment::from_ident(ident));
|
2016-02-14 01:47:27 +00:00
|
|
|
|
|
2016-04-11 05:35:18 +00:00
|
|
|
|
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
2016-02-14 01:47:27 +00:00
|
|
|
|
// add the module to the lookup
|
2016-02-02 20:21:24 +00:00
|
|
|
|
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
|
2016-12-22 08:27:26 +00:00
|
|
|
|
if seen_modules.insert(module.def_id().unwrap()) {
|
2016-06-28 23:03:56 +00:00
|
|
|
|
worklist.push((module, path_segments, is_extern));
|
|
|
|
|
}
|
2016-02-14 01:47:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
candidates
|
2016-02-14 01:47:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-09-30 08:27:02 +00:00
|
|
|
|
fn find_module(&mut self,
|
|
|
|
|
module_def: Def)
|
|
|
|
|
-> Option<(Module<'a>, ImportSuggestion)>
|
|
|
|
|
{
|
|
|
|
|
let mut result = None;
|
|
|
|
|
let mut worklist = Vec::new();
|
|
|
|
|
let mut seen_modules = FxHashSet();
|
|
|
|
|
worklist.push((self.graph_root, Vec::new()));
|
|
|
|
|
|
|
|
|
|
while let Some((in_module, path_segments)) = worklist.pop() {
|
|
|
|
|
// abort if the module is already found
|
|
|
|
|
if let Some(_) = result { break; }
|
|
|
|
|
|
|
|
|
|
self.populate_module_if_necessary(in_module);
|
|
|
|
|
|
2017-11-23 19:09:27 +00:00
|
|
|
|
in_module.for_each_child_stable(|ident, _, name_binding| {
|
2017-11-29 19:20:49 +00:00
|
|
|
|
// abort if the module is already found or if name_binding is private external
|
|
|
|
|
if result.is_some() || !name_binding.vis.is_visible_locally() {
|
|
|
|
|
return
|
2017-09-30 08:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
if let Some(module) = name_binding.module() {
|
|
|
|
|
// form the path
|
|
|
|
|
let mut path_segments = path_segments.clone();
|
2018-03-19 00:54:56 +00:00
|
|
|
|
path_segments.push(ast::PathSegment::from_ident(ident));
|
2017-09-30 08:27:02 +00:00
|
|
|
|
if module.def() == Some(module_def) {
|
|
|
|
|
let path = Path {
|
|
|
|
|
span: name_binding.span,
|
|
|
|
|
segments: path_segments,
|
|
|
|
|
};
|
|
|
|
|
result = Some((module, ImportSuggestion { path: path }));
|
|
|
|
|
} else {
|
|
|
|
|
// add the module to the lookup
|
|
|
|
|
if seen_modules.insert(module.def_id().unwrap()) {
|
|
|
|
|
worklist.push((module, path_segments));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn collect_enum_variants(&mut self, enum_def: Def) -> Option<Vec<Path>> {
|
|
|
|
|
if let Def::Enum(..) = enum_def {} else {
|
|
|
|
|
panic!("Non-enum def passed to collect_enum_variants: {:?}", enum_def)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.find_module(enum_def).map(|(enum_module, enum_import_suggestion)| {
|
2017-11-23 13:10:23 +00:00
|
|
|
|
self.populate_module_if_necessary(enum_module);
|
|
|
|
|
|
2017-09-30 08:27:02 +00:00
|
|
|
|
let mut variants = Vec::new();
|
|
|
|
|
enum_module.for_each_child_stable(|ident, _, name_binding| {
|
|
|
|
|
if let Def::Variant(..) = name_binding.def() {
|
|
|
|
|
let mut segms = enum_import_suggestion.path.segments.clone();
|
2018-03-19 00:54:56 +00:00
|
|
|
|
segms.push(ast::PathSegment::from_ident(ident));
|
2017-09-30 08:27:02 +00:00
|
|
|
|
variants.push(Path {
|
|
|
|
|
span: name_binding.span,
|
|
|
|
|
segments: segms,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
variants
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 04:44:23 +00:00
|
|
|
|
fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
|
|
|
|
|
debug!("(recording def) recording {:?} for {}", resolution, node_id);
|
2016-05-03 20:44:27 +00:00
|
|
|
|
if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
|
2016-04-24 03:26:10 +00:00
|
|
|
|
panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
|
2014-09-18 21:05:52 +00:00
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
|
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
2018-01-29 05:12:09 +00:00
|
|
|
|
match vis.node {
|
|
|
|
|
ast::VisibilityKind::Public => ty::Visibility::Public,
|
|
|
|
|
ast::VisibilityKind::Crate(..) => {
|
|
|
|
|
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
|
|
|
|
|
}
|
|
|
|
|
ast::VisibilityKind::Inherited => {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
|
2016-04-09 23:19:53 +00:00
|
|
|
|
}
|
2018-01-29 05:12:09 +00:00
|
|
|
|
ast::VisibilityKind::Restricted { ref path, id, .. } => {
|
2018-03-09 23:02:39 +00:00
|
|
|
|
// Visibilities are resolved as global by default, add starting root segment.
|
|
|
|
|
let segments = path.make_root().iter().chain(path.segments.iter())
|
2018-03-18 22:21:30 +00:00
|
|
|
|
.map(|seg| seg.ident)
|
2018-03-09 23:02:39 +00:00
|
|
|
|
.collect::<Vec<_>>();
|
2018-05-22 22:43:02 +00:00
|
|
|
|
let def = self.smart_resolve_path_fragment(
|
|
|
|
|
id,
|
|
|
|
|
None,
|
|
|
|
|
&segments,
|
|
|
|
|
path.span,
|
|
|
|
|
PathSource::Visibility,
|
|
|
|
|
CrateLint::SimplePath(id),
|
|
|
|
|
).base_def();
|
2016-11-30 22:35:25 +00:00
|
|
|
|
if def == Def::Err {
|
|
|
|
|
ty::Visibility::Public
|
|
|
|
|
} else {
|
|
|
|
|
let vis = ty::Visibility::Restricted(def.def_id());
|
|
|
|
|
if self.is_accessible(vis) {
|
|
|
|
|
vis
|
|
|
|
|
} else {
|
|
|
|
|
self.session.span_err(path.span, "visibilities can only be restricted \
|
|
|
|
|
to ancestor modules");
|
|
|
|
|
ty::Visibility::Public
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-09 23:19:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-10 00:44:14 +00:00
|
|
|
|
fn is_accessible(&self, vis: ty::Visibility) -> bool {
|
2016-12-20 08:32:15 +00:00
|
|
|
|
vis.is_accessible_from(self.current_module.normal_ancestor_id, self)
|
2016-02-25 04:40:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 00:33:06 +00:00
|
|
|
|
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
|
2016-12-20 08:32:15 +00:00
|
|
|
|
vis.is_accessible_from(module.normal_ancestor_id, self)
|
2016-08-20 00:33:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-17 09:03:59 +00:00
|
|
|
|
fn report_errors(&mut self, krate: &Crate) {
|
2016-10-11 03:21:40 +00:00
|
|
|
|
self.report_shadowing_errors();
|
2017-08-17 09:03:59 +00:00
|
|
|
|
self.report_with_use_injections(krate);
|
2017-11-16 14:03:25 +00:00
|
|
|
|
self.report_proc_macro_import(krate);
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut reported_spans = FxHashSet();
|
2016-08-22 08:30:07 +00:00
|
|
|
|
|
2018-05-14 22:24:34 +00:00
|
|
|
|
for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
|
2016-08-22 08:30:07 +00:00
|
|
|
|
if !reported_spans.insert(span) { continue }
|
2016-11-27 10:58:46 +00:00
|
|
|
|
let participle = |binding: &NameBinding| {
|
|
|
|
|
if binding.is_import() { "imported" } else { "defined" }
|
|
|
|
|
};
|
2017-01-11 22:18:08 +00:00
|
|
|
|
let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1));
|
|
|
|
|
let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2));
|
2017-03-11 10:58:19 +00:00
|
|
|
|
let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() {
|
2016-12-09 11:08:39 +00:00
|
|
|
|
format!("consider adding an explicit import of `{}` to disambiguate", name)
|
|
|
|
|
} else if let Def::Macro(..) = b1.def() {
|
|
|
|
|
format!("macro-expanded {} do not shadow",
|
|
|
|
|
if b1.is_import() { "macro imports" } else { "macros" })
|
|
|
|
|
} else {
|
|
|
|
|
format!("macro-expanded {} do not shadow when used in a macro invocation path",
|
|
|
|
|
if b1.is_import() { "imports" } else { "items" })
|
|
|
|
|
};
|
2018-05-14 22:24:34 +00:00
|
|
|
|
|
|
|
|
|
let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
|
|
|
|
|
err.span_note(b1.span, &msg1);
|
|
|
|
|
match b2.def() {
|
|
|
|
|
Def::Macro(..) if b2.span == DUMMY_SP =>
|
|
|
|
|
err.note(&format!("`{}` is also a builtin macro", name)),
|
|
|
|
|
_ => err.span_note(b2.span, &msg2),
|
|
|
|
|
};
|
|
|
|
|
err.note(¬e).emit();
|
2016-08-22 08:30:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-25 04:40:46 +00:00
|
|
|
|
for &PrivacyError(span, name, binding) in &self.privacy_errors {
|
|
|
|
|
if !reported_spans.insert(span) { continue }
|
2017-06-02 19:38:52 +00:00
|
|
|
|
span_err!(self.session, span, E0603, "{} `{}` is private", binding.descr(), name);
|
2016-02-25 04:40:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
2017-08-17 09:03:59 +00:00
|
|
|
|
fn report_with_use_injections(&mut self, krate: &Crate) {
|
|
|
|
|
for UseError { mut err, candidates, node_id, better } in self.use_injections.drain(..) {
|
2017-11-16 12:14:22 +00:00
|
|
|
|
let (span, found_use) = UsePlacementFinder::check(krate, node_id);
|
2017-08-17 09:03:59 +00:00
|
|
|
|
if !candidates.is_empty() {
|
2017-11-16 12:14:22 +00:00
|
|
|
|
show_candidates(&mut err, span, &candidates, better, found_use);
|
2017-08-17 09:03:59 +00:00
|
|
|
|
}
|
|
|
|
|
err.emit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-11 03:21:40 +00:00
|
|
|
|
fn report_shadowing_errors(&mut self) {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
|
|
|
|
|
self.resolve_legacy_scope(scope, ident, true);
|
2016-10-31 22:17:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-08 03:02:55 +00:00
|
|
|
|
let mut reported_errors = FxHashSet();
|
2016-10-31 06:48:59 +00:00
|
|
|
|
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
|
2017-03-22 08:39:51 +00:00
|
|
|
|
if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
|
|
|
|
|
reported_errors.insert((binding.ident, binding.span)) {
|
|
|
|
|
let msg = format!("`{}` is already in scope", binding.ident);
|
2016-10-31 06:48:59 +00:00
|
|
|
|
self.session.struct_span_err(binding.span, &msg)
|
2016-10-11 03:42:06 +00:00
|
|
|
|
.note("macro-expanded `macro_rules!`s may not shadow \
|
|
|
|
|
existing macros (see RFC 1560)")
|
2016-10-11 03:21:40 +00:00
|
|
|
|
.emit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-31 17:31:48 +00:00
|
|
|
|
fn report_conflict<'b>(&mut self,
|
2016-03-16 05:20:58 +00:00
|
|
|
|
parent: Module,
|
2016-11-29 02:07:12 +00:00
|
|
|
|
ident: Ident,
|
2016-03-16 05:20:58 +00:00
|
|
|
|
ns: Namespace,
|
2017-10-31 17:31:48 +00:00
|
|
|
|
new_binding: &NameBinding<'b>,
|
|
|
|
|
old_binding: &NameBinding<'b>) {
|
2016-03-16 05:20:58 +00:00
|
|
|
|
// Error on the second of two conflicting names
|
2017-07-31 20:04:34 +00:00
|
|
|
|
if old_binding.span.lo() > new_binding.span.lo() {
|
2017-05-18 03:29:58 +00:00
|
|
|
|
return self.report_conflict(parent, ident, ns, old_binding, new_binding);
|
2016-03-16 05:20:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-18 09:45:06 +00:00
|
|
|
|
let container = match parent.kind {
|
|
|
|
|
ModuleKind::Def(Def::Mod(_), _) => "module",
|
|
|
|
|
ModuleKind::Def(Def::Trait(_), _) => "trait",
|
|
|
|
|
ModuleKind::Block(..) => "block",
|
2016-03-16 05:20:58 +00:00
|
|
|
|
_ => "enum",
|
|
|
|
|
};
|
|
|
|
|
|
2017-05-18 03:29:58 +00:00
|
|
|
|
let old_noun = match old_binding.is_import() {
|
|
|
|
|
true => "import",
|
|
|
|
|
false => "definition",
|
2016-03-16 05:20:58 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-05-18 03:29:58 +00:00
|
|
|
|
let new_participle = match new_binding.is_import() {
|
|
|
|
|
true => "imported",
|
|
|
|
|
false => "defined",
|
|
|
|
|
};
|
|
|
|
|
|
2017-12-18 06:44:32 +00:00
|
|
|
|
let (name, span) = (ident.name, self.session.codemap().def_span(new_binding.span));
|
2016-10-28 07:30:23 +00:00
|
|
|
|
|
|
|
|
|
if let Some(s) = self.name_already_seen.get(&name) {
|
|
|
|
|
if s == &span {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-18 03:29:58 +00:00
|
|
|
|
let old_kind = match (ns, old_binding.module()) {
|
|
|
|
|
(ValueNS, _) => "value",
|
|
|
|
|
(MacroNS, _) => "macro",
|
|
|
|
|
(TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
|
|
|
|
|
(TypeNS, Some(module)) if module.is_normal() => "module",
|
|
|
|
|
(TypeNS, Some(module)) if module.is_trait() => "trait",
|
|
|
|
|
(TypeNS, _) => "type",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let namespace = match ns {
|
|
|
|
|
ValueNS => "value",
|
|
|
|
|
MacroNS => "macro",
|
|
|
|
|
TypeNS => "type",
|
2016-03-16 05:20:58 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-05-18 03:29:58 +00:00
|
|
|
|
let msg = format!("the name `{}` is defined multiple times", name);
|
|
|
|
|
|
|
|
|
|
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
|
2016-12-12 08:17:47 +00:00
|
|
|
|
(true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
|
2017-05-18 03:29:58 +00:00
|
|
|
|
(true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
|
2016-12-12 08:17:47 +00:00
|
|
|
|
true => struct_span_err!(self.session, span, E0254, "{}", msg),
|
|
|
|
|
false => struct_span_err!(self.session, span, E0260, "{}", msg),
|
2016-08-29 10:50:08 +00:00
|
|
|
|
},
|
2017-05-18 03:29:58 +00:00
|
|
|
|
_ => match (old_binding.is_import(), new_binding.is_import()) {
|
2016-12-12 08:17:47 +00:00
|
|
|
|
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
|
|
|
|
|
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
|
|
|
|
|
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
|
2016-03-16 05:20:58 +00:00
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
2017-05-18 03:29:58 +00:00
|
|
|
|
err.note(&format!("`{}` must be defined only once in the {} namespace of this {}",
|
|
|
|
|
name,
|
|
|
|
|
namespace,
|
|
|
|
|
container));
|
|
|
|
|
|
|
|
|
|
err.span_label(span, format!("`{}` re{} here", name, new_participle));
|
2017-11-07 02:40:21 +00:00
|
|
|
|
if old_binding.span != DUMMY_SP {
|
2017-12-18 06:44:32 +00:00
|
|
|
|
err.span_label(self.session.codemap().def_span(old_binding.span),
|
|
|
|
|
format!("previous {} of the {} `{}` here", old_noun, old_kind, name));
|
2016-03-16 05:20:58 +00:00
|
|
|
|
}
|
2017-05-18 03:29:58 +00:00
|
|
|
|
|
2017-10-31 17:31:48 +00:00
|
|
|
|
// See https://github.com/rust-lang/rust/issues/32354
|
|
|
|
|
if old_binding.is_import() || new_binding.is_import() {
|
2017-11-07 02:40:21 +00:00
|
|
|
|
let binding = if new_binding.is_import() && new_binding.span != DUMMY_SP {
|
2017-10-31 17:31:48 +00:00
|
|
|
|
new_binding
|
|
|
|
|
} else {
|
|
|
|
|
old_binding
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let cm = self.session.codemap();
|
|
|
|
|
let rename_msg = "You can use `as` to change the binding name of the import";
|
|
|
|
|
|
2017-11-08 02:01:35 +00:00
|
|
|
|
if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
|
|
|
|
|
binding.is_renamed_extern_crate()) {
|
2018-01-29 01:48:54 +00:00
|
|
|
|
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
|
|
|
|
|
format!("Other{}", name)
|
|
|
|
|
} else {
|
|
|
|
|
format!("other_{}", name)
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-31 17:31:48 +00:00
|
|
|
|
err.span_suggestion(binding.span,
|
|
|
|
|
rename_msg,
|
2018-01-26 06:40:38 +00:00
|
|
|
|
if snippet.ends_with(';') {
|
2018-01-29 01:48:54 +00:00
|
|
|
|
format!("{} as {};",
|
2018-01-26 06:40:38 +00:00
|
|
|
|
&snippet[..snippet.len()-1],
|
2018-01-29 01:48:54 +00:00
|
|
|
|
suggested_name)
|
2018-01-26 06:40:38 +00:00
|
|
|
|
} else {
|
2018-01-29 01:48:54 +00:00
|
|
|
|
format!("{} as {}", snippet, suggested_name)
|
2018-01-26 06:40:38 +00:00
|
|
|
|
});
|
2017-10-31 17:31:48 +00:00
|
|
|
|
} else {
|
|
|
|
|
err.span_label(binding.span, rename_msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-16 05:20:58 +00:00
|
|
|
|
err.emit();
|
2016-10-28 07:30:23 +00:00
|
|
|
|
self.name_already_seen.insert(name, span);
|
2016-03-16 05:20:58 +00:00
|
|
|
|
}
|
2017-01-10 05:15:02 +00:00
|
|
|
|
|
2017-01-09 09:31:14 +00:00
|
|
|
|
fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
|
|
|
|
|
if self.proc_macro_enabled { return; }
|
|
|
|
|
|
|
|
|
|
for attr in attrs {
|
2017-03-11 10:58:19 +00:00
|
|
|
|
if attr.path.segments.len() > 1 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2018-03-18 00:53:41 +00:00
|
|
|
|
let ident = attr.path.segments[0].ident;
|
2017-05-12 09:21:11 +00:00
|
|
|
|
let result = self.resolve_lexical_macro_path_segment(ident,
|
|
|
|
|
MacroNS,
|
|
|
|
|
false,
|
|
|
|
|
attr.path.span);
|
2017-03-11 10:58:19 +00:00
|
|
|
|
if let Ok(binding) = result {
|
|
|
|
|
if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
|
2017-01-09 09:31:14 +00:00
|
|
|
|
attr::mark_known(attr);
|
|
|
|
|
|
|
|
|
|
let msg = "attribute procedural macros are experimental";
|
|
|
|
|
let feature = "proc_macro";
|
|
|
|
|
|
|
|
|
|
feature_err(&self.session.parse_sess, feature,
|
|
|
|
|
attr.span, GateIssue::Language, msg)
|
2017-12-20 03:53:39 +00:00
|
|
|
|
.span_label(binding.span(), "procedural macro imported here")
|
2017-01-09 09:31:14 +00:00
|
|
|
|
.emit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-03-16 05:20:58 +00:00
|
|
|
|
}
|
2015-03-15 21:44:19 +00:00
|
|
|
|
|
2018-03-18 13:47:09 +00:00
|
|
|
|
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {
|
|
|
|
|
namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name()
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-18 13:47:09 +00:00
|
|
|
|
fn is_self_value(path: &[Ident], namespace: Namespace) -> bool {
|
|
|
|
|
namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name()
|
2016-11-30 22:35:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-18 13:47:09 +00:00
|
|
|
|
fn names_to_string(idents: &[Ident]) -> String {
|
2015-03-15 21:44:19 +00:00
|
|
|
|
let mut result = String::new();
|
2017-07-23 22:15:45 +00:00
|
|
|
|
for (i, ident) in idents.iter()
|
2018-03-18 13:47:09 +00:00
|
|
|
|
.filter(|ident| ident.name != keywords::CrateRoot.name())
|
2017-07-23 22:15:45 +00:00
|
|
|
|
.enumerate() {
|
2016-12-05 03:51:11 +00:00
|
|
|
|
if i > 0 {
|
|
|
|
|
result.push_str("::");
|
|
|
|
|
}
|
2018-03-18 13:47:09 +00:00
|
|
|
|
result.push_str(&ident.name.as_str());
|
2015-10-26 19:31:11 +00:00
|
|
|
|
}
|
2015-03-15 21:44:19 +00:00
|
|
|
|
result
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-30 22:35:25 +00:00
|
|
|
|
fn path_names_to_string(path: &Path) -> String {
|
2017-07-23 22:15:45 +00:00
|
|
|
|
names_to_string(&path.segments.iter()
|
2018-03-18 13:47:09 +00:00
|
|
|
|
.map(|seg| seg.ident)
|
2017-07-23 22:15:45 +00:00
|
|
|
|
.collect::<Vec<_>>())
|
2015-03-15 21:44:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 22:14:45 +00:00
|
|
|
|
/// Get the path for an enum and the variant from an `ImportSuggestion` for an enum variant.
|
2017-04-03 14:46:35 +00:00
|
|
|
|
fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, String) {
|
2017-03-23 22:14:45 +00:00
|
|
|
|
let variant_path = &suggestion.path;
|
|
|
|
|
let variant_path_string = path_names_to_string(variant_path);
|
|
|
|
|
|
|
|
|
|
let path_len = suggestion.path.segments.len();
|
|
|
|
|
let enum_path = ast::Path {
|
|
|
|
|
span: suggestion.path.span,
|
|
|
|
|
segments: suggestion.path.segments[0..path_len - 1].to_vec(),
|
|
|
|
|
};
|
|
|
|
|
let enum_path_string = path_names_to_string(&enum_path);
|
|
|
|
|
|
2017-04-03 14:46:35 +00:00
|
|
|
|
(suggestion.path.span, variant_path_string, enum_path_string)
|
2017-03-23 22:14:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-02-14 01:47:27 +00:00
|
|
|
|
/// When an entity with a given name is not available in scope, we search for
|
|
|
|
|
/// entities with that name in all crates. This method allows outputting the
|
|
|
|
|
/// results of this search in a programmer-friendly way
|
2017-05-10 11:19:29 +00:00
|
|
|
|
fn show_candidates(err: &mut DiagnosticBuilder,
|
2017-09-01 09:14:04 +00:00
|
|
|
|
// This is `None` if all placement locations are inside expansions
|
|
|
|
|
span: Option<Span>,
|
2016-11-30 22:35:25 +00:00
|
|
|
|
candidates: &[ImportSuggestion],
|
2017-08-18 10:46:28 +00:00
|
|
|
|
better: bool,
|
|
|
|
|
found_use: bool) {
|
2016-11-30 22:35:25 +00:00
|
|
|
|
|
|
|
|
|
// we want consistent results across executions, but candidates are produced
|
|
|
|
|
// by iterating through a hash map, so make sure they are ordered:
|
|
|
|
|
let mut path_strings: Vec<_> =
|
|
|
|
|
candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
|
|
|
|
|
path_strings.sort();
|
|
|
|
|
|
|
|
|
|
let better = if better { "better " } else { "" };
|
|
|
|
|
let msg_diff = match path_strings.len() {
|
|
|
|
|
1 => " is found in another module, you can import it",
|
|
|
|
|
_ => "s are found in other modules, you can import them",
|
2016-02-14 01:47:27 +00:00
|
|
|
|
};
|
2017-05-10 11:19:29 +00:00
|
|
|
|
let msg = format!("possible {}candidate{} into scope", better, msg_diff);
|
|
|
|
|
|
2017-09-01 09:14:04 +00:00
|
|
|
|
if let Some(span) = span {
|
|
|
|
|
for candidate in &mut path_strings {
|
|
|
|
|
// produce an additional newline to separate the new use statement
|
|
|
|
|
// from the directly following item.
|
|
|
|
|
let additional_newline = if found_use {
|
|
|
|
|
""
|
|
|
|
|
} else {
|
|
|
|
|
"\n"
|
|
|
|
|
};
|
|
|
|
|
*candidate = format!("use {};\n{}", candidate, additional_newline);
|
|
|
|
|
}
|
2017-01-19 00:33:25 +00:00
|
|
|
|
|
2017-09-01 09:14:04 +00:00
|
|
|
|
err.span_suggestions(span, &msg, path_strings);
|
|
|
|
|
} else {
|
|
|
|
|
let mut msg = msg;
|
|
|
|
|
msg.push(':');
|
|
|
|
|
for candidate in path_strings {
|
|
|
|
|
msg.push('\n');
|
|
|
|
|
msg.push_str(&candidate);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-14 01:47:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-15 21:44:19 +00:00
|
|
|
|
/// A somewhat inefficient routine to obtain the name of a module.
|
2018-01-16 19:47:14 +00:00
|
|
|
|
fn module_to_string(module: Module) -> Option<String> {
|
2015-03-15 21:44:19 +00:00
|
|
|
|
let mut names = Vec::new();
|
|
|
|
|
|
2016-10-16 03:06:09 +00:00
|
|
|
|
fn collect_mod(names: &mut Vec<Ident>, module: Module) {
|
2016-09-18 09:45:06 +00:00
|
|
|
|
if let ModuleKind::Def(_, name) = module.kind {
|
|
|
|
|
if let Some(parent) = module.parent {
|
2016-10-16 03:06:09 +00:00
|
|
|
|
names.push(Ident::with_empty_ctxt(name));
|
2016-09-18 09:45:06 +00:00
|
|
|
|
collect_mod(names, parent);
|
2015-03-15 21:44:19 +00:00
|
|
|
|
}
|
2016-09-18 09:45:06 +00:00
|
|
|
|
} else {
|
|
|
|
|
// danger, shouldn't be ident?
|
2016-11-16 08:21:52 +00:00
|
|
|
|
names.push(Ident::from_str("<opaque>"));
|
2016-10-01 07:38:47 +00:00
|
|
|
|
collect_mod(names, module.parent.unwrap());
|
2015-03-15 21:44:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
collect_mod(&mut names, module);
|
|
|
|
|
|
2015-03-24 23:53:34 +00:00
|
|
|
|
if names.is_empty() {
|
2018-01-16 19:47:14 +00:00
|
|
|
|
return None;
|
2015-03-15 21:44:19 +00:00
|
|
|
|
}
|
2018-01-16 19:47:14 +00:00
|
|
|
|
Some(names_to_string(&names.into_iter()
|
2017-07-23 22:15:45 +00:00
|
|
|
|
.rev()
|
2018-01-16 19:47:14 +00:00
|
|
|
|
.collect::<Vec<_>>()))
|
2015-03-15 21:44:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-11 07:59:11 +00:00
|
|
|
|
fn err_path_resolution() -> PathResolution {
|
2016-06-03 20:15:00 +00:00
|
|
|
|
PathResolution::new(Def::Err)
|
2015-12-11 07:59:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
|
#[derive(PartialEq,Copy, Clone)]
|
2014-11-23 09:29:41 +00:00
|
|
|
|
pub enum MakeGlobMap {
|
|
|
|
|
Yes,
|
2015-10-26 19:31:11 +00:00
|
|
|
|
No,
|
2013-02-19 07:40:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 22:43:02 +00:00
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
2018-05-22 15:10:17 +00:00
|
|
|
|
enum CrateLint {
|
|
|
|
|
/// Do not issue the lint
|
|
|
|
|
No,
|
|
|
|
|
|
|
|
|
|
/// This lint applies to some random path like `impl ::foo::Bar`
|
|
|
|
|
/// or whatever. In this case, we can take the span of that path.
|
|
|
|
|
SimplePath(NodeId),
|
|
|
|
|
|
|
|
|
|
/// This lint comes from a `use` statement. In this case, what we
|
|
|
|
|
/// care about really is the *root* `use` statement; e.g., if we
|
|
|
|
|
/// have nested things like `use a::{b, c}`, we care about the
|
|
|
|
|
/// `use a` part.
|
|
|
|
|
UsePath { root_id: NodeId, root_span: Span },
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-28 02:48:22 +00:00
|
|
|
|
__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
|