2015-03-16 10:44:19 +13:00
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08: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.
|
|
|
|
|
2014-12-19 00:46:26 +02:00
|
|
|
#![crate_name = "rustc_resolve"]
|
2015-08-13 10:21:36 -07:00
|
|
|
#![unstable(feature = "rustc_private", issue = "27812")]
|
2014-12-19 00:46:26 +02:00
|
|
|
#![crate_type = "dylib"]
|
|
|
|
#![crate_type = "rlib"]
|
2015-08-09 14:15:05 -07:00
|
|
|
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
2015-05-15 16:04:01 -07:00
|
|
|
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
2015-08-09 14:15:05 -07:00
|
|
|
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
2016-01-21 15:26:19 -08:00
|
|
|
#![cfg_attr(not(stage0), deny(warnings))]
|
2014-12-19 00:46:26 +02:00
|
|
|
|
2015-04-28 16:36:22 -07:00
|
|
|
#![feature(associated_consts)]
|
2015-01-30 12:26:44 -08:00
|
|
|
#![feature(rustc_diagnostic_macros)]
|
2015-01-22 18:22:03 -08:00
|
|
|
#![feature(rustc_private)]
|
2015-01-30 12:26:44 -08:00
|
|
|
#![feature(staged_api)]
|
2014-12-19 00:46:26 +02:00
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
|
|
|
#[macro_use]
|
|
|
|
extern crate syntax;
|
2016-06-21 18:08:13 -04: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 20:31:11 +01:00
|
|
|
#[macro_use]
|
2014-12-19 00:46:26 +02:00
|
|
|
extern crate rustc;
|
|
|
|
|
2014-11-06 00:05:53 -08:00
|
|
|
use self::Namespace::*;
|
|
|
|
use self::FallbackSuggestion::*;
|
|
|
|
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};
|
2016-09-16 02:52:09 +00:00
|
|
|
use rustc::middle::cstore::CrateLoader;
|
2014-12-19 00:46:26 +02:00
|
|
|
use rustc::session::Session;
|
|
|
|
use rustc::lint;
|
2016-03-29 12:54:26 +03:00
|
|
|
use rustc::hir::def::*;
|
2016-08-31 14:00:29 +03:00
|
|
|
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
2016-04-09 23:19:53 +00:00
|
|
|
use rustc::ty;
|
2016-04-19 22:43:10 +09:00
|
|
|
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
|
2016-11-08 14:02:55 +11:00
|
|
|
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet};
|
2012-12-23 17:41:37 -05:00
|
|
|
|
2016-10-16 03:39:52 +00:00
|
|
|
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
2016-02-08 16:09:01 +01:00
|
|
|
use syntax::ast::{self, FloatTy};
|
2016-10-22 23:34:18 +00:00
|
|
|
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, SpannedIdent, IntTy, UintTy};
|
2016-10-06 08:04:30 +00:00
|
|
|
use syntax::ext::base::SyntaxExtension;
|
2016-11-25 06:07:21 +00:00
|
|
|
use syntax::ext::base::Determinacy::{Determined, Undetermined};
|
2016-11-16 10:52:37 +00:00
|
|
|
use syntax::symbol::{Symbol, keywords};
|
2015-12-14 22:36:31 +05:30
|
|
|
use syntax::util::lev_distance::find_best_match_for_name;
|
2015-07-31 00:04:06 -07: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};
|
|
|
|
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
|
|
|
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
2016-06-03 23:15:00 +03:00
|
|
|
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
2016-12-10 06:45:58 +00:00
|
|
|
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-12-09 11:08:39 +00:00
|
|
|
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
2016-06-21 18:08:13 -04:00
|
|
|
use errors::DiagnosticBuilder;
|
|
|
|
|
2013-12-20 21:14:25 -08:00
|
|
|
use std::cell::{Cell, RefCell};
|
2014-11-28 15:41:16 +13:00
|
|
|
use std::fmt;
|
2014-02-01 04:35:36 +08:00
|
|
|
use std::mem::replace;
|
2016-09-16 06:45:03 +00:00
|
|
|
use std::rc::Rc;
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-11-10 10:11:25 +00:00
|
|
|
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
|
2016-10-31 22:17:15 +00:00
|
|
|
use macros::{InvocationData, LegacyBinding, LegacyScope};
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2015-01-16 15:54:58 -08: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 15:54:58 -08:00
|
|
|
|
2016-09-07 23:21:59 +00:00
|
|
|
mod macros;
|
2014-12-10 19:46:38 -08:00
|
|
|
mod check_unused;
|
2014-12-30 12:16:42 -06:00
|
|
|
mod build_reduced_graph;
|
2015-03-16 10:44:19 +13:00
|
|
|
mod resolve_imports;
|
2014-12-19 09:13:54 +02:00
|
|
|
|
2015-11-21 15:07:50 +05:30
|
|
|
enum SuggestionType {
|
|
|
|
Macro(String),
|
2016-11-16 10:52:37 +00:00
|
|
|
Function(Symbol),
|
2015-11-21 15:07:50 +05:30
|
|
|
NotFound,
|
|
|
|
}
|
|
|
|
|
2016-02-14 02:47:27 +01:00
|
|
|
/// Candidates for a name resolution failure
|
2016-03-17 01:05:29 +00:00
|
|
|
struct SuggestedCandidates {
|
2016-02-14 02:47:27 +01:00
|
|
|
name: String,
|
|
|
|
candidates: Vec<Path>,
|
|
|
|
}
|
|
|
|
|
2016-03-17 01:05:29 +00:00
|
|
|
enum ResolutionError<'a> {
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0401: can't use type parameters from outer function
|
2015-07-14 16:32:43 +02:00
|
|
|
TypeParametersFromOuterFunction,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0402: cannot use an outer type parameter in this context
|
2015-07-14 16:32:43 +02:00
|
|
|
OuterTypeParameterContext,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0403: the name is already used for a type parameter in this type parameter list
|
2016-08-16 20:47:45 -05:00
|
|
|
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0404: is not a trait
|
2016-10-26 20:51:49 -07:00
|
|
|
IsNotATrait(&'a str, &'a str),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0405: use of undeclared trait name
|
2016-02-14 02:47:27 +01:00
|
|
|
UndeclaredTraitName(&'a str, SuggestedCandidates),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0407: method is not a member of trait
|
2015-07-14 19:42:38 +02:00
|
|
|
MethodNotMemberOfTrait(Name, &'a str),
|
2015-07-18 19:56:15 -04: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),
|
2016-05-06 20:42:23 +05:30
|
|
|
/// error E0408: variable `{}` from pattern #{} is not bound in pattern #{}
|
|
|
|
VariableNotBoundInPattern(Name, usize, usize),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
|
2016-08-16 22:13:09 +03:00
|
|
|
VariableBoundWithDifferentMode(Name, usize, Span),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0411: use of `Self` outside of an impl or trait
|
2015-07-14 16:32:43 +02:00
|
|
|
SelfUsedOutsideImplOrTrait,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0412: use of undeclared
|
2016-02-14 02:47:27 +01:00
|
|
|
UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0415: identifier is bound more than once in this parameter list
|
2015-07-14 19:42:38 +02:00
|
|
|
IdentifierBoundMoreThanOnceInParameterList(&'a str),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0416: identifier is bound more than once in the same pattern
|
2015-07-14 19:42:38 +02:00
|
|
|
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0423: is a struct variant name, but this expression uses it like a function name
|
2015-07-14 19:42:38 +02:00
|
|
|
StructVariantUsedAsFunction(&'a str),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0424: `self` is not available in a static method
|
2015-07-14 16:32:43 +02:00
|
|
|
SelfNotAvailableInStaticMethod,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0425: unresolved name
|
2016-05-13 17:17:10 +02:00
|
|
|
UnresolvedName {
|
|
|
|
path: &'a str,
|
|
|
|
message: &'a str,
|
|
|
|
context: UnresolvedNameContext<'a>,
|
|
|
|
is_static_method: bool,
|
2016-05-26 15:29:17 +02:00
|
|
|
is_field: bool,
|
|
|
|
def: Def,
|
2016-05-13 17:17:10 +02:00
|
|
|
},
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0426: use of undeclared label
|
2015-07-14 19:42:38 +02:00
|
|
|
UndeclaredLabel(&'a str),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0429: `self` imports are only allowed within a { } list
|
2015-07-14 16:32:43 +02:00
|
|
|
SelfImportsOnlyAllowedWithin,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0430: `self` import can only appear once in the list
|
2015-07-14 16:32:43 +02:00
|
|
|
SelfImportCanOnlyAppearOnceInTheList,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0431: `self` import can only appear in an import list with a non-empty prefix
|
2015-07-14 16:32:43 +02:00
|
|
|
SelfImportOnlyInImportListWithNonEmptyPrefix,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0432: unresolved import
|
2015-07-31 10:22:13 +02:00
|
|
|
UnresolvedImport(Option<(&'a str, &'a str)>),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0433: failed to resolve
|
2015-07-14 19:42:38 +02:00
|
|
|
FailedToResolve(&'a str),
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0434: can't capture dynamic environment in a fn item
|
2015-07-14 16:32:43 +02:00
|
|
|
CannotCaptureDynamicEnvironmentInFnItem,
|
2015-07-14 15:37:52 +02:00
|
|
|
/// error E0435: attempt to use a non-constant value in a constant
|
2015-07-14 16:32:43 +02:00
|
|
|
AttemptToUseNonConstantValueInConstant,
|
2016-06-03 23:15:00 +03:00
|
|
|
/// error E0530: X bindings cannot shadow Ys
|
2016-07-29 15:19:29 +00:00
|
|
|
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
|
2016-06-03 23:15:00 +03:00
|
|
|
/// error E0531: unresolved pattern path kind `name`
|
2016-06-03 23:15:00 +03:00
|
|
|
PatPathUnresolved(&'a str, &'a Path),
|
2016-06-03 23:15:00 +03:00
|
|
|
/// error E0532: expected pattern path kind, found another pattern path kind
|
2016-06-03 23:15:00 +03:00
|
|
|
PatPathUnexpected(&'a str, &'a str, &'a Path),
|
2015-07-13 02:05:02 +02:00
|
|
|
}
|
|
|
|
|
2015-12-18 17:42:46 +01:00
|
|
|
/// Context of where `ResolutionError::UnresolvedName` arose.
|
2015-12-11 00:00:17 +01:00
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
2016-04-24 21:10:54 +00:00
|
|
|
enum UnresolvedNameContext<'a> {
|
|
|
|
/// `PathIsMod(parent)` indicates that a given path, used in
|
2015-12-18 17:42:46 +01:00
|
|
|
/// expression context, actually resolved to a module rather than
|
2016-04-24 21:10:54 +00:00
|
|
|
/// a value. The optional expression attached to the variant is the
|
|
|
|
/// the parent of the erroneous path expression.
|
|
|
|
PathIsMod(Option<&'a Expr>),
|
2015-12-18 17:42:46 +01:00
|
|
|
|
|
|
|
/// `Other` means we have no extra information about the context
|
|
|
|
/// of the unresolved name error. (Maybe we could eliminate all
|
|
|
|
/// such cases; but for now, this is an information-free default.)
|
2015-12-11 00:00:17 +01:00
|
|
|
Other,
|
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
fn resolve_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
2016-06-21 18:08:13 -04:00
|
|
|
span: syntax_pos::Span,
|
2016-04-24 03:26:10 +00:00
|
|
|
resolution_error: ResolutionError<'c>) {
|
2015-12-23 19:27:20 +13:00
|
|
|
resolve_struct_error(resolver, span, resolution_error).emit();
|
2015-12-21 10:00:43 +13:00
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
|
2016-06-21 18:08:13 -04:00
|
|
|
span: syntax_pos::Span,
|
2016-04-24 03:26:10 +00:00
|
|
|
resolution_error: ResolutionError<'c>)
|
|
|
|
-> DiagnosticBuilder<'a> {
|
2015-12-23 19:27:20 +13:00
|
|
|
match resolution_error {
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::TypeParametersFromOuterFunction => {
|
2016-05-11 14:42:18 -07:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0401,
|
|
|
|
"can't use type parameters from outer function; \
|
|
|
|
try using a local type parameter instead");
|
2016-05-12 16:39:09 -07:00
|
|
|
err.span_label(span, &format!("use of type variable from outer function"));
|
2016-05-11 14:42:18 -07:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::OuterTypeParameterContext => {
|
2015-12-21 10:00:43 +13:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0402,
|
|
|
|
"cannot use an outer type parameter in this context")
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-08-16 20:47:45 -05: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);
|
|
|
|
err.span_label(span, &format!("already used"));
|
|
|
|
err.span_label(first_use_span.clone(), &format!("first use of `{}`", name));
|
|
|
|
err
|
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-10-26 20:51:49 -07:00
|
|
|
ResolutionError::IsNotATrait(name, kind_name) => {
|
2016-08-05 16:59:44 +09:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0404,
|
|
|
|
"`{}` is not a trait",
|
|
|
|
name);
|
2016-10-26 20:51:49 -07:00
|
|
|
err.span_label(span, &format!("expected trait, found {}", kind_name));
|
2016-08-05 16:59:44 +09:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-02-14 02:47:27 +01:00
|
|
|
ResolutionError::UndeclaredTraitName(name, candidates) => {
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0405,
|
|
|
|
"trait `{}` is not in scope",
|
|
|
|
name);
|
2016-04-20 14:49:16 -04:00
|
|
|
show_candidates(&mut err, &candidates);
|
2016-05-12 16:39:09 -07:00
|
|
|
err.span_label(span, &format!("`{}` is not in scope", name));
|
2016-02-14 02:47:27 +01:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
|
2016-08-17 00:03:53 +02:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0407,
|
|
|
|
"method `{}` is not a member of trait `{}`",
|
|
|
|
method,
|
|
|
|
trait_);
|
2016-09-12 17:47:59 -04:00
|
|
|
err.span_label(span, &format!("not a member of trait `{}`", trait_));
|
2016-08-17 00:03:53 +02:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-18 19:56:15 -04:00
|
|
|
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
|
2016-08-21 18:43:58 +05:30
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0437,
|
|
|
|
"type `{}` is not a member of trait `{}`",
|
|
|
|
type_,
|
2016-08-21 18:43:58 +05:30
|
|
|
trait_);
|
2016-09-12 17:47:59 -04:00
|
|
|
err.span_label(span, &format!("not a member of trait `{}`", trait_));
|
2016-08-21 18:43:58 +05:30
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-18 19:56:15 -04:00
|
|
|
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
|
2016-08-21 18:43:58 +05:30
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0438,
|
|
|
|
"const `{}` is not a member of trait `{}`",
|
|
|
|
const_,
|
2016-08-21 18:43:58 +05:30
|
|
|
trait_);
|
2016-09-12 17:47:59 -04:00
|
|
|
err.span_label(span, &format!("not a member of trait `{}`", trait_));
|
2016-08-21 18:43:58 +05:30
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-05-06 20:42:23 +05:30
|
|
|
ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
|
2016-09-06 23:00:35 +02:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0408,
|
2016-05-06 20:42:23 +05:30
|
|
|
"variable `{}` from pattern #{} is not bound in pattern #{}",
|
2015-12-21 10:00:43 +13:00
|
|
|
variable_name,
|
2016-05-06 20:42:23 +05:30
|
|
|
from,
|
2016-09-06 23:00:35 +02:00
|
|
|
to);
|
|
|
|
err.span_label(span, &format!("pattern doesn't bind `{}`", variable_name));
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-08-16 22:13:09 +03:00
|
|
|
ResolutionError::VariableBoundWithDifferentMode(variable_name,
|
|
|
|
pattern_number,
|
|
|
|
first_binding_span) => {
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0409,
|
|
|
|
"variable `{}` is bound with different mode in pattern #{} than in \
|
|
|
|
pattern #1",
|
|
|
|
variable_name,
|
2016-08-16 22:13:09 +03:00
|
|
|
pattern_number);
|
|
|
|
err.span_label(span, &format!("bound in different ways"));
|
|
|
|
err.span_label(first_binding_span, &format!("first binding"));
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::SelfUsedOutsideImplOrTrait => {
|
2016-05-11 14:42:18 -07:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0411,
|
|
|
|
"use of `Self` outside of an impl or trait");
|
2016-05-13 12:57:34 -07:00
|
|
|
err.span_label(span, &format!("used outside of impl or trait"));
|
2016-05-11 14:42:18 -07:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-02-14 02:47:27 +01:00
|
|
|
ResolutionError::UseOfUndeclared(kind, name, candidates) => {
|
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0412,
|
|
|
|
"{} `{}` is undefined or not in scope",
|
|
|
|
kind,
|
|
|
|
name);
|
2016-04-20 14:49:16 -04:00
|
|
|
show_candidates(&mut err, &candidates);
|
2016-05-12 16:39:09 -07:00
|
|
|
err.span_label(span, &format!("undefined or not in scope"));
|
2016-02-14 02:47:27 +01:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
2016-05-11 14:42:18 -07:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0415,
|
|
|
|
"identifier `{}` is bound more than once in this parameter list",
|
2016-05-11 14:42:18 -07:00
|
|
|
identifier);
|
2016-05-12 16:39:09 -07:00
|
|
|
err.span_label(span, &format!("used as parameter more than once"));
|
2016-05-11 14:42:18 -07:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
|
2016-05-11 14:42:18 -07:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0416,
|
|
|
|
"identifier `{}` is bound more than once in the same pattern",
|
2016-05-11 14:42:18 -07:00
|
|
|
identifier);
|
2016-05-12 16:39:09 -07:00
|
|
|
err.span_label(span, &format!("used in a pattern more than once"));
|
2016-05-11 14:42:18 -07:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::StructVariantUsedAsFunction(path_name) => {
|
2016-08-22 13:57:37 +08:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0423,
|
|
|
|
"`{}` is the name of a struct or struct variant, but this expression \
|
|
|
|
uses it like a function name",
|
2016-08-22 13:57:37 +08:00
|
|
|
path_name);
|
|
|
|
err.span_label(span, &format!("struct called like a function"));
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::SelfNotAvailableInStaticMethod => {
|
2016-08-20 02:41:51 +02:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0424,
|
2016-08-20 02:41:51 +02:00
|
|
|
"`self` is not available in a static method");
|
|
|
|
err.span_label(span, &format!("not available in static method"));
|
|
|
|
err.note(&format!("maybe a `self` argument is missing?"));
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2016-05-13 17:17:10 +02:00
|
|
|
ResolutionError::UnresolvedName { path, message: msg, context, is_static_method,
|
2016-05-26 15:29:17 +02:00
|
|
|
is_field, def } => {
|
2015-12-24 10:54:37 +13:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0425,
|
2016-09-26 16:05:46 -07:00
|
|
|
"unresolved name `{}`",
|
|
|
|
path);
|
|
|
|
if msg != "" {
|
|
|
|
err.span_label(span, &msg);
|
|
|
|
} else {
|
|
|
|
err.span_label(span, &format!("unresolved name"));
|
|
|
|
}
|
|
|
|
|
2015-12-11 00:00:17 +01:00
|
|
|
match context {
|
2016-05-13 17:17:10 +02:00
|
|
|
UnresolvedNameContext::Other => {
|
|
|
|
if msg.is_empty() && is_static_method && is_field {
|
|
|
|
err.help("this is an associated function, you don't have access to \
|
|
|
|
this type's fields or methods");
|
|
|
|
}
|
|
|
|
}
|
2016-04-24 21:10:54 +00:00
|
|
|
UnresolvedNameContext::PathIsMod(parent) => {
|
2016-04-20 14:49:16 -04:00
|
|
|
err.help(&match parent.map(|parent| &parent.node) {
|
2016-04-24 03:26:10 +00:00
|
|
|
Some(&ExprKind::Field(_, ident)) => {
|
2016-05-26 15:29:17 +02:00
|
|
|
format!("to reference an item from the `{module}` module, \
|
2016-04-24 21:10:54 +00:00
|
|
|
use `{module}::{ident}`",
|
|
|
|
module = path,
|
|
|
|
ident = ident.node)
|
2015-12-11 00:00:17 +01:00
|
|
|
}
|
2016-08-26 19:23:42 +03:00
|
|
|
Some(&ExprKind::MethodCall(ident, ..)) => {
|
2016-05-26 15:29:17 +02:00
|
|
|
format!("to call a function from the `{module}` module, \
|
2016-04-24 21:10:54 +00:00
|
|
|
use `{module}::{ident}(..)`",
|
|
|
|
module = path,
|
|
|
|
ident = ident.node)
|
|
|
|
}
|
|
|
|
_ => {
|
2016-05-26 15:29:17 +02:00
|
|
|
format!("{def} `{module}` cannot be used as an expression",
|
|
|
|
def = def.kind_name(),
|
2016-04-24 21:10:54 +00:00
|
|
|
module = path)
|
|
|
|
}
|
|
|
|
});
|
2015-12-11 00:00:17 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-21 10:00:43 +13:00
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::UndeclaredLabel(name) => {
|
2016-08-19 22:31:31 +02:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0426,
|
|
|
|
"use of undeclared label `{}`",
|
|
|
|
name);
|
|
|
|
err.span_label(span, &format!("undeclared label `{}`",&name));
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
2015-12-21 10:00:43 +13:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0429,
|
|
|
|
"{}",
|
|
|
|
"`self` imports are only allowed within a { } list")
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
|
2015-12-21 10:00:43 +13:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0430,
|
|
|
|
"`self` import can only appear once in the list")
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
|
2015-12-21 10:00:43 +13:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0431,
|
|
|
|
"`self` import can only appear in an import list with a \
|
|
|
|
non-empty prefix")
|
2015-07-14 15:37:52 +02:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::UnresolvedImport(name) => {
|
2015-07-14 15:37:52 +02:00
|
|
|
let msg = match name {
|
2016-08-22 13:57:10 +08:00
|
|
|
Some((n, _)) => format!("unresolved import `{}`", n),
|
2015-10-26 20:31:11 +01:00
|
|
|
None => "unresolved import".to_owned(),
|
2015-07-14 15:37:52 +02:00
|
|
|
};
|
2016-08-22 13:57:10 +08:00
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg);
|
|
|
|
if let Some((_, p)) = name {
|
|
|
|
err.span_label(span, &p);
|
|
|
|
}
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::FailedToResolve(msg) => {
|
2016-08-11 10:17:12 -07:00
|
|
|
let mut err = struct_span_err!(resolver.session, span, E0433,
|
|
|
|
"failed to resolve. {}", msg);
|
2016-08-09 00:26:43 +02:00
|
|
|
err.span_label(span, &msg);
|
|
|
|
err
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-07-14 19:42:38 +02:00
|
|
|
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
2015-12-21 10:00:43 +13:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0434,
|
|
|
|
"{}",
|
|
|
|
"can't capture dynamic environment in a fn item; use the || { ... } \
|
|
|
|
closure form instead")
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
|
|
|
ResolutionError::AttemptToUseNonConstantValueInConstant => {
|
2016-08-21 18:43:58 +05:30
|
|
|
let mut err = struct_span_err!(resolver.session,
|
2015-12-21 10:00:43 +13:00
|
|
|
span,
|
|
|
|
E0435,
|
2016-08-21 18:43:58 +05:30
|
|
|
"attempt to use a non-constant value in a constant");
|
|
|
|
err.span_label(span, &format!("non-constant used with constant"));
|
|
|
|
err
|
2015-10-26 20:31:11 +01: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 23:15:00 +03:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
2016-06-03 23:15:00 +03:00
|
|
|
E0530,
|
2016-06-03 23:15:00 +03:00
|
|
|
"{}s cannot shadow {}s", what_binding, shadows_what);
|
|
|
|
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" };
|
|
|
|
let msg = &format!("a {} `{}` is {} here", shadows_what, name, participle);
|
|
|
|
err.span_label(binding.span, msg);
|
2016-06-03 23:15:00 +03:00
|
|
|
err
|
|
|
|
}
|
|
|
|
ResolutionError::PatPathUnresolved(expected_what, path) => {
|
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
2016-06-03 23:15:00 +03:00
|
|
|
E0531,
|
2016-06-03 23:15:00 +03:00
|
|
|
"unresolved {} `{}`",
|
|
|
|
expected_what,
|
2016-09-15 00:51:46 +03:00
|
|
|
path)
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
|
|
|
ResolutionError::PatPathUnexpected(expected_what, found_what, path) => {
|
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
2016-06-03 23:15:00 +03:00
|
|
|
E0532,
|
2016-06-03 23:15:00 +03:00
|
|
|
"expected {}, found {} `{}`",
|
|
|
|
expected_what,
|
|
|
|
found_what,
|
2016-09-15 00:51:46 +03:00
|
|
|
path)
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2015-12-23 19:27:20 +13:00
|
|
|
}
|
2015-07-13 02:05:02 +02:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone)]
|
2014-12-18 19:17:41 +02:00
|
|
|
struct BindingInfo {
|
2013-08-31 18:13:04 +02:00
|
|
|
span: Span,
|
2013-09-02 03:45:37 +02:00
|
|
|
binding_mode: BindingMode,
|
2012-08-06 07:20:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Map from the name in a pattern to its binding mode.
|
2016-11-08 14:02:55 +11:00
|
|
|
type BindingMap = FxHashMap<Ident, BindingInfo>;
|
2012-08-06 07:20:23 -07:00
|
|
|
|
2016-06-03 23:15:00 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
enum PatternSource {
|
|
|
|
Match,
|
|
|
|
IfLet,
|
|
|
|
WhileLet,
|
|
|
|
Let,
|
|
|
|
For,
|
|
|
|
FnParam,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PatternSource {
|
|
|
|
fn is_refutable(self) -> bool {
|
|
|
|
match self {
|
|
|
|
PatternSource::Match | PatternSource::IfLet | PatternSource::WhileLet => true,
|
|
|
|
PatternSource::Let | PatternSource::For | PatternSource::FnParam => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
2015-05-14 23:40:16 +12:00
|
|
|
pub enum Namespace {
|
2012-05-22 10:54:12 -07:00
|
|
|
TypeNS,
|
2015-10-26 20:31:11 +01:00
|
|
|
ValueNS,
|
2016-10-25 22:05:02 +00:00
|
|
|
MacroNS,
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
#[derive(Clone, Default, Debug)]
|
|
|
|
pub struct PerNS<T> {
|
|
|
|
value_ns: T,
|
|
|
|
type_ns: T,
|
2016-11-10 10:29:36 +00:00
|
|
|
macro_ns: Option<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,
|
2016-11-10 10:29:36 +00:00
|
|
|
MacroNS => self.macro_ns.as_ref().unwrap(),
|
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,
|
2016-11-10 10:29:36 +00:00
|
|
|
MacroNS => self.macro_ns.as_mut().unwrap(),
|
2016-11-10 06:19:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
|
|
|
fn visit_item(&mut self, item: &'tcx Item) {
|
2013-09-26 19:10:16 -07:00
|
|
|
self.resolve_item(item);
|
2013-08-13 18:52:41 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_arm(&mut self, arm: &'tcx Arm) {
|
2013-09-26 19:10:16 -07:00
|
|
|
self.resolve_arm(arm);
|
2013-08-13 18:52:41 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_block(&mut self, block: &'tcx Block) {
|
2013-09-26 19:10:16 -07:00
|
|
|
self.resolve_block(block);
|
2013-08-13 18:52:41 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01: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 18:52:41 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_local(&mut self, local: &'tcx Local) {
|
2013-09-26 19:10:16 -07:00
|
|
|
self.resolve_local(local);
|
2013-08-13 18:52:41 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_ty(&mut self, ty: &'tcx Ty) {
|
2013-09-26 19:10:16 -07:00
|
|
|
self.resolve_type(ty);
|
2013-08-13 18:52:41 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_poly_trait_ref(&mut self,
|
|
|
|
tref: &'tcx ast::PolyTraitRef,
|
|
|
|
m: &'tcx ast::TraitBoundModifier) {
|
2016-11-25 06:07:21 +00:00
|
|
|
let ast::Path { ref segments, span, global } = tref.trait_ref.path;
|
|
|
|
let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
|
|
|
|
let def = self.resolve_trait_reference(&path, global, None, span);
|
2016-11-22 11:32:52 +00:00
|
|
|
self.record_def(tref.trait_ref.ref_id, def);
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_poly_trait_ref(self, tref, m);
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
2015-10-26 20:31:11 +01:00
|
|
|
fn visit_variant(&mut self,
|
2016-12-06 11:26:52 +01:00
|
|
|
variant: &'tcx ast::Variant,
|
|
|
|
generics: &'tcx Generics,
|
2015-10-26 20:31:11 +01:00
|
|
|
item_id: ast::NodeId) {
|
2015-02-05 09:19:07 +02:00
|
|
|
if let Some(ref dis_expr) = variant.node.disr_expr {
|
|
|
|
// resolve the discriminator expr as a constant
|
|
|
|
self.with_constant_rib(|this| {
|
2015-11-17 18:56:13 -05:00
|
|
|
this.visit_expr(dis_expr);
|
2015-02-05 09:19:07 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
// `visit::walk_variant` without the discriminant expression.
|
2015-10-26 20:31:11 +01:00
|
|
|
self.visit_variant_data(&variant.node.data,
|
|
|
|
variant.node.name,
|
|
|
|
generics,
|
|
|
|
item_id,
|
|
|
|
variant.span);
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
|
2015-02-05 09:19:07 +02:00
|
|
|
let type_parameters = match foreign_item.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
ForeignItemKind::Fn(_, ref generics) => {
|
2016-08-15 01:07:09 +03:00
|
|
|
HasTypeParameters(generics, ItemRibKind)
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
ForeignItemKind::Static(..) => NoTypeParameters,
|
2015-02-05 09:19:07 +02: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 09:19:07 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
fn visit_fn(&mut self,
|
2016-12-06 11:26:52 +01:00
|
|
|
function_kind: FnKind<'tcx>,
|
|
|
|
declaration: &'tcx FnDecl,
|
2015-02-05 09:19:07 +02:00
|
|
|
_: Span,
|
|
|
|
node_id: NodeId) {
|
|
|
|
let rib_kind = match function_kind {
|
2016-08-26 19:23:42 +03:00
|
|
|
FnKind::ItemFn(_, generics, ..) => {
|
2015-02-05 09:19:07 +02:00
|
|
|
self.visit_generics(generics);
|
|
|
|
ItemRibKind
|
|
|
|
}
|
2016-10-26 02:17:29 +03:00
|
|
|
FnKind::Method(_, sig, _, _) => {
|
2015-03-11 23:38:58 +02:00
|
|
|
self.visit_generics(&sig.generics);
|
2016-03-06 15:54:44 +03:00
|
|
|
MethodRibKind(!sig.decl.has_self())
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
2016-10-26 02:17:29 +03:00
|
|
|
FnKind::Closure(_) => ClosureRibKind(node_id),
|
2015-02-05 09:19:07 +02:00
|
|
|
};
|
2016-10-26 02:17:29 +03: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-26 02:17:29 +03: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 09:19:07 +02:00
|
|
|
}
|
2013-08-13 18:52:41 +02:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-02-07 23:58:14 +00:00
|
|
|
pub type ErrorMessage = Option<(Span, String)>;
|
2014-06-05 22:37:52 +01:00
|
|
|
|
2014-05-08 22:35:09 +01:00
|
|
|
enum FallbackSuggestion {
|
|
|
|
NoSuggestion,
|
|
|
|
Field,
|
2014-08-04 13:56:56 -07:00
|
|
|
TraitItem,
|
2014-10-15 13:33:20 +13:00
|
|
|
TraitMethod(String),
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone)]
|
2016-04-24 03:26:10 +00:00
|
|
|
enum TypeParameters<'a, 'b> {
|
2014-05-31 18:53:13 -04:00
|
|
|
NoTypeParameters,
|
2015-10-26 20:31:11 +01:00
|
|
|
HasTypeParameters(// Type parameters.
|
2016-04-24 03:26:10 +00:00
|
|
|
&'b Generics,
|
2014-05-31 18:53:13 -04:00
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
// The kind of the rib used for type parameters.
|
2016-04-24 03:26:10 +00:00
|
|
|
RibKind<'a>),
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2014-09-17 17:28:19 +03:00
|
|
|
// The rib kind controls the translation of local
|
2016-01-20 22:31:10 +03:00
|
|
|
// definitions (`Def::Local`) to upvars (`Def::Upvar`).
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
2016-01-22 09:55:29 +00:00
|
|
|
enum RibKind<'a> {
|
2012-05-22 10:54:12 -07:00
|
|
|
// No translation needs to be applied.
|
|
|
|
NormalRibKind,
|
2012-07-06 19:06:58 -07:00
|
|
|
|
2014-09-15 00:40:45 +03:00
|
|
|
// We passed through a closure scope at the given node ID.
|
|
|
|
// Translate upvars as appropriate.
|
2015-01-24 22:04:41 +02:00
|
|
|
ClosureRibKind(NodeId /* func id */),
|
2012-07-06 19:06:58 -07:00
|
|
|
|
2012-12-10 13:47:54 -08:00
|
|
|
// We passed through an impl or trait and are now in one of its
|
2013-06-06 10:38:41 +03:00
|
|
|
// methods. Allow references to ty params that impl or trait
|
2012-07-26 14:04:03 -07:00
|
|
|
// binds. Disallow any other upvars (including other ty params that are
|
|
|
|
// upvars).
|
2016-05-13 17:17:10 +02:00
|
|
|
//
|
|
|
|
// The boolean value represents the fact that this method is static or not.
|
|
|
|
MethodRibKind(bool),
|
2012-07-26 14:04:03 -07:00
|
|
|
|
2014-05-31 01:54:04 -04:00
|
|
|
// We passed through an item scope. Disallow upvars.
|
|
|
|
ItemRibKind,
|
2012-10-15 12:27:09 -07:00
|
|
|
|
|
|
|
// We're in a constant item. Can't refer to dynamic stuff.
|
2015-10-26 20:31:11 +01:00
|
|
|
ConstantItemRibKind,
|
2016-01-22 09:55:29 +00:00
|
|
|
|
2016-02-24 04:48:31 +00:00
|
|
|
// We passed through a module.
|
|
|
|
ModuleRibKind(Module<'a>),
|
2016-06-26 03:32:45 +00:00
|
|
|
|
|
|
|
// We passed through a `macro_rules!` statement with the given expansion
|
2016-06-22 08:03:42 +00:00
|
|
|
MacroDefinition(Mark),
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-14 19:20:56 -07:00
|
|
|
/// One local scope.
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Debug)]
|
2016-01-22 09:55:29 +00:00
|
|
|
struct Rib<'a> {
|
2016-11-08 14:02:55 +11:00
|
|
|
bindings: FxHashMap<Ident, Def>,
|
2016-01-22 09:55:29 +00:00
|
|
|
kind: RibKind<'a>,
|
2012-09-05 15:58:43 -07:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
impl<'a> Rib<'a> {
|
|
|
|
fn new(kind: RibKind<'a>) -> Rib<'a> {
|
2013-08-31 18:13:04 +02:00
|
|
|
Rib {
|
2016-11-08 14:02:55 +11:00
|
|
|
bindings: FxHashMap(),
|
2015-10-26 20:31:11 +01:00
|
|
|
kind: kind,
|
2013-08-31 18:13:04 +02:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-03 20:44:23 +02:00
|
|
|
/// A definition along with the index of the rib it was found on
|
2016-11-25 06:07:21 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2015-11-03 20:44:23 +02:00
|
|
|
struct LocalDef {
|
|
|
|
ribs: Option<(Namespace, usize)>,
|
2015-10-26 20:31:11 +01:00
|
|
|
def: Def,
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
|
|
|
|
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-15 02:12:08 +03:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2016-11-25 06:07:21 +00:00
|
|
|
enum PathScope {
|
|
|
|
Global,
|
|
|
|
Lexical,
|
|
|
|
Import,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
enum PathResult<'a> {
|
|
|
|
Module(Module<'a>),
|
|
|
|
NonModule(PathResolution),
|
|
|
|
Indeterminate,
|
|
|
|
Failed(String, bool /* is the error from the last segment? */),
|
|
|
|
}
|
|
|
|
|
2016-09-18 09:45:06 +00:00
|
|
|
enum ModuleKind {
|
|
|
|
Block(NodeId),
|
|
|
|
Def(Def, Name),
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 22:53:12 +01: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-08-22 00:24:11 +00:00
|
|
|
// The node id of the closest normal module (`mod`) ancestor (including this module).
|
2016-08-29 05:29:01 +00:00
|
|
|
normal_ancestor_id: Option<NodeId>,
|
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>>>>,
|
|
|
|
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
|
2016-11-27 10:58:46 +00:00
|
|
|
macro_resolutions: RefCell<Vec<(Box<[Ident]>, PathScope, Span)>>,
|
2012-05-22 10:54:12 -07: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 21:47:01 +02: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-21 18:39:30 -07: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-19 18:53:59 -08:00
|
|
|
populated: Cell<bool>,
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-11-26 12:47:52 +00:00
|
|
|
pub 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> {
|
2016-09-19 05:25:17 +00:00
|
|
|
fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
|
2016-11-26 12:47:52 +00:00
|
|
|
ModuleData {
|
2016-09-18 09:45:06 +00:00
|
|
|
parent: parent,
|
|
|
|
kind: kind,
|
2016-09-19 05:25:17 +00:00
|
|
|
normal_ancestor_id: None,
|
2016-11-08 14:02:55 +11: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()),
|
2016-03-17 11:05:09 +00:00
|
|
|
globs: RefCell::new((Vec::new())),
|
2016-04-18 00:00:18 +00:00
|
|
|
traits: RefCell::new(None),
|
2016-09-19 05:25:17 +00:00
|
|
|
populated: Cell::new(true),
|
2016-01-11 21:19:29 +00:00
|
|
|
}
|
2012-09-05 15:58:43 -07: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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 18:13:04 +02:00
|
|
|
}
|
2012-09-05 15:58:43 -07:00
|
|
|
}
|
2016-10-22 22:08:08 +00:00
|
|
|
|
|
|
|
fn is_local(&self) -> bool {
|
|
|
|
self.normal_ancestor_id.is_some()
|
|
|
|
}
|
2015-08-06 12:47:10 +02:00
|
|
|
}
|
|
|
|
|
2016-11-26 12:47:52 +00:00
|
|
|
impl<'a> fmt::Debug for ModuleData<'a> {
|
2014-11-28 15:41:16 +13: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 15:41:16 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 09:10:41 +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-17 17:55:34 -07: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>,
|
2016-12-09 11:08:39 +00:00
|
|
|
legacy: bool,
|
2016-08-20 05:23:19 +00:00
|
|
|
}
|
2012-09-07 19:04:40 -07:00
|
|
|
}
|
|
|
|
|
2016-02-25 04:40:46 +00:00
|
|
|
struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
|
|
|
|
|
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-12-09 11:08:39 +00:00
|
|
|
legacy: bool,
|
2016-09-06 03:47:11 +00:00
|
|
|
}
|
|
|
|
|
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-12-09 11:08:39 +00:00
|
|
|
NameBindingKind::Ambiguity { legacy: true, b1, .. } => b1.module(),
|
2016-11-27 00:23:54 +00:00
|
|
|
_ => None,
|
2013-05-13 16:13:20 -07: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-12-09 11:08:39 +00:00
|
|
|
NameBindingKind::Ambiguity { legacy: true, b1, .. } => b1.def(),
|
2016-08-20 05:23:19 +00:00
|
|
|
NameBindingKind::Ambiguity { .. } => Def::Err,
|
2012-10-15 18:04:15 -07:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2012-10-15 14:56:42 -07:00
|
|
|
|
2016-11-27 10:27:41 +00:00
|
|
|
fn get_macro(&self, resolver: &mut Resolver<'a>) -> Rc<SyntaxExtension> {
|
|
|
|
match self.kind {
|
|
|
|
NameBindingKind::Import { binding, .. } => binding.get_macro(resolver),
|
|
|
|
NameBindingKind::Ambiguity { b1, .. } => b1.get_macro(resolver),
|
|
|
|
_ => resolver.get_macro(self.def()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
if self.is_variant() { ty::Visibility::Public } else { self.vis }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_variant(&self) -> bool {
|
|
|
|
match self.kind {
|
2016-09-15 00:51:46 +03: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 {
|
|
|
|
subclass: ImportDirectiveSubclass::ExternCrate, ..
|
|
|
|
}, ..
|
|
|
|
} => 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
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
2012-08-17 17:55:34 -07:00
|
|
|
}
|
|
|
|
|
2012-07-04 22:53:12 +01:00
|
|
|
/// Interns the names of the primitive types.
|
2013-10-02 14:33:01 +02:00
|
|
|
struct PrimitiveTypeTable {
|
2016-11-08 14:02:55 +11:00
|
|
|
primitive_types: FxHashMap<Name, PrimTy>,
|
2012-09-07 19:04:40 -07:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2013-05-31 15:17:22 -07:00
|
|
|
impl PrimitiveTypeTable {
|
2014-05-28 20:36:05 +01:00
|
|
|
fn new() -> PrimitiveTypeTable {
|
2016-11-08 14:02:55 +11:00
|
|
|
let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() };
|
2015-10-26 20:31:11 +01:00
|
|
|
|
|
|
|
table.intern("bool", TyBool);
|
|
|
|
table.intern("char", TyChar);
|
2016-02-08 16:09:01 +01:00
|
|
|
table.intern("f32", TyFloat(FloatTy::F32));
|
|
|
|
table.intern("f64", TyFloat(FloatTy::F64));
|
2016-02-08 16:20:57 +01:00
|
|
|
table.intern("isize", TyInt(IntTy::Is));
|
|
|
|
table.intern("i8", TyInt(IntTy::I8));
|
|
|
|
table.intern("i16", TyInt(IntTy::I16));
|
|
|
|
table.intern("i32", TyInt(IntTy::I32));
|
|
|
|
table.intern("i64", TyInt(IntTy::I64));
|
2015-10-26 20:31:11 +01:00
|
|
|
table.intern("str", TyStr);
|
2016-02-08 16:20:57 +01:00
|
|
|
table.intern("usize", TyUint(UintTy::Us));
|
|
|
|
table.intern("u8", TyUint(UintTy::U8));
|
|
|
|
table.intern("u16", TyUint(UintTy::U16));
|
|
|
|
table.intern("u32", TyUint(UintTy::U32));
|
|
|
|
table.intern("u64", TyUint(UintTy::U64));
|
2014-05-28 20:36:05 +01:00
|
|
|
|
|
|
|
table
|
|
|
|
}
|
|
|
|
|
2014-01-09 15:05:33 +02: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 10:54:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 22:53:12 +01:00
|
|
|
/// The main resolver class.
|
2016-04-24 03:26:10 +00:00
|
|
|
pub struct Resolver<'a> {
|
2014-03-05 16:36:01 +02:00
|
|
|
session: &'a Session,
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-06-22 01:54:34 +00:00
|
|
|
pub definitions: Definitions,
|
2014-11-23 22:29:41 +13:00
|
|
|
|
2016-06-26 03:32:45 +00:00
|
|
|
// Maps the node id of a statement to the expansions of the `macro_rules!`s
|
|
|
|
// immediately above the statement (if appropriate).
|
2016-11-08 14:02:55 +11:00
|
|
|
macros_at_scope: FxHashMap<NodeId, Vec<Mark>>,
|
2016-06-26 03:32:45 +00:00
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
graph_root: Module<'a>,
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-06-05 09:56:05 +00:00
|
|
|
prelude: Option<Module<'a>>,
|
|
|
|
|
2016-11-08 14:02:55 +11:00
|
|
|
trait_item_map: FxHashMap<(Name, DefId), bool /* is static method? */>,
|
2014-05-06 16:37:32 -07:00
|
|
|
|
2016-09-15 00:51:46 +03:00
|
|
|
// Names of fields of an item `DefId` accessible with dot syntax.
|
|
|
|
// Used for hints during error reporting.
|
2016-11-08 14:02:55 +11:00
|
|
|
field_names: FxHashMap<DefId, Vec<Name>>,
|
2012-07-11 15:00:40 -07:00
|
|
|
|
2016-08-15 08:19:09 +00:00
|
|
|
// All imports known to succeed or fail.
|
|
|
|
determined_imports: Vec<&'a ImportDirective<'a>>,
|
|
|
|
|
|
|
|
// All non-determined imports.
|
2016-08-17 00:52:18 +00:00
|
|
|
indeterminate_imports: Vec<&'a ImportDirective<'a>>,
|
2012-05-22 10:54:12 -07:00
|
|
|
|
|
|
|
// The module that represents the current item scope.
|
2016-01-11 21:19:29 +00:00
|
|
|
current_module: Module<'a>,
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
// The current set of local scopes for types and values.
|
2013-02-14 18:37:25 -08:00
|
|
|
// FIXME #4948: Reuse ribs to avoid allocation.
|
2016-11-10 06:19:54 +00:00
|
|
|
ribs: PerNS<Vec<Rib<'a>>>,
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2012-08-14 19:20:56 -07:00
|
|
|
// The current set of local scopes, for labels.
|
2016-01-22 09:55:29 +00:00
|
|
|
label_ribs: Vec<Rib<'a>>,
|
2012-08-14 19:20:56 -07:00
|
|
|
|
2012-07-11 15:00:40 -07:00
|
|
|
// The trait that the current context can refer to.
|
2014-05-08 22:35:09 +01:00
|
|
|
current_trait_ref: Option<(DefId, TraitRef)>,
|
|
|
|
|
|
|
|
// The current self type if inside an impl (used for better errors).
|
|
|
|
current_self_type: Option<Ty>,
|
2012-07-11 15:00:40 -07:00
|
|
|
|
2012-09-19 18:52:49 -07:00
|
|
|
// The idents for the primitive types.
|
2014-04-14 11:30:59 +03:00
|
|
|
primitive_type_table: PrimitiveTypeTable,
|
2012-05-22 10:54:12 -07: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-03 23:12:37 -06: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 01:15:17 -04:00
|
|
|
|
2016-04-17 20:41:57 +00:00
|
|
|
// A map from nodes to modules, both normal (`mod`) modules and 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-07-27 14:43:06 -04:00
|
|
|
module_map: NodeMap<Module<'a>>,
|
2016-10-28 05:56:06 +00:00
|
|
|
extern_crate_roots: FxHashMap<(CrateNum, 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,
|
2014-11-23 22:29:41 +13: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 22:29:41 +13:00
|
|
|
|
2016-11-08 14:02:55 +11:00
|
|
|
used_imports: FxHashSet<(NodeId, Namespace)>,
|
|
|
|
used_crates: FxHashSet<CrateNum>,
|
2016-05-04 06:00:27 +00:00
|
|
|
pub maybe_unused_trait_imports: NodeSet,
|
2015-05-14 23:40:16 +12:00
|
|
|
|
2016-02-25 04:40:46 +00:00
|
|
|
privacy_errors: Vec<PrivacyError<'a>>,
|
2016-09-06 03:47:11 +00:00
|
|
|
ambiguity_errors: Vec<AmbiguityError<'a>>,
|
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>,
|
2016-11-10 10:29:36 +00:00
|
|
|
use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
|
2016-09-05 03:46:05 +00:00
|
|
|
|
2016-09-21 06:25:09 +00:00
|
|
|
pub exported_macros: Vec<ast::MacroDef>,
|
2016-09-16 02:52:09 +00:00
|
|
|
crate_loader: &'a mut CrateLoader,
|
2016-11-08 14:02:55 +11:00
|
|
|
macro_names: FxHashSet<Name>,
|
2016-11-07 22:08:26 +00:00
|
|
|
builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
|
2016-11-23 01:51:37 +00:00
|
|
|
lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
|
2016-10-28 06:52:45 +00:00
|
|
|
macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
|
|
|
|
macro_exports: Vec<Export>,
|
2016-09-07 23:21:59 +00:00
|
|
|
|
|
|
|
// Maps the `Mark` of an expansion to its containing module or block.
|
2016-11-08 14:02:55 +11:00
|
|
|
invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
|
2016-10-28 00:30:23 -07:00
|
|
|
|
|
|
|
// Avoid duplicated errors for "name already defined".
|
|
|
|
name_already_seen: FxHashMap<Name, Span>,
|
2016-01-11 21:19:29 +00:00
|
|
|
}
|
|
|
|
|
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-07 19:04:40 -07:00
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
impl<'a> ty::NodeIdTree for Resolver<'a> {
|
2016-08-22 00:24:11 +00:00
|
|
|
fn is_descendant_of(&self, mut node: NodeId, ancestor: NodeId) -> bool {
|
|
|
|
while node != ancestor {
|
2016-09-18 09:45:06 +00:00
|
|
|
node = match self.module_map[&node].parent {
|
2016-08-29 05:29:01 +00:00
|
|
|
Some(parent) => parent.normal_ancestor_id.unwrap(),
|
2016-04-27 02:29:59 +00:00
|
|
|
None => return false,
|
2016-08-22 00:24:11 +00:00
|
|
|
}
|
2016-04-27 02:29:59 +00:00
|
|
|
}
|
2016-04-27 19:30:16 +00:00
|
|
|
true
|
2016-04-27 02:29:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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) {
|
2016-05-02 23:26:18 +00:00
|
|
|
let namespace = if is_value { ValueNS } else { TypeNS };
|
2016-11-25 06:07:21 +00:00
|
|
|
let hir::Path { ref segments, span, global, ref mut def } = *path;
|
|
|
|
let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
|
|
|
|
let scope = if global { PathScope::Global } else { PathScope::Lexical };
|
|
|
|
match self.resolve_path(&path, scope, Some(namespace), Some(span)) {
|
|
|
|
PathResult::Module(module) => *def = module.def().unwrap(),
|
|
|
|
PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def,
|
|
|
|
PathResult::NonModule(..) => match self.resolve_path(&path, scope, None, Some(span)) {
|
|
|
|
PathResult::Failed(msg, _) => {
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
},
|
|
|
|
PathResult::Indeterminate => unreachable!(),
|
|
|
|
PathResult::Failed(msg, _) => {
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
2016-05-02 23:26:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-06 15:54:44 +03:00
|
|
|
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
|
|
|
|
self.def_map.get(&id).cloned()
|
|
|
|
}
|
|
|
|
|
2016-08-29 05:12:03 +03:00
|
|
|
fn definitions(&mut self) -> &mut Definitions {
|
|
|
|
&mut self.definitions
|
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,
|
2016-09-19 05:25:17 +00:00
|
|
|
krate: &Crate,
|
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-09-19 05:25:17 +00:00
|
|
|
let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX));
|
2016-11-26 12:47:52 +00:00
|
|
|
let graph_root = arenas.alloc_module(ModuleData {
|
2016-09-19 05:25:17 +00:00
|
|
|
normal_ancestor_id: Some(CRATE_NODE_ID),
|
|
|
|
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
|
2016-11-26 12:47:52 +00:00
|
|
|
..ModuleData::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
|
2016-09-19 05:25:17 +00:00
|
|
|
});
|
2016-04-27 02:29:59 +00:00
|
|
|
let mut module_map = NodeMap();
|
|
|
|
module_map.insert(CRATE_NODE_ID, graph_root);
|
2014-05-28 20:36:05 +01:00
|
|
|
|
2016-09-14 09:55:20 +00:00
|
|
|
let mut definitions = Definitions::new();
|
|
|
|
DefCollector::new(&mut definitions).collect_root();
|
|
|
|
|
2016-11-08 14:02:55 +11: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
|
|
|
|
2014-05-28 20:36:05 +01:00
|
|
|
Resolver {
|
|
|
|
session: session,
|
|
|
|
|
2016-09-14 09:55:20 +00:00
|
|
|
definitions: definitions,
|
2016-11-08 14:02:55 +11:00
|
|
|
macros_at_scope: FxHashMap(),
|
2014-11-23 22:29:41 +13:00
|
|
|
|
2014-05-28 20:36:05 +01:00
|
|
|
// The outermost module has def ID 0; this is not reflected in the
|
|
|
|
// AST.
|
2016-01-11 21:19:29 +00:00
|
|
|
graph_root: graph_root,
|
2016-06-05 09:56:05 +00:00
|
|
|
prelude: None,
|
2014-05-28 20:36:05 +01:00
|
|
|
|
2016-11-08 14:02:55 +11:00
|
|
|
trait_item_map: FxHashMap(),
|
|
|
|
field_names: FxHashMap(),
|
2014-05-28 20:36:05 +01: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 20:36:05 +01: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))],
|
2016-11-10 10:29:36 +00:00
|
|
|
macro_ns: None,
|
2016-11-10 06:19:54 +00:00
|
|
|
},
|
2014-09-29 18:06:13 -05:00
|
|
|
label_ribs: Vec::new(),
|
2014-05-28 20:36:05 +01: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-03 23:12:37 -06:00
|
|
|
freevars: NodeMap(),
|
|
|
|
freevars_seen: NodeMap(),
|
2015-01-16 14:27:43 -08:00
|
|
|
export_map: NodeMap(),
|
|
|
|
trait_map: NodeMap(),
|
2016-04-27 02:29:59 +00:00
|
|
|
module_map: module_map,
|
2016-10-28 05:17:06 +00:00
|
|
|
extern_crate_roots: FxHashMap(),
|
2014-05-28 20:36:05 +01:00
|
|
|
|
2014-11-23 22:29:41 +13:00
|
|
|
make_glob_map: make_glob_map == MakeGlobMap::Yes,
|
2016-03-29 13:14:01 +03:00
|
|
|
glob_map: NodeMap(),
|
2015-05-14 23:40:16 +12:00
|
|
|
|
2016-11-08 14:02:55 +11:00
|
|
|
used_imports: FxHashSet(),
|
|
|
|
used_crates: FxHashSet(),
|
2016-04-19 22:43:10 +09:00
|
|
|
maybe_unused_trait_imports: NodeSet(),
|
|
|
|
|
2016-02-25 04:40:46 +00:00
|
|
|
privacy_errors: Vec::new(),
|
2016-08-22 08:30:07 +00:00
|
|
|
ambiguity_errors: Vec::new(),
|
2016-10-11 03:21:40 +00:00
|
|
|
disallowed_shadowing: Vec::new(),
|
2016-01-11 21:19:29 +00:00
|
|
|
|
|
|
|
arenas: 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,
|
|
|
|
}),
|
2016-11-10 10:29:36 +00:00
|
|
|
use_extern_macros: session.features.borrow().use_extern_macros,
|
2016-09-05 03:46:05 +00:00
|
|
|
|
2016-09-21 06:25:09 +00:00
|
|
|
exported_macros: Vec::new(),
|
2016-09-16 02:52:09 +00:00
|
|
|
crate_loader: crate_loader,
|
2016-11-08 14:02:55 +11:00
|
|
|
macro_names: FxHashSet(),
|
|
|
|
builtin_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(),
|
2016-10-03 23:48:19 +00:00
|
|
|
invocations: invocations,
|
2016-10-28 00:30:23 -07:00
|
|
|
name_already_seen: FxHashMap(),
|
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 20:36:05 +01:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
fn per_ns<T, F: FnMut(&mut Self, Namespace) -> T>(&mut self, mut f: F) -> PerNS<T> {
|
|
|
|
PerNS {
|
|
|
|
type_ns: f(self, TypeNS),
|
|
|
|
value_ns: f(self, ValueNS),
|
2016-11-10 10:29:36 +00:00
|
|
|
macro_ns: match self.use_extern_macros {
|
|
|
|
true => Some(f(self, MacroNS)),
|
|
|
|
false => None,
|
|
|
|
},
|
2016-11-10 06:19:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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();
|
2016-06-22 01:54:34 +00:00
|
|
|
visit::walk_crate(self, krate);
|
|
|
|
|
|
|
|
check_unused::check_crate(self, krate);
|
2016-08-22 08:30:07 +00:00
|
|
|
self.report_errors();
|
2016-09-16 02:52:09 +00:00
|
|
|
self.crate_loader.postprocess(krate);
|
2016-06-22 01:54:34 +00:00
|
|
|
}
|
|
|
|
|
2016-09-19 05:25:17 +00:00
|
|
|
fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> {
|
2016-11-26 12:47:52 +00:00
|
|
|
self.arenas.alloc_module(ModuleData {
|
2016-09-19 05:25:17 +00:00
|
|
|
normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None },
|
|
|
|
populated: Cell::new(local),
|
2016-11-26 12:47:52 +00:00
|
|
|
..ModuleData::new(Some(parent), kind)
|
2016-09-19 05:25:17 +00:00
|
|
|
})
|
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-02-07 23:58:14 +00:00
|
|
|
// track extern crates for unused_extern_crate lint
|
2016-11-26 12:47:52 +00:00
|
|
|
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleData::def_id) {
|
2016-02-07 23:58:14 +00:00
|
|
|
self.used_crates.insert(krate);
|
|
|
|
}
|
|
|
|
|
2016-09-05 05:27:58 +00:00
|
|
|
match binding.kind {
|
|
|
|
NameBindingKind::Import { directive, binding, ref used } if !used.get() => {
|
|
|
|
used.set(true);
|
|
|
|
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,
|
2016-12-09 11:08:39 +00:00
|
|
|
NameBindingKind::Ambiguity { b1, b2, legacy } => {
|
2016-11-10 10:29:36 +00:00
|
|
|
self.ambiguity_errors.push(AmbiguityError {
|
2016-12-20 11:50:30 -08:00
|
|
|
span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy: legacy,
|
2016-11-10 10:29:36 +00:00
|
|
|
});
|
2016-12-09 11:08:39 +00:00
|
|
|
if legacy {
|
2016-12-20 12:18:55 -08:00
|
|
|
self.record_use(ident, ns, b1, span);
|
2016-12-09 11:08:39 +00:00
|
|
|
}
|
|
|
|
!legacy
|
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 22:29:41 +13: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 22:29:41 +13: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 10:44:43 -08: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,
|
2016-08-05 01:58:59 +00:00
|
|
|
record_used: Option<Span>)
|
2016-03-12 08:03:13 +00:00
|
|
|
-> Option<LexicalScopeBinding<'a>> {
|
2016-06-22 02:50:05 +00:00
|
|
|
if ns == TypeNS {
|
2016-11-29 02:07:12 +00:00
|
|
|
ident = ident.unhygienize();
|
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.
|
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-25 06:07:21 +00:00
|
|
|
return Some(LexicalScopeBinding::Def(if let Some(span) = record_used {
|
|
|
|
self.adjust_local_def(LocalDef { ribs: Some((ns, i)), def: def }, span)
|
|
|
|
} else {
|
|
|
|
def
|
2016-03-12 08:03:13 +00:00
|
|
|
}));
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
if let ModuleRibKind(module) = self.ribs[ns][i].kind {
|
2016-11-29 02:07:12 +00:00
|
|
|
let item = self.resolve_ident_in_module(module, ident, ns, false, record_used);
|
2016-11-26 12:21:47 +00:00
|
|
|
if let Ok(binding) = item {
|
2016-03-12 08:03:13 +00:00
|
|
|
// The ident resolves to an item.
|
|
|
|
return Some(LexicalScopeBinding::Item(binding));
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2016-03-12 08:03:13 +00:00
|
|
|
|
2016-09-18 09:45:06 +00:00
|
|
|
if let ModuleKind::Block(..) = module.kind { // We can see through blocks
|
2016-09-19 05:25:17 +00:00
|
|
|
} else if !module.no_implicit_prelude {
|
2016-09-18 09:45:06 +00:00
|
|
|
return self.prelude.and_then(|prelude| {
|
2016-11-29 02:07:12 +00:00
|
|
|
self.resolve_ident_in_module(prelude, ident, ns, false, None).ok()
|
2016-09-18 09:45:06 +00:00
|
|
|
}).map(LexicalScopeBinding::Item)
|
|
|
|
} else {
|
|
|
|
return None;
|
2016-06-05 08:02:04 +00:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2016-06-26 03:32:45 +00:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
if let MacroDefinition(mac) = self.ribs[ns][i].kind {
|
2016-06-26 03:32:45 +00:00
|
|
|
// If an invocation of this macro created `ident`, give up on `ident`
|
|
|
|
// and switch to `ident`'s source from the macro definition.
|
2016-06-22 08:03:42 +00:00
|
|
|
let (source_ctxt, source_macro) = ident.ctxt.source();
|
|
|
|
if source_macro == mac {
|
|
|
|
ident.ctxt = source_ctxt;
|
2016-06-26 03:32:45 +00:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2016-03-08 21:44:19 +00:00
|
|
|
|
2016-03-12 08:03:13 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2016-10-23 02:44:36 +00:00
|
|
|
fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a> {
|
|
|
|
while crate_var_ctxt.source().0 != SyntaxContext::empty() {
|
|
|
|
crate_var_ctxt = crate_var_ctxt.source().0;
|
|
|
|
}
|
|
|
|
let module = self.invocations[&crate_var_ctxt.source().1].module.get();
|
|
|
|
if module.is_local() { self.graph_root } else { module }
|
|
|
|
}
|
|
|
|
|
2012-05-22 10:54:12 -07:00
|
|
|
// AST resolution
|
|
|
|
//
|
2012-07-06 19:06:58 -07:00
|
|
|
// We maintain a list of value ribs and type ribs.
|
2012-05-22 10:54:12 -07: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.
|
|
|
|
|
2016-02-13 23:39:51 +00:00
|
|
|
fn with_scope<F>(&mut self, id: NodeId, f: F)
|
2015-10-26 20:31:11 +01:00
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
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 10:54:12 -07:00
|
|
|
|
2016-11-10 10:29:36 +00:00
|
|
|
self.finalize_current_module_macro_resolutions();
|
2016-02-24 04:48:31 +00:00
|
|
|
f(self);
|
2012-05-22 10:54:12 -07: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();
|
2016-02-24 04:48:31 +00:00
|
|
|
} else {
|
|
|
|
f(self);
|
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2014-12-27 21:47:42 +09:00
|
|
|
/// Searches the current set of local scopes for labels.
|
|
|
|
/// Stops after meeting a closure.
|
2016-10-16 02:38:08 +00:00
|
|
|
fn search_label(&self, mut ident: Ident) -> Option<Def> {
|
2014-12-26 20:08:00 +09:00
|
|
|
for rib in self.label_ribs.iter().rev() {
|
|
|
|
match rib.kind {
|
|
|
|
NormalRibKind => {
|
|
|
|
// Continue
|
|
|
|
}
|
2016-07-15 05:14:48 +00:00
|
|
|
MacroDefinition(mac) => {
|
|
|
|
// If an invocation of this macro created `ident`, give up on `ident`
|
|
|
|
// and switch to `ident`'s source from the macro definition.
|
2016-06-22 08:03:42 +00:00
|
|
|
let (source_ctxt, source_macro) = ident.ctxt.source();
|
|
|
|
if source_macro == mac {
|
|
|
|
ident.ctxt = source_ctxt;
|
2016-07-15 05:14:48 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-26 20:08:00 +09:00
|
|
|
_ => {
|
|
|
|
// Do not resolve labels across function boundary
|
2015-10-26 20:31:11 +01:00
|
|
|
return None;
|
2014-12-26 20:08:00 +09:00
|
|
|
}
|
|
|
|
}
|
2016-06-22 02:50:05 +00:00
|
|
|
let result = rib.bindings.get(&ident).cloned();
|
2014-12-27 21:47:42 +09:00
|
|
|
if result.is_some() {
|
2015-10-26 20:31:11 +01:00
|
|
|
return result;
|
2014-12-26 20:08:00 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2014-01-09 15:05:33 +02:00
|
|
|
fn resolve_item(&mut self, item: &Item) {
|
2016-04-24 03:26:10 +00:00
|
|
|
let name = item.ident.name;
|
2014-09-30 19:11:34 -05:00
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
debug!("(resolving item) resolving {}", name);
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2013-03-20 01:17:42 -04:00
|
|
|
match item.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
ItemKind::Enum(_, ref generics) |
|
|
|
|
ItemKind::Ty(_, ref generics) |
|
2016-08-15 01:07:09 +03:00
|
|
|
ItemKind::Struct(_, ref generics) |
|
2016-08-29 05:04:31 +00:00
|
|
|
ItemKind::Union(_, ref generics) |
|
2016-08-26 19:23:42 +03:00
|
|
|
ItemKind::Fn(.., ref generics, _) => {
|
2016-08-15 01:07:09 +03: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 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
ItemKind::DefaultImpl(_, ref trait_ref) => {
|
2016-10-26 20:51:49 -07:00
|
|
|
self.with_optional_trait_ref(Some(trait_ref), |_, _| {}, None);
|
2015-01-22 22:15:02 +01:00
|
|
|
}
|
2016-08-26 19:23:42 +03:00
|
|
|
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
|
2015-02-05 09:19:07 +02:00
|
|
|
self.resolve_implementation(generics,
|
2015-04-03 17:13:52 +13:00
|
|
|
opt_trait_ref,
|
2016-02-09 21:27:42 +01:00
|
|
|
&self_type,
|
2015-04-03 17:13:52 +13:00
|
|
|
item.id,
|
2016-04-24 03:26:10 +00:00
|
|
|
impl_items),
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
|
2015-04-07 17:59:10 +12:00
|
|
|
// Create a new rib for the trait-wide type parameters.
|
2016-08-15 01:07:09 +03: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 22:31:10 +03:00
|
|
|
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
|
2015-04-03 17:13:52 +13:00
|
|
|
this.visit_generics(generics);
|
2015-09-29 00:23:54 +03:00
|
|
|
walk_list!(this, visit_ty_param_bound, bounds);
|
2015-04-03 17:13:52 +13:00
|
|
|
|
|
|
|
for trait_item in trait_items {
|
2015-03-15 19:35:25 -06:00
|
|
|
match trait_item.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
TraitItemKind::Const(_, ref default) => {
|
2015-03-15 19:35:25 -06:00
|
|
|
// Only impose the restrictions of
|
|
|
|
// ConstRibKind if there's an actual constant
|
|
|
|
// expression in a provided default.
|
|
|
|
if default.is_some() {
|
|
|
|
this.with_constant_rib(|this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_trait_item(this, trait_item)
|
2015-03-15 19:35:25 -06:00
|
|
|
});
|
|
|
|
} else {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_trait_item(this, trait_item)
|
2015-03-15 19:35:25 -06:00
|
|
|
}
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
TraitItemKind::Method(ref sig, _) => {
|
2015-03-15 19:35:25 -06:00
|
|
|
let type_parameters =
|
|
|
|
HasTypeParameters(&sig.generics,
|
2016-03-06 15:54:44 +03:00
|
|
|
MethodRibKind(!sig.decl.has_self()));
|
2015-03-15 19:35:25 -06:00
|
|
|
this.with_type_parameter_rib(type_parameters, |this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_trait_item(this, trait_item)
|
2015-03-15 19:35:25 -06:00
|
|
|
});
|
2015-04-03 17:13:52 +13:00
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
TraitItemKind::Type(..) => {
|
2015-03-15 19:35:25 -06:00
|
|
|
this.with_type_parameter_rib(NoTypeParameters, |this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_trait_item(this, trait_item)
|
2015-03-15 19:35:25 -06:00
|
|
|
});
|
2015-04-03 17:13:52 +13:00
|
|
|
}
|
2016-06-11 02:00:07 +01:00
|
|
|
TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
|
2015-04-03 17:13:52 +13:00
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
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 15:42:55 -08:00
|
|
|
});
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
ItemKind::Const(..) | ItemKind::Static(..) => {
|
2013-09-26 19:10:16 -07:00
|
|
|
self.with_constant_rib(|this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_item(this, item);
|
2012-10-15 12:27:09 -07:00
|
|
|
});
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2012-07-05 12:10:33 -07:00
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
ItemKind::Use(ref view_path) => {
|
2015-09-15 01:07:17 +03:00
|
|
|
match view_path.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
ast::ViewPathList(ref prefix, ref items) => {
|
2016-11-25 06:07:21 +00:00
|
|
|
let path: Vec<_> =
|
|
|
|
prefix.segments.iter().map(|seg| seg.identifier).collect();
|
2015-09-16 00:50:50 +03:00
|
|
|
// Resolve prefix of an import with empty braces (issue #28388)
|
|
|
|
if items.is_empty() && !prefix.segments.is_empty() {
|
2016-11-25 06:07:21 +00:00
|
|
|
let (scope, span) = (PathScope::Import, prefix.span);
|
|
|
|
// FIXME(#38012) This should be a module path, not anything in TypeNS.
|
|
|
|
let result =
|
|
|
|
self.resolve_path(&path, scope, Some(TypeNS), Some(span));
|
|
|
|
let (def, msg) = match result {
|
|
|
|
PathResult::Module(module) => (module.def().unwrap(), None),
|
|
|
|
PathResult::NonModule(res) if res.depth == 0 =>
|
|
|
|
(res.base_def, None),
|
|
|
|
PathResult::NonModule(_) => {
|
|
|
|
// Resolve a module path for better errors
|
|
|
|
match self.resolve_path(&path, scope, None, Some(span)) {
|
|
|
|
PathResult::Failed(msg, _) => (Def::Err, Some(msg)),
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
2015-09-16 00:50:50 +03:00
|
|
|
}
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResult::Indeterminate => unreachable!(),
|
|
|
|
PathResult::Failed(msg, _) => (Def::Err, Some(msg)),
|
|
|
|
};
|
|
|
|
if let Some(msg) = msg {
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
2015-09-15 01:07:17 +03:00
|
|
|
}
|
2016-11-25 06:07:21 +00:00
|
|
|
self.record_def(item.id, PathResolution::new(def));
|
2015-09-15 01:07:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
2015-02-08 19:29:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
ItemKind::ExternCrate(_) => {
|
2013-12-25 11:10:33 -07:00
|
|
|
// do nothing, these are just around to be encoded
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 20:31:11 +01:00
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2012-08-06 12:34:08 -07:00
|
|
|
match type_parameters {
|
2016-08-15 01:07:09 +03:00
|
|
|
HasTypeParameters(generics, rib_kind) => {
|
2014-09-29 18:06:13 -05:00
|
|
|
let mut function_type_rib = Rib::new(rib_kind);
|
2016-11-08 14:02:55 +11:00
|
|
|
let mut seen_bindings = FxHashMap();
|
2016-08-15 01:07:09 +03:00
|
|
|
for type_parameter in &generics.ty_params {
|
2016-04-24 03:26:10 +00:00
|
|
|
let name = type_parameter.ident.name;
|
2015-02-05 09:19:07 +02:00
|
|
|
debug!("with_type_parameter_rib: {}", type_parameter.id);
|
2014-10-08 21:28:50 -07:00
|
|
|
|
2016-08-16 20:47:45 -05:00
|
|
|
if seen_bindings.contains_key(&name) {
|
|
|
|
let span = seen_bindings.get(&name).unwrap();
|
2015-07-14 16:32:43 +02:00
|
|
|
resolve_error(self,
|
|
|
|
type_parameter.span,
|
2016-08-16 20:47:45 -05:00
|
|
|
ResolutionError::NameAlreadyUsedInTypeParameterList(name,
|
|
|
|
span));
|
2014-10-08 21:28:50 -07:00
|
|
|
}
|
2016-08-16 20:47:45 -05:00
|
|
|
seen_bindings.entry(name).or_insert(type_parameter.span);
|
2014-10-08 21:28:50 -07:00
|
|
|
|
2013-06-26 15:56:13 -07:00
|
|
|
// plain insert (no renaming)
|
2016-04-24 03:26:10 +00:00
|
|
|
let def_id = self.definitions.local_def_id(type_parameter.id);
|
2016-08-15 01:07:09 +03:00
|
|
|
let def = Def::TyParam(def_id);
|
2016-10-16 02:38:08 +00:00
|
|
|
function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def);
|
2016-07-07 18:20:26 +03:00
|
|
|
self.record_def(type_parameter.id, PathResolution::new(def));
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[TypeNS].push(function_type_rib);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2012-08-03 19:59:04 -07:00
|
|
|
NoTypeParameters => {
|
2012-05-22 10:54:12 -07:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-26 19:10:16 -07:00
|
|
|
f(self);
|
2012-05-22 10:54:12 -07: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 10:54:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
fn with_label_rib<F>(&mut self, f: F)
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2014-09-29 18:06:13 -05:00
|
|
|
self.label_ribs.push(Rib::new(NormalRibKind));
|
2013-09-26 19:10:16 -07:00
|
|
|
f(self);
|
2016-04-23 21:20:17 +00:00
|
|
|
self.label_ribs.pop();
|
2012-08-14 19:20:56 -07:00
|
|
|
}
|
2013-02-21 11:08:50 -08:00
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
fn with_constant_rib<F>(&mut self, f: F)
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
|
|
|
|
self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind));
|
2013-09-26 19:10:16 -07:00
|
|
|
f(self);
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[TypeNS].pop();
|
|
|
|
self.ribs[ValueNS].pop();
|
2012-10-15 12:27:09 -07:00
|
|
|
}
|
|
|
|
|
2013-10-02 14:33:01 +02:00
|
|
|
fn resolve_trait_reference(&mut self,
|
2016-11-25 06:07:21 +00:00
|
|
|
path: &[Ident],
|
|
|
|
global: bool,
|
|
|
|
generics: Option<&Generics>,
|
|
|
|
span: Span)
|
2016-11-22 11:32:52 +00:00
|
|
|
-> PathResolution {
|
2016-11-25 06:07:21 +00:00
|
|
|
let scope = if global { PathScope::Global } else { PathScope::Lexical };
|
|
|
|
let def = match self.resolve_path(path, scope, None, Some(span)) {
|
|
|
|
PathResult::Module(module) => Some(module.def().unwrap()),
|
|
|
|
PathResult::NonModule(..) => return err_path_resolution(),
|
|
|
|
PathResult::Failed(msg, false) => {
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
|
|
|
return err_path_resolution();
|
|
|
|
}
|
|
|
|
_ => match self.resolve_path(path, scope, Some(TypeNS), None) {
|
|
|
|
PathResult::NonModule(path_resolution) => Some(path_resolution.base_def),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(def) = def {
|
|
|
|
if let Def::Trait(_) = def {
|
|
|
|
return PathResolution::new(def);
|
2016-07-31 20:40:03 +00:00
|
|
|
}
|
2016-04-27 01:18:04 +00:00
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
let mut err = resolve_struct_error(self, span, {
|
|
|
|
ResolutionError::IsNotATrait(&names_to_string(path), def.kind_name())
|
2016-07-31 20:40:03 +00:00
|
|
|
});
|
2016-10-26 20:51:49 -07:00
|
|
|
if let Some(generics) = generics {
|
2016-11-25 06:07:21 +00:00
|
|
|
if let Some(span) = generics.span_for_name(&names_to_string(path)) {
|
2016-10-26 20:51:49 -07:00
|
|
|
err.span_label(span, &"type parameter defined here");
|
|
|
|
}
|
|
|
|
}
|
2016-07-31 20:40:03 +00:00
|
|
|
|
|
|
|
// If it's a typedef, give a note
|
2016-11-25 06:07:21 +00:00
|
|
|
if let Def::TyAlias(..) = def {
|
2016-07-31 21:29:01 +00:00
|
|
|
err.note(&format!("type aliases cannot be used for traits"));
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
2016-07-31 20:40:03 +00:00
|
|
|
err.emit();
|
2016-11-22 11:32:52 +00:00
|
|
|
} else {
|
2016-02-14 02:47:27 +01:00
|
|
|
// find possible candidates
|
2016-11-25 06:07:21 +00:00
|
|
|
let is_trait = |def| match def { Def::Trait(_) => true, _ => false };
|
|
|
|
let candidates = self.lookup_candidates(path.last().unwrap().name, TypeNS, is_trait);
|
2016-02-14 02:47:27 +01:00
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
let path = names_to_string(path);
|
|
|
|
resolve_error(self, span, ResolutionError::UndeclaredTraitName(&path, candidates));
|
2016-11-22 11:32:52 +00:00
|
|
|
}
|
|
|
|
err_path_resolution()
|
2013-03-27 06:16:28 -04:00
|
|
|
}
|
|
|
|
|
2015-04-03 17:13:52 +13:00
|
|
|
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
|
|
|
|
where F: FnOnce(&mut Resolver) -> T
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2014-05-08 22:35:09 +01: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
|
|
|
|
}
|
|
|
|
|
2016-10-26 20:51:49 -07:00
|
|
|
fn with_optional_trait_ref<T, F>(&mut self,
|
|
|
|
opt_trait_ref: Option<&TraitRef>,
|
|
|
|
f: F,
|
|
|
|
generics: Option<&Generics>)
|
|
|
|
-> T
|
2015-04-03 17:13:52 +13:00
|
|
|
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
2014-12-08 20:26:43 -05:00
|
|
|
{
|
2015-02-05 09:19:07 +02:00
|
|
|
let mut new_val = None;
|
2015-04-03 17:13:52 +13:00
|
|
|
let mut new_id = None;
|
2015-02-24 08:28:11 +02:00
|
|
|
if let Some(trait_ref) = opt_trait_ref {
|
2016-11-25 06:07:21 +00:00
|
|
|
let ast::Path { ref segments, span, global } = trait_ref.path;
|
|
|
|
let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
|
|
|
|
let path_res = self.resolve_trait_reference(&path, global, generics, span);
|
2016-11-22 11:32:52 +00:00
|
|
|
assert!(path_res.depth == 0);
|
|
|
|
self.record_def(trait_ref.ref_id, path_res);
|
|
|
|
if path_res.base_def != Def::Err {
|
2015-04-03 17:13:52 +13:00
|
|
|
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
|
|
|
new_id = Some(path_res.base_def.def_id());
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_trait_ref(self, trait_ref);
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
2014-05-08 22:35:09 +01:00
|
|
|
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
|
2015-04-03 17:13:52 +13:00
|
|
|
let result = f(self, new_id);
|
2014-05-08 22:35:09 +01:00
|
|
|
self.current_trait_ref = original_trait_ref;
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2015-04-03 17:13:52 +13: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 17:13:52 +13:00
|
|
|
f(self);
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[TypeNS].pop();
|
2015-04-03 17:13:52 +13:00
|
|
|
}
|
|
|
|
|
2013-10-02 14:33:01 +02:00
|
|
|
fn resolve_implementation(&mut self,
|
2014-05-31 18:53:13 -04:00
|
|
|
generics: &Generics,
|
|
|
|
opt_trait_reference: &Option<TraitRef>,
|
|
|
|
self_type: &Ty,
|
2015-04-03 17:13:52 +13:00
|
|
|
item_id: NodeId,
|
2015-12-07 17:17:41 +03:00
|
|
|
impl_items: &[ImplItem]) {
|
2012-05-22 10:54:12 -07:00
|
|
|
// If applicable, create a rib for the type parameters.
|
2016-08-15 01:07:09 +03:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
|
2012-05-22 10:54:12 -07:00
|
|
|
// Resolve the type parameters.
|
2015-02-05 09:19:07 +02:00
|
|
|
this.visit_generics(generics);
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2012-07-31 10:27:51 -07:00
|
|
|
// Resolve the trait reference, if necessary.
|
2015-04-03 17:13:52 +13:00
|
|
|
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
2014-05-08 22:35:09 +01:00
|
|
|
// Resolve the self type.
|
2015-02-05 09:19:07 +02:00
|
|
|
this.visit_ty(self_type);
|
2014-05-08 22:35:09 +01:00
|
|
|
|
2016-08-31 14:08:22 +03:00
|
|
|
let item_def_id = this.definitions.local_def_id(item_id);
|
|
|
|
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
|
2015-04-03 17:13:52 +13:00
|
|
|
this.with_current_self_type(self_type, |this| {
|
|
|
|
for impl_item in impl_items {
|
2016-04-09 23:19:53 +00:00
|
|
|
this.resolve_visibility(&impl_item.vis);
|
2015-04-03 17:13:52 +13:00
|
|
|
match impl_item.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
ImplItemKind::Const(..) => {
|
2015-07-18 19:56:15 -04:00
|
|
|
// If this is a trait impl, ensure the const
|
2015-03-15 19:35:25 -06:00
|
|
|
// exists in trait
|
2016-04-24 03:26:10 +00:00
|
|
|
this.check_trait_item(impl_item.ident.name,
|
2015-07-18 19:56:15 -04:00
|
|
|
impl_item.span,
|
|
|
|
|n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
|
2016-05-11 22:45:49 +03:00
|
|
|
visit::walk_impl_item(this, impl_item);
|
2015-03-15 19:35:25 -06:00
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
ImplItemKind::Method(ref sig, _) => {
|
2015-04-03 17:13:52 +13:00
|
|
|
// If this is a trait impl, ensure the method
|
|
|
|
// exists in trait
|
2016-04-24 03:26:10 +00:00
|
|
|
this.check_trait_item(impl_item.ident.name,
|
2015-07-18 19:56:15 -04:00
|
|
|
impl_item.span,
|
|
|
|
|n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
|
2015-04-03 17:13:52 +13:00
|
|
|
|
|
|
|
// We also need a new scope for the method-
|
|
|
|
// specific type parameters.
|
|
|
|
let type_parameters =
|
|
|
|
HasTypeParameters(&sig.generics,
|
2016-03-06 15:54:44 +03:00
|
|
|
MethodRibKind(!sig.decl.has_self()));
|
2015-04-03 17:13:52 +13:00
|
|
|
this.with_type_parameter_rib(type_parameters, |this| {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_impl_item(this, impl_item);
|
2015-04-03 17:13:52 +13:00
|
|
|
});
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
ImplItemKind::Type(ref ty) => {
|
2015-07-18 19:56:15 -04:00
|
|
|
// If this is a trait impl, ensure the type
|
2015-04-03 17:13:52 +13:00
|
|
|
// exists in trait
|
2016-04-24 03:26:10 +00:00
|
|
|
this.check_trait_item(impl_item.ident.name,
|
2015-07-18 19:56:15 -04:00
|
|
|
impl_item.span,
|
|
|
|
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
|
2014-08-05 19:44:21 -07:00
|
|
|
|
2015-04-03 17:13:52 +13:00
|
|
|
this.visit_ty(ty);
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
|
2014-08-05 19:44:21 -07:00
|
|
|
}
|
2014-08-04 13:56:56 -07:00
|
|
|
}
|
2015-04-03 17:13:52 +13:00
|
|
|
});
|
2014-05-08 22:35:09 +01:00
|
|
|
});
|
2016-10-26 20:51:49 -07:00
|
|
|
}, Some(&generics));
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2015-07-18 19:56:15 -04:00
|
|
|
fn check_trait_item<F>(&self, name: Name, span: Span, err: F)
|
2015-10-26 20:31:11 +01: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.
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some((did, ref trait_ref)) = self.current_trait_ref {
|
2015-02-11 09:32:25 +02:00
|
|
|
if !self.trait_item_map.contains_key(&(name, did)) {
|
2015-03-16 10:44:19 +13:00
|
|
|
let path_str = path_names_to_string(&trait_ref.path, 0);
|
2016-02-09 21:27:42 +01:00
|
|
|
resolve_error(self, span, err(name, &path_str));
|
2014-06-18 14:16:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 14:00:46 +02:00
|
|
|
fn resolve_local(&mut self, local: &Local) {
|
2012-05-22 10:54:12 -07:00
|
|
|
// Resolve the type.
|
2015-09-29 00:23:54 +03:00
|
|
|
walk_list!(self, visit_ty, &local.ty);
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2015-02-05 09:19:07 +02:00
|
|
|
// Resolve the initializer.
|
2015-09-29 00:23:54 +03:00
|
|
|
walk_list!(self, visit_expr, &local.init);
|
2012-05-22 10:54:12 -07:00
|
|
|
|
|
|
|
// Resolve the pattern.
|
2016-11-08 14:02:55 +11:00
|
|
|
self.resolve_pattern(&local.pat, PatternSource::Let, &mut FxHashMap());
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2013-09-05 14:15:00 -07: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 11:30:59 +03:00
|
|
|
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
|
2016-11-08 14:02:55 +11: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 {
|
|
|
|
if sub_pat.is_some() || match self.def_map.get(&pat.id) {
|
|
|
|
Some(&PathResolution { base_def: Def::Local(..), .. }) => true,
|
|
|
|
_ => false,
|
|
|
|
} {
|
|
|
|
let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
|
2016-06-22 02:50:05 +00:00
|
|
|
binding_map.insert(ident.node, binding_info);
|
2016-04-24 03:26:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
binding_map
|
2012-07-10 18:24:41 -07:00
|
|
|
}
|
|
|
|
|
2013-09-05 14:15:00 -07: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.
|
2013-10-02 14:33:01 +02:00
|
|
|
fn check_consistent_bindings(&mut self, arm: &Arm) {
|
2015-03-24 16:53:34 -07:00
|
|
|
if arm.pats.is_empty() {
|
2015-10-26 20:31:11 +01:00
|
|
|
return;
|
2014-02-28 15:25:15 -08:00
|
|
|
}
|
2016-02-09 21:27:42 +01:00
|
|
|
let map_0 = self.binding_mode_map(&arm.pats[0]);
|
2013-08-03 12:45:23 -04:00
|
|
|
for (i, p) in arm.pats.iter().enumerate() {
|
2016-02-09 21:27:42 +01:00
|
|
|
let map_i = self.binding_mode_map(&p);
|
2012-08-06 07:20:23 -07:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for (&key, &binding_0) in &map_0 {
|
2014-11-06 12:25:16 -05:00
|
|
|
match map_i.get(&key) {
|
2015-10-26 20:31:11 +01:00
|
|
|
None => {
|
2016-06-22 02:50:05 +00:00
|
|
|
let error = ResolutionError::VariableNotBoundInPattern(key.name, 1, i + 1);
|
|
|
|
resolve_error(self, p.span, error);
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
|
|
|
Some(binding_i) => {
|
|
|
|
if binding_0.binding_mode != binding_i.binding_mode {
|
|
|
|
resolve_error(self,
|
|
|
|
binding_i.span,
|
2016-08-16 22:13:09 +03:00
|
|
|
ResolutionError::VariableBoundWithDifferentMode(
|
|
|
|
key.name,
|
|
|
|
i + 1,
|
|
|
|
binding_0.span));
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2014-05-28 09:24:28 -07:00
|
|
|
}
|
2012-08-06 07:20:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for (&key, &binding) in &map_i {
|
2013-02-08 17:08:02 -05:00
|
|
|
if !map_0.contains_key(&key) {
|
2015-07-14 16:32:43 +02:00
|
|
|
resolve_error(self,
|
|
|
|
binding.span,
|
2016-06-22 02:50:05 +00:00
|
|
|
ResolutionError::VariableNotBoundInPattern(key.name, i + 1, 1));
|
2012-08-06 07:20:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-10 18:24:41 -07:00
|
|
|
}
|
|
|
|
|
2013-10-02 14:33:01 +02: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 10:54:12 -07:00
|
|
|
|
2016-11-08 14:02:55 +11:00
|
|
|
let mut bindings_list = FxHashMap();
|
2015-01-31 12:20:46 -05:00
|
|
|
for pattern in &arm.pats {
|
2016-06-03 23:15:00 +03:00
|
|
|
self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-10 18:24:41 -07:00
|
|
|
// This has to happen *after* we determine which
|
|
|
|
// pat_idents are variants
|
|
|
|
self.check_consistent_bindings(arm);
|
|
|
|
|
2015-09-29 00:23:54 +03:00
|
|
|
walk_list!(self, visit_expr, &arm.guard);
|
2016-02-09 21:27:42 +01:00
|
|
|
self.visit_expr(&arm.body);
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[ValueNS].pop();
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2014-01-06 14:00:46 +02:00
|
|
|
fn resolve_block(&mut self, block: &Block) {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("(resolving block) entering block");
|
2012-05-22 10:54:12 -07: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-04-17 20:41:57 +00:00
|
|
|
let anonymous_module = self.module_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 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Descend into the block.
|
2016-06-26 03:32:45 +00:00
|
|
|
for stmt in &block.stmts {
|
|
|
|
if let Some(marks) = self.macros_at_scope.remove(&stmt.id) {
|
2016-07-15 05:14:48 +00:00
|
|
|
num_macro_definition_ribs += marks.len() as u32;
|
2016-06-26 03:32:45 +00:00
|
|
|
for mark in marks {
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark)));
|
2016-07-15 05:14:48 +00:00
|
|
|
self.label_ribs.push(Rib::new(MacroDefinition(mark)));
|
2016-06-26 03:32:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.visit_stmt(stmt);
|
|
|
|
}
|
2012-05-22 10:54:12 -07: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 23:40:16 +12:00
|
|
|
}
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("(resolving block) leaving block");
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2013-10-02 14:33:01 +02:00
|
|
|
fn resolve_type(&mut self, ty: &Ty) {
|
2016-11-26 12:29:21 +00:00
|
|
|
if let TyKind::Path(ref maybe_qself, ref path) = ty.node {
|
|
|
|
// This is a path in the type namespace. Walk through scopes looking for it.
|
|
|
|
if let Some(def) =
|
|
|
|
self.resolve_possibly_assoc_item(ty.id, maybe_qself.as_ref(), path, TypeNS) {
|
|
|
|
match def.base_def {
|
|
|
|
Def::Mod(..) if def.depth == 0 => {
|
|
|
|
self.session.span_err(path.span, "expected type, found module");
|
|
|
|
self.record_def(ty.id, err_path_resolution());
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2016-11-26 12:29:21 +00:00
|
|
|
_ => {
|
|
|
|
// Write the result into the def map.
|
|
|
|
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
|
|
|
path_names_to_string(path, 0), ty.id, def);
|
|
|
|
self.record_def(ty.id, def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.record_def(ty.id, err_path_resolution());
|
|
|
|
// Keep reporting some errors even if they're ignored above.
|
|
|
|
let kind = if maybe_qself.is_some() { "associated type" } else { "type name" };
|
|
|
|
let is_invalid_self_type_name = {
|
|
|
|
path.segments.len() > 0 &&
|
|
|
|
maybe_qself.is_none() &&
|
|
|
|
path.segments[0].identifier.name == keywords::SelfType.name()
|
|
|
|
};
|
|
|
|
|
|
|
|
if is_invalid_self_type_name {
|
|
|
|
resolve_error(self, ty.span, ResolutionError::SelfUsedOutsideImplOrTrait);
|
2016-04-07 00:42:29 +00:00
|
|
|
} else {
|
2016-11-26 12:29:21 +00:00
|
|
|
let type_name = path.segments.last().unwrap().identifier.name;
|
|
|
|
let candidates = self.lookup_candidates(type_name, TypeNS, |def| {
|
|
|
|
match def {
|
|
|
|
Def::Trait(_) |
|
|
|
|
Def::Enum(_) |
|
|
|
|
Def::Struct(_) |
|
|
|
|
Def::Union(_) |
|
|
|
|
Def::TyAlias(_) => true,
|
|
|
|
_ => false,
|
2015-07-13 00:31:09 +02:00
|
|
|
}
|
2016-11-26 12:29:21 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
let name = &path_names_to_string(path, 0);
|
|
|
|
let error = ResolutionError::UseOfUndeclared(kind, name, candidates);
|
|
|
|
resolve_error(self, ty.span, error);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2014-11-20 15:08:48 -05:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2015-02-05 09:19:07 +02:00
|
|
|
// Resolve embedded types.
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_ty(self, ty);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-06-03 23:15:00 +03:00
|
|
|
fn fresh_binding(&mut self,
|
2016-10-22 23:34:18 +00:00
|
|
|
ident: &SpannedIdent,
|
2016-06-03 23:15:00 +03:00
|
|
|
pat_id: NodeId,
|
|
|
|
outer_pat_id: NodeId,
|
|
|
|
pat_src: PatternSource,
|
2016-11-08 14:02:55 +11:00
|
|
|
bindings: &mut FxHashMap<Ident, NodeId>)
|
2016-06-03 23:15:00 +03:00
|
|
|
-> PathResolution {
|
|
|
|
// Add the binding to the local ribs, if it
|
2016-06-03 23:15:00 +03:00
|
|
|
// doesn't already exist in the bindings map. (We
|
|
|
|
// must not add it if it's in the bindings map
|
2016-06-03 23:15:00 +03:00
|
|
|
// because that breaks the assumptions later
|
|
|
|
// passes make about or-patterns.)
|
2016-08-31 14:08:22 +03:00
|
|
|
let mut def = Def::Local(self.definitions.local_def_id(pat_id));
|
2016-06-22 02:50:05 +00:00
|
|
|
match bindings.get(&ident.node).cloned() {
|
2016-06-03 23:15:00 +03:00
|
|
|
Some(id) if id == outer_pat_id => {
|
|
|
|
// `Variant(a, a)`, error
|
|
|
|
resolve_error(
|
|
|
|
self,
|
|
|
|
ident.span,
|
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
|
|
|
|
&ident.node.name.as_str())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Some(..) if pat_src == PatternSource::FnParam => {
|
|
|
|
// `fn f(a: u8, a: u8)`, error
|
|
|
|
resolve_error(
|
|
|
|
self,
|
|
|
|
ident.span,
|
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
|
|
|
|
&ident.node.name.as_str())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Some(..) if pat_src == PatternSource::Match => {
|
2016-06-03 23:15:00 +03:00
|
|
|
// `Variant1(a) | Variant2(a)`, ok
|
|
|
|
// Reuse definition from the first `a`.
|
2016-11-10 06:19:54 +00:00
|
|
|
def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node];
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
|
|
|
Some(..) => {
|
|
|
|
span_bug!(ident.span, "two bindings with the same name from \
|
|
|
|
unexpected pattern source {:?}", pat_src);
|
|
|
|
}
|
|
|
|
None => {
|
2016-06-11 18:47:47 +03:00
|
|
|
// A completely fresh binding, add to the lists if it's valid.
|
2016-06-03 23:15:00 +03:00
|
|
|
if ident.node.name != keywords::Invalid.name() {
|
2016-06-22 02:50:05 +00:00
|
|
|
bindings.insert(ident.node, outer_pat_id);
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def);
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2016-06-11 18:47:47 +03:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-06-03 23:15:00 +03:00
|
|
|
PathResolution::new(def)
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2016-05-05 20:20:23 +00:00
|
|
|
|
2016-06-03 23:15:00 +03:00
|
|
|
fn resolve_pattern_path<ExpectedFn>(&mut self,
|
2016-06-03 23:15:00 +03:00
|
|
|
pat_id: NodeId,
|
|
|
|
qself: Option<&QSelf>,
|
|
|
|
path: &Path,
|
|
|
|
namespace: Namespace,
|
|
|
|
expected_fn: ExpectedFn,
|
|
|
|
expected_what: &str)
|
2016-06-03 23:15:00 +03:00
|
|
|
where ExpectedFn: FnOnce(Def) -> bool
|
|
|
|
{
|
2016-06-03 23:15:00 +03:00
|
|
|
let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
|
|
|
|
qself, path, namespace) {
|
|
|
|
if resolution.depth == 0 {
|
2016-07-17 00:15:15 +03:00
|
|
|
if expected_fn(resolution.base_def) || resolution.base_def == Def::Err {
|
2016-06-03 23:15:00 +03:00
|
|
|
resolution
|
2016-06-03 23:15:00 +03:00
|
|
|
} else {
|
2016-06-03 23:15:00 +03:00
|
|
|
resolve_error(
|
|
|
|
self,
|
|
|
|
path.span,
|
|
|
|
ResolutionError::PatPathUnexpected(expected_what,
|
|
|
|
resolution.kind_name(), path)
|
|
|
|
);
|
2016-06-03 23:15:00 +03:00
|
|
|
err_path_resolution()
|
|
|
|
}
|
2016-06-03 23:15:00 +03:00
|
|
|
} else {
|
|
|
|
// 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.
|
2016-06-03 23:15:00 +03:00
|
|
|
if namespace == ValueNS {
|
|
|
|
let item_name = path.segments.last().unwrap().identifier.name;
|
|
|
|
let traits = self.get_traits_containing_item(item_name);
|
|
|
|
self.trait_map.insert(pat_id, traits);
|
2015-03-25 10:53:28 -06:00
|
|
|
}
|
2016-06-03 23:15:00 +03:00
|
|
|
resolution
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2016-06-03 23:15:00 +03:00
|
|
|
} else {
|
2016-11-25 06:07:21 +00:00
|
|
|
let error = ResolutionError::PatPathUnresolved(expected_what, path);
|
|
|
|
resolve_error(self, path.span, error);
|
2016-06-03 23:15:00 +03:00
|
|
|
err_path_resolution()
|
2016-06-03 23:15:00 +03:00
|
|
|
};
|
2015-03-25 10:53:28 -06:00
|
|
|
|
2016-06-03 23:15:00 +03:00
|
|
|
self.record_def(pat_id, resolution);
|
|
|
|
}
|
|
|
|
|
2016-09-15 00:51:46 +03:00
|
|
|
fn resolve_struct_path(&mut self, node_id: NodeId, path: &Path) {
|
|
|
|
// Resolution logic is equivalent for expressions and patterns,
|
|
|
|
// reuse `resolve_pattern_path` for both.
|
|
|
|
self.resolve_pattern_path(node_id, None, path, TypeNS, |def| {
|
|
|
|
match def {
|
|
|
|
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
|
|
|
|
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}, "struct, variant or union type");
|
|
|
|
}
|
|
|
|
|
2016-06-03 23:15:00 +03: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 14:02:55 +11:00
|
|
|
bindings: &mut FxHashMap<Ident, NodeId>) {
|
2016-06-03 23:15:00 +03:00
|
|
|
// Visit all direct subpatterns of this pattern.
|
2016-06-03 23:15:00 +03:00
|
|
|
let outer_pat_id = pat.id;
|
|
|
|
pat.walk(&mut |pat| {
|
|
|
|
match pat.node {
|
|
|
|
PatKind::Ident(bmode, ref ident, ref opt_pat) => {
|
|
|
|
// First try to resolve the identifier as some existing
|
|
|
|
// entity, then fall back to a fresh binding.
|
2016-08-05 01:58:59 +00:00
|
|
|
let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None)
|
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| {
|
2016-06-03 23:15:00 +03:00
|
|
|
let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
|
|
|
|
bmode != BindingMode::ByValue(Mutability::Immutable);
|
2016-07-29 15:19:29 +00:00
|
|
|
match def {
|
2016-09-15 00:51:46 +03:00
|
|
|
Def::StructCtor(_, CtorKind::Const) |
|
|
|
|
Def::VariantCtor(_, CtorKind::Const) |
|
|
|
|
Def::Const(..) if !always_binding => {
|
|
|
|
// A unit struct/variant or constant pattern.
|
2016-11-29 02:07:12 +00:00
|
|
|
self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
|
2016-07-29 15:19:29 +00:00
|
|
|
Some(PathResolution::new(def))
|
2015-03-25 10:53:28 -06:00
|
|
|
}
|
2016-09-15 00:51:46 +03:00
|
|
|
Def::StructCtor(..) | Def::VariantCtor(..) |
|
2016-09-15 00:51:46 +03:00
|
|
|
Def::Const(..) | Def::Static(..) => {
|
2016-06-03 23:15:00 +03:00
|
|
|
// A fresh binding that shadows something unacceptable.
|
2015-07-14 15:37:52 +02:00
|
|
|
resolve_error(
|
2015-07-14 16:32:43 +02:00
|
|
|
self,
|
2016-06-03 23:15:00 +03:00
|
|
|
ident.span,
|
|
|
|
ResolutionError::BindingShadowsSomethingUnacceptable(
|
2016-07-29 15:19:29 +00:00
|
|
|
pat_src.descr(), ident.node.name, binding.unwrap())
|
2015-07-14 15:37:52 +02:00
|
|
|
);
|
2016-06-11 18:47:47 +03:00
|
|
|
None
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
2016-07-17 00:15:15 +03:00
|
|
|
Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
|
2016-06-03 23:15:00 +03:00
|
|
|
// These entities are explicitly allowed
|
|
|
|
// to be shadowed by fresh bindings.
|
2016-06-11 18:47:47 +03:00
|
|
|
None
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
|
|
|
def => {
|
|
|
|
span_bug!(ident.span, "unexpected definition for an \
|
2016-09-15 00:51:46 +03:00
|
|
|
identifier in pattern: {:?}", def);
|
2015-02-17 06:44:23 +02:00
|
|
|
}
|
2013-03-12 22:39:32 -07:00
|
|
|
}
|
2016-06-11 18:47:47 +03:00
|
|
|
}).unwrap_or_else(|| {
|
2016-06-03 23:15:00 +03:00
|
|
|
self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
|
2016-06-11 18:47:47 +03:00
|
|
|
});
|
2016-06-03 23:15:00 +03:00
|
|
|
|
|
|
|
self.record_def(pat.id, resolution);
|
2012-07-10 12:29:30 -07:00
|
|
|
}
|
|
|
|
|
2016-09-15 00:51:46 +03:00
|
|
|
PatKind::TupleStruct(ref path, ..) => {
|
2016-06-03 23:15:00 +03:00
|
|
|
self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
|
|
|
|
match def {
|
2016-09-15 00:51:46 +03:00
|
|
|
Def::StructCtor(_, CtorKind::Fn) |
|
|
|
|
Def::VariantCtor(_, CtorKind::Fn) => true,
|
2016-06-03 23:15:00 +03:00
|
|
|
_ => false,
|
2012-08-07 19:12:58 -07:00
|
|
|
}
|
2016-09-15 00:51:46 +03:00
|
|
|
}, "tuple struct/variant");
|
2016-06-03 23:15:00 +03:00
|
|
|
}
|
|
|
|
|
2016-06-11 18:47:47 +03:00
|
|
|
PatKind::Path(ref qself, ref path) => {
|
|
|
|
self.resolve_pattern_path(pat.id, qself.as_ref(), path, ValueNS, |def| {
|
2016-06-03 23:15:00 +03:00
|
|
|
match def {
|
2016-09-15 00:51:46 +03:00
|
|
|
Def::StructCtor(_, CtorKind::Const) |
|
|
|
|
Def::VariantCtor(_, CtorKind::Const) |
|
2016-06-11 01:31:25 +03:00
|
|
|
Def::Const(..) | Def::AssociatedConst(..) => true,
|
2016-06-03 23:15:00 +03:00
|
|
|
_ => false,
|
2012-08-06 17:01:14 -07:00
|
|
|
}
|
2016-09-15 00:51:46 +03:00
|
|
|
}, "unit struct/variant or constant");
|
2015-02-05 09:19:07 +02:00
|
|
|
}
|
|
|
|
|
2016-08-26 19:23:42 +03:00
|
|
|
PatKind::Struct(ref path, ..) => {
|
2016-09-15 00:51:46 +03:00
|
|
|
self.resolve_struct_path(pat.id, path);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2016-06-03 23:15:00 +03:00
|
|
|
|
|
|
|
_ => {}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2013-08-02 02:17:20 -04:00
|
|
|
true
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2016-05-05 20:20:23 +00:00
|
|
|
|
2016-06-03 23:15:00 +03:00
|
|
|
visit::walk_pat(self, pat);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2015-03-25 10:53:28 -06:00
|
|
|
/// Handles paths that may refer to associated items
|
|
|
|
fn resolve_possibly_assoc_item(&mut self,
|
|
|
|
id: NodeId,
|
2016-06-03 23:15:00 +03:00
|
|
|
maybe_qself: Option<&QSelf>,
|
2015-03-25 10:53:28 -06:00
|
|
|
path: &Path,
|
2016-11-25 06:07:21 +00:00
|
|
|
ns: Namespace)
|
2016-06-03 23:15:00 +03:00
|
|
|
-> Option<PathResolution> {
|
2016-11-25 06:07:21 +00:00
|
|
|
let ast::Path { ref segments, global, span } = *path;
|
|
|
|
let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
|
|
|
|
let scope = if global { PathScope::Global } else { PathScope::Lexical };
|
|
|
|
|
|
|
|
if let Some(qself) = maybe_qself {
|
|
|
|
if qself.position == 0 {
|
|
|
|
// FIXME: Create some fake resolution that can't possibly be a type.
|
|
|
|
return Some(PathResolution {
|
|
|
|
base_def: Def::Mod(self.definitions.local_def_id(ast::CRATE_NODE_ID)),
|
|
|
|
depth: path.len(),
|
|
|
|
});
|
2015-05-07 01:52:38 -06:00
|
|
|
}
|
2016-11-25 06:07:21 +00:00
|
|
|
// Make sure the trait is valid.
|
|
|
|
self.resolve_trait_reference(&path[..qself.position], global, None, span);
|
2015-03-25 10:53:28 -06:00
|
|
|
}
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
let result = match self.resolve_path(&path, scope, Some(ns), Some(span)) {
|
|
|
|
PathResult::NonModule(path_res) => match path_res.base_def {
|
|
|
|
Def::Trait(..) if maybe_qself.is_some() => return None,
|
|
|
|
_ => path_res,
|
|
|
|
},
|
|
|
|
PathResult::Module(module) if !module.is_normal() => {
|
|
|
|
PathResolution::new(module.def().unwrap())
|
2016-03-10 22:01:38 +03:00
|
|
|
}
|
2016-03-08 21:40:13 +03: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 22:01:38 +03:00
|
|
|
// u8::max_value() // OK, resolves to associated function <u8>::max_value,
|
|
|
|
// // not to non-existent std::u8::max_value
|
2016-03-08 21:40:13 +03:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
// Such behavior is required for backward compatibility.
|
|
|
|
// The same fallback is used when `a` resolves to nothing.
|
2016-12-15 02:12:08 +03:00
|
|
|
PathResult::Module(..) | PathResult::Failed(..)
|
|
|
|
if scope == PathScope::Lexical && (ns == TypeNS || path.len() > 1) &&
|
|
|
|
self.primitive_type_table.primitive_types.contains_key(&path[0].name) => {
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResolution {
|
|
|
|
base_def: Def::PrimTy(self.primitive_type_table.primitive_types[&path[0].name]),
|
|
|
|
depth: segments.len() - 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
|
|
|
|
PathResult::Failed(msg, false) => {
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
|
|
|
err_path_resolution()
|
|
|
|
}
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
|
|
|
|
if path.len() == 1 || result.base_def == Def::Err {
|
|
|
|
return Some(result);
|
2015-03-30 12:21:20 +13:00
|
|
|
}
|
2013-08-08 11:38:10 -07:00
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
let unqualified_result = {
|
|
|
|
match self.resolve_path(&[*path.last().unwrap()], PathScope::Lexical, Some(ns), None) {
|
|
|
|
PathResult::NonModule(path_res) => path_res.base_def,
|
|
|
|
PathResult::Module(module) => module.def().unwrap(),
|
|
|
|
_ => return Some(result),
|
2015-03-30 12:21:20 +13:00
|
|
|
}
|
2016-11-25 06:07:21 +00:00
|
|
|
};
|
|
|
|
if result.base_def == unqualified_result && path[0].name != "$crate" {
|
|
|
|
let lint = lint::builtin::UNUSED_QUALIFICATIONS;
|
|
|
|
self.session.add_lint(lint, id, span, "unnecessary qualification".to_string());
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2015-03-30 12:21:20 +13:00
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
Some(result)
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
fn resolve_path(&mut self,
|
|
|
|
path: &[Ident],
|
|
|
|
scope: PathScope,
|
|
|
|
opt_ns: Option<Namespace>, // `None` indicates a module path
|
|
|
|
record_used: Option<Span>)
|
|
|
|
-> PathResult<'a> {
|
|
|
|
let (mut module, allow_self) = match scope {
|
|
|
|
PathScope::Lexical => (None, true),
|
|
|
|
PathScope::Import => (Some(self.graph_root), true),
|
|
|
|
PathScope::Global => (Some(self.graph_root), false),
|
|
|
|
};
|
|
|
|
let mut allow_super = allow_self;
|
|
|
|
|
|
|
|
for (i, &ident) in path.iter().enumerate() {
|
|
|
|
let is_last = i == path.len() - 1;
|
|
|
|
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
|
|
|
|
|
|
|
if i == 0 && allow_self && ns == TypeNS && ident.name == keywords::SelfValue.name() {
|
|
|
|
module = Some(self.module_map[&self.current_module.normal_ancestor_id.unwrap()]);
|
|
|
|
continue
|
|
|
|
} else if i == 0 && allow_self && ns == TypeNS && ident.name == "$crate" {
|
|
|
|
module = Some(self.resolve_crate_var(ident.ctxt));
|
|
|
|
continue
|
|
|
|
} else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() {
|
|
|
|
let current_module = if i == 0 { self.current_module } else { module.unwrap() };
|
|
|
|
let self_module = self.module_map[¤t_module.normal_ancestor_id.unwrap()];
|
|
|
|
if let Some(parent) = self_module.parent {
|
|
|
|
module = Some(self.module_map[&parent.normal_ancestor_id.unwrap()]);
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
let msg = "There are too many initial `super`s.".to_string();
|
|
|
|
return PathResult::Failed(msg, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allow_super = false;
|
|
|
|
|
|
|
|
let binding = if let Some(module) = module {
|
2016-11-29 02:07:12 +00:00
|
|
|
self.resolve_ident_in_module(module, ident, ns, false, record_used)
|
2016-11-27 10:58:46 +00:00
|
|
|
} else if opt_ns == Some(MacroNS) {
|
2016-11-29 02:07:12 +00:00
|
|
|
self.resolve_lexical_macro_path_segment(ident, ns, record_used)
|
2016-11-25 06:07:21 +00:00
|
|
|
} else {
|
|
|
|
match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
|
|
|
|
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
2016-11-27 10:58:46 +00:00
|
|
|
Some(LexicalScopeBinding::Def(def))
|
|
|
|
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
|
2016-11-25 06:07:21 +00:00
|
|
|
return PathResult::NonModule(PathResolution {
|
|
|
|
base_def: def,
|
|
|
|
depth: path.len() - 1,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => Err(if record_used.is_some() { Determined } else { Undetermined }),
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match binding {
|
|
|
|
Ok(binding) => {
|
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);
|
|
|
|
} else if binding.def() == Def::Err {
|
|
|
|
return PathResult::NonModule(err_path_resolution());
|
2016-11-27 10:58:46 +00:00
|
|
|
} else if opt_ns.is_some() && !(opt_ns == Some(MacroNS) && !is_last) {
|
2016-11-25 06:07:21 +00:00
|
|
|
return PathResult::NonModule(PathResolution {
|
|
|
|
base_def: binding.def(),
|
|
|
|
depth: path.len() - i - 1,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return PathResult::Failed(format!("Not a module `{}`", ident), is_last);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(Undetermined) => return PathResult::Indeterminate,
|
|
|
|
Err(Determined) => {
|
|
|
|
if let Some(module) = module {
|
|
|
|
if opt_ns.is_some() && !module.is_normal() {
|
|
|
|
return PathResult::NonModule(PathResolution {
|
|
|
|
base_def: module.def().unwrap(),
|
|
|
|
depth: path.len() - i,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
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 =
|
|
|
|
self.lookup_candidates(ident.name, TypeNS, is_mod).candidates;
|
|
|
|
candidates.sort_by_key(|path| (path.segments.len(), path.to_string()));
|
|
|
|
if let Some(candidate) = candidates.get(0) {
|
|
|
|
format!("Did you mean `{}`?", candidate)
|
|
|
|
} else {
|
|
|
|
format!("Maybe a missing `extern crate {};`?", ident)
|
|
|
|
}
|
|
|
|
} else if i == 0 {
|
|
|
|
format!("Use of undeclared type or module `{}`", ident)
|
|
|
|
} else {
|
|
|
|
format!("Could not find `{}` in `{}`", ident, path[i - 1])
|
|
|
|
};
|
|
|
|
return PathResult::Failed(msg, is_last);
|
|
|
|
}
|
|
|
|
}
|
2016-01-20 22:29:47 +13:00
|
|
|
}
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResult::Module(module.unwrap())
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve a local definition, potentially adjusting for closures.
|
2016-11-22 11:32:52 +00:00
|
|
|
fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Def {
|
2015-11-03 20:44:23 +02:00
|
|
|
let ribs = match local_def.ribs {
|
2016-11-10 06:19:54 +00:00
|
|
|
Some((ns, i)) => &self.ribs[ns][i + 1..],
|
|
|
|
None => &[] as &[_],
|
2015-11-03 20:44:23 +02:00
|
|
|
};
|
|
|
|
let mut def = local_def.def;
|
|
|
|
match def {
|
2016-01-20 22:31:10 +03:00
|
|
|
Def::Upvar(..) => {
|
2016-03-28 23:11:50 +02:00
|
|
|
span_bug!(span, "unexpected {:?} in bindings", def)
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
2016-08-31 14:08:22 +03:00
|
|
|
Def::Local(def_id) => {
|
2015-11-03 20:44:23 +02:00
|
|
|
for rib in ribs {
|
|
|
|
match rib.kind {
|
2016-06-26 03:32:45 +00:00
|
|
|
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => {
|
2015-11-03 20:44:23 +02:00
|
|
|
// Nothing to do. Continue.
|
|
|
|
}
|
|
|
|
ClosureRibKind(function_id) => {
|
|
|
|
let prev_def = def;
|
2016-08-31 14:08:22 +03:00
|
|
|
let node_id = self.definitions.as_local_node_id(def_id).unwrap();
|
2015-11-03 20:44:23 +02:00
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
let seen = self.freevars_seen
|
|
|
|
.entry(function_id)
|
|
|
|
.or_insert_with(|| NodeMap());
|
2015-11-03 20:44:23 +02:00
|
|
|
if let Some(&index) = seen.get(&node_id) {
|
2016-08-31 14:08:22 +03:00
|
|
|
def = Def::Upvar(def_id, index, function_id);
|
2015-11-03 20:44:23 +02:00
|
|
|
continue;
|
|
|
|
}
|
2015-10-26 20:31:11 +01:00
|
|
|
let vec = self.freevars
|
|
|
|
.entry(function_id)
|
|
|
|
.or_insert_with(|| vec![]);
|
2015-11-03 20:44:23 +02:00
|
|
|
let depth = vec.len();
|
2015-10-26 20:31:11 +01:00
|
|
|
vec.push(Freevar {
|
|
|
|
def: prev_def,
|
|
|
|
span: span,
|
|
|
|
});
|
2015-11-03 20:44:23 +02:00
|
|
|
|
2016-08-31 14:08:22 +03:00
|
|
|
def = Def::Upvar(def_id, depth, function_id);
|
2015-11-03 20:44:23 +02:00
|
|
|
seen.insert(node_id, depth);
|
|
|
|
}
|
2016-05-13 17:17:10 +02:00
|
|
|
ItemRibKind | MethodRibKind(_) => {
|
2015-11-03 20:44:23 +02:00
|
|
|
// This was an attempt to access an upvar inside a
|
|
|
|
// named function item. This is not allowed, so we
|
|
|
|
// report an error.
|
2015-10-26 20:31:11 +01:00
|
|
|
resolve_error(self,
|
|
|
|
span,
|
|
|
|
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
|
2016-11-22 11:32:52 +00:00
|
|
|
return Def::Err;
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
// Still doesn't deal with upvars
|
2015-10-26 20:31:11 +01:00
|
|
|
resolve_error(self,
|
|
|
|
span,
|
|
|
|
ResolutionError::AttemptToUseNonConstantValueInConstant);
|
2016-11-22 11:32:52 +00:00
|
|
|
return Def::Err;
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-20 22:31:10 +03:00
|
|
|
Def::TyParam(..) | Def::SelfTy(..) => {
|
2015-11-03 20:44:23 +02:00
|
|
|
for rib in ribs {
|
|
|
|
match rib.kind {
|
2016-05-13 17:17:10 +02:00
|
|
|
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
|
2016-06-26 03:32:45 +00:00
|
|
|
ModuleRibKind(..) | MacroDefinition(..) => {
|
2015-11-03 20:44:23 +02:00
|
|
|
// Nothing to do. Continue.
|
|
|
|
}
|
|
|
|
ItemRibKind => {
|
|
|
|
// This was an attempt to use a type parameter outside
|
|
|
|
// its scope.
|
|
|
|
|
|
|
|
resolve_error(self,
|
|
|
|
span,
|
|
|
|
ResolutionError::TypeParametersFromOuterFunction);
|
2016-11-22 11:32:52 +00:00
|
|
|
return Def::Err;
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
// see #9186
|
|
|
|
resolve_error(self, span, ResolutionError::OuterTypeParameterContext);
|
2016-11-22 11:32:52 +00:00
|
|
|
return Def::Err;
|
2015-11-03 20:44:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2016-11-22 11:32:52 +00:00
|
|
|
return def;
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-07-05 08:47:58 +00:00
|
|
|
// Calls `f` with a `Resolver` whose current lexical scope is `module`'s lexical scope,
|
|
|
|
// i.e. the module's items and the prelude (unless the module is `#[no_implicit_prelude]`).
|
2016-07-05 22:38:41 +00:00
|
|
|
// FIXME #34673: This needs testing.
|
2016-07-05 08:47:58 +00:00
|
|
|
pub fn with_module_lexical_scope<T, F>(&mut self, module: Module<'a>, f: F) -> T
|
|
|
|
where F: FnOnce(&mut Resolver<'a>) -> T,
|
|
|
|
{
|
|
|
|
self.with_empty_ribs(|this| {
|
2016-11-10 06:19:54 +00:00
|
|
|
this.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
|
|
|
|
this.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
|
2016-07-05 08:47:58 +00:00
|
|
|
f(this)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn with_empty_ribs<T, F>(&mut self, f: F) -> T
|
|
|
|
where F: FnOnce(&mut Resolver<'a>) -> T,
|
|
|
|
{
|
2016-11-10 06:19:54 +00:00
|
|
|
let ribs = replace(&mut self.ribs, PerNS::<Vec<Rib>>::default());
|
2016-07-05 08:47:58 +00:00
|
|
|
let label_ribs = replace(&mut self.label_ribs, Vec::new());
|
|
|
|
|
|
|
|
let result = f(self);
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs = ribs;
|
2016-07-05 08:47:58 +00:00
|
|
|
self.label_ribs = label_ribs;
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2014-05-08 22:35:09 +01:00
|
|
|
fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
|
2016-04-26 07:58:58 +00:00
|
|
|
fn extract_node_id(t: &Ty) -> Option<NodeId> {
|
2014-05-19 22:27:03 +01: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 22:27:03 +01: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-04-26 07:58:58 +00:00
|
|
|
if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
|
2014-05-19 22:27:03 +01:00
|
|
|
// Look for a field with the same name in the current self_type.
|
2016-06-03 23:15:00 +03:00
|
|
|
if let Some(resolution) = self.def_map.get(&node_id) {
|
|
|
|
match resolution.base_def {
|
2016-09-15 00:51:46 +03:00
|
|
|
Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
|
2016-09-15 00:51:46 +03:00
|
|
|
if let Some(field_names) = self.field_names.get(&did) {
|
|
|
|
if field_names.iter().any(|&field_name| name == field_name) {
|
2016-06-03 23:15:00 +03:00
|
|
|
return Field;
|
|
|
|
}
|
2014-05-19 22:27:03 +01:00
|
|
|
}
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
2016-06-03 23:15:00 +03:00
|
|
|
_ => {}
|
|
|
|
}
|
2014-05-19 22:27:03 +01:00
|
|
|
}
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Look for a method in the current trait.
|
2015-02-11 09:32:25 +02:00
|
|
|
if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
|
2016-04-26 08:29:13 +00:00
|
|
|
if let Some(&is_static_method) = self.trait_item_map.get(&(name, trait_did)) {
|
|
|
|
if is_static_method {
|
2015-03-16 10:44:19 +13:00
|
|
|
return TraitMethod(path_names_to_string(&trait_ref.path, 0));
|
2015-02-11 09:32:25 +02:00
|
|
|
} else {
|
|
|
|
return TraitItem;
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NoSuggestion
|
|
|
|
}
|
|
|
|
|
2015-12-14 22:36:31 +05:30
|
|
|
fn find_best_match(&mut self, name: &str) -> SuggestionType {
|
2016-11-17 14:04:20 +00:00
|
|
|
if let Some(macro_name) = self.macro_names.iter().find(|&n| n == &name) {
|
2015-11-21 15:07:50 +05:30
|
|
|
return SuggestionType::Macro(format!("{}!", macro_name));
|
|
|
|
}
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
let names = self.ribs[ValueNS]
|
2015-12-14 22:36:31 +05:30
|
|
|
.iter()
|
|
|
|
.rev()
|
2016-06-22 02:50:05 +00:00
|
|
|
.flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name));
|
2013-02-23 00:22:51 -08:00
|
|
|
|
2015-12-14 22:36:31 +05:30
|
|
|
if let Some(found) = find_best_match_for_name(names, name, None) {
|
2016-11-16 10:52:37 +00:00
|
|
|
if found != name {
|
2015-12-14 22:36:31 +05:30
|
|
|
return SuggestionType::Function(found);
|
2013-02-23 00:22:51 -08:00
|
|
|
}
|
2015-12-14 22:36:31 +05:30
|
|
|
} SuggestionType::NotFound
|
2013-02-23 00:22:51 -08:00
|
|
|
}
|
|
|
|
|
2016-10-22 23:34:18 +00:00
|
|
|
fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, block: &Block) {
|
2016-04-24 03:26:10 +00:00
|
|
|
if let Some(label) = label {
|
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| {
|
2016-10-22 23:34:18 +00:00
|
|
|
this.label_ribs.last_mut().unwrap().bindings.insert(label.node, def);
|
2016-04-24 03:26:10 +00:00
|
|
|
this.visit_block(block);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
self.visit_block(block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-24 21:10:54 +00:00
|
|
|
fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
|
2012-08-17 16:53:07 -07:00
|
|
|
// First, record candidate traits for this expression if it could
|
|
|
|
// result in the invocation of a method call.
|
2012-07-11 15:00:40 -07:00
|
|
|
|
|
|
|
self.record_candidate_traits_for_expr_if_necessary(expr);
|
|
|
|
|
2012-05-22 10:54:12 -07:00
|
|
|
// Next, resolve the node.
|
2012-08-06 12:34:08 -07:00
|
|
|
match expr.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
ExprKind::Path(ref maybe_qself, ref path) => {
|
2012-05-22 10:54:12 -07:00
|
|
|
// This is a local path in the value namespace. Walk through
|
|
|
|
// scopes looking for it.
|
2016-06-03 23:15:00 +03:00
|
|
|
if let Some(path_res) = self.resolve_possibly_assoc_item(expr.id,
|
|
|
|
maybe_qself.as_ref(), path, ValueNS) {
|
2014-12-10 16:11:19 +09:00
|
|
|
// Check if struct variant
|
2016-09-15 00:51:46 +03:00
|
|
|
let is_struct_variant = match path_res.base_def {
|
|
|
|
Def::VariantCtor(_, CtorKind::Fictive) => true,
|
|
|
|
_ => false,
|
2016-01-17 22:57:54 +03:00
|
|
|
};
|
|
|
|
if is_struct_variant {
|
2015-03-16 10:44:19 +13:00
|
|
|
let path_name = path_names_to_string(path, 0);
|
2015-07-13 19:32:45 +02:00
|
|
|
|
2015-12-21 10:00:43 +13:00
|
|
|
let mut err = resolve_struct_error(self,
|
|
|
|
expr.span,
|
2016-02-09 21:27:42 +01:00
|
|
|
ResolutionError::StructVariantUsedAsFunction(&path_name));
|
2014-12-10 16:11:19 +09:00
|
|
|
|
2015-10-26 20:31:11 +01:00
|
|
|
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
2015-02-24 16:07:54 +02:00
|
|
|
path_name);
|
2016-11-25 06:07:21 +00:00
|
|
|
err.help(&msg);
|
2015-12-23 19:27:20 +13:00
|
|
|
err.emit();
|
2015-12-11 20:59:11 +13:00
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-02-17 06:44:23 +02:00
|
|
|
} else {
|
2012-05-22 10:54:12 -07:00
|
|
|
// Write the result into the def map.
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("(resolving expr) resolved `{}`",
|
2015-03-16 10:44:19 +13:00
|
|
|
path_names_to_string(path, 0));
|
2014-09-30 19:11:34 -05:00
|
|
|
|
2015-02-11 09:33:49 +02:00
|
|
|
// Partial resolutions will need the set of traits in scope,
|
|
|
|
// so they can be completed during typeck.
|
2015-02-17 06:44:23 +02:00
|
|
|
if path_res.depth != 0 {
|
2015-02-11 09:33:49 +02:00
|
|
|
let method_name = path.segments.last().unwrap().identifier.name;
|
2015-03-25 10:53:28 -06:00
|
|
|
let traits = self.get_traits_containing_item(method_name);
|
2015-02-11 09:33:49 +02:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
|
|
|
}
|
|
|
|
|
2015-02-17 06:44:23 +02:00
|
|
|
self.record_def(expr.id, path_res);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
2015-02-17 06:44:23 +02:00
|
|
|
} else {
|
|
|
|
// Be helpful if the name refers to a struct
|
2015-03-16 10:44:19 +13:00
|
|
|
let path_name = path_names_to_string(path, 0);
|
2016-11-25 06:07:21 +00:00
|
|
|
let ast::Path { ref segments, global, .. } = *path;
|
|
|
|
let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
|
|
|
|
let scope = if global { PathScope::Global } else { PathScope::Lexical };
|
|
|
|
let type_res = match self.resolve_path(&path, scope, Some(TypeNS), None) {
|
|
|
|
PathResult::NonModule(type_res) => Some(type_res),
|
|
|
|
_ => None,
|
|
|
|
};
|
2015-12-11 20:59:11 +13:00
|
|
|
|
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-02-17 06:44:23 +02:00
|
|
|
|
2016-11-22 11:32:52 +00:00
|
|
|
if let Some(Def::Struct(..)) = type_res.map(|r| r.base_def) {
|
2016-04-07 04:13:34 +00:00
|
|
|
let error_variant =
|
|
|
|
ResolutionError::StructVariantUsedAsFunction(&path_name);
|
2016-04-07 00:42:29 +00:00
|
|
|
let mut err = resolve_struct_error(self, expr.span, error_variant);
|
|
|
|
|
|
|
|
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
|
|
|
path_name);
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
err.help(&msg);
|
2016-04-07 00:42:29 +00:00
|
|
|
err.emit();
|
|
|
|
} else {
|
|
|
|
// Keep reporting some errors even if they're ignored above.
|
2016-11-26 12:29:21 +00:00
|
|
|
let mut method_scope = false;
|
|
|
|
let mut is_static = false;
|
|
|
|
self.ribs[ValueNS].iter().rev().all(|rib| {
|
|
|
|
method_scope = match rib.kind {
|
|
|
|
MethodRibKind(is_static_) => {
|
|
|
|
is_static = is_static_;
|
|
|
|
true
|
|
|
|
}
|
|
|
|
ItemRibKind | ConstantItemRibKind => false,
|
|
|
|
_ => return true, // Keep advancing
|
|
|
|
};
|
|
|
|
false // Stop advancing
|
|
|
|
});
|
2014-05-08 22:35:09 +01:00
|
|
|
|
2016-11-26 12:29:21 +00:00
|
|
|
if method_scope && keywords::SelfValue.name() == &*path_name {
|
|
|
|
let error = ResolutionError::SelfNotAvailableInStaticMethod;
|
|
|
|
resolve_error(self, expr.span, error);
|
|
|
|
} else {
|
|
|
|
let fallback =
|
|
|
|
self.find_fallback_in_self_type(path.last().unwrap().name);
|
|
|
|
let (mut msg, is_field) = match fallback {
|
|
|
|
NoSuggestion => {
|
|
|
|
// limit search to 5 to reduce the number
|
|
|
|
// of stupid suggestions
|
|
|
|
(match self.find_best_match(&path_name) {
|
|
|
|
SuggestionType::Macro(s) => {
|
|
|
|
format!("the macro `{}`", s)
|
|
|
|
}
|
|
|
|
SuggestionType::Function(s) => format!("`{}`", s),
|
|
|
|
SuggestionType::NotFound => "".to_string(),
|
|
|
|
}, false)
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
2016-11-26 12:29:21 +00:00
|
|
|
Field => {
|
|
|
|
(if is_static && method_scope {
|
|
|
|
"".to_string()
|
|
|
|
} else {
|
|
|
|
format!("`self.{}`", path_name)
|
|
|
|
}, true)
|
|
|
|
}
|
|
|
|
TraitItem => (format!("to call `self.{}`", path_name), false),
|
|
|
|
TraitMethod(path_str) =>
|
|
|
|
(format!("to call `{}::{}`", path_str, path_name), false),
|
|
|
|
};
|
2015-02-17 06:44:23 +02:00
|
|
|
|
2016-11-26 12:29:21 +00:00
|
|
|
let mut context = UnresolvedNameContext::Other;
|
|
|
|
let mut def = Def::Err;
|
|
|
|
if !msg.is_empty() {
|
|
|
|
msg = format!("did you mean {}?", msg);
|
|
|
|
} else {
|
|
|
|
// we display a help message if this is a module
|
|
|
|
if let PathResult::Module(module) =
|
|
|
|
self.resolve_path(&path, scope, None, None) {
|
|
|
|
def = module.def().unwrap();
|
|
|
|
context = UnresolvedNameContext::PathIsMod(parent);
|
|
|
|
}
|
2014-05-08 22:35:09 +01:00
|
|
|
}
|
2016-11-26 12:29:21 +00:00
|
|
|
|
|
|
|
let error = ResolutionError::UnresolvedName {
|
|
|
|
path: &path_name,
|
|
|
|
message: &msg,
|
|
|
|
context: context,
|
|
|
|
is_static_method: method_scope && is_static,
|
|
|
|
is_field: is_field,
|
|
|
|
def: def,
|
|
|
|
};
|
|
|
|
resolve_error(self, expr.span, error);
|
2012-08-22 20:40:42 +02:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_expr(self, expr);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-08-26 19:23:42 +03:00
|
|
|
ExprKind::Struct(ref path, ..) => {
|
2016-09-15 00:51:46 +03:00
|
|
|
self.resolve_struct_path(expr.id, path);
|
2012-07-23 18:44:59 -07:00
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_expr(self, expr);
|
2012-07-23 18:44:59 -07: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 15:15:06 -07:00
|
|
|
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
2016-06-22 02:50:05 +00:00
|
|
|
match self.search_label(label.node) {
|
2014-05-16 10:45:16 -07:00
|
|
|
None => {
|
2015-12-11 20:59:11 +13:00
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-07-14 16:32:43 +02:00
|
|
|
resolve_error(self,
|
2015-09-02 22:29:41 +03:00
|
|
|
label.span,
|
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 15:15:06 -07:00
|
|
|
ResolutionError::UndeclaredLabel(&label.node.name.as_str()));
|
2014-05-16 10:45:16 -07:00
|
|
|
}
|
2016-03-12 04:49:25 +00:00
|
|
|
Some(def @ Def::Label(_)) => {
|
2014-02-12 08:19:18 +13:00
|
|
|
// Since this def is a label, it is never read.
|
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 15:15:06 -07:00
|
|
|
self.record_def(expr.id, PathResolution::new(def));
|
2013-05-10 15:15:06 -07: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 15:15:06 -07:00
|
|
|
span_bug!(expr.span, "label wasn't mapped to a label def!");
|
2013-05-10 15:15:06 -07: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 15:15:06 -07:00
|
|
|
|
|
|
|
// visit `break` argument if any
|
|
|
|
visit::walk_expr(self, expr);
|
2013-05-10 15:15:06 -07:00
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
|
|
|
|
ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
|
|
|
|
self.visit_expr(subexpression);
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
self.ribs[ValueNS].push(Rib::new(NormalRibKind));
|
2016-11-08 14:02:55 +11:00
|
|
|
self.resolve_pattern(pattern, PatternSource::IfLet, &mut FxHashMap());
|
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) => {
|
|
|
|
self.visit_expr(subexpression);
|
|
|
|
self.resolve_labeled_block(label, expr.id, &block);
|
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
ExprKind::WhileLet(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 14:02:55 +11:00
|
|
|
self.resolve_pattern(pattern, PatternSource::WhileLet, &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
|
|
|
}
|
|
|
|
|
|
|
|
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 14:02:55 +11: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
|
|
|
}
|
|
|
|
|
|
|
|
ExprKind::Field(ref subexpression, _) => {
|
2016-04-24 21:10:54 +00:00
|
|
|
self.resolve_expr(subexpression, Some(expr));
|
|
|
|
}
|
2016-04-24 03:26:10 +00:00
|
|
|
ExprKind::MethodCall(_, ref types, ref arguments) => {
|
2016-04-24 21:10:54 +00:00
|
|
|
let mut arguments = arguments.iter();
|
|
|
|
self.resolve_expr(arguments.next().unwrap(), Some(expr));
|
|
|
|
for argument in arguments {
|
|
|
|
self.resolve_expr(argument, None);
|
|
|
|
}
|
|
|
|
for ty in types.iter() {
|
|
|
|
self.visit_ty(ty);
|
|
|
|
}
|
|
|
|
}
|
2013-05-10 15:15:06 -07:00
|
|
|
|
2012-08-03 19:59:04 -07:00
|
|
|
_ => {
|
2016-04-24 03:26:10 +00:00
|
|
|
visit::walk_expr(self, expr);
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 14:00:46 +02:00
|
|
|
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
|
2012-08-06 12:34:08 -07:00
|
|
|
match expr.node {
|
2016-04-24 03:26:10 +00:00
|
|
|
ExprKind::Field(_, name) => {
|
2013-06-01 15:31:56 -07: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.
|
2016-04-24 03:26:10 +00:00
|
|
|
let traits = self.get_traits_containing_item(name.node.name);
|
2014-02-24 10:36:24 +02:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-07-11 15:00:40 -07:00
|
|
|
}
|
2016-08-26 19:23:42 +03:00
|
|
|
ExprKind::MethodCall(name, ..) => {
|
2015-10-26 20:31:11 +01:00
|
|
|
debug!("(recording candidate traits for expr) recording traits for {}",
|
2013-06-18 09:39:16 -07:00
|
|
|
expr.id);
|
2016-04-24 03:26:10 +00:00
|
|
|
let traits = self.get_traits_containing_item(name.node.name);
|
2014-02-24 10:36:24 +02:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-11-30 11:18:25 -08:00
|
|
|
}
|
2012-07-27 19:32:42 -07:00
|
|
|
_ => {
|
2012-07-11 15:00:40 -07:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-19 22:43:10 +09:00
|
|
|
fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
|
2015-10-26 20:31:11 +01:00
|
|
|
debug!("(getting traits containing item) looking for '{}'", name);
|
2014-04-22 19:06:43 +03:00
|
|
|
|
2014-03-04 10:02:49 -08:00
|
|
|
let mut found_traits = Vec::new();
|
2016-03-07 23:10:53 +00:00
|
|
|
// Look for the current trait.
|
|
|
|
if let Some((trait_def_id, _)) = self.current_trait_ref {
|
|
|
|
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
2016-12-14 09:59:41 +00:00
|
|
|
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None });
|
2014-04-22 19:06:43 +03:00
|
|
|
}
|
2016-03-07 23:10:53 +00:00
|
|
|
}
|
2012-07-11 15:00:40 -07:00
|
|
|
|
2016-03-07 23:10:53 +00:00
|
|
|
let mut search_module = self.current_module;
|
|
|
|
loop {
|
2016-12-14 09:59:41 +00:00
|
|
|
self.get_traits_in_module_containing_item(name, search_module, &mut found_traits);
|
|
|
|
match search_module.kind {
|
|
|
|
ModuleKind::Block(..) => search_module = search_module.parent.unwrap(),
|
|
|
|
_ => break,
|
|
|
|
}
|
|
|
|
}
|
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 {
|
|
|
|
self.get_traits_in_module_containing_item(name, prelude, &mut found_traits);
|
2014-04-22 19:06:43 +03:00
|
|
|
}
|
2012-07-11 15:00:40 -07:00
|
|
|
}
|
|
|
|
|
2014-04-22 19:06:43 +03:00
|
|
|
found_traits
|
2012-07-11 15:00:40 -07:00
|
|
|
}
|
|
|
|
|
2016-12-14 09:59:41 +00:00
|
|
|
fn get_traits_in_module_containing_item(&mut self,
|
|
|
|
name: Name,
|
|
|
|
module: Module,
|
|
|
|
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() {
|
|
|
|
let trait_def_id = binding.def().def_id();
|
|
|
|
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
|
|
|
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,
|
|
|
|
};
|
|
|
|
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-14 02:47:27 +01: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).
|
|
|
|
fn lookup_candidates<FilterFn>(&mut self,
|
|
|
|
lookup_name: Name,
|
|
|
|
namespace: Namespace,
|
|
|
|
filter_fn: FilterFn) -> SuggestedCandidates
|
|
|
|
where FilterFn: Fn(Def) -> bool {
|
|
|
|
|
|
|
|
let mut lookup_results = Vec::new();
|
|
|
|
let mut worklist = Vec::new();
|
|
|
|
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 02:47:27 +01:00
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
in_module.for_each_child(|ident, ns, name_binding| {
|
2016-02-14 02:47:27 +01:00
|
|
|
|
|
|
|
// avoid imports entirely
|
2016-10-28 03:40:58 +00:00
|
|
|
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
|
2016-02-14 02:47:27 +01: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 02:47:27 +01:00
|
|
|
// create the path
|
2016-04-27 01:13:15 +00:00
|
|
|
let span = name_binding.span;
|
2016-02-14 02:47:27 +01:00
|
|
|
let mut segms = path_segments.clone();
|
2016-12-10 06:45:58 +00:00
|
|
|
segms.push(ident.into());
|
2016-02-14 02:47:27 +01:00
|
|
|
let path = Path {
|
|
|
|
span: span,
|
2016-11-25 06:07:21 +00:00
|
|
|
global: false,
|
2016-02-14 02:47:27 +01: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-02-14 02:47:27 +01:00
|
|
|
lookup_results.push(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// collect submodules to explore
|
2016-11-27 00:23:54 +00:00
|
|
|
if let Some(module) = name_binding.module() {
|
2016-02-14 02:47:27 +01:00
|
|
|
// form the path
|
2016-10-28 03:40:58 +00:00
|
|
|
let mut path_segments = path_segments.clone();
|
2016-12-10 06:45:58 +00:00
|
|
|
path_segments.push(ident.into());
|
2016-02-14 02:47:27 +01:00
|
|
|
|
2016-04-11 05:35:18 +00:00
|
|
|
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
2016-02-14 02:47:27 +01: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-09-18 09:45:06 +00:00
|
|
|
if !worklist.iter().any(|&(m, ..)| m.def() == module.def()) {
|
2016-06-28 23:03:56 +00:00
|
|
|
worklist.push((module, path_segments, is_extern));
|
|
|
|
}
|
2016-02-14 02:47:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
SuggestedCandidates {
|
|
|
|
name: lookup_name.as_str().to_string(),
|
|
|
|
candidates: lookup_results,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-17 06:44:23 +02: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 17:05:52 -04:00
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
2016-11-25 06:07:21 +00:00
|
|
|
let (segments, span, id) = match *vis {
|
2016-04-24 03:26:10 +00:00
|
|
|
ast::Visibility::Public => return ty::Visibility::Public,
|
|
|
|
ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
|
2016-11-25 06:07:21 +00:00
|
|
|
ast::Visibility::Restricted { ref path, id } => (&path.segments, path.span, id),
|
2016-08-22 00:24:11 +00:00
|
|
|
ast::Visibility::Inherited => {
|
2016-08-29 05:29:01 +00:00
|
|
|
return ty::Visibility::Restricted(self.current_module.normal_ancestor_id.unwrap());
|
2016-08-22 00:24:11 +00:00
|
|
|
}
|
2016-04-09 23:19:53 +00:00
|
|
|
};
|
|
|
|
|
2016-11-25 06:07:21 +00:00
|
|
|
let path: Vec<_> = segments.iter().map(|seg| seg.identifier).collect();
|
2016-06-03 23:15:00 +03:00
|
|
|
let mut path_resolution = err_path_resolution();
|
2016-11-25 06:07:21 +00:00
|
|
|
let vis = match self.resolve_path(&path, PathScope::Import, None, Some(span)) {
|
|
|
|
PathResult::Module(module) => {
|
2016-09-18 09:45:06 +00:00
|
|
|
path_resolution = PathResolution::new(module.def().unwrap());
|
2016-08-29 05:29:01 +00:00
|
|
|
ty::Visibility::Restricted(module.normal_ancestor_id.unwrap())
|
2016-04-09 23:19:53 +00:00
|
|
|
}
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResult::Failed(msg, _) => {
|
|
|
|
self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
|
2016-04-09 23:19:53 +00:00
|
|
|
ty::Visibility::Public
|
|
|
|
}
|
2016-11-25 06:07:21 +00:00
|
|
|
_ => ty::Visibility::Public,
|
2016-04-09 23:19:53 +00:00
|
|
|
};
|
2016-06-03 23:15:00 +03:00
|
|
|
self.def_map.insert(id, path_resolution);
|
2016-04-09 23:19:53 +00:00
|
|
|
if !self.is_accessible(vis) {
|
|
|
|
let msg = format!("visibilities can only be restricted to ancestor modules");
|
2016-11-25 06:07:21 +00:00
|
|
|
self.session.span_err(span, &msg);
|
2016-04-09 23:19:53 +00:00
|
|
|
}
|
|
|
|
vis
|
|
|
|
}
|
|
|
|
|
2016-04-10 00:44:14 +00:00
|
|
|
fn is_accessible(&self, vis: ty::Visibility) -> bool {
|
2016-08-29 05:29:01 +00:00
|
|
|
vis.is_accessible_from(self.current_module.normal_ancestor_id.unwrap(), 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-08-29 05:29:01 +00:00
|
|
|
vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self)
|
2016-08-20 00:33:06 +00:00
|
|
|
}
|
|
|
|
|
2016-10-11 03:21:40 +00:00
|
|
|
fn report_errors(&mut self) {
|
|
|
|
self.report_shadowing_errors();
|
2016-11-08 14:02:55 +11:00
|
|
|
let mut reported_spans = FxHashSet();
|
2016-08-22 08:30:07 +00:00
|
|
|
|
2016-12-09 11:08:39 +00:00
|
|
|
for &AmbiguityError { span, name, b1, b2, lexical, legacy } 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" }
|
|
|
|
};
|
|
|
|
let msg1 = format!("`{}` could resolve to the name {} here", name, participle(b1));
|
|
|
|
let msg2 = format!("`{}` could also resolve to the name {} here", name, participle(b2));
|
2016-12-09 11:08:39 +00:00
|
|
|
let note = if !lexical && b1.is_glob_import() {
|
|
|
|
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" })
|
|
|
|
};
|
|
|
|
if legacy {
|
|
|
|
let id = match b2.kind {
|
|
|
|
NameBindingKind::Import { directive, .. } => directive.id,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
let mut span = MultiSpan::from_span(span);
|
|
|
|
span.push_span_label(b1.span, msg1);
|
|
|
|
span.push_span_label(b2.span, msg2);
|
|
|
|
let msg = format!("`{}` is ambiguous", name);
|
|
|
|
self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg);
|
|
|
|
} else {
|
|
|
|
self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
|
|
|
|
.span_note(b1.span, &msg1)
|
|
|
|
.span_note(b2.span, &msg2)
|
|
|
|
.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 }
|
|
|
|
if binding.is_extern_crate() {
|
|
|
|
// Warn when using an inaccessible extern crate.
|
2016-10-28 03:40:58 +00:00
|
|
|
let node_id = match binding.kind {
|
|
|
|
NameBindingKind::Import { directive, .. } => directive.id,
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2016-02-25 04:40:46 +00:00
|
|
|
let msg = format!("extern crate `{}` is private", name);
|
|
|
|
self.session.add_lint(lint::builtin::INACCESSIBLE_EXTERN_CRATE, node_id, span, msg);
|
|
|
|
} else {
|
2016-08-20 07:26:26 +00:00
|
|
|
let def = binding.def();
|
2016-02-25 04:40:46 +00:00
|
|
|
self.session.span_err(span, &format!("{} `{}` is private", def.kind_name(), name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 10:54:12 -07:00
|
|
|
|
2016-10-11 03:21:40 +00:00
|
|
|
fn report_shadowing_errors(&mut self) {
|
2016-10-31 22:17:15 +00:00
|
|
|
for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
|
2016-11-10 10:29:36 +00:00
|
|
|
self.resolve_legacy_scope(scope, name, true);
|
2016-10-31 22:17:15 +00:00
|
|
|
}
|
|
|
|
|
2016-11-08 14:02:55 +11:00
|
|
|
let mut reported_errors = FxHashSet();
|
2016-10-31 06:48:59 +00:00
|
|
|
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
|
2016-11-23 01:51:37 +00:00
|
|
|
if self.resolve_legacy_scope(&binding.parent, binding.name, false).is_some() &&
|
2016-10-31 06:48:59 +00:00
|
|
|
reported_errors.insert((binding.name, binding.span)) {
|
|
|
|
let msg = format!("`{}` is already in scope", binding.name);
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-28 00:30:23 -07:00
|
|
|
fn report_conflict(&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,
|
|
|
|
binding: &NameBinding,
|
|
|
|
old_binding: &NameBinding) {
|
|
|
|
// Error on the second of two conflicting names
|
2016-04-27 01:13:15 +00:00
|
|
|
if old_binding.span.lo > binding.span.lo {
|
2016-11-29 02:07:12 +00:00
|
|
|
return self.report_conflict(parent, ident, ns, old_binding, 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",
|
|
|
|
};
|
|
|
|
|
2016-10-28 03:40:58 +00:00
|
|
|
let (participle, noun) = match old_binding.is_import() {
|
2016-03-16 05:20:58 +00:00
|
|
|
true => ("imported", "import"),
|
|
|
|
false => ("defined", "definition"),
|
|
|
|
};
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
let (name, span) = (ident.name, binding.span);
|
2016-10-28 00:30:23 -07:00
|
|
|
|
|
|
|
if let Some(s) = self.name_already_seen.get(&name) {
|
|
|
|
if s == &span {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 05:20:58 +00:00
|
|
|
let msg = {
|
|
|
|
let kind = match (ns, old_binding.module()) {
|
|
|
|
(ValueNS, _) => "a value",
|
2016-10-25 22:05:02 +00:00
|
|
|
(MacroNS, _) => "a macro",
|
2016-10-28 03:40:58 +00:00
|
|
|
(TypeNS, _) if old_binding.is_extern_crate() => "an extern crate",
|
2016-11-27 00:23:54 +00:00
|
|
|
(TypeNS, Some(module)) if module.is_normal() => "a module",
|
|
|
|
(TypeNS, Some(module)) if module.is_trait() => "a trait",
|
2016-03-16 05:20:58 +00:00
|
|
|
(TypeNS, _) => "a type",
|
|
|
|
};
|
|
|
|
format!("{} named `{}` has already been {} in this {}",
|
|
|
|
kind, name, participle, container)
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) {
|
2016-12-12 08:17:47 +00:00
|
|
|
(true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
|
|
|
|
(true, _) | (_, true) => match binding.is_import() && old_binding.is_import() {
|
|
|
|
true => struct_span_err!(self.session, span, E0254, "{}", msg),
|
|
|
|
false => struct_span_err!(self.session, span, E0260, "{}", msg),
|
2016-08-29 16:20:08 +05:30
|
|
|
},
|
2016-03-16 05:20:58 +00:00
|
|
|
_ => match (old_binding.is_import(), 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
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2016-12-12 08:17:47 +00:00
|
|
|
err.span_label(span, &format!("`{}` already {}", name, participle));
|
2016-06-21 18:08:13 -04:00
|
|
|
if old_binding.span != syntax_pos::DUMMY_SP {
|
2016-05-12 16:39:09 -07:00
|
|
|
err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name));
|
2016-03-16 05:20:58 +00:00
|
|
|
}
|
|
|
|
err.emit();
|
2016-10-28 00:30:23 -07:00
|
|
|
self.name_already_seen.insert(name, span);
|
2016-03-16 05:20:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-10-16 03:06:09 +00:00
|
|
|
fn names_to_string(names: &[Ident]) -> String {
|
2015-03-16 10:44:19 +13:00
|
|
|
let mut first = true;
|
|
|
|
let mut result = String::new();
|
2016-10-16 03:06:09 +00:00
|
|
|
for ident in names {
|
2015-03-16 10:44:19 +13:00
|
|
|
if first {
|
|
|
|
first = false
|
|
|
|
} else {
|
|
|
|
result.push_str("::")
|
|
|
|
}
|
2016-10-16 03:06:09 +00:00
|
|
|
result.push_str(&ident.name.as_str());
|
2015-10-26 20:31:11 +01:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_names_to_string(path: &Path, depth: usize) -> String {
|
2016-10-16 03:06:09 +00:00
|
|
|
let names: Vec<_> =
|
|
|
|
path.segments[..path.segments.len() - depth].iter().map(|seg| seg.identifier).collect();
|
|
|
|
names_to_string(&names)
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-02-14 02:47:27 +01: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
|
|
|
|
fn show_candidates(session: &mut DiagnosticBuilder,
|
|
|
|
candidates: &SuggestedCandidates) {
|
|
|
|
|
|
|
|
let paths = &candidates.candidates;
|
|
|
|
|
|
|
|
if paths.len() > 0 {
|
|
|
|
// don't show more than MAX_CANDIDATES results, so
|
|
|
|
// we're consistent with the trait suggestions
|
|
|
|
const MAX_CANDIDATES: usize = 5;
|
|
|
|
|
|
|
|
// 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<_> = paths.into_iter()
|
|
|
|
.map(|p| path_names_to_string(&p, 0))
|
|
|
|
.collect();
|
|
|
|
path_strings.sort();
|
|
|
|
|
|
|
|
// behave differently based on how many candidates we have:
|
|
|
|
if !paths.is_empty() {
|
|
|
|
if paths.len() == 1 {
|
2016-04-20 14:49:16 -04:00
|
|
|
session.help(
|
2016-03-20 16:02:31 +13:00
|
|
|
&format!("you can import it into scope: `use {};`.",
|
2016-02-14 02:47:27 +01:00
|
|
|
&path_strings[0]),
|
|
|
|
);
|
|
|
|
} else {
|
2016-04-20 14:49:16 -04:00
|
|
|
session.help("you can import several candidates \
|
2016-02-14 02:47:27 +01:00
|
|
|
into scope (`use ...;`):");
|
|
|
|
let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1;
|
|
|
|
|
|
|
|
for (idx, path_string) in path_strings.iter().enumerate() {
|
|
|
|
if idx == MAX_CANDIDATES - 1 && count > 1 {
|
2016-04-20 14:49:16 -04:00
|
|
|
session.help(
|
2016-02-14 02:47:27 +01:00
|
|
|
&format!(" and {} other candidates", count).to_string(),
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
} else {
|
2016-04-20 14:49:16 -04:00
|
|
|
session.help(
|
2016-02-14 02:47:27 +01:00
|
|
|
&format!(" `{}`", path_string).to_string(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// nothing found:
|
2016-04-20 14:49:16 -04:00
|
|
|
session.help(
|
2016-02-14 02:47:27 +01:00
|
|
|
&format!("no candidates by the name of `{}` found in your \
|
|
|
|
project; maybe you misspelled the name or forgot to import \
|
|
|
|
an external crate?", candidates.name.to_string()),
|
|
|
|
);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-03-16 10:44:19 +13:00
|
|
|
/// A somewhat inefficient routine to obtain the name of a module.
|
2016-02-17 20:20:41 -05:00
|
|
|
fn module_to_string(module: Module) -> String {
|
2015-03-16 10:44:19 +13: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-16 10:44:19 +13: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-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
collect_mod(&mut names, module);
|
|
|
|
|
2015-03-24 16:53:34 -07:00
|
|
|
if names.is_empty() {
|
2015-03-16 10:44:19 +13:00
|
|
|
return "???".to_string();
|
|
|
|
}
|
2016-10-16 03:06:09 +00:00
|
|
|
names_to_string(&names.into_iter().rev().collect::<Vec<_>>())
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2015-12-11 20:59:11 +13:00
|
|
|
fn err_path_resolution() -> PathResolution {
|
2016-06-03 23:15:00 +03:00
|
|
|
PathResolution::new(Def::Err)
|
2015-12-11 20:59:11 +13:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(PartialEq,Copy, Clone)]
|
2014-11-23 22:29:41 +13:00
|
|
|
pub enum MakeGlobMap {
|
|
|
|
Yes,
|
2015-10-26 20:31:11 +01:00
|
|
|
No,
|
2013-02-19 02:40:42 -05:00
|
|
|
}
|
|
|
|
|
2015-04-28 12:48:22 +10:00
|
|
|
__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
|