#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_sort_by_cached_key)]
#![recursion_limit="256"]
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
#[macro_use]
extern crate syntax;
extern crate syntax_pos;
extern crate rustc_errors as errors;
extern crate arena;
#[macro_use]
extern crate rustc;
extern crate rustc_data_structures;
extern crate rustc_metadata;
pub use rustc::hir::def::{Namespace, PerNS};
use self::TypeParameters::*;
use self::RibKind::*;
use rustc::hir::map::{Definitions, DefCollector};
use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
use rustc::middle::cstore::CrateStore;
use rustc::session::Session;
use rustc::lint;
use rustc::hir::def::*;
use rustc::hir::def::Namespace::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::session::config::nightly_options;
use rustc::ty;
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use syntax::source_map::SourceMap;
use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::base::MacroKind;
use syntax::symbol::{Symbol, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::visit::{self, FnKind, Visitor};
use syntax::attr;
use syntax::ast::{CRATE_NODE_ID, Arm, IsAsync, BindingMode, Block, Crate, Expr, ExprKind};
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics};
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use std::cell::{Cell, RefCell};
use std::{cmp, fmt, iter, mem, ptr};
use std::collections::BTreeSet;
use std::mem::replace;
use rustc_data_structures::ptr_key::PtrKey;
use rustc_data_structures::sync::Lrc;
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
use macros::{InvocationData, LegacyBinding, ParentScope};
// N.B., this module needs to be declared first so diagnostics are
// registered before they are used.
mod diagnostics;
mod error_reporting;
mod macros;
mod check_unused;
mod build_reduced_graph;
mod resolve_imports;
fn is_known_tool(name: Name) -> bool {
["clippy", "rustfmt"].contains(&&*name.as_str())
}
enum Weak {
Yes,
No,
}
enum ScopeSet {
Import(Namespace),
AbsolutePath(Namespace),
Macro(MacroKind),
Module,
}
/// A free importable items suggested in case of resolution failure.
struct ImportSuggestion {
path: Path,
}
/// A field or associated item from self type suggested in case of resolution failure.
enum AssocSuggestion {
Field,
MethodWithSelf,
AssocItem,
}
#[derive(Eq)]
struct BindingError {
name: Name,
origin: BTreeSet,
target: BTreeSet,
}
impl PartialOrd for BindingError {
fn partial_cmp(&self, other: &BindingError) -> Option {
Some(self.cmp(other))
}
}
impl PartialEq for BindingError {
fn eq(&self, other: &BindingError) -> bool {
self.name == other.name
}
}
impl Ord for BindingError {
fn cmp(&self, other: &BindingError) -> cmp::Ordering {
self.name.cmp(&other.name)
}
}
enum ResolutionError<'a> {
/// error E0401: can't use type parameters from outer function
TypeParametersFromOuterFunction(Def),
/// error E0403: the name is already used for a type parameter in this type parameter list
NameAlreadyUsedInTypeParameterList(Name, &'a Span),
/// error E0407: method is not a member of trait
MethodNotMemberOfTrait(Name, &'a str),
/// 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),
/// error E0408: variable `{}` is not bound in all patterns
VariableNotBoundInPattern(&'a BindingError),
/// error E0409: variable `{}` is bound in inconsistent ways within the same match arm
VariableBoundWithDifferentMode(Name, Span),
/// error E0415: identifier is bound more than once in this parameter list
IdentifierBoundMoreThanOnceInParameterList(&'a str),
/// error E0416: identifier is bound more than once in the same pattern
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
/// error E0426: use of undeclared label
UndeclaredLabel(&'a str, Option),
/// error E0429: `self` imports are only allowed within a { } list
SelfImportsOnlyAllowedWithin,
/// error E0430: `self` import can only appear once in the list
SelfImportCanOnlyAppearOnceInTheList,
/// error E0431: `self` import can only appear in an import list with a non-empty prefix
SelfImportOnlyInImportListWithNonEmptyPrefix,
/// error E0433: failed to resolve
FailedToResolve(&'a str),
/// error E0434: can't capture dynamic environment in a fn item
CannotCaptureDynamicEnvironmentInFnItem,
/// error E0435: attempt to use a non-constant value in a constant
AttemptToUseNonConstantValueInConstant,
/// error E0530: X bindings cannot shadow Ys
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
/// error E0128: type parameters with a default cannot use forward declared identifiers
ForwardDeclaredTyParam,
}
/// Combines an error with provided span and emits it
///
/// This takes the error provided, combines it with the span and any additional spans inside the
/// error and emits it.
fn resolve_error<'sess, 'a>(resolver: &'sess Resolver,
span: Span,
resolution_error: ResolutionError<'a>) {
resolve_struct_error(resolver, span, resolution_error).emit();
}
fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
span: Span,
resolution_error: ResolutionError<'a>)
-> DiagnosticBuilder<'sess> {
match resolution_error {
ResolutionError::TypeParametersFromOuterFunction(outer_def) => {
let mut err = struct_span_err!(resolver.session,
span,
E0401,
"can't use type parameters from outer function");
err.span_label(span, "use of type variable from outer function");
let cm = resolver.session.source_map();
match outer_def {
Def::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| {
resolver.definitions.opt_span(def_id)
}) {
err.span_label(
reduce_impl_span_to_impl_keyword(cm, impl_span),
"`Self` type implicitly declared here, by this `impl`",
);
}
match (maybe_trait_defid, maybe_impl_defid) {
(Some(_), None) => {
err.span_label(span, "can't use `Self` here");
}
(_, Some(_)) => {
err.span_label(span, "use a type here instead");
}
(None, None) => bug!("`impl` without trait nor type?"),
}
return err;
},
Def::TyParam(typaram_defid) => {
if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) {
err.span_label(typaram_span, "type variable from outer function");
}
},
_ => {
bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
Def::TyParam")
}
}
// Try to retrieve the span of the function signature and generate a new message with
// a local type parameter
let sugg_msg = "try using a local type parameter instead";
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
// Suggest the modification to the user
err.span_suggestion_with_applicability(
sugg_span,
sugg_msg,
new_snippet,
Applicability::MachineApplicable,
);
} else if let Some(sp) = cm.generate_fn_name_span(span) {
err.span_label(sp, "try adding a local type parameter in this method instead");
} else {
err.help("try using a local type parameter instead");
}
err
}
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, "already used");
err.span_label(first_use_span.clone(), format!("first use of `{}`", name));
err
}
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
let mut err = struct_span_err!(resolver.session,
span,
E0407,
"method `{}` is not a member of trait `{}`",
method,
trait_);
err.span_label(span, format!("not a member of trait `{}`", trait_));
err
}
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
let mut err = struct_span_err!(resolver.session,
span,
E0437,
"type `{}` is not a member of trait `{}`",
type_,
trait_);
err.span_label(span, format!("not a member of trait `{}`", trait_));
err
}
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
let mut err = struct_span_err!(resolver.session,
span,
E0438,
"const `{}` is not a member of trait `{}`",
const_,
trait_);
err.span_label(span, format!("not a member of trait `{}`", trait_));
err
}
ResolutionError::VariableNotBoundInPattern(binding_error) => {
let target_sp = binding_error.target.iter().cloned().collect::>();
let msp = MultiSpan::from_spans(target_sp.clone());
let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
let mut err = resolver.session.struct_span_err_with_code(
msp,
&msg,
DiagnosticId::Error("E0408".into()),
);
for sp in target_sp {
err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
}
let origin_sp = binding_error.origin.iter().cloned();
for sp in origin_sp {
err.span_label(sp, "variable not in all patterns");
}
err
}
ResolutionError::VariableBoundWithDifferentMode(variable_name,
first_binding_span) => {
let mut err = struct_span_err!(resolver.session,
span,
E0409,
"variable `{}` is bound in inconsistent \
ways within the same match arm",
variable_name);
err.span_label(span, "bound in different ways");
err.span_label(first_binding_span, "first binding");
err
}
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
let mut err = struct_span_err!(resolver.session,
span,
E0415,
"identifier `{}` is bound more than once in this parameter list",
identifier);
err.span_label(span, "used as parameter more than once");
err
}
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
let mut err = struct_span_err!(resolver.session,
span,
E0416,
"identifier `{}` is bound more than once in the same pattern",
identifier);
err.span_label(span, "used in a pattern more than once");
err
}
ResolutionError::UndeclaredLabel(name, lev_candidate) => {
let mut err = struct_span_err!(resolver.session,
span,
E0426,
"use of undeclared label `{}`",
name);
if let Some(lev_candidate) = lev_candidate {
err.span_label(span, format!("did you mean `{}`?", lev_candidate));
} else {
err.span_label(span, format!("undeclared label `{}`", name));
}
err
}
ResolutionError::SelfImportsOnlyAllowedWithin => {
struct_span_err!(resolver.session,
span,
E0429,
"{}",
"`self` imports are only allowed within a { } list")
}
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
let mut err = struct_span_err!(resolver.session, span, E0430,
"`self` import can only appear once in an import list");
err.span_label(span, "can only appear once in an import list");
err
}
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
let mut err = struct_span_err!(resolver.session, span, E0431,
"`self` import can only appear in an import list with \
a non-empty prefix");
err.span_label(span, "can only appear in an import list with a non-empty prefix");
err
}
ResolutionError::FailedToResolve(msg) => {
let mut err = struct_span_err!(resolver.session, span, E0433,
"failed to resolve: {}", msg);
err.span_label(span, msg);
err
}
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
let mut err = struct_span_err!(resolver.session,
span,
E0434,
"{}",
"can't capture dynamic environment in a fn item");
err.help("use the `|| { ... }` closure form instead");
err
}
ResolutionError::AttemptToUseNonConstantValueInConstant => {
let mut err = struct_span_err!(resolver.session, span, E0435,
"attempt to use a non-constant value in a constant");
err.span_label(span, "non-constant value");
err
}
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
let shadows_what = binding.descr();
let mut err = struct_span_err!(resolver.session, span, E0530, "{}s cannot shadow {}s",
what_binding, shadows_what);
err.span_label(span, format!("cannot be named the same as {} {}",
binding.article(), shadows_what));
let participle = if binding.is_import() { "imported" } else { "defined" };
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
err.span_label(binding.span, msg);
err
}
ResolutionError::ForwardDeclaredTyParam => {
let mut err = struct_span_err!(resolver.session, span, E0128,
"type parameters with a default cannot use \
forward declared identifiers");
err.span_label(
span, "defaulted type parameters cannot be forward declared".to_string());
err
}
}
}
/// Adjust the impl span so that just the `impl` keyword is taken by removing
/// everything after `<` (`"impl Iterator for A {}" -> "impl"`) and
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`)
///
/// Attention: The method used is very fragile since it essentially duplicates the work of the
/// parser. If you need to use this function or something similar, please consider updating the
/// source_map functions and this function to something more robust.
fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
let impl_span = cm.span_until_char(impl_span, '<');
let impl_span = cm.span_until_whitespace(impl_span);
impl_span
}
#[derive(Copy, Clone, Debug)]
struct BindingInfo {
span: Span,
binding_mode: BindingMode,
}
/// Map from the name in a pattern to its binding mode.
type BindingMap = FxHashMap;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum PatternSource {
Match,
IfLet,
WhileLet,
Let,
For,
FnParam,
}
impl PatternSource {
fn descr(self) -> &'static str {
match self {
PatternSource::Match => "match binding",
PatternSource::IfLet => "if let binding",
PatternSource::WhileLet => "while let binding",
PatternSource::Let => "let binding",
PatternSource::For => "for binding",
PatternSource::FnParam => "function parameter",
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum AliasPossibility {
No,
Maybe,
}
#[derive(Copy, Clone, Debug)]
enum PathSource<'a> {
// Type paths `Path`.
Type,
// Trait paths in bounds or impls.
Trait(AliasPossibility),
// Expression paths `path`, with optional parent context.
Expr(Option<&'a Expr>),
// Paths in path patterns `Path`.
Pat,
// Paths in struct expressions and patterns `Path { .. }`.
Struct,
// Paths in tuple struct patterns `Path(..)`.
TupleStruct,
// `m::A::B` in `::B::C`.
TraitItem(Namespace),
// Path in `pub(path)`
Visibility,
}
impl<'a> PathSource<'a> {
fn namespace(self) -> Namespace {
match self {
PathSource::Type | PathSource::Trait(_) | PathSource::Struct |
PathSource::Visibility => TypeNS,
PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct => ValueNS,
PathSource::TraitItem(ns) => ns,
}
}
fn global_by_default(self) -> bool {
match self {
PathSource::Visibility => true,
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
PathSource::Struct | PathSource::TupleStruct |
PathSource::Trait(_) | PathSource::TraitItem(..) => false,
}
}
fn defer_to_typeck(self) -> bool {
match self {
PathSource::Type | PathSource::Expr(..) | PathSource::Pat |
PathSource::Struct | PathSource::TupleStruct => true,
PathSource::Trait(_) | PathSource::TraitItem(..) |
PathSource::Visibility => false,
}
}
fn descr_expected(self) -> &'static str {
match self {
PathSource::Type => "type",
PathSource::Trait(_) => "trait",
PathSource::Pat => "unit struct/variant or constant",
PathSource::Struct => "struct, variant or union type",
PathSource::TupleStruct => "tuple struct/variant",
PathSource::Visibility => "module",
PathSource::TraitItem(ns) => match ns {
TypeNS => "associated type",
ValueNS => "method or associated constant",
MacroNS => bug!("associated macro"),
},
PathSource::Expr(parent) => match parent.map(|p| &p.node) {
// "function" here means "anything callable" rather than `Def::Fn`,
// this is not precise but usually more helpful than just "value".
Some(&ExprKind::Call(..)) => "function",
_ => "value",
},
}
}
fn is_expected(self, def: Def) -> bool {
match self {
PathSource::Type => match def {
Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
Def::Trait(..) | Def::TraitAlias(..) | Def::TyAlias(..) |
Def::AssociatedTy(..) | Def::PrimTy(..) | Def::TyParam(..) |
Def::SelfTy(..) | Def::Existential(..) |
Def::ForeignTy(..) => true,
_ => false,
},
PathSource::Trait(AliasPossibility::No) => match def {
Def::Trait(..) => true,
_ => false,
},
PathSource::Trait(AliasPossibility::Maybe) => match def {
Def::Trait(..) => true,
Def::TraitAlias(..) => true,
_ => false,
},
PathSource::Expr(..) => match def {
Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
Def::SelfCtor(..) => true,
_ => false,
},
PathSource::Pat => match def {
Def::StructCtor(_, CtorKind::Const) |
Def::VariantCtor(_, CtorKind::Const) |
Def::Const(..) | Def::AssociatedConst(..) |
Def::SelfCtor(..) => true,
_ => false,
},
PathSource::TupleStruct => match def {
Def::StructCtor(_, CtorKind::Fn) |
Def::VariantCtor(_, CtorKind::Fn) |
Def::SelfCtor(..) => true,
_ => false,
},
PathSource::Struct => match def {
Def::Struct(..) | Def::Union(..) | Def::Variant(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => true,
_ => false,
},
PathSource::TraitItem(ns) => match def {
Def::AssociatedConst(..) | Def::Method(..) if ns == ValueNS => true,
Def::AssociatedTy(..) if ns == TypeNS => true,
_ => false,
},
PathSource::Visibility => match def {
Def::Mod(..) => true,
_ => false,
},
}
}
fn error_code(self, has_unexpected_resolution: bool) -> &'static str {
__diagnostic_used!(E0404);
__diagnostic_used!(E0405);
__diagnostic_used!(E0412);
__diagnostic_used!(E0422);
__diagnostic_used!(E0423);
__diagnostic_used!(E0425);
__diagnostic_used!(E0531);
__diagnostic_used!(E0532);
__diagnostic_used!(E0573);
__diagnostic_used!(E0574);
__diagnostic_used!(E0575);
__diagnostic_used!(E0576);
__diagnostic_used!(E0577);
__diagnostic_used!(E0578);
match (self, has_unexpected_resolution) {
(PathSource::Trait(_), true) => "E0404",
(PathSource::Trait(_), false) => "E0405",
(PathSource::Type, true) => "E0573",
(PathSource::Type, false) => "E0412",
(PathSource::Struct, true) => "E0574",
(PathSource::Struct, false) => "E0422",
(PathSource::Expr(..), true) => "E0423",
(PathSource::Expr(..), false) => "E0425",
(PathSource::Pat, true) | (PathSource::TupleStruct, true) => "E0532",
(PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531",
(PathSource::TraitItem(..), true) => "E0575",
(PathSource::TraitItem(..), false) => "E0576",
(PathSource::Visibility, true) => "E0577",
(PathSource::Visibility, false) => "E0578",
}
}
}
// A minimal representation of a path segment. We use this in resolve because
// we synthesize 'path segments' which don't have the rest of an AST or HIR
// `PathSegment`.
#[derive(Clone, Copy, Debug)]
pub struct Segment {
ident: Ident,
id: Option,
}
impl Segment {
fn from_path(path: &Path) -> Vec {
path.segments.iter().map(|s| s.into()).collect()
}
fn from_ident(ident: Ident) -> Segment {
Segment {
ident,
id: None,
}
}
fn names_to_string(segments: &[Segment]) -> String {
names_to_string(&segments.iter()
.map(|seg| seg.ident)
.collect::>())
}
}
impl<'a> From<&'a ast::PathSegment> for Segment {
fn from(seg: &'a ast::PathSegment) -> Segment {
Segment {
ident: seg.ident,
id: Some(seg.id),
}
}
}
struct UsePlacementFinder {
target_module: NodeId,
span: Option,
found_use: bool,
}
impl UsePlacementFinder {
fn check(krate: &Crate, target_module: NodeId) -> (Option, bool) {
let mut finder = UsePlacementFinder {
target_module,
span: None,
found_use: false,
};
visit::walk_crate(&mut finder, krate);
(finder.span, finder.found_use)
}
}
impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
fn visit_mod(
&mut self,
module: &'tcx ast::Mod,
_: Span,
_: &[ast::Attribute],
node_id: NodeId,
) {
if self.span.is_some() {
return;
}
if node_id != self.target_module {
visit::walk_mod(self, module);
return;
}
// find a use statement
for item in &module.items {
match item.node {
ItemKind::Use(..) => {
// don't suggest placing a use before the prelude
// import or other generated ones
if item.span.ctxt().outer().expn_info().is_none() {
self.span = Some(item.span.shrink_to_lo());
self.found_use = true;
return;
}
},
// don't place use before extern crate
ItemKind::ExternCrate(_) => {}
// but place them before the first other item
_ => if self.span.map_or(true, |span| item.span < span ) {
if item.span.ctxt().outer().expn_info().is_none() {
// don't insert between attributes and an item
if item.attrs.is_empty() {
self.span = Some(item.span.shrink_to_lo());
} else {
// find the first attribute on the item
for attr in &item.attrs {
if self.span.map_or(true, |span| attr.span < span) {
self.span = Some(attr.span.shrink_to_lo());
}
}
}
}
},
}
}
}
}
/// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes.
impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
fn visit_item(&mut self, item: &'tcx Item) {
self.resolve_item(item);
}
fn visit_arm(&mut self, arm: &'tcx Arm) {
self.resolve_arm(arm);
}
fn visit_block(&mut self, block: &'tcx Block) {
self.resolve_block(block);
}
fn visit_anon_const(&mut self, constant: &'tcx ast::AnonConst) {
self.with_constant_rib(|this| {
visit::walk_anon_const(this, constant);
});
}
fn visit_expr(&mut self, expr: &'tcx Expr) {
self.resolve_expr(expr, None);
}
fn visit_local(&mut self, local: &'tcx Local) {
self.resolve_local(local);
}
fn visit_ty(&mut self, ty: &'tcx Ty) {
match ty.node {
TyKind::Path(ref qself, ref path) => {
self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type);
}
TyKind::ImplicitSelf => {
let self_ty = keywords::SelfUpper.ident();
let def = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span)
.map_or(Def::Err, |d| d.def());
self.record_def(ty.id, PathResolution::new(def));
}
_ => (),
}
visit::walk_ty(self, ty);
}
fn visit_poly_trait_ref(&mut self,
tref: &'tcx ast::PolyTraitRef,
m: &'tcx ast::TraitBoundModifier) {
self.smart_resolve_path(tref.trait_ref.ref_id, None,
&tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
visit::walk_poly_trait_ref(self, tref, m);
}
fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
let type_parameters = match foreign_item.node {
ForeignItemKind::Fn(_, ref generics) => {
HasTypeParameters(generics, ItemRibKind)
}
ForeignItemKind::Static(..) => NoTypeParameters,
ForeignItemKind::Ty => NoTypeParameters,
ForeignItemKind::Macro(..) => NoTypeParameters,
};
self.with_type_parameter_rib(type_parameters, |this| {
visit::walk_foreign_item(this, foreign_item);
});
}
fn visit_fn(&mut self,
function_kind: FnKind<'tcx>,
declaration: &'tcx FnDecl,
_: Span,
node_id: NodeId)
{
let (rib_kind, asyncness) = match function_kind {
FnKind::ItemFn(_, ref header, ..) =>
(ItemRibKind, header.asyncness),
FnKind::Method(_, ref sig, _, _) =>
(TraitOrImplItemRibKind, sig.header.asyncness),
FnKind::Closure(_) =>
// Async closures aren't resolved through `visit_fn`-- they're
// processed separately
(ClosureRibKind(node_id), IsAsync::NotAsync),
};
// Create a value rib for the function.
self.ribs[ValueNS].push(Rib::new(rib_kind));
// 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::default();
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, potentially inside the body of an async closure
if let IsAsync::Async { closure_id, .. } = asyncness {
let rib_kind = ClosureRibKind(closure_id);
self.ribs[ValueNS].push(Rib::new(rib_kind));
self.label_ribs.push(Rib::new(rib_kind));
}
match function_kind {
FnKind::ItemFn(.., body) |
FnKind::Method(.., body) => {
self.visit_block(body);
}
FnKind::Closure(body) => {
self.visit_expr(body);
}
};
// Leave the body of the async closure
if asyncness.is_async() {
self.label_ribs.pop();
self.ribs[ValueNS].pop();
}
debug!("(resolving function) leaving function");
self.label_ribs.pop();
self.ribs[ValueNS].pop();
}
fn visit_generics(&mut self, generics: &'tcx Generics) {
// For type parameter defaults, we have to ban access
// to following type parameters, as the Substs can only
// provide previous type parameters as they're built. We
// put all the parameters on the ban list and then remove
// them one by one as they are processed and become available.
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
let mut found_default = false;
default_ban_rib.bindings.extend(generics.params.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref default, .. } => {
found_default |= default.is_some();
if found_default {
Some((Ident::with_empty_ctxt(param.ident.name), Def::Err))
} else {
None
}
}
}));
for param in &generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
GenericParamKind::Type { ref default, .. } => {
for bound in ¶m.bounds {
self.visit_param_bound(bound);
}
if let Some(ref ty) = default {
self.ribs[TypeNS].push(default_ban_rib);
self.visit_ty(ty);
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
}
// Allow all following defaults to refer to this type parameter.
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
}
}
}
for p in &generics.where_clause.predicates {
self.visit_where_predicate(p);
}
}
}
#[derive(Copy, Clone)]
enum TypeParameters<'a, 'b> {
NoTypeParameters,
HasTypeParameters(// Type parameters.
&'b Generics,
// The kind of the rib used for type parameters.
RibKind<'a>),
}
/// The rib kind controls the translation of local
/// definitions (`Def::Local`) to upvars (`Def::Upvar`).
#[derive(Copy, Clone, Debug)]
enum RibKind<'a> {
/// No translation needs to be applied.
NormalRibKind,
/// We passed through a closure scope at the given node ID.
/// Translate upvars as appropriate.
ClosureRibKind(NodeId /* func id */),
/// We passed through an impl or trait and are now in one of its
/// methods or associated types. Allow references to ty params that impl or trait
/// binds. Disallow any other upvars (including other ty params that are
/// upvars).
TraitOrImplItemRibKind,
/// We passed through an item scope. Disallow upvars.
ItemRibKind,
/// We're in a constant item. Can't refer to dynamic stuff.
ConstantItemRibKind,
/// We passed through a module.
ModuleRibKind(Module<'a>),
/// We passed through a `macro_rules!` statement
MacroDefinition(DefId),
/// All bindings in this rib are type parameters that can't be used
/// from the default of a type parameter because they're not declared
/// before said type parameter. Also see the `visit_generics` override.
ForwardTyParamBanRibKind,
}
/// One local scope.
///
/// A rib represents a scope names can live in. Note that these appear in many places, not just
/// around braces. At any place where the list of accessible names (of the given namespace)
/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
/// etc.
///
/// Different [rib kinds](enum.RibKind) are transparent for different names.
///
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
/// resolving, the name is looked up from inside out.
#[derive(Debug)]
struct Rib<'a> {
bindings: FxHashMap,
kind: RibKind<'a>,
}
impl<'a> Rib<'a> {
fn new(kind: RibKind<'a>) -> Rib<'a> {
Rib {
bindings: Default::default(),
kind,
}
}
}
/// An intermediate resolution result.
///
/// This refers to the thing referred by a name. The difference between `Def` and `Item` is that
/// items are visible in their whole block, while defs only from the place they are defined
/// forward.
enum LexicalScopeBinding<'a> {
Item(&'a NameBinding<'a>),
Def(Def),
}
impl<'a> LexicalScopeBinding<'a> {
fn item(self) -> Option<&'a NameBinding<'a>> {
match self {
LexicalScopeBinding::Item(binding) => Some(binding),
_ => None,
}
}
fn def(self) -> Def {
match self {
LexicalScopeBinding::Item(binding) => binding.def(),
LexicalScopeBinding::Def(def) => def,
}
}
}
#[derive(Copy, Clone, Debug)]
enum ModuleOrUniformRoot<'a> {
/// Regular module.
Module(Module<'a>),
/// Virtual module that denotes resolution in crate root with fallback to extern prelude.
CrateRootAndExternPrelude,
/// Virtual module that denotes resolution in extern prelude.
/// Used for paths starting with `::` on 2018 edition or `extern::`.
ExternPrelude,
/// Virtual module that denotes resolution in current scope.
/// Used only for resolving single-segment imports. The reason it exists is that import paths
/// are always split into two parts, the first of which should be some kind of module.
CurrentScope,
}
impl ModuleOrUniformRoot<'_> {
fn same_def(lhs: Self, rhs: Self) -> bool {
match (lhs, rhs) {
(ModuleOrUniformRoot::Module(lhs),
ModuleOrUniformRoot::Module(rhs)) => lhs.def() == rhs.def(),
(ModuleOrUniformRoot::CrateRootAndExternPrelude,
ModuleOrUniformRoot::CrateRootAndExternPrelude) |
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) |
(ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
_ => false,
}
}
}
#[derive(Clone, Debug)]
enum PathResult<'a> {
Module(ModuleOrUniformRoot<'a>),
NonModule(PathResolution),
Indeterminate,
Failed(Span, String, bool /* is the error from the last segment? */),
}
enum ModuleKind {
/// An anonymous module, eg. just a block.
///
/// ```
/// fn main() {
/// fn f() {} // (1)
/// { // This is an anonymous module
/// f(); // This resolves to (2) as we are inside the block.
/// fn f() {} // (2)
/// }
/// f(); // Resolves to (1)
/// }
/// ```
Block(NodeId),
/// Any module with a name.
///
/// This could be:
///
/// * A normal module ‒ either `mod from_file;` or `mod from_block { }`.
/// * A trait or an enum (it implicitly contains associated types, methods and variant
/// constructors).
Def(Def, Name),
}
/// One node in the tree of modules.
pub struct ModuleData<'a> {
parent: Option>,
kind: ModuleKind,
// The def id of the closest normal module (`mod`) ancestor (including this module).
normal_ancestor_id: DefId,
resolutions: RefCell>>>,
single_segment_macro_resolutions: RefCell,
Option<&'a NameBinding<'a>>)>>,
multi_segment_macro_resolutions: RefCell, Span, MacroKind, ParentScope<'a>,
Option)>>,
builtin_attrs: RefCell)>>,
// Macro invocations that can expand into items in this module.
unresolved_invocations: RefCell>,
no_implicit_prelude: bool,
glob_importers: RefCell>>,
globs: RefCell>>,
// Used to memoize the traits in this module for faster searches through all traits in scope.
traits: RefCell