2015-03-15 21:44:19 +00:00
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
2012-12-04 00:48:01 +00:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-12-18 22:46:26 +00:00
|
|
|
#![crate_name = "rustc_resolve"]
|
2015-08-13 17:21:36 +00:00
|
|
|
#![unstable(feature = "rustc_private", issue = "27812")]
|
2014-12-18 22:46:26 +00:00
|
|
|
#![crate_type = "dylib"]
|
|
|
|
#![crate_type = "rlib"]
|
2015-08-09 21:15:05 +00:00
|
|
|
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
2015-05-15 23:04:01 +00:00
|
|
|
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
2015-08-09 21:15:05 +00:00
|
|
|
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
2016-01-21 23:26:19 +00:00
|
|
|
#![cfg_attr(not(stage0), deny(warnings))]
|
2014-12-18 22:46:26 +00:00
|
|
|
|
2015-04-28 23:36:22 +00:00
|
|
|
#![feature(associated_consts)]
|
2015-07-31 16:58:59 +00:00
|
|
|
#![feature(borrow_state)]
|
2015-01-30 20:26:44 +00:00
|
|
|
#![feature(rustc_diagnostic_macros)]
|
2015-01-23 02:22:03 +00:00
|
|
|
#![feature(rustc_private)]
|
2015-01-30 20:26:44 +00:00
|
|
|
#![feature(staged_api)]
|
2014-12-18 22:46:26 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate log;
|
|
|
|
#[macro_use]
|
|
|
|
extern crate syntax;
|
2016-01-11 21:19:29 +00:00
|
|
|
extern crate arena;
|
2015-10-26 19:31:11 +00:00
|
|
|
#[macro_use]
|
|
|
|
#[no_link]
|
|
|
|
extern crate rustc_bitflags;
|
2015-07-31 07:04:06 +00:00
|
|
|
extern crate rustc_front;
|
2014-12-18 22:46:26 +00:00
|
|
|
extern crate rustc;
|
|
|
|
|
2014-11-06 08:05:53 +00:00
|
|
|
use self::PatternBindingMode::*;
|
|
|
|
use self::Namespace::*;
|
|
|
|
use self::ResolveResult::*;
|
|
|
|
use self::FallbackSuggestion::*;
|
|
|
|
use self::TypeParameters::*;
|
|
|
|
use self::RibKind::*;
|
|
|
|
use self::UseLexicalScopeFlag::*;
|
|
|
|
use self::ModulePrefixResult::*;
|
2015-03-25 16:53:28 +00:00
|
|
|
use self::AssocItemResolveResult::*;
|
2014-11-06 08:05:53 +00:00
|
|
|
use self::BareIdentifierPatternResolution::*;
|
|
|
|
use self::ParentLink::*;
|
|
|
|
use self::FallbackChecks::*;
|
|
|
|
|
2015-07-31 07:04:06 +00:00
|
|
|
use rustc::front::map as hir_map;
|
2014-12-18 22:46:26 +00:00
|
|
|
use rustc::session::Session;
|
|
|
|
use rustc::lint;
|
2015-11-24 22:00:26 +00:00
|
|
|
use rustc::middle::cstore::{CrateStore, DefLike, DlDef};
|
2014-12-18 22:46:26 +00:00
|
|
|
use rustc::middle::def::*;
|
2015-08-16 13:06:23 +00:00
|
|
|
use rustc::middle::def_id::DefId;
|
2015-12-01 17:38:40 +00:00
|
|
|
use rustc::middle::pat_util::pat_bindings;
|
2014-12-18 22:46:26 +00:00
|
|
|
use rustc::middle::privacy::*;
|
|
|
|
use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
|
2015-01-24 20:54:52 +00:00
|
|
|
use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
|
2015-08-18 21:54:56 +00:00
|
|
|
use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
|
2012-12-23 22:41:37 +00:00
|
|
|
|
2013-05-22 01:24:42 +00:00
|
|
|
use syntax::ast;
|
2015-12-12 03:29:35 +00:00
|
|
|
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
|
2015-09-14 09:58:20 +00:00
|
|
|
use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
|
2014-08-13 03:31:30 +00:00
|
|
|
use syntax::attr::AttrMetaMethods;
|
2015-02-05 07:19:07 +00:00
|
|
|
use syntax::codemap::{self, Span, Pos};
|
2015-12-20 21:00:43 +00:00
|
|
|
use syntax::errors::DiagnosticBuilder;
|
|
|
|
use syntax::parse::token::{self, special_names, special_idents};
|
2015-12-14 17:06:31 +00:00
|
|
|
use syntax::util::lev_distance::find_best_match_for_name;
|
2015-07-31 07:04:06 +00:00
|
|
|
|
2015-11-17 23:56:13 +00:00
|
|
|
use rustc_front::intravisit::{self, FnKind, Visitor};
|
2015-07-31 07:04:06 +00:00
|
|
|
use rustc_front::hir;
|
|
|
|
use rustc_front::hir::{Arm, BindByRef, BindByValue, BindingMode, Block};
|
2015-11-11 09:37:25 +00:00
|
|
|
use rustc_front::hir::Crate;
|
2015-12-24 19:44:14 +00:00
|
|
|
use rustc_front::hir::{Expr, ExprAgain, ExprBreak, ExprCall, ExprField};
|
2015-07-31 07:04:06 +00:00
|
|
|
use rustc_front::hir::{ExprLoop, ExprWhile, ExprMethodCall};
|
|
|
|
use rustc_front::hir::{ExprPath, ExprStruct, FnDecl};
|
|
|
|
use rustc_front::hir::{ForeignItemFn, ForeignItemStatic, Generics};
|
|
|
|
use rustc_front::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
|
|
|
|
use rustc_front::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
|
|
|
|
use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
|
2015-11-11 09:37:25 +00:00
|
|
|
use rustc_front::hir::Local;
|
2015-07-31 07:04:06 +00:00
|
|
|
use rustc_front::hir::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
|
|
|
|
use rustc_front::hir::{PatRange, PatStruct, Path, PrimTy};
|
2015-09-14 09:58:20 +00:00
|
|
|
use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
|
|
|
|
use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
|
2015-07-31 07:04:06 +00:00
|
|
|
use rustc_front::util::walk_pat;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
use std::collections::{hash_map, HashMap, HashSet};
|
2013-12-21 05:14:25 +00:00
|
|
|
use std::cell::{Cell, RefCell};
|
2014-11-28 02:41:16 +00:00
|
|
|
use std::fmt;
|
2014-01-31 20:35:36 +00:00
|
|
|
use std::mem::replace;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
use resolve_imports::{Target, ImportDirective, ImportResolution};
|
2015-03-15 21:44:19 +00:00
|
|
|
use resolve_imports::Shadowable;
|
|
|
|
|
2015-01-16 23:54:58 +00:00
|
|
|
// NB: This module needs to be declared first so diagnostics are
|
|
|
|
// registered before they are used.
|
|
|
|
pub mod diagnostics;
|
|
|
|
|
2014-12-11 03:46:38 +00:00
|
|
|
mod check_unused;
|
2014-12-30 18:16:42 +00:00
|
|
|
mod build_reduced_graph;
|
2015-03-15 21:44:19 +00:00
|
|
|
mod resolve_imports;
|
2014-12-19 07:13:54 +00:00
|
|
|
|
2015-08-10 06:39:24 +00:00
|
|
|
// Perform the callback, not walking deeper if the return is true
|
|
|
|
macro_rules! execute_callback {
|
|
|
|
($node: expr, $walker: expr) => (
|
|
|
|
if let Some(ref callback) = $walker.callback {
|
|
|
|
if callback($node, &mut $walker.resolved) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2015-11-21 09:37:50 +00:00
|
|
|
enum SuggestionType {
|
|
|
|
Macro(String),
|
2015-12-14 17:06:31 +00:00
|
|
|
Function(token::InternedString),
|
2015-11-21 09:37:50 +00:00
|
|
|
NotFound,
|
|
|
|
}
|
|
|
|
|
2015-07-14 17:42:38 +00:00
|
|
|
pub enum ResolutionError<'a> {
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0401: can't use type parameters from outer function
|
2015-07-14 14:32:43 +00:00
|
|
|
TypeParametersFromOuterFunction,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0402: cannot use an outer type parameter in this context
|
2015-07-14 14:32:43 +00:00
|
|
|
OuterTypeParameterContext,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0403: the name is already used for a type parameter in this type parameter list
|
2015-07-14 17:42:38 +00:00
|
|
|
NameAlreadyUsedInTypeParameterList(Name),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0404: is not a trait
|
2015-07-14 17:42:38 +00:00
|
|
|
IsNotATrait(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0405: use of undeclared trait name
|
2015-07-14 17:42:38 +00:00
|
|
|
UndeclaredTraitName(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0406: undeclared associated type
|
2015-07-14 14:32:43 +00:00
|
|
|
UndeclaredAssociatedType,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0407: method is not a member of trait
|
2015-07-14 17:42:38 +00:00
|
|
|
MethodNotMemberOfTrait(Name, &'a str),
|
2015-07-18 23:56:15 +00:00
|
|
|
/// error E0437: type is not a member of trait
|
|
|
|
TypeNotMemberOfTrait(Name, &'a str),
|
|
|
|
/// error E0438: const is not a member of trait
|
|
|
|
ConstNotMemberOfTrait(Name, &'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0408: variable `{}` from pattern #1 is not bound in pattern
|
2015-07-14 17:42:38 +00:00
|
|
|
VariableNotBoundInPattern(Name, usize),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
|
2015-07-14 17:42:38 +00:00
|
|
|
VariableBoundWithDifferentMode(Name, usize),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0410: variable from pattern is not bound in pattern #1
|
2015-07-14 17:42:38 +00:00
|
|
|
VariableNotBoundInParentPattern(Name, usize),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0411: use of `Self` outside of an impl or trait
|
2015-07-14 14:32:43 +00:00
|
|
|
SelfUsedOutsideImplOrTrait,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0412: use of undeclared
|
2015-07-14 17:42:38 +00:00
|
|
|
UseOfUndeclared(&'a str, &'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0413: declaration shadows an enum variant or unit-like struct in scope
|
2015-07-14 17:42:38 +00:00
|
|
|
DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0414: only irrefutable patterns allowed here
|
2015-11-11 19:16:57 +00:00
|
|
|
OnlyIrrefutablePatternsAllowedHere(DefId, Name),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0415: identifier is bound more than once in this parameter list
|
2015-07-14 17:42:38 +00:00
|
|
|
IdentifierBoundMoreThanOnceInParameterList(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0416: identifier is bound more than once in the same pattern
|
2015-07-14 17:42:38 +00:00
|
|
|
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0417: static variables cannot be referenced in a pattern
|
2015-07-14 14:32:43 +00:00
|
|
|
StaticVariableReference,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0418: is not an enum variant, struct or const
|
2015-07-14 17:42:38 +00:00
|
|
|
NotAnEnumVariantStructOrConst(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0419: unresolved enum variant, struct or const
|
2015-07-14 17:42:38 +00:00
|
|
|
UnresolvedEnumVariantStructOrConst(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0420: is not an associated const
|
2015-07-14 17:42:38 +00:00
|
|
|
NotAnAssociatedConst(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0421: unresolved associated const
|
2015-07-14 17:42:38 +00:00
|
|
|
UnresolvedAssociatedConst(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0422: does not name a struct
|
2015-07-14 17:42:38 +00:00
|
|
|
DoesNotNameAStruct(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0423: is a struct variant name, but this expression uses it like a function name
|
2015-07-14 17:42:38 +00:00
|
|
|
StructVariantUsedAsFunction(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0424: `self` is not available in a static method
|
2015-07-14 14:32:43 +00:00
|
|
|
SelfNotAvailableInStaticMethod,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0425: unresolved name
|
2015-12-10 23:00:17 +00:00
|
|
|
UnresolvedName(&'a str, &'a str, UnresolvedNameContext),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0426: use of undeclared label
|
2015-07-14 17:42:38 +00:00
|
|
|
UndeclaredLabel(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0427: cannot use `ref` binding mode with ...
|
2015-07-14 17:42:38 +00:00
|
|
|
CannotUseRefBindingModeWith(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0428: duplicate definition
|
2015-07-14 17:42:38 +00:00
|
|
|
DuplicateDefinition(&'a str, Name),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0429: `self` imports are only allowed within a { } list
|
2015-07-14 14:32:43 +00:00
|
|
|
SelfImportsOnlyAllowedWithin,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0430: `self` import can only appear once in the list
|
2015-07-14 14:32:43 +00:00
|
|
|
SelfImportCanOnlyAppearOnceInTheList,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0431: `self` import can only appear in an import list with a non-empty prefix
|
2015-07-14 14:32:43 +00:00
|
|
|
SelfImportOnlyInImportListWithNonEmptyPrefix,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0432: unresolved import
|
2015-07-31 08:22:13 +00:00
|
|
|
UnresolvedImport(Option<(&'a str, &'a str)>),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0433: failed to resolve
|
2015-07-14 17:42:38 +00:00
|
|
|
FailedToResolve(&'a str),
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0434: can't capture dynamic environment in a fn item
|
2015-07-14 14:32:43 +00:00
|
|
|
CannotCaptureDynamicEnvironmentInFnItem,
|
2015-07-14 13:37:52 +00:00
|
|
|
/// error E0435: attempt to use a non-constant value in a constant
|
2015-07-14 14:32:43 +00:00
|
|
|
AttemptToUseNonConstantValueInConstant,
|
2015-07-13 00:05:02 +00:00
|
|
|
}
|
|
|
|
|
2015-12-18 16:42:46 +00:00
|
|
|
/// Context of where `ResolutionError::UnresolvedName` arose.
|
2015-12-10 23:00:17 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub enum UnresolvedNameContext {
|
2015-12-18 16:42:46 +00:00
|
|
|
/// `PathIsMod(id)` indicates that a given path, used in
|
|
|
|
/// expression context, actually resolved to a module rather than
|
|
|
|
/// a value. The `id` attached to the variant is the node id of
|
|
|
|
/// the erroneous path expression.
|
2015-12-10 23:00:17 +00:00
|
|
|
PathIsMod(ast::NodeId),
|
2015-12-18 16:42:46 +00: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-10 23:00:17 +00:00
|
|
|
Other,
|
|
|
|
}
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
|
|
|
|
span: syntax::codemap::Span,
|
|
|
|
resolution_error: ResolutionError<'b>) {
|
2015-12-23 06:27:20 +00:00
|
|
|
resolve_struct_error(resolver, span, resolution_error).emit();
|
2015-12-20 21:00:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
|
|
|
|
span: syntax::codemap::Span,
|
|
|
|
resolution_error: ResolutionError<'b>)
|
2015-12-23 06:27:20 +00:00
|
|
|
-> DiagnosticBuilder<'a> {
|
2015-07-14 17:42:38 +00:00
|
|
|
if !resolver.emit_errors {
|
2015-12-23 06:27:20 +00:00
|
|
|
return resolver.session.diagnostic().struct_dummy();
|
2015-07-14 17:42:38 +00:00
|
|
|
}
|
2015-12-20 21:00:43 +00:00
|
|
|
|
2015-12-23 06:27:20 +00:00
|
|
|
match resolution_error {
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::TypeParametersFromOuterFunction => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0401,
|
|
|
|
"can't use type parameters from outer function; try using a local \
|
|
|
|
type parameter instead")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::OuterTypeParameterContext => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0402,
|
|
|
|
"cannot use an outer type parameter in this context")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::NameAlreadyUsedInTypeParameterList(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0403,
|
|
|
|
"the name `{}` is already used for a type parameter in this type \
|
|
|
|
parameter list",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::IsNotATrait(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UndeclaredTraitName(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0405,
|
|
|
|
"use of undeclared trait name `{}`",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UndeclaredAssociatedType => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session, span, E0406, "undeclared associated type")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0407,
|
|
|
|
"method `{}` is not a member of trait `{}`",
|
|
|
|
method,
|
|
|
|
trait_)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-18 23:56:15 +00:00
|
|
|
ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0437,
|
|
|
|
"type `{}` is not a member of trait `{}`",
|
|
|
|
type_,
|
|
|
|
trait_)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-18 23:56:15 +00:00
|
|
|
ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0438,
|
|
|
|
"const `{}` is not a member of trait `{}`",
|
|
|
|
const_,
|
|
|
|
trait_)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0408,
|
|
|
|
"variable `{}` from pattern #1 is not bound in pattern #{}",
|
|
|
|
variable_name,
|
|
|
|
pattern_number)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0409,
|
|
|
|
"variable `{}` is bound with different mode in pattern #{} than in \
|
|
|
|
pattern #1",
|
|
|
|
variable_name,
|
|
|
|
pattern_number)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0410,
|
|
|
|
"variable `{}` from pattern #{} is not bound in pattern #1",
|
|
|
|
variable_name,
|
|
|
|
pattern_number)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::SelfUsedOutsideImplOrTrait => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0411,
|
|
|
|
"use of `Self` outside of an impl or trait")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UseOfUndeclared(kind, name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0412,
|
|
|
|
"use of undeclared {} `{}`",
|
|
|
|
kind,
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0413,
|
|
|
|
"declaration of `{}` shadows an enum variant \
|
|
|
|
or unit-like struct in scope",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-11-11 19:16:57 +00:00
|
|
|
ResolutionError::OnlyIrrefutablePatternsAllowedHere(did, name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0414,
|
|
|
|
"only irrefutable patterns allowed here");
|
|
|
|
err.span_note(span,
|
|
|
|
"there already is a constant in scope sharing the same \
|
|
|
|
name as this pattern");
|
2015-11-11 19:16:57 +00:00
|
|
|
if let Some(sp) = resolver.ast_map.span_if_local(did) {
|
2015-12-20 21:00:43 +00:00
|
|
|
err.span_note(sp, "constant defined here");
|
2015-11-11 19:16:57 +00:00
|
|
|
}
|
2015-11-11 20:38:37 +00:00
|
|
|
if let Some(directive) = resolver.current_module
|
|
|
|
.import_resolutions
|
2015-10-26 19:31:11 +00:00
|
|
|
.borrow()
|
2016-01-14 01:42:45 +00:00
|
|
|
.get(&(name, ValueNS)) {
|
|
|
|
let item = resolver.ast_map.expect_item(directive.id);
|
2015-12-20 21:00:43 +00:00
|
|
|
err.span_note(item.span, "constant imported here");
|
2015-11-11 19:16:57 +00:00
|
|
|
}
|
2015-12-20 21:00:43 +00:00
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0415,
|
|
|
|
"identifier `{}` is bound more than once in this parameter list",
|
|
|
|
identifier)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0416,
|
|
|
|
"identifier `{}` is bound more than once in the same pattern",
|
|
|
|
identifier)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::StaticVariableReference => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0417,
|
|
|
|
"static variables cannot be referenced in a pattern, use a \
|
|
|
|
`const` instead")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::NotAnEnumVariantStructOrConst(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0418,
|
|
|
|
"`{}` is not an enum variant, struct or const",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UnresolvedEnumVariantStructOrConst(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0419,
|
|
|
|
"unresolved enum variant, struct or const `{}`",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::NotAnAssociatedConst(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0420,
|
|
|
|
"`{}` is not an associated const",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UnresolvedAssociatedConst(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0421,
|
|
|
|
"unresolved associated const `{}`",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::DoesNotNameAStruct(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0422,
|
|
|
|
"`{}` does not name a structure",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::StructVariantUsedAsFunction(path_name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0423,
|
|
|
|
"`{}` is the name of a struct or struct variant, but this expression \
|
|
|
|
uses it like a function name",
|
|
|
|
path_name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::SelfNotAvailableInStaticMethod => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0424,
|
|
|
|
"`self` is not available in a static method. Maybe a `self` \
|
|
|
|
argument is missing?")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-12-10 23:00:17 +00:00
|
|
|
ResolutionError::UnresolvedName(path, msg, context) => {
|
2015-12-23 21:54:37 +00:00
|
|
|
let mut err = struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0425,
|
|
|
|
"unresolved name `{}`{}",
|
|
|
|
path,
|
|
|
|
msg);
|
2015-12-10 23:00:17 +00:00
|
|
|
|
|
|
|
match context {
|
2015-12-24 19:44:14 +00:00
|
|
|
UnresolvedNameContext::Other => { } // no help available
|
2015-12-10 23:00:17 +00:00
|
|
|
UnresolvedNameContext::PathIsMod(id) => {
|
|
|
|
let mut help_msg = String::new();
|
|
|
|
let parent_id = resolver.ast_map.get_parent_node(id);
|
|
|
|
if let Some(hir_map::Node::NodeExpr(e)) = resolver.ast_map.find(parent_id) {
|
|
|
|
match e.node {
|
|
|
|
ExprField(_, ident) => {
|
|
|
|
help_msg = format!("To reference an item from the \
|
|
|
|
`{module}` module, use \
|
|
|
|
`{module}::{ident}`",
|
|
|
|
module = &*path,
|
|
|
|
ident = ident.node);
|
|
|
|
}
|
|
|
|
ExprMethodCall(ident, _, _) => {
|
|
|
|
help_msg = format!("To call a function from the \
|
|
|
|
`{module}` module, use \
|
|
|
|
`{module}::{ident}(..)`",
|
|
|
|
module = &*path,
|
|
|
|
ident = ident.node);
|
|
|
|
}
|
2015-12-24 19:44:14 +00:00
|
|
|
ExprCall(_, _) => {
|
|
|
|
help_msg = format!("No function corresponds to `{module}(..)`",
|
|
|
|
module = &*path);
|
|
|
|
}
|
|
|
|
_ => { } // no help available
|
2015-12-10 23:00:17 +00:00
|
|
|
}
|
2015-12-24 19:44:14 +00:00
|
|
|
} else {
|
|
|
|
help_msg = format!("Module `{module}` cannot be the value of an expression",
|
|
|
|
module = &*path);
|
2015-12-10 23:00:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !help_msg.is_empty() {
|
2015-12-20 21:00:43 +00:00
|
|
|
err.fileline_help(span, &help_msg);
|
2015-12-10 23:00:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-12-20 21:00:43 +00:00
|
|
|
err
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UndeclaredLabel(name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0426,
|
|
|
|
"use of undeclared label `{}`",
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::CannotUseRefBindingModeWith(descr) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0427,
|
|
|
|
"cannot use `ref` binding mode with {}",
|
|
|
|
descr)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::DuplicateDefinition(namespace, name) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0428,
|
|
|
|
"duplicate definition of {} `{}`",
|
|
|
|
namespace,
|
|
|
|
name)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0429,
|
|
|
|
"{}",
|
|
|
|
"`self` imports are only allowed within a { } list")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0430,
|
|
|
|
"`self` import can only appear once in the list")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
|
2015-12-20 21:00:43 +00: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 13:37:52 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UnresolvedImport(name) => {
|
2015-07-14 13:37:52 +00:00
|
|
|
let msg = match name {
|
2015-07-31 08:22:13 +00:00
|
|
|
Some((n, p)) => format!("unresolved import `{}`{}", n, p),
|
2015-10-26 19:31:11 +00:00
|
|
|
None => "unresolved import".to_owned(),
|
2015-07-14 13:37:52 +00:00
|
|
|
};
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session, span, E0432, "{}", msg)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::FailedToResolve(msg) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
|
2015-12-20 21:00:43 +00: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 19:31:11 +00:00
|
|
|
}
|
|
|
|
ResolutionError::AttemptToUseNonConstantValueInConstant => {
|
2015-12-20 21:00:43 +00:00
|
|
|
struct_span_err!(resolver.session,
|
|
|
|
span,
|
|
|
|
E0435,
|
|
|
|
"attempt to use a non-constant value in a constant")
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-12-23 06:27:20 +00:00
|
|
|
}
|
2015-07-13 00:05:02 +00:00
|
|
|
}
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2014-12-18 17:17:41 +00:00
|
|
|
struct BindingInfo {
|
2013-08-31 16:13:04 +00:00
|
|
|
span: Span,
|
2013-09-02 01:45:37 +00:00
|
|
|
binding_mode: BindingMode,
|
2012-08-06 14:20:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Map from the name in a pattern to its binding mode.
|
2014-12-18 17:17:41 +00:00
|
|
|
type BindingMap = HashMap<Name, BindingInfo>;
|
2012-08-06 14:20:23 +00:00
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2013-10-02 12:33:01 +00:00
|
|
|
enum PatternBindingMode {
|
2012-05-22 17:54:12 +00:00
|
|
|
RefutableMode,
|
2012-11-07 02:41:06 +00:00
|
|
|
LocalIrrefutableMode,
|
2013-04-24 08:29:46 +00:00
|
|
|
ArgumentIrrefutableMode,
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
2015-05-14 11:40:16 +00:00
|
|
|
pub enum Namespace {
|
2012-05-22 17:54:12 +00:00
|
|
|
TypeNS,
|
2015-10-26 19:31:11 +00:00
|
|
|
ValueNS,
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 09:29:41 +00:00
|
|
|
impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
|
2015-11-17 23:56:13 +00:00
|
|
|
fn visit_nested_item(&mut self, item: hir::ItemId) {
|
|
|
|
self.visit_item(self.ast_map.expect_item(item.id))
|
|
|
|
}
|
2014-09-12 10:10:30 +00:00
|
|
|
fn visit_item(&mut self, item: &Item) {
|
2015-07-31 07:04:06 +00:00
|
|
|
execute_callback!(hir_map::Node::NodeItem(item), self);
|
2013-09-27 02:10:16 +00:00
|
|
|
self.resolve_item(item);
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2014-09-12 10:10:30 +00:00
|
|
|
fn visit_arm(&mut self, arm: &Arm) {
|
2013-09-27 02:10:16 +00:00
|
|
|
self.resolve_arm(arm);
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2014-09-12 10:10:30 +00:00
|
|
|
fn visit_block(&mut self, block: &Block) {
|
2015-07-31 07:04:06 +00:00
|
|
|
execute_callback!(hir_map::Node::NodeBlock(block), self);
|
2013-09-27 02:10:16 +00:00
|
|
|
self.resolve_block(block);
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2014-09-12 10:10:30 +00:00
|
|
|
fn visit_expr(&mut self, expr: &Expr) {
|
2015-07-31 07:04:06 +00:00
|
|
|
execute_callback!(hir_map::Node::NodeExpr(expr), self);
|
2013-09-27 02:10:16 +00:00
|
|
|
self.resolve_expr(expr);
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2014-09-12 10:10:30 +00:00
|
|
|
fn visit_local(&mut self, local: &Local) {
|
2015-07-31 07:04:06 +00:00
|
|
|
execute_callback!(hir_map::Node::NodeLocal(&*local.pat), self);
|
2013-09-27 02:10:16 +00:00
|
|
|
self.resolve_local(local);
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2014-09-12 10:10:30 +00:00
|
|
|
fn visit_ty(&mut self, ty: &Ty) {
|
2013-09-27 02:10:16 +00:00
|
|
|
self.resolve_type(ty);
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2015-02-05 07:19:07 +00:00
|
|
|
fn visit_generics(&mut self, generics: &Generics) {
|
|
|
|
self.resolve_generics(generics);
|
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBoundModifier) {
|
2015-02-05 07:19:07 +00:00
|
|
|
match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
|
|
|
|
Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
|
2015-10-26 19:31:11 +00:00
|
|
|
Err(_) => {
|
|
|
|
// error already reported
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(tref.trait_ref.ref_id, err_path_resolution())
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_poly_trait_ref(self, tref, m);
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
fn visit_variant(&mut self,
|
|
|
|
variant: &hir::Variant,
|
|
|
|
generics: &Generics,
|
|
|
|
item_id: ast::NodeId) {
|
2015-07-31 07:04:06 +00:00
|
|
|
execute_callback!(hir_map::Node::NodeVariant(variant), self);
|
2015-02-05 07:19:07 +00: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 23:56:13 +00:00
|
|
|
this.visit_expr(dis_expr);
|
2015-02-05 07:19:07 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:56:13 +00:00
|
|
|
// `intravisit::walk_variant` without the discriminant expression.
|
2015-10-26 19:31:11 +00:00
|
|
|
self.visit_variant_data(&variant.node.data,
|
|
|
|
variant.node.name,
|
|
|
|
generics,
|
|
|
|
item_id,
|
|
|
|
variant.span);
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
|
|
|
|
execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self);
|
2015-02-05 07:19:07 +00:00
|
|
|
let type_parameters = match foreign_item.node {
|
|
|
|
ForeignItemFn(_, ref generics) => {
|
|
|
|
HasTypeParameters(generics, FnSpace, ItemRibKind)
|
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
ForeignItemStatic(..) => NoTypeParameters,
|
2015-02-05 07:19:07 +00:00
|
|
|
};
|
|
|
|
self.with_type_parameter_rib(type_parameters, |this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_foreign_item(this, foreign_item);
|
2015-02-05 07:19:07 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
fn visit_fn(&mut self,
|
2015-08-26 10:00:14 +00:00
|
|
|
function_kind: FnKind<'v>,
|
2015-02-05 07:19:07 +00:00
|
|
|
declaration: &'v FnDecl,
|
|
|
|
block: &'v Block,
|
|
|
|
_: Span,
|
|
|
|
node_id: NodeId) {
|
|
|
|
let rib_kind = match function_kind {
|
2015-08-26 10:00:14 +00:00
|
|
|
FnKind::ItemFn(_, generics, _, _, _, _) => {
|
2015-02-05 07:19:07 +00:00
|
|
|
self.visit_generics(generics);
|
|
|
|
ItemRibKind
|
|
|
|
}
|
2015-08-26 10:00:14 +00:00
|
|
|
FnKind::Method(_, sig, _) => {
|
2015-03-11 21:38:58 +00:00
|
|
|
self.visit_generics(&sig.generics);
|
|
|
|
self.visit_explicit_self(&sig.explicit_self);
|
2015-02-05 07:19:07 +00:00
|
|
|
MethodRibKind
|
|
|
|
}
|
2015-10-26 18:10:41 +00:00
|
|
|
FnKind::Closure => ClosureRibKind(node_id),
|
2015-02-05 07:19:07 +00:00
|
|
|
};
|
|
|
|
self.resolve_function(rib_kind, declaration, block);
|
|
|
|
}
|
2013-08-13 16:52:41 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2014-06-05 21:37:52 +00:00
|
|
|
type ErrorMessage = Option<(Span, String)>;
|
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq)]
|
2013-10-02 12:33:01 +00:00
|
|
|
enum ResolveResult<T> {
|
2015-10-26 19:31:11 +00:00
|
|
|
Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
|
|
|
|
Indeterminate, // Couldn't determine due to unresolved globs.
|
|
|
|
Success(T), // Successfully resolved the import.
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-05-31 22:17:22 +00:00
|
|
|
impl<T> ResolveResult<T> {
|
2015-07-31 16:58:59 +00:00
|
|
|
fn success(&self) -> bool {
|
2015-10-26 19:31:11 +00:00
|
|
|
match *self {
|
|
|
|
Success(_) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
2012-09-08 01:53:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-08 21:35:09 +00:00
|
|
|
enum FallbackSuggestion {
|
|
|
|
NoSuggestion,
|
|
|
|
Field,
|
|
|
|
Method,
|
2014-08-04 20:56:56 +00:00
|
|
|
TraitItem,
|
2014-05-22 23:57:53 +00:00
|
|
|
StaticMethod(String),
|
2014-10-15 00:33:20 +00:00
|
|
|
TraitMethod(String),
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2016-01-22 09:55:29 +00:00
|
|
|
enum TypeParameters<'tcx, 'a> {
|
2014-05-31 22:53:13 +00:00
|
|
|
NoTypeParameters,
|
2015-10-26 19:31:11 +00:00
|
|
|
HasTypeParameters(// Type parameters.
|
|
|
|
&'a Generics,
|
2014-05-31 22:53:13 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
// Identifies the things that these parameters
|
|
|
|
// were declared on (type, fn, etc)
|
|
|
|
ParamSpace,
|
2014-05-31 22:53:13 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
// The kind of the rib used for type parameters.
|
2016-01-22 09:55:29 +00:00
|
|
|
RibKind<'tcx>),
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 14:28:19 +00:00
|
|
|
// The rib kind controls the translation of local
|
2016-01-20 19:31:10 +00:00
|
|
|
// definitions (`Def::Local`) to upvars (`Def::Upvar`).
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
2016-01-22 09:55:29 +00:00
|
|
|
enum RibKind<'a> {
|
2012-05-22 17:54:12 +00:00
|
|
|
// No translation needs to be applied.
|
|
|
|
NormalRibKind,
|
2012-07-07 02:06:58 +00:00
|
|
|
|
2014-09-14 21:40:45 +00:00
|
|
|
// We passed through a closure scope at the given node ID.
|
|
|
|
// Translate upvars as appropriate.
|
2015-01-24 20:04:41 +00:00
|
|
|
ClosureRibKind(NodeId /* func id */),
|
2012-07-07 02:06:58 +00:00
|
|
|
|
2012-12-10 21:47:54 +00:00
|
|
|
// We passed through an impl or trait and are now in one of its
|
2013-06-06 07:38:41 +00:00
|
|
|
// methods. Allow references to ty params that impl or trait
|
2012-07-26 21:04:03 +00:00
|
|
|
// binds. Disallow any other upvars (including other ty params that are
|
|
|
|
// upvars).
|
2015-02-05 07:19:07 +00:00
|
|
|
MethodRibKind,
|
2012-07-26 21:04:03 +00:00
|
|
|
|
2014-05-31 05:54:04 +00:00
|
|
|
// We passed through an item scope. Disallow upvars.
|
|
|
|
ItemRibKind,
|
2012-10-15 19:27:09 +00:00
|
|
|
|
|
|
|
// We're in a constant item. Can't refer to dynamic stuff.
|
2015-10-26 19:31:11 +00:00
|
|
|
ConstantItemRibKind,
|
2016-01-22 09:55:29 +00:00
|
|
|
|
|
|
|
// We passed through an anonymous module.
|
|
|
|
AnonymousModuleRibKind(Module<'a>),
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2013-10-02 12:33:01 +00:00
|
|
|
enum UseLexicalScopeFlag {
|
2012-12-13 21:05:22 +00:00
|
|
|
DontUseLexicalScope,
|
2015-10-26 19:31:11 +00:00
|
|
|
UseLexicalScope,
|
2012-12-13 21:05:22 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
enum ModulePrefixResult<'a> {
|
2012-12-23 22:41:37 +00:00
|
|
|
NoPrefixFound,
|
2016-01-11 21:19:29 +00:00
|
|
|
PrefixFound(Module<'a>, usize),
|
2012-12-13 21:05:22 +00:00
|
|
|
}
|
|
|
|
|
2015-03-25 16:53:28 +00:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
enum AssocItemResolveResult {
|
|
|
|
/// Syntax such as `<T>::item`, which can't be resolved until type
|
|
|
|
/// checking.
|
|
|
|
TypecheckRequired,
|
|
|
|
/// We should have been able to resolve the associated item.
|
|
|
|
ResolveAttempt(Option<PathResolution>),
|
|
|
|
}
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2013-10-02 12:33:01 +00:00
|
|
|
enum BareIdentifierPatternResolution {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
FoundStructOrEnumVariant(Def, LastPrivate),
|
2015-11-11 19:16:57 +00:00
|
|
|
FoundConst(Def, LastPrivate, Name),
|
2015-10-26 19:31:11 +00:00
|
|
|
BareIdentifierPatternUnresolved,
|
2012-07-07 02:06:58 +00:00
|
|
|
}
|
|
|
|
|
2012-08-15 02:20:56 +00:00
|
|
|
/// One local scope.
|
2015-01-28 13:34:18 +00:00
|
|
|
#[derive(Debug)]
|
2016-01-22 09:55:29 +00:00
|
|
|
struct Rib<'a> {
|
2014-09-29 23:06:13 +00:00
|
|
|
bindings: HashMap<Name, DefLike>,
|
2016-01-22 09:55:29 +00:00
|
|
|
kind: RibKind<'a>,
|
2012-09-05 22:58:43 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
impl<'a> Rib<'a> {
|
|
|
|
fn new(kind: RibKind<'a>) -> Rib<'a> {
|
2013-08-31 16:13:04 +00:00
|
|
|
Rib {
|
2014-09-29 23:06:13 +00:00
|
|
|
bindings: HashMap::new(),
|
2015-10-26 19:31:11 +00:00
|
|
|
kind: kind,
|
2013-08-31 16:13:04 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-03 18:44:23 +00:00
|
|
|
/// A definition along with the index of the rib it was found on
|
|
|
|
struct LocalDef {
|
|
|
|
ribs: Option<(Namespace, usize)>,
|
2015-10-26 19:31:11 +00:00
|
|
|
def: Def,
|
2015-11-03 18:44:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LocalDef {
|
|
|
|
fn from_def(def: Def) -> Self {
|
|
|
|
LocalDef {
|
|
|
|
ribs: None,
|
2015-10-26 19:31:11 +00:00
|
|
|
def: def,
|
2015-11-03 18:44:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
/// The link from a module up to its nearest parent node.
|
2015-01-28 13:34:18 +00:00
|
|
|
#[derive(Clone,Debug)]
|
2016-01-11 21:19:29 +00:00
|
|
|
enum ParentLink<'a> {
|
2012-05-22 17:54:12 +00:00
|
|
|
NoParentLink,
|
2016-01-11 21:19:29 +00:00
|
|
|
ModuleParentLink(Module<'a>, Name),
|
|
|
|
BlockParentLink(Module<'a>, NodeId),
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
/// One node in the tree of modules.
|
2016-01-11 21:19:29 +00:00
|
|
|
pub struct ModuleS<'a> {
|
|
|
|
parent_link: ParentLink<'a>,
|
2015-11-16 07:59:50 +00:00
|
|
|
def: Cell<Option<Def>>,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
is_public: bool,
|
2016-01-29 22:21:36 +00:00
|
|
|
is_extern_crate: bool,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
children: RefCell<HashMap<(Name, Namespace), NameBinding<'a>>>,
|
2014-04-14 08:30:59 +00:00
|
|
|
imports: RefCell<Vec<ImportDirective>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The anonymous children of this node. Anonymous children 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-01-11 21:19:29 +00:00
|
|
|
anonymous_children: RefCell<NodeMap<Module<'a>>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The status of resolving each import in this module.
|
2016-01-14 01:42:45 +00:00
|
|
|
import_resolutions: RefCell<HashMap<(Name, Namespace), ImportResolution<'a>>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The number of unresolved globs that this module exports.
|
2015-03-26 00:06:52 +00:00
|
|
|
glob_count: Cell<usize>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-08-05 19:47:01 +00:00
|
|
|
// The number of unresolved pub imports (both regular and globs) in this module
|
|
|
|
pub_count: Cell<usize>,
|
|
|
|
|
|
|
|
// The number of unresolved pub glob imports in this module
|
|
|
|
pub_glob_count: Cell<usize>,
|
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
// The index of the import we're resolving.
|
2015-03-26 00:06:52 +00:00
|
|
|
resolved_import_count: Cell<usize>,
|
2013-08-22 01:39:30 +00:00
|
|
|
|
|
|
|
// Whether this module is populated. If not populated, any attempt to
|
|
|
|
// access the children must be preceded with a
|
|
|
|
// `populate_module_if_necessary` call.
|
2013-12-20 02:53:59 +00:00
|
|
|
populated: Cell<bool>,
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
pub type Module<'a> = &'a ModuleS<'a>;
|
|
|
|
|
|
|
|
impl<'a> ModuleS<'a> {
|
|
|
|
fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool, is_public: bool) -> Self {
|
|
|
|
ModuleS {
|
2013-08-31 16:13:04 +00:00
|
|
|
parent_link: parent_link,
|
2015-11-16 07:59:50 +00:00
|
|
|
def: Cell::new(def),
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
is_public: is_public,
|
2016-01-29 22:21:36 +00:00
|
|
|
is_extern_crate: false,
|
2013-12-21 23:32:44 +00:00
|
|
|
children: RefCell::new(HashMap::new()),
|
2014-03-04 18:02:49 +00:00
|
|
|
imports: RefCell::new(Vec::new()),
|
2015-01-16 22:27:43 +00:00
|
|
|
anonymous_children: RefCell::new(NodeMap()),
|
2013-12-21 23:15:54 +00:00
|
|
|
import_resolutions: RefCell::new(HashMap::new()),
|
2013-12-20 02:59:03 +00:00
|
|
|
glob_count: Cell::new(0),
|
2015-08-05 19:47:01 +00:00
|
|
|
pub_count: Cell::new(0),
|
|
|
|
pub_glob_count: Cell::new(0),
|
2013-12-20 03:01:02 +00:00
|
|
|
resolved_import_count: Cell::new(0),
|
2013-12-20 02:53:59 +00:00
|
|
|
populated: Cell::new(!external),
|
2016-01-11 21:19:29 +00:00
|
|
|
}
|
2012-09-05 22:58:43 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
fn get_child(&self, name: Name, ns: Namespace) -> Option<NameBinding<'a>> {
|
|
|
|
self.children.borrow().get(&(name, ns)).cloned()
|
|
|
|
}
|
|
|
|
|
2016-01-29 22:21:36 +00:00
|
|
|
// If the name is not yet defined, define the name and return None.
|
|
|
|
// Otherwise, return the existing definition.
|
|
|
|
fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>)
|
|
|
|
-> Option<NameBinding<'a>> {
|
2016-01-14 01:42:45 +00:00
|
|
|
match self.children.borrow_mut().entry((name, ns)) {
|
2016-01-29 22:21:36 +00:00
|
|
|
hash_map::Entry::Vacant(entry) => { entry.insert(binding); None }
|
|
|
|
hash_map::Entry::Occupied(entry) => { Some(entry.get().clone()) },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn for_each_local_child<F: FnMut(Name, Namespace, &NameBinding<'a>)>(&self, mut f: F) {
|
|
|
|
for (&(name, ns), name_binding) in self.children.borrow().iter() {
|
|
|
|
if !name_binding.is_extern_crate() {
|
|
|
|
f(name, ns, name_binding)
|
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-16 07:59:50 +00:00
|
|
|
fn def_id(&self) -> Option<DefId> {
|
|
|
|
self.def.get().as_ref().map(Def::def_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_normal(&self) -> bool {
|
|
|
|
match self.def.get() {
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Mod(_)) | Some(Def::ForeignMod(_)) => true,
|
2015-11-16 07:59:50 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_trait(&self) -> bool {
|
|
|
|
match self.def.get() {
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Trait(_)) => true,
|
2015-11-16 07:59:50 +00:00
|
|
|
_ => false,
|
2013-08-31 16:13:04 +00:00
|
|
|
}
|
2012-09-05 22:58:43 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn all_imports_resolved(&self) -> bool {
|
2015-07-31 16:58:59 +00:00
|
|
|
if self.imports.borrow_state() == ::std::cell::BorrowState::Writing {
|
|
|
|
// it is currently being resolved ! so nope
|
|
|
|
false
|
|
|
|
} else {
|
|
|
|
self.imports.borrow().len() == self.resolved_import_count.get()
|
|
|
|
}
|
2012-09-08 02:04:40 +00:00
|
|
|
}
|
|
|
|
|
2015-08-06 10:47:10 +00:00
|
|
|
pub fn inc_glob_count(&self) {
|
|
|
|
self.glob_count.set(self.glob_count.get() + 1);
|
|
|
|
}
|
|
|
|
pub fn dec_glob_count(&self) {
|
|
|
|
assert!(self.glob_count.get() > 0);
|
|
|
|
self.glob_count.set(self.glob_count.get() - 1);
|
|
|
|
}
|
|
|
|
pub fn inc_pub_count(&self) {
|
|
|
|
self.pub_count.set(self.pub_count.get() + 1);
|
|
|
|
}
|
|
|
|
pub fn dec_pub_count(&self) {
|
|
|
|
assert!(self.pub_count.get() > 0);
|
|
|
|
self.pub_count.set(self.pub_count.get() - 1);
|
|
|
|
}
|
|
|
|
pub fn inc_pub_glob_count(&self) {
|
|
|
|
self.pub_glob_count.set(self.pub_glob_count.get() + 1);
|
|
|
|
}
|
|
|
|
pub fn dec_pub_glob_count(&self) {
|
|
|
|
assert!(self.pub_glob_count.get() > 0);
|
|
|
|
self.pub_glob_count.set(self.pub_glob_count.get() - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
impl<'a> fmt::Debug for ModuleS<'a> {
|
2014-11-28 02:41:16 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2015-10-26 19:31:11 +00:00
|
|
|
write!(f,
|
2015-11-16 07:59:50 +00:00
|
|
|
"{:?}, {}",
|
|
|
|
self.def,
|
2015-10-26 19:31:11 +00:00
|
|
|
if self.is_public {
|
|
|
|
"public"
|
|
|
|
} else {
|
|
|
|
"private"
|
|
|
|
})
|
2014-11-28 02:41:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-19 06:46:08 +00:00
|
|
|
bitflags! {
|
2015-01-28 13:34:18 +00:00
|
|
|
#[derive(Debug)]
|
2014-10-19 06:46:08 +00:00
|
|
|
flags DefModifiers: u8 {
|
2015-12-04 18:51:18 +00:00
|
|
|
// Enum variants are always considered `PUBLIC`, this is needed for `use Enum::Variant`
|
|
|
|
// or `use Enum::*` to work on private enums.
|
2015-04-28 23:36:22 +00:00
|
|
|
const PUBLIC = 1 << 0,
|
|
|
|
const IMPORTABLE = 1 << 1,
|
2015-12-04 18:51:18 +00:00
|
|
|
// Variants are considered `PUBLIC`, but some of them live in private enums.
|
2015-11-24 00:36:12 +00:00
|
|
|
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
|
|
|
|
const PRIVATE_VARIANT = 1 << 2,
|
2014-10-19 06:46:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 09:10:41 +00:00
|
|
|
// Records a possibly-private value, type, or module definition.
|
2016-01-14 01:42:45 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct NameBinding<'a> {
|
|
|
|
modifiers: DefModifiers, // see note in ImportResolution about how to use this
|
2016-01-11 21:19:29 +00:00
|
|
|
def_or_module: DefOrModule<'a>,
|
2015-11-16 02:10:09 +00:00
|
|
|
span: Option<Span>,
|
2012-08-18 00:55:34 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2016-01-11 21:19:29 +00:00
|
|
|
enum DefOrModule<'a> {
|
2015-11-17 09:10:41 +00:00
|
|
|
Def(Def),
|
2016-01-11 21:19:29 +00:00
|
|
|
Module(Module<'a>),
|
2012-09-08 02:04:40 +00:00
|
|
|
}
|
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
impl<'a> NameBinding<'a> {
|
2016-01-11 21:19:29 +00:00
|
|
|
fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
|
2015-11-16 07:59:50 +00:00
|
|
|
let modifiers = if module.is_public {
|
2015-04-28 23:36:22 +00:00
|
|
|
DefModifiers::PUBLIC
|
|
|
|
} else {
|
|
|
|
DefModifiers::empty()
|
|
|
|
} | DefModifiers::IMPORTABLE;
|
2015-11-16 07:59:50 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
NameBinding { modifiers: modifiers, def_or_module: DefOrModule::Module(module), span: span }
|
2015-11-17 09:10:41 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
fn module(&self) -> Option<Module<'a>> {
|
2015-11-17 09:10:41 +00:00
|
|
|
match self.def_or_module {
|
2016-01-11 21:19:29 +00:00
|
|
|
DefOrModule::Module(ref module) => Some(module),
|
2015-11-17 09:10:41 +00:00
|
|
|
DefOrModule::Def(_) => None,
|
2013-05-13 23:13:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-16 02:10:09 +00:00
|
|
|
fn def(&self) -> Option<Def> {
|
2015-11-17 09:10:41 +00:00
|
|
|
match self.def_or_module {
|
|
|
|
DefOrModule::Def(def) => Some(def),
|
|
|
|
DefOrModule::Module(ref module) => module.def.get(),
|
2012-10-16 01:04:15 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-10-15 21:56:42 +00:00
|
|
|
|
2015-11-16 02:10:09 +00:00
|
|
|
fn defined_with(&self, modifiers: DefModifiers) -> bool {
|
2016-01-14 01:42:45 +00:00
|
|
|
self.modifiers.contains(modifiers)
|
2015-11-16 02:10:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn is_public(&self) -> bool {
|
|
|
|
self.defined_with(DefModifiers::PUBLIC)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn def_and_lp(&self) -> (Def, LastPrivate) {
|
|
|
|
let def = self.def().unwrap();
|
|
|
|
(def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) }))
|
|
|
|
}
|
2016-01-29 22:21:36 +00:00
|
|
|
|
|
|
|
fn is_extern_crate(&self) -> bool {
|
|
|
|
self.module().map(|module| module.is_extern_crate).unwrap_or(false)
|
|
|
|
}
|
2012-08-18 00:55:34 +00:00
|
|
|
}
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
/// Interns the names of the primitive types.
|
2013-10-02 12:33:01 +00:00
|
|
|
struct PrimitiveTypeTable {
|
2014-01-09 13:05:33 +00:00
|
|
|
primitive_types: HashMap<Name, PrimTy>,
|
2012-09-08 02:04:40 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2013-05-31 22:17:22 +00:00
|
|
|
impl PrimitiveTypeTable {
|
2014-05-28 19:36:05 +00:00
|
|
|
fn new() -> PrimitiveTypeTable {
|
2015-10-26 19:31:11 +00:00
|
|
|
let mut table = PrimitiveTypeTable { primitive_types: HashMap::new() };
|
|
|
|
|
|
|
|
table.intern("bool", TyBool);
|
|
|
|
table.intern("char", TyChar);
|
|
|
|
table.intern("f32", TyFloat(TyF32));
|
|
|
|
table.intern("f64", TyFloat(TyF64));
|
|
|
|
table.intern("isize", TyInt(TyIs));
|
|
|
|
table.intern("i8", TyInt(TyI8));
|
|
|
|
table.intern("i16", TyInt(TyI16));
|
|
|
|
table.intern("i32", TyInt(TyI32));
|
|
|
|
table.intern("i64", TyInt(TyI64));
|
|
|
|
table.intern("str", TyStr);
|
|
|
|
table.intern("usize", TyUint(TyUs));
|
|
|
|
table.intern("u8", TyUint(TyU8));
|
|
|
|
table.intern("u16", TyUint(TyU16));
|
|
|
|
table.intern("u32", TyUint(TyU32));
|
|
|
|
table.intern("u64", TyUint(TyU64));
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
|
|
table
|
|
|
|
}
|
|
|
|
|
2014-01-09 13:05:33 +00:00
|
|
|
fn intern(&mut self, string: &str, primitive_type: PrimTy) {
|
2013-06-26 22:56:13 +00:00
|
|
|
self.primitive_types.insert(token::intern(string), primitive_type);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
/// The main resolver class.
|
2015-10-26 19:31:11 +00:00
|
|
|
pub struct Resolver<'a, 'tcx: 'a> {
|
2014-03-05 14:36:01 +00:00
|
|
|
session: &'a Session,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-07-31 07:04:06 +00:00
|
|
|
ast_map: &'a hir_map::Map<'tcx>,
|
2014-11-23 09:29:41 +00:00
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
graph_root: Module<'a>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-02-11 07:32:25 +00:00
|
|
|
trait_item_map: FnvHashMap<(Name, DefId), DefId>,
|
2014-05-06 23:37:32 +00:00
|
|
|
|
2014-05-08 21:35:09 +00:00
|
|
|
structs: FnvHashMap<DefId, Vec<Name>>,
|
2012-07-11 22:00:40 +00:00
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
// The number of imports that are currently unresolved.
|
2015-03-26 00:06:52 +00:00
|
|
|
unresolved_imports: usize,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The module that represents the current item scope.
|
2016-01-11 21:19:29 +00:00
|
|
|
current_module: Module<'a>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The current set of local scopes, for values.
|
2013-02-15 02:37:25 +00:00
|
|
|
// FIXME #4948: Reuse ribs to avoid allocation.
|
2016-01-22 09:55:29 +00:00
|
|
|
value_ribs: Vec<Rib<'a>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The current set of local scopes, for types.
|
2016-01-22 09:55:29 +00:00
|
|
|
type_ribs: Vec<Rib<'a>>,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2012-08-15 02:20:56 +00:00
|
|
|
// The current set of local scopes, for labels.
|
2016-01-22 09:55:29 +00:00
|
|
|
label_ribs: Vec<Rib<'a>>,
|
2012-08-15 02:20:56 +00:00
|
|
|
|
2012-07-11 22:00:40 +00:00
|
|
|
// The trait that the current context can refer to.
|
2014-05-08 21:35:09 +00: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 22:00:40 +00:00
|
|
|
|
2012-09-20 01:52:49 +00:00
|
|
|
// The idents for the primitive types.
|
2014-04-14 08:30:59 +00:00
|
|
|
primitive_type_table: PrimitiveTypeTable,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-11-04 06:02:22 +00:00
|
|
|
def_map: RefCell<DefMap>,
|
2015-11-04 05:12:37 +00:00
|
|
|
freevars: FreevarMap,
|
|
|
|
freevars_seen: NodeMap<NodeMap<usize>>,
|
2014-12-18 18:27:17 +00:00
|
|
|
export_map: ExportMap,
|
2012-09-07 02:40:15 +00:00
|
|
|
trait_map: TraitMap,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
external_exports: ExternalExports,
|
2013-04-30 05:15:17 +00:00
|
|
|
|
2013-08-14 00:54:14 +00:00
|
|
|
// Whether or not to print error messages. Can be set to true
|
|
|
|
// when getting additional info for error message suggestions,
|
|
|
|
// so as to avoid printing duplicate errors
|
|
|
|
emit_errors: bool,
|
|
|
|
|
2014-11-23 09:29:41 +00:00
|
|
|
make_glob_map: bool,
|
|
|
|
// Maps imports to the names of items actually imported (this actually maps
|
|
|
|
// all imports, but only glob imports are actually interesting).
|
|
|
|
glob_map: GlobMap,
|
|
|
|
|
2014-02-11 19:19:18 +00:00
|
|
|
used_imports: HashSet<(NodeId, Namespace)>,
|
2014-09-11 17:14:43 +00:00
|
|
|
used_crates: HashSet<CrateNum>,
|
2015-05-14 11:40:16 +00:00
|
|
|
|
|
|
|
// Callback function for intercepting walks
|
2015-07-31 07:04:06 +00:00
|
|
|
callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>,
|
2015-05-14 11:40:16 +00:00
|
|
|
// The intention is that the callback modifies this flag.
|
|
|
|
// Once set, the resolver falls out of the walk, preserving the ribs.
|
|
|
|
resolved: bool,
|
2016-01-11 21:19:29 +00:00
|
|
|
|
|
|
|
arenas: &'a ResolverArenas<'a>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ResolverArenas<'a> {
|
|
|
|
modules: arena::TypedArena<ModuleS<'a>>,
|
2012-09-08 02:04:40 +00:00
|
|
|
}
|
|
|
|
|
2015-01-04 03:54:18 +00:00
|
|
|
#[derive(PartialEq)]
|
2014-11-06 08:05:53 +00:00
|
|
|
enum FallbackChecks {
|
|
|
|
Everything,
|
2015-10-26 19:31:11 +00:00
|
|
|
OnlyTraitAndStatics,
|
2014-11-06 08:05:53 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 09:29:41 +00:00
|
|
|
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|
|
|
fn new(session: &'a Session,
|
2015-07-31 07:04:06 +00:00
|
|
|
ast_map: &'a hir_map::Map<'tcx>,
|
2016-01-11 21:19:29 +00:00
|
|
|
make_glob_map: MakeGlobMap,
|
|
|
|
arenas: &'a ResolverArenas<'a>)
|
2015-10-26 19:31:11 +00:00
|
|
|
-> Resolver<'a, 'tcx> {
|
2015-09-04 17:52:28 +00:00
|
|
|
let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
|
2016-01-20 19:31:10 +00:00
|
|
|
let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, true);
|
2016-01-11 21:19:29 +00:00
|
|
|
let graph_root = arenas.modules.alloc(graph_root);
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
|
|
Resolver {
|
|
|
|
session: session,
|
|
|
|
|
2014-11-23 09:29:41 +00:00
|
|
|
ast_map: ast_map,
|
|
|
|
|
2014-05-28 19:36:05 +00: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,
|
2014-05-28 19:36:05 +00:00
|
|
|
|
2015-01-16 22:27:43 +00:00
|
|
|
trait_item_map: FnvHashMap(),
|
|
|
|
structs: FnvHashMap(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
|
|
unresolved_imports: 0,
|
|
|
|
|
2015-11-18 01:22:32 +00:00
|
|
|
current_module: graph_root,
|
2014-09-29 23:06:13 +00:00
|
|
|
value_ribs: Vec::new(),
|
|
|
|
type_ribs: Vec::new(),
|
|
|
|
label_ribs: Vec::new(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
|
|
current_trait_ref: None,
|
|
|
|
current_self_type: None,
|
|
|
|
|
|
|
|
primitive_type_table: PrimitiveTypeTable::new(),
|
|
|
|
|
2015-01-16 22:27:43 +00:00
|
|
|
def_map: RefCell::new(NodeMap()),
|
2015-11-04 05:12:37 +00:00
|
|
|
freevars: NodeMap(),
|
|
|
|
freevars_seen: NodeMap(),
|
2015-01-16 22:27:43 +00:00
|
|
|
export_map: NodeMap(),
|
|
|
|
trait_map: NodeMap(),
|
2014-05-28 19:36:05 +00:00
|
|
|
used_imports: HashSet::new(),
|
2014-09-11 17:14:43 +00:00
|
|
|
used_crates: HashSet::new(),
|
2015-01-16 22:27:43 +00:00
|
|
|
external_exports: DefIdSet(),
|
2014-05-28 19:36:05 +00:00
|
|
|
|
|
|
|
emit_errors: true,
|
2014-11-23 09:29:41 +00:00
|
|
|
make_glob_map: make_glob_map == MakeGlobMap::Yes,
|
|
|
|
glob_map: HashMap::new(),
|
2015-05-14 11:40:16 +00:00
|
|
|
|
|
|
|
callback: None,
|
|
|
|
resolved: false,
|
2016-01-11 21:19:29 +00:00
|
|
|
|
|
|
|
arenas: arenas,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn arenas() -> ResolverArenas<'a> {
|
|
|
|
ResolverArenas {
|
|
|
|
modules: arena::TypedArena::new(),
|
2014-05-28 19:36:05 +00:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
fn new_module(&self,
|
|
|
|
parent_link: ParentLink<'a>,
|
|
|
|
def: Option<Def>,
|
|
|
|
external: bool,
|
|
|
|
is_public: bool) -> Module<'a> {
|
|
|
|
self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public))
|
|
|
|
}
|
|
|
|
|
2016-01-29 22:21:36 +00:00
|
|
|
fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def) -> Module<'a> {
|
|
|
|
let mut module = ModuleS::new(parent_link, Some(def), false, true);
|
|
|
|
module.is_extern_crate = true;
|
|
|
|
self.arenas.modules.alloc(module)
|
|
|
|
}
|
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec<Rib<'a>> {
|
|
|
|
match ns { ValueNS => &mut self.value_ribs, TypeNS => &mut self.type_ribs }
|
|
|
|
}
|
|
|
|
|
2014-11-23 09:29:41 +00:00
|
|
|
#[inline]
|
|
|
|
fn record_import_use(&mut self, import_id: NodeId, name: Name) {
|
|
|
|
if !self.make_glob_map {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if self.glob_map.contains_key(&import_id) {
|
2015-03-20 17:22:57 +00:00
|
|
|
self.glob_map.get_mut(&import_id).unwrap().insert(name);
|
2014-11-23 09:29:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut new_set = HashSet::new();
|
|
|
|
new_set.insert(name);
|
|
|
|
self.glob_map.insert(import_id, new_set);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_trait_name(&self, did: DefId) -> Name {
|
2015-09-04 17:52:28 +00:00
|
|
|
if let Some(node_id) = self.ast_map.as_local_node_id(did) {
|
|
|
|
self.ast_map.expect_item(node_id).name
|
2014-11-23 09:29:41 +00:00
|
|
|
} else {
|
2015-11-20 15:46:39 +00:00
|
|
|
self.session.cstore.item_name(did)
|
2014-11-23 09:29:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
/// Resolves the given module path from the given root `module_`.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_module_path_from_root(&mut self,
|
2016-01-11 21:19:29 +00:00
|
|
|
module_: Module<'a>,
|
2014-10-01 00:11:34 +00:00
|
|
|
module_path: &[Name],
|
2015-03-26 00:06:52 +00:00
|
|
|
index: usize,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
span: Span,
|
|
|
|
lp: LastPrivate)
|
2016-01-11 21:19:29 +00:00
|
|
|
-> ResolveResult<(Module<'a>, LastPrivate)> {
|
2016-01-29 22:21:36 +00:00
|
|
|
fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option<Module<'a>> {
|
|
|
|
match module.get_child(needle, TypeNS) {
|
|
|
|
Some(ref binding) if binding.is_extern_crate() => Some(module),
|
|
|
|
_ => match module.parent_link {
|
2015-02-13 07:33:44 +00:00
|
|
|
ModuleParentLink(ref parent, _) => {
|
2016-01-11 21:19:29 +00:00
|
|
|
search_parent_externals(needle, parent)
|
2014-06-04 22:55:10 +00:00
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
_ => None,
|
|
|
|
},
|
2015-02-13 07:33:44 +00:00
|
|
|
}
|
2014-06-04 22:55:10 +00:00
|
|
|
}
|
|
|
|
|
2012-07-31 23:38:41 +00:00
|
|
|
let mut search_module = module_;
|
2012-05-22 17:54:12 +00:00
|
|
|
let mut index = index;
|
2013-03-07 23:37:14 +00:00
|
|
|
let module_path_len = module_path.len();
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
let mut closest_private = lp;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// Resolve the module part of the path. This does not involve looking
|
|
|
|
// upward though scope chains; we simply resolve names directly in
|
|
|
|
// modules as we go.
|
|
|
|
while index < module_path_len {
|
2013-03-07 23:37:14 +00:00
|
|
|
let name = module_path[index];
|
2016-01-26 09:52:33 +00:00
|
|
|
match self.resolve_name_in_module(search_module, name, TypeNS, false) {
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(None) => {
|
2015-07-28 16:07:20 +00:00
|
|
|
let segment_name = name.as_str();
|
2016-01-11 21:19:29 +00:00
|
|
|
let module_name = module_to_string(search_module);
|
2014-06-05 21:37:52 +00:00
|
|
|
let mut span = span;
|
2015-02-18 19:48:57 +00:00
|
|
|
let msg = if "???" == &module_name[..] {
|
2015-02-03 23:48:39 +00:00
|
|
|
span.hi = span.lo + Pos::from_usize(segment_name.len());
|
2014-06-04 22:55:10 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
match search_parent_externals(name, &self.current_module) {
|
2014-06-04 22:55:10 +00:00
|
|
|
Some(module) => {
|
2015-03-15 21:44:19 +00:00
|
|
|
let path_str = names_to_string(module_path);
|
|
|
|
let target_mod_str = module_to_string(&*module);
|
2015-10-26 19:31:11 +00:00
|
|
|
let current_mod_str = module_to_string(&*self.current_module);
|
2014-06-04 22:55:10 +00:00
|
|
|
|
|
|
|
let prefix = if target_mod_str == current_mod_str {
|
|
|
|
"self::".to_string()
|
|
|
|
} else {
|
|
|
|
format!("{}::", target_mod_str)
|
|
|
|
};
|
|
|
|
|
2014-06-05 21:37:52 +00:00
|
|
|
format!("Did you mean `{}{}`?", prefix, path_str)
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
|
|
|
None => format!("Maybe a missing `extern crate {}`?", segment_name),
|
2014-06-04 22:55:10 +00:00
|
|
|
}
|
2014-06-05 21:37:52 +00:00
|
|
|
} else {
|
2015-10-26 19:31:11 +00:00
|
|
|
format!("Could not find `{}` in `{}`", segment_name, module_name)
|
2014-06-05 21:37:52 +00:00
|
|
|
};
|
2014-06-04 22:55:10 +00:00
|
|
|
|
2014-06-05 21:37:52 +00:00
|
|
|
return Failed(Some((span, msg)));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => return Failed(err),
|
2012-08-04 02:59:04 +00:00
|
|
|
Indeterminate => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving module path for import) module resolution is \
|
|
|
|
indeterminate: {}",
|
|
|
|
name);
|
2012-08-02 00:30:05 +00:00
|
|
|
return Indeterminate;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((target, used_proxy)) => {
|
2012-10-16 01:04:15 +00:00
|
|
|
// Check to see whether there are type bindings, and, if
|
|
|
|
// so, whether there is a module within.
|
2015-11-16 02:10:09 +00:00
|
|
|
if let Some(module_def) = target.binding.module() {
|
|
|
|
// track extern crates for unused_extern_crate lint
|
2015-11-16 07:59:50 +00:00
|
|
|
if let Some(did) = module_def.def_id() {
|
2015-11-16 02:10:09 +00:00
|
|
|
self.used_crates.insert(did.krate);
|
|
|
|
}
|
2014-10-19 06:46:08 +00:00
|
|
|
|
2015-11-16 02:10:09 +00:00
|
|
|
search_module = module_def;
|
2014-09-11 17:14:43 +00:00
|
|
|
|
2015-11-16 02:10:09 +00:00
|
|
|
// Keep track of the closest private module used
|
|
|
|
// when resolving this import chain.
|
|
|
|
if !used_proxy && !search_module.is_public {
|
2015-11-16 07:59:50 +00:00
|
|
|
if let Some(did) = search_module.def_id() {
|
2015-11-16 02:10:09 +00:00
|
|
|
closest_private = LastMod(DependsOn(did));
|
2012-10-16 01:04:15 +00:00
|
|
|
}
|
|
|
|
}
|
2015-11-16 02:10:09 +00:00
|
|
|
} else {
|
|
|
|
let msg = format!("Not a module `{}`", name);
|
|
|
|
return Failed(Some((span, msg)));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-29 20:08:40 +00:00
|
|
|
index += 1;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
return Success((search_module, closest_private));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
/// Attempts to resolve the module part of an import directive or path
|
|
|
|
/// rooted at the given module.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
///
|
|
|
|
/// On success, returns the resolved module, and the closest *private*
|
|
|
|
/// module found to the destination when resolving this path.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_module_path(&mut self,
|
2016-01-11 21:19:29 +00:00
|
|
|
module_: Module<'a>,
|
2014-10-01 00:11:34 +00:00
|
|
|
module_path: &[Name],
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
use_lexical_scope: UseLexicalScopeFlag,
|
2016-01-26 09:52:33 +00:00
|
|
|
span: Span)
|
2016-01-11 21:19:29 +00:00
|
|
|
-> ResolveResult<(Module<'a>, LastPrivate)> {
|
2013-03-01 18:44:43 +00:00
|
|
|
let module_path_len = module_path.len();
|
2013-03-29 01:39:09 +00:00
|
|
|
assert!(module_path_len > 0);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2014-12-04 19:58:52 +00:00
|
|
|
debug!("(resolving module path for import) processing `{}` rooted at `{}`",
|
2015-03-15 21:44:19 +00:00
|
|
|
names_to_string(module_path),
|
|
|
|
module_to_string(&*module_));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2012-12-23 22:41:37 +00:00
|
|
|
// Resolve the module prefix, if any.
|
2016-01-11 21:19:29 +00:00
|
|
|
let module_prefix_result = self.resolve_module_prefix(module_, module_path);
|
2012-12-13 21:05:22 +00:00
|
|
|
|
2013-04-12 05:15:30 +00:00
|
|
|
let search_module;
|
|
|
|
let start_index;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
let last_private;
|
2012-12-23 22:41:37 +00:00
|
|
|
match module_prefix_result {
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(None) => {
|
2015-03-15 21:44:19 +00:00
|
|
|
let mpath = names_to_string(module_path);
|
2015-02-18 19:48:57 +00:00
|
|
|
let mpath = &mpath[..];
|
2014-06-05 21:37:52 +00:00
|
|
|
match mpath.rfind(':') {
|
2013-05-14 23:49:04 +00:00
|
|
|
Some(idx) => {
|
2014-06-05 21:37:52 +00:00
|
|
|
let msg = format!("Could not find `{}` in `{}`",
|
2015-10-26 19:31:11 +00:00
|
|
|
// idx +- 1 to account for the
|
|
|
|
// colons on either side
|
|
|
|
&mpath[idx + 1..],
|
|
|
|
&mpath[..idx - 1]);
|
2014-06-05 21:37:52 +00:00
|
|
|
return Failed(Some((span, msg)));
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2014-11-29 04:09:12 +00:00
|
|
|
None => {
|
2015-10-26 19:31:11 +00:00
|
|
|
return Failed(None);
|
2014-11-29 04:09:12 +00:00
|
|
|
}
|
2014-06-05 21:37:52 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => return Failed(err),
|
2012-08-04 02:59:04 +00:00
|
|
|
Indeterminate => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving module path for import) indeterminate; bailing");
|
2012-08-02 00:30:05 +00:00
|
|
|
return Indeterminate;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-12-23 22:41:37 +00:00
|
|
|
Success(NoPrefixFound) => {
|
|
|
|
// There was no prefix, so we're considering the first element
|
|
|
|
// of the path. How we handle this depends on whether we were
|
|
|
|
// instructed to use lexical scope or not.
|
|
|
|
match use_lexical_scope {
|
|
|
|
DontUseLexicalScope => {
|
|
|
|
// This is a crate-relative path. We will start the
|
|
|
|
// resolution process at index zero.
|
2016-01-11 21:19:29 +00:00
|
|
|
search_module = self.graph_root;
|
2012-12-23 22:41:37 +00:00
|
|
|
start_index = 0;
|
2014-02-11 19:19:18 +00:00
|
|
|
last_private = LastMod(AllPublic);
|
2012-12-23 22:41:37 +00:00
|
|
|
}
|
|
|
|
UseLexicalScope => {
|
|
|
|
// This is not a crate-relative path. We resolve the
|
|
|
|
// first component of the path in the current lexical
|
|
|
|
// scope and then proceed to resolve below that.
|
2015-10-26 19:31:11 +00:00
|
|
|
match self.resolve_module_in_lexical_scope(module_, module_path[0]) {
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => return Failed(err),
|
2012-12-23 22:41:37 +00:00
|
|
|
Indeterminate => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving module path for import) indeterminate; bailing");
|
2012-12-23 22:41:37 +00:00
|
|
|
return Indeterminate;
|
|
|
|
}
|
|
|
|
Success(containing_module) => {
|
|
|
|
search_module = containing_module;
|
|
|
|
start_index = 1;
|
2014-02-11 19:19:18 +00:00
|
|
|
last_private = LastMod(AllPublic);
|
2012-12-23 22:41:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-14 08:30:59 +00:00
|
|
|
Success(PrefixFound(ref containing_module, index)) => {
|
2016-01-11 21:19:29 +00:00
|
|
|
search_module = containing_module;
|
2012-12-23 22:41:37 +00:00
|
|
|
start_index = index;
|
2015-11-16 07:59:50 +00:00
|
|
|
last_private = LastMod(DependsOn(containing_module.def_id()
|
2014-02-11 19:19:18 +00:00
|
|
|
.unwrap()));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
self.resolve_module_path_from_root(search_module,
|
|
|
|
module_path,
|
|
|
|
start_index,
|
|
|
|
span,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
last_private)
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
/// Invariant: This must only be called during main resolution, not during
|
|
|
|
/// import resolution.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_item_in_lexical_scope(&mut self,
|
2016-01-11 21:19:29 +00:00
|
|
|
module_: Module<'a>,
|
2014-10-01 00:11:34 +00:00
|
|
|
name: Name,
|
2015-12-12 03:30:53 +00:00
|
|
|
namespace: Namespace,
|
|
|
|
record_used: bool)
|
2016-01-11 21:19:29 +00:00
|
|
|
-> ResolveResult<(Target<'a>, bool)> {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
|
2015-07-08 20:55:22 +00:00
|
|
|
name,
|
2012-05-22 17:54:12 +00:00
|
|
|
namespace,
|
2015-03-15 21:44:19 +00:00
|
|
|
module_to_string(&*module_));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// The current module node is handled specially. First, check for
|
|
|
|
// its immediate children.
|
2014-12-30 18:16:42 +00:00
|
|
|
build_reduced_graph::populate_module_if_necessary(self, &module_);
|
2013-12-21 23:32:44 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
if let Some(binding) = module_.get_child(name, namespace) {
|
|
|
|
debug!("top name bindings succeeded");
|
|
|
|
return Success((Target::new(module_, binding, Shadowable::Never), false));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now check for its import directives. We don't have to have resolved
|
|
|
|
// all its imports in the usual way; this is because chains of
|
|
|
|
// adjacent import statements are processed as though they mutated the
|
|
|
|
// current scope.
|
2016-01-14 01:42:45 +00:00
|
|
|
if let Some(import_resolution) =
|
|
|
|
module_.import_resolutions.borrow().get(&(name, namespace)) {
|
|
|
|
match import_resolution.target.clone() {
|
2014-11-29 21:41:21 +00:00
|
|
|
None => {
|
|
|
|
// Not found; continue.
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item in lexical scope) found import resolution, but not \
|
|
|
|
in namespace {:?}",
|
2014-11-29 21:41:21 +00:00
|
|
|
namespace);
|
|
|
|
}
|
|
|
|
Some(target) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item in lexical scope) using import resolution");
|
2014-11-29 21:41:21 +00:00
|
|
|
// track used imports and extern crates as well
|
2016-01-14 01:42:45 +00:00
|
|
|
let id = import_resolution.id;
|
2015-12-12 03:30:53 +00:00
|
|
|
if record_used {
|
|
|
|
self.used_imports.insert((id, namespace));
|
|
|
|
self.record_import_use(id, name);
|
|
|
|
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
|
|
|
|
self.used_crates.insert(kid);
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2014-11-29 21:41:21 +00:00
|
|
|
return Success((target, false));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, proceed up the scope chain looking for parent modules.
|
2012-07-31 23:38:41 +00:00
|
|
|
let mut search_module = module_;
|
2012-05-22 17:54:12 +00:00
|
|
|
loop {
|
|
|
|
// Go to the next parent.
|
2016-01-11 21:19:29 +00:00
|
|
|
match search_module.parent_link {
|
2012-08-04 02:59:04 +00:00
|
|
|
NoParentLink => {
|
2012-05-22 17:54:12 +00:00
|
|
|
// No more parents. This module was unresolved.
|
2016-02-01 03:26:16 +00:00
|
|
|
debug!("(resolving item in lexical scope) unresolved module: no parent module");
|
2014-06-05 21:37:52 +00:00
|
|
|
return Failed(None);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-12-23 22:41:37 +00:00
|
|
|
ModuleParentLink(parent_module_node, _) => {
|
2015-11-16 07:59:50 +00:00
|
|
|
if search_module.is_normal() {
|
|
|
|
// We stop the search here.
|
|
|
|
debug!("(resolving item in lexical scope) unresolved module: not \
|
|
|
|
searching through module parents");
|
2014-06-05 21:37:52 +00:00
|
|
|
return Failed(None);
|
2015-11-16 07:59:50 +00:00
|
|
|
} else {
|
2016-01-11 21:19:29 +00:00
|
|
|
search_module = parent_module_node;
|
2012-12-23 22:41:37 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-11 21:19:29 +00:00
|
|
|
BlockParentLink(parent_module_node, _) => {
|
|
|
|
search_module = parent_module_node;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve the name in the parent module.
|
2016-01-26 09:52:33 +00:00
|
|
|
match self.resolve_name_in_module(search_module, name, namespace, true) {
|
2015-07-08 20:55:22 +00:00
|
|
|
Failed(Some((span, msg))) => {
|
2015-07-14 17:42:38 +00:00
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(None) => (), // Continue up the search chain.
|
2012-08-04 02:59:04 +00:00
|
|
|
Indeterminate => {
|
2012-05-22 17:54:12 +00:00
|
|
|
// We couldn't see through the higher scope because of an
|
|
|
|
// unresolved import higher up. Bail.
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item in lexical scope) indeterminate higher scope; bailing");
|
2012-08-02 00:30:05 +00:00
|
|
|
return Indeterminate;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((target, used_reexport)) => {
|
2012-05-22 17:54:12 +00:00
|
|
|
// We found the module.
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item in lexical scope) found name in module, done");
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
return Success((target, used_reexport));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 22:17:22 +00:00
|
|
|
/// Resolves a module name in the current lexical scope.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_module_in_lexical_scope(&mut self,
|
2016-01-11 21:19:29 +00:00
|
|
|
module_: Module<'a>,
|
2014-10-01 00:11:34 +00:00
|
|
|
name: Name)
|
2016-01-11 21:19:29 +00:00
|
|
|
-> ResolveResult<Module<'a>> {
|
2012-12-13 21:05:22 +00:00
|
|
|
// If this module is an anonymous module, resolve the item in the
|
|
|
|
// lexical scope. Otherwise, resolve the item from the crate root.
|
2015-12-12 03:30:53 +00:00
|
|
|
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
|
2012-12-13 21:05:22 +00:00
|
|
|
match resolve_result {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((target, _)) => {
|
2015-11-16 02:10:09 +00:00
|
|
|
if let Some(module_def) = target.binding.module() {
|
|
|
|
return Success(module_def)
|
|
|
|
} else {
|
|
|
|
debug!("!!! (resolving module in lexical scope) module \
|
|
|
|
wasn't actually a module!");
|
|
|
|
return Failed(None);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-04 02:59:04 +00:00
|
|
|
Indeterminate => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving module in lexical scope) indeterminate; bailing");
|
2012-08-02 00:30:05 +00:00
|
|
|
return Indeterminate;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => {
|
|
|
|
debug!("(resolving module in lexical scope) failed to resolve");
|
|
|
|
return Failed(err);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 22:17:22 +00:00
|
|
|
/// Returns the nearest normal module parent of the given module.
|
2016-01-11 21:19:29 +00:00
|
|
|
fn get_nearest_normal_module_parent(&mut self, module_: Module<'a>) -> Option<Module<'a>> {
|
2012-12-23 22:41:37 +00:00
|
|
|
let mut module_ = module_;
|
|
|
|
loop {
|
2016-01-11 21:19:29 +00:00
|
|
|
match module_.parent_link {
|
2012-12-23 22:41:37 +00:00
|
|
|
NoParentLink => return None,
|
|
|
|
ModuleParentLink(new_module, _) |
|
|
|
|
BlockParentLink(new_module, _) => {
|
2016-01-11 21:19:29 +00:00
|
|
|
let new_module = new_module;
|
2015-11-16 07:59:50 +00:00
|
|
|
if new_module.is_normal() {
|
|
|
|
return Some(new_module);
|
2012-12-23 22:41:37 +00:00
|
|
|
}
|
2015-11-16 07:59:50 +00:00
|
|
|
module_ = new_module;
|
2012-12-23 22:41:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 22:17:22 +00:00
|
|
|
/// Returns the nearest normal module parent of the given module, or the
|
|
|
|
/// module itself if it is a normal module.
|
2016-01-11 21:19:29 +00:00
|
|
|
fn get_nearest_normal_module_parent_or_self(&mut self, module_: Module<'a>) -> Module<'a> {
|
2015-11-16 07:59:50 +00:00
|
|
|
if module_.is_normal() {
|
|
|
|
return module_;
|
|
|
|
}
|
2016-01-11 21:19:29 +00:00
|
|
|
match self.get_nearest_normal_module_parent(module_) {
|
2015-11-16 07:59:50 +00:00
|
|
|
None => module_,
|
|
|
|
Some(new_module) => new_module,
|
2012-12-23 22:41:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-26 22:56:13 +00:00
|
|
|
/// Resolves a "module prefix". A module prefix is one or both of (a) `self::`;
|
2013-05-31 22:17:22 +00:00
|
|
|
/// (b) some chain of `super::`.
|
2013-06-26 22:56:13 +00:00
|
|
|
/// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_module_prefix(&mut self,
|
2016-01-11 21:19:29 +00:00
|
|
|
module_: Module<'a>,
|
2014-10-01 00:11:34 +00:00
|
|
|
module_path: &[Name])
|
2016-01-11 21:19:29 +00:00
|
|
|
-> ResolveResult<ModulePrefixResult<'a>> {
|
2012-12-23 22:41:37 +00:00
|
|
|
// Start at the current module if we see `self` or `super`, or at the
|
|
|
|
// top of the crate otherwise.
|
2015-07-28 16:07:20 +00:00
|
|
|
let mut i = match &*module_path[0].as_str() {
|
|
|
|
"self" => 1,
|
|
|
|
"super" => 0,
|
|
|
|
_ => return Success(NoPrefixFound),
|
|
|
|
};
|
|
|
|
let mut containing_module = self.get_nearest_normal_module_parent_or_self(module_);
|
2012-12-23 22:41:37 +00:00
|
|
|
|
|
|
|
// Now loop through all the `super`s we find.
|
2015-07-28 16:07:20 +00:00
|
|
|
while i < module_path.len() && "super" == module_path[i].as_str() {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving module prefix) resolving `super` at {}",
|
2015-03-15 21:44:19 +00:00
|
|
|
module_to_string(&*containing_module));
|
2012-12-23 22:41:37 +00:00
|
|
|
match self.get_nearest_normal_module_parent(containing_module) {
|
2014-06-05 21:37:52 +00:00
|
|
|
None => return Failed(None),
|
2012-12-23 22:41:37 +00:00
|
|
|
Some(new_module) => {
|
|
|
|
containing_module = new_module;
|
|
|
|
i += 1;
|
2012-12-13 21:05:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving module prefix) finished resolving prefix at {}",
|
2015-03-15 21:44:19 +00:00
|
|
|
module_to_string(&*containing_module));
|
2012-12-23 22:41:37 +00:00
|
|
|
|
|
|
|
return Success(PrefixFound(containing_module, i));
|
2012-12-13 21:05:22 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
/// Attempts to resolve the supplied name in the given module for the
|
|
|
|
/// given namespace. If successful, returns the target corresponding to
|
|
|
|
/// the name.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
///
|
|
|
|
/// The boolean returned on success is an indicator of whether this lookup
|
|
|
|
/// passed through a public re-export proxy.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_name_in_module(&mut self,
|
2016-01-11 21:19:29 +00:00
|
|
|
module_: Module<'a>,
|
2014-05-08 21:35:09 +00:00
|
|
|
name: Name,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
namespace: Namespace,
|
2014-04-08 21:31:25 +00:00
|
|
|
allow_private_imports: bool)
|
2016-01-11 21:19:29 +00:00
|
|
|
-> ResolveResult<(Target<'a>, bool)> {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving name in module) resolving `{}` in `{}`",
|
2015-07-08 20:55:22 +00:00
|
|
|
name,
|
2015-03-15 21:44:19 +00:00
|
|
|
module_to_string(&*module_));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// First, check the direct children of the module.
|
2014-12-30 18:16:42 +00:00
|
|
|
build_reduced_graph::populate_module_if_necessary(self, &module_);
|
2013-12-21 23:32:44 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
if let Some(binding) = module_.get_child(name, namespace) {
|
|
|
|
debug!("(resolving name in module) found node as child");
|
|
|
|
return Success((Target::new(module_, binding, Shadowable::Never), false));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
// Check the list of resolved imports.
|
2016-01-14 01:42:45 +00:00
|
|
|
match module_.import_resolutions.borrow().get(&(name, namespace)) {
|
|
|
|
Some(import_resolution) if allow_private_imports || import_resolution.is_public => {
|
|
|
|
if import_resolution.is_public && import_resolution.outstanding_references != 0 {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving name in module) import unresolved; bailing out");
|
2012-08-02 00:30:05 +00:00
|
|
|
return Indeterminate;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
match import_resolution.target.clone() {
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving name in module) name found, but not in namespace {:?}",
|
2012-08-23 00:24:52 +00:00
|
|
|
namespace);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Some(target) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving name in module) resolved to import");
|
2014-09-11 17:14:43 +00:00
|
|
|
// track used imports and extern crates as well
|
2016-01-14 01:42:45 +00:00
|
|
|
let id = import_resolution.id;
|
2014-11-23 09:29:41 +00:00
|
|
|
self.used_imports.insert((id, namespace));
|
|
|
|
self.record_import_use(id, name);
|
2015-11-16 07:59:50 +00:00
|
|
|
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
|
2014-11-29 21:41:21 +00:00
|
|
|
self.used_crates.insert(kid);
|
2014-09-11 17:14:43 +00:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
return Success((target, true));
|
2013-03-01 18:44:43 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-08 21:31:25 +00:00
|
|
|
Some(..) | None => {} // Continue.
|
2013-03-27 02:53:33 +00:00
|
|
|
}
|
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
// We're out of luck.
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving name in module) failed to resolve `{}`", name);
|
2014-06-05 21:37:52 +00:00
|
|
|
return Failed(None);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
fn report_unresolved_imports(&mut self, module_: Module<'a>) {
|
2013-12-20 03:01:02 +00:00
|
|
|
let index = module_.resolved_import_count.get();
|
2014-03-21 02:49:20 +00:00
|
|
|
let imports = module_.imports.borrow();
|
|
|
|
let import_count = imports.len();
|
2012-05-22 17:54:12 +00:00
|
|
|
if index != import_count {
|
2015-07-31 08:22:13 +00:00
|
|
|
resolve_error(self,
|
|
|
|
(*imports)[index].span,
|
|
|
|
ResolutionError::UnresolvedImport(None));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Descend into children and anonymous children.
|
2014-12-30 18:16:42 +00:00
|
|
|
build_reduced_graph::populate_module_if_necessary(self, &module_);
|
2013-12-21 23:32:44 +00:00
|
|
|
|
2016-01-29 22:21:36 +00:00
|
|
|
module_.for_each_local_child(|_, _, child_node| {
|
2016-01-14 01:42:45 +00:00
|
|
|
match child_node.module() {
|
2014-03-21 02:49:20 +00:00
|
|
|
None => {
|
|
|
|
// Continue.
|
|
|
|
}
|
|
|
|
Some(child_module) => {
|
|
|
|
self.report_unresolved_imports(child_module);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-29 22:21:36 +00:00
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-06-11 12:56:07 +00:00
|
|
|
for (_, module_) in module_.anonymous_children.borrow().iter() {
|
2016-01-11 21:19:29 +00:00
|
|
|
self.report_unresolved_imports(module_);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AST resolution
|
|
|
|
//
|
2012-07-07 02:06:58 +00:00
|
|
|
// We maintain a list of value ribs and type ribs.
|
2012-05-22 17:54:12 +00:00
|
|
|
//
|
|
|
|
// Simultaneously, we keep track of the current position in the module
|
|
|
|
// graph in the `current_module` pointer. When we go to resolve a name in
|
|
|
|
// the value or type namespaces, we first look through all the ribs and
|
|
|
|
// then query the module graph. When we resolve a name in the module
|
|
|
|
// namespace, we can skip all the ribs (since nested modules are not
|
|
|
|
// allowed within blocks in Rust) and jump straight to the current module
|
|
|
|
// graph node.
|
|
|
|
//
|
|
|
|
// Named implementations are handled separately. When we find a method
|
|
|
|
// call, we consult the module node to find all of the implementations in
|
|
|
|
// scope. This information is lazily cached in the module node. We then
|
|
|
|
// generate a fake "implementation scope" containing all the
|
|
|
|
// implementations thus found, for compatibility with old resolve pass.
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn with_scope<F>(&mut self, name: Option<Name>, f: F)
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2016-01-11 21:19:29 +00:00
|
|
|
let orig_module = self.current_module;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// Move down in the graph.
|
2012-08-06 19:34:08 +00:00
|
|
|
match name {
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2012-07-11 22:00:40 +00:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
2012-08-20 19:23:37 +00:00
|
|
|
Some(name) => {
|
2014-12-30 18:16:42 +00:00
|
|
|
build_reduced_graph::populate_module_if_necessary(self, &orig_module);
|
2013-12-21 23:32:44 +00:00
|
|
|
|
2016-01-14 01:42:45 +00:00
|
|
|
match orig_module.get_child(name, TypeNS) {
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("!!! (with scope) didn't find `{}` in `{}`",
|
2015-07-08 20:55:22 +00:00
|
|
|
name,
|
2015-03-15 21:44:19 +00:00
|
|
|
module_to_string(&*orig_module));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
Some(name_binding) => {
|
|
|
|
match name_binding.module() {
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("!!! (with scope) didn't find module for `{}` in `{}`",
|
2015-07-08 20:55:22 +00:00
|
|
|
name,
|
2015-03-15 21:44:19 +00:00
|
|
|
module_to_string(&*orig_module));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-08-20 19:23:37 +00:00
|
|
|
Some(module_) => {
|
2012-07-31 23:38:41 +00:00
|
|
|
self.current_module = module_;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-27 02:10:16 +00:00
|
|
|
f(self);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
self.current_module = orig_module;
|
|
|
|
}
|
|
|
|
|
2014-12-27 12:47:42 +00:00
|
|
|
/// Searches the current set of local scopes for labels.
|
|
|
|
/// Stops after meeting a closure.
|
2014-12-26 11:08:00 +00:00
|
|
|
fn search_label(&self, name: Name) -> Option<DefLike> {
|
|
|
|
for rib in self.label_ribs.iter().rev() {
|
|
|
|
match rib.kind {
|
|
|
|
NormalRibKind => {
|
|
|
|
// Continue
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// Do not resolve labels across function boundary
|
2015-10-26 19:31:11 +00:00
|
|
|
return None;
|
2014-12-26 11:08:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
let result = rib.bindings.get(&name).cloned();
|
2014-12-27 12:47:42 +00:00
|
|
|
if result.is_some() {
|
2015-10-26 19:31:11 +00:00
|
|
|
return result;
|
2014-12-26 11:08:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2015-07-31 07:04:06 +00:00
|
|
|
fn resolve_crate(&mut self, krate: &hir::Crate) {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving crate) starting");
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_crate(self, krate);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-02-08 16:29:47 +00:00
|
|
|
fn check_if_primitive_type_name(&self, name: Name, span: Span) {
|
|
|
|
if let Some(_) = self.primitive_type_table.primitive_types.get(&name) {
|
2015-10-26 19:31:11 +00:00
|
|
|
span_err!(self.session,
|
|
|
|
span,
|
|
|
|
E0317,
|
|
|
|
"user-defined types or type parameters cannot shadow the primitive types");
|
2015-02-08 16:29:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-09 13:05:33 +00:00
|
|
|
fn resolve_item(&mut self, item: &Item) {
|
2015-09-20 01:50:30 +00:00
|
|
|
let name = item.name;
|
2014-10-01 00:11:34 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item) resolving {}", name);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2013-03-20 05:17:42 +00:00
|
|
|
match item.node {
|
2015-02-05 07:19:07 +00:00
|
|
|
ItemEnum(_, ref generics) |
|
|
|
|
ItemTy(_, ref generics) |
|
|
|
|
ItemStruct(_, ref generics) => {
|
2015-02-08 16:29:47 +00:00
|
|
|
self.check_if_primitive_type_name(name, item.span);
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
|
2015-11-17 23:56:13 +00:00
|
|
|
|this| intravisit::walk_item(this, item));
|
2012-10-15 19:27:09 +00:00
|
|
|
}
|
2015-02-25 20:05:07 +00:00
|
|
|
ItemFn(_, _, _, _, ref generics, _) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind),
|
2015-11-17 23:56:13 +00:00
|
|
|
|this| intravisit::walk_item(this, item));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-02-07 13:24:34 +00:00
|
|
|
ItemDefaultImpl(_, ref trait_ref) => {
|
2015-04-03 04:13:52 +00:00
|
|
|
self.with_optional_trait_ref(Some(trait_ref), |_, _| {});
|
2015-01-22 21:15:02 +00:00
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
|
2015-02-05 07:19:07 +00:00
|
|
|
self.resolve_implementation(generics,
|
2015-04-03 04:13:52 +00:00
|
|
|
opt_trait_ref,
|
2014-05-16 17:15:33 +00:00
|
|
|
&**self_type,
|
2015-04-03 04:13:52 +00:00
|
|
|
item.id,
|
2015-12-07 14:17:41 +00:00
|
|
|
impl_items);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2014-12-24 06:38:10 +00:00
|
|
|
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
|
2015-02-08 16:29:47 +00:00
|
|
|
self.check_if_primitive_type_name(name, item.span);
|
|
|
|
|
2015-04-07 05:59:10 +00:00
|
|
|
// Create a new rib for the trait-wide type parameters.
|
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
|
|
|
TypeSpace,
|
|
|
|
ItemRibKind),
|
|
|
|
|this| {
|
2015-09-02 20:11:32 +00:00
|
|
|
let local_def_id = this.ast_map.local_def_id(item.id);
|
2016-01-20 19:31:10 +00:00
|
|
|
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
|
2015-04-03 04:13:52 +00:00
|
|
|
this.visit_generics(generics);
|
2015-09-28 21:23:54 +00:00
|
|
|
walk_list!(this, visit_ty_param_bound, bounds);
|
2015-04-03 04:13:52 +00:00
|
|
|
|
|
|
|
for trait_item in trait_items {
|
2015-03-16 01:35:25 +00:00
|
|
|
match trait_item.node {
|
2015-07-31 07:04:06 +00:00
|
|
|
hir::ConstTraitItem(_, ref default) => {
|
2015-03-16 01:35:25 +00: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| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_trait_item(this, trait_item)
|
2015-03-16 01:35:25 +00:00
|
|
|
});
|
|
|
|
} else {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_trait_item(this, trait_item)
|
2015-03-16 01:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
hir::MethodTraitItem(ref sig, _) => {
|
2015-03-16 01:35:25 +00:00
|
|
|
let type_parameters =
|
|
|
|
HasTypeParameters(&sig.generics,
|
|
|
|
FnSpace,
|
|
|
|
MethodRibKind);
|
|
|
|
this.with_type_parameter_rib(type_parameters, |this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_trait_item(this, trait_item)
|
2015-03-16 01:35:25 +00:00
|
|
|
});
|
2015-04-03 04:13:52 +00:00
|
|
|
}
|
2015-07-31 07:04:06 +00:00
|
|
|
hir::TypeTraitItem(..) => {
|
2015-09-20 01:50:30 +00:00
|
|
|
this.check_if_primitive_type_name(trait_item.name,
|
2015-04-03 04:13:52 +00:00
|
|
|
trait_item.span);
|
2015-03-16 01:35:25 +00:00
|
|
|
this.with_type_parameter_rib(NoTypeParameters, |this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_trait_item(this, trait_item)
|
2015-03-16 01:35:25 +00:00
|
|
|
});
|
2015-04-03 04:13:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
2013-11-21 23:42:55 +00:00
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
ItemMod(_) | ItemForeignMod(_) => {
|
2014-10-01 00:11:34 +00:00
|
|
|
self.with_scope(Some(name), |this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_item(this, item);
|
2013-11-21 23:42:55 +00:00
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 15:17:01 +00:00
|
|
|
ItemConst(..) | ItemStatic(..) => {
|
2013-09-27 02:10:16 +00:00
|
|
|
self.with_constant_rib(|this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_item(this, item);
|
2012-10-15 19:27:09 +00:00
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-07-05 19:10:33 +00:00
|
|
|
|
2015-02-08 16:29:47 +00:00
|
|
|
ItemUse(ref view_path) => {
|
|
|
|
// check for imports shadowing primitive types
|
2015-09-20 11:51:40 +00:00
|
|
|
let check_rename = |this: &Self, id, name| {
|
2015-09-15 21:50:50 +00:00
|
|
|
match this.def_map.borrow().get(&id).map(|d| d.full_def()) {
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Enum(..)) | Some(Def::TyAlias(..)) | Some(Def::Struct(..)) |
|
|
|
|
Some(Def::Trait(..)) | None => {
|
2015-09-20 11:51:40 +00:00
|
|
|
this.check_if_primitive_type_name(name, item.span);
|
2015-02-08 16:29:47 +00:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2015-09-14 22:07:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
match view_path.node {
|
2015-09-20 11:51:40 +00:00
|
|
|
hir::ViewPathSimple(name, _) => {
|
|
|
|
check_rename(self, item.id, name);
|
2015-09-14 22:07:17 +00:00
|
|
|
}
|
2015-09-15 21:50:50 +00:00
|
|
|
hir::ViewPathList(ref prefix, ref items) => {
|
2015-09-14 22:07:17 +00:00
|
|
|
for item in items {
|
2015-09-20 11:51:40 +00:00
|
|
|
if let Some(name) = item.node.rename() {
|
|
|
|
check_rename(self, item.node.id(), name);
|
2015-09-15 21:50:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve prefix of an import with empty braces (issue #28388)
|
|
|
|
if items.is_empty() && !prefix.segments.is_empty() {
|
|
|
|
match self.resolve_crate_relative_path(prefix.span,
|
|
|
|
&prefix.segments,
|
|
|
|
TypeNS) {
|
2015-10-26 19:31:11 +00:00
|
|
|
Some((def, lp)) =>
|
|
|
|
self.record_def(item.id, PathResolution::new(def, lp, 0)),
|
2015-09-15 21:50:50 +00:00
|
|
|
None => {
|
|
|
|
resolve_error(self,
|
|
|
|
prefix.span,
|
|
|
|
ResolutionError::FailedToResolve(
|
|
|
|
&path_names_to_string(prefix, 0)));
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(item.id, err_path_resolution());
|
2015-09-15 21:50:50 +00:00
|
|
|
}
|
2015-09-14 22:07:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
2015-02-08 16:29:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 07:04:06 +00:00
|
|
|
ItemExternCrate(_) => {
|
2013-12-25 18:10:33 +00:00
|
|
|
// do nothing, these are just around to be encoded
|
2014-12-23 19:34:36 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00: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 19:31:11 +00:00
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2012-08-06 19:34:08 +00:00
|
|
|
match type_parameters {
|
2015-02-05 07:19:07 +00:00
|
|
|
HasTypeParameters(generics, space, rib_kind) => {
|
2014-09-29 23:06:13 +00:00
|
|
|
let mut function_type_rib = Rib::new(rib_kind);
|
2014-10-09 04:28:50 +00:00
|
|
|
let mut seen_bindings = HashSet::new();
|
2013-08-03 16:45:23 +00:00
|
|
|
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
|
2015-09-20 13:47:24 +00:00
|
|
|
let name = type_parameter.name;
|
2015-02-05 07:19:07 +00:00
|
|
|
debug!("with_type_parameter_rib: {}", type_parameter.id);
|
2014-10-09 04:28:50 +00:00
|
|
|
|
2014-10-01 00:11:34 +00:00
|
|
|
if seen_bindings.contains(&name) {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
type_parameter.span,
|
2015-10-26 19:31:11 +00:00
|
|
|
ResolutionError::NameAlreadyUsedInTypeParameterList(name));
|
2014-10-09 04:28:50 +00:00
|
|
|
}
|
2014-10-01 00:11:34 +00:00
|
|
|
seen_bindings.insert(name);
|
2014-10-09 04:28:50 +00:00
|
|
|
|
2013-06-26 22:56:13 +00:00
|
|
|
// plain insert (no renaming)
|
2015-10-26 19:31:11 +00:00
|
|
|
function_type_rib.bindings
|
|
|
|
.insert(name,
|
2016-01-20 19:31:10 +00:00
|
|
|
DlDef(Def::TyParam(space,
|
2015-10-26 19:31:11 +00:00
|
|
|
index as u32,
|
|
|
|
self.ast_map
|
|
|
|
.local_def_id(type_parameter.id),
|
|
|
|
name)));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2014-09-29 23:06:13 +00:00
|
|
|
self.type_ribs.push(function_type_rib);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2012-08-04 02:59:04 +00:00
|
|
|
NoTypeParameters => {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-27 02:10:16 +00:00
|
|
|
f(self);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2012-08-06 19:34:08 +00:00
|
|
|
match type_parameters {
|
2015-10-26 19:31:11 +00:00
|
|
|
HasTypeParameters(..) => {
|
|
|
|
if !self.resolved {
|
|
|
|
self.type_ribs.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NoTypeParameters => {}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn with_label_rib<F>(&mut self, f: F)
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2014-09-29 23:06:13 +00:00
|
|
|
self.label_ribs.push(Rib::new(NormalRibKind));
|
2013-09-27 02:10:16 +00:00
|
|
|
f(self);
|
2015-05-14 11:40:16 +00:00
|
|
|
if !self.resolved {
|
|
|
|
self.label_ribs.pop();
|
|
|
|
}
|
2012-08-15 02:20:56 +00:00
|
|
|
}
|
2013-02-21 19:08:50 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn with_constant_rib<F>(&mut self, f: F)
|
|
|
|
where F: FnOnce(&mut Resolver)
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2014-09-29 23:06:13 +00:00
|
|
|
self.value_ribs.push(Rib::new(ConstantItemRibKind));
|
|
|
|
self.type_ribs.push(Rib::new(ConstantItemRibKind));
|
2013-09-27 02:10:16 +00:00
|
|
|
f(self);
|
2015-05-14 11:40:16 +00:00
|
|
|
if !self.resolved {
|
|
|
|
self.type_ribs.pop();
|
|
|
|
self.value_ribs.pop();
|
|
|
|
}
|
2012-10-15 19:27:09 +00:00
|
|
|
}
|
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
fn resolve_function(&mut self, rib_kind: RibKind<'a>, declaration: &FnDecl, block: &Block) {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Create a value rib for the function.
|
2015-02-05 07:19:07 +00:00
|
|
|
self.value_ribs.push(Rib::new(rib_kind));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2012-08-15 02:20:56 +00:00
|
|
|
// Create a label rib for the function.
|
2015-02-05 07:19:07 +00:00
|
|
|
self.label_ribs.push(Rib::new(rib_kind));
|
2012-08-15 02:20:56 +00:00
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
// Add each argument to the rib.
|
|
|
|
let mut bindings_list = HashMap::new();
|
|
|
|
for argument in &declaration.inputs {
|
2015-10-26 19:31:11 +00:00
|
|
|
self.resolve_pattern(&*argument.pat, ArgumentIrrefutableMode, &mut bindings_list);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
self.visit_ty(&*argument.ty);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
debug!("(resolving function) recorded argument");
|
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_fn_ret_ty(self, &declaration.output);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
// Resolve the function body.
|
2015-11-17 23:56:13 +00:00
|
|
|
self.visit_block(block);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
debug!("(resolving function) leaving function");
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-05-14 11:40:16 +00:00
|
|
|
if !self.resolved {
|
|
|
|
self.label_ribs.pop();
|
|
|
|
self.value_ribs.pop();
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_trait_reference(&mut self,
|
2014-07-08 02:26:02 +00:00
|
|
|
id: NodeId,
|
2015-01-30 08:09:44 +00:00
|
|
|
trait_path: &Path,
|
2015-02-05 07:19:07 +00:00
|
|
|
path_depth: usize)
|
2015-02-17 04:44:23 +00:00
|
|
|
-> Result<PathResolution, ()> {
|
|
|
|
if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
|
2016-01-20 19:31:10 +00:00
|
|
|
if let Def::Trait(_) = path_res.base_def {
|
2015-02-17 04:44:23 +00:00
|
|
|
debug!("(resolving trait) found trait def: {:?}", path_res);
|
|
|
|
Ok(path_res)
|
|
|
|
} else {
|
2015-12-20 21:00:43 +00:00
|
|
|
let mut err =
|
|
|
|
resolve_struct_error(self,
|
|
|
|
trait_path.span,
|
|
|
|
ResolutionError::IsNotATrait(&*path_names_to_string(trait_path,
|
|
|
|
path_depth)));
|
2015-02-05 07:19:07 +00:00
|
|
|
|
|
|
|
// If it's a typedef, give a note
|
2016-01-20 19:31:10 +00:00
|
|
|
if let Def::TyAlias(..) = path_res.base_def {
|
2015-12-23 06:27:20 +00:00
|
|
|
err.span_note(trait_path.span,
|
|
|
|
"`type` aliases cannot be used for traits");
|
2014-06-19 22:23:51 +00:00
|
|
|
}
|
2015-12-23 06:27:20 +00:00
|
|
|
err.emit();
|
2015-02-05 07:19:07 +00:00
|
|
|
Err(())
|
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
} else {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
trait_path.span,
|
2015-10-26 19:31:11 +00:00
|
|
|
ResolutionError::UndeclaredTraitName(&*path_names_to_string(trait_path,
|
|
|
|
path_depth)));
|
2015-02-17 04:44:23 +00:00
|
|
|
Err(())
|
2013-03-27 10:16:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
fn resolve_generics(&mut self, generics: &Generics) {
|
2015-06-11 12:56:07 +00:00
|
|
|
for type_parameter in generics.ty_params.iter() {
|
2015-09-20 13:47:24 +00:00
|
|
|
self.check_if_primitive_type_name(type_parameter.name, type_parameter.span);
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
|
|
|
for predicate in &generics.where_clause.predicates {
|
2014-11-29 04:08:30 +00:00
|
|
|
match predicate {
|
2015-07-31 07:04:06 +00:00
|
|
|
&hir::WherePredicate::BoundPredicate(_) |
|
|
|
|
&hir::WherePredicate::RegionPredicate(_) => {}
|
|
|
|
&hir::WherePredicate::EqPredicate(ref eq_pred) => {
|
2015-02-17 04:44:23 +00:00
|
|
|
let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
|
2016-01-20 19:31:10 +00:00
|
|
|
if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res {
|
2015-02-17 04:44:23 +00:00
|
|
|
self.record_def(eq_pred.id, path_res.unwrap());
|
|
|
|
} else {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
eq_pred.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UndeclaredAssociatedType);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(eq_pred.id, err_path_resolution());
|
2014-11-29 04:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-11 16:32:26 +00:00
|
|
|
}
|
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_generics(self, generics);
|
2012-07-10 20:44:20 +00:00
|
|
|
}
|
|
|
|
|
2015-04-03 04:13:52 +00:00
|
|
|
fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
|
|
|
|
where F: FnOnce(&mut Resolver) -> T
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2014-05-08 21:35:09 +00:00
|
|
|
// Handle nested impls (inside fn bodies)
|
|
|
|
let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
|
|
|
|
let result = f(self);
|
|
|
|
self.current_self_type = previous_value;
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
|
2015-04-03 04:13:52 +00:00
|
|
|
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2015-02-05 07:19:07 +00:00
|
|
|
let mut new_val = None;
|
2015-04-03 04:13:52 +00:00
|
|
|
let mut new_id = None;
|
2015-02-24 06:28:11 +00:00
|
|
|
if let Some(trait_ref) = opt_trait_ref {
|
2015-04-03 04:13:52 +00:00
|
|
|
if let Ok(path_res) = self.resolve_trait_reference(trait_ref.ref_id,
|
2015-10-26 19:31:11 +00:00
|
|
|
&trait_ref.path,
|
|
|
|
0) {
|
2015-04-03 04:13:52 +00:00
|
|
|
assert!(path_res.depth == 0);
|
|
|
|
self.record_def(trait_ref.ref_id, path_res);
|
|
|
|
new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
|
|
|
|
new_id = Some(path_res.base_def.def_id());
|
2015-12-11 07:59:11 +00:00
|
|
|
} else {
|
|
|
|
self.record_def(trait_ref.ref_id, err_path_resolution());
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_trait_ref(self, trait_ref);
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
|
2015-04-03 04:13:52 +00:00
|
|
|
let result = f(self, new_id);
|
2014-05-08 21:35:09 +00:00
|
|
|
self.current_trait_ref = original_trait_ref;
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2015-04-03 04:13:52 +00:00
|
|
|
fn with_self_rib<F>(&mut self, self_def: Def, f: F)
|
|
|
|
where F: FnOnce(&mut Resolver)
|
|
|
|
{
|
|
|
|
let mut self_type_rib = Rib::new(NormalRibKind);
|
|
|
|
|
|
|
|
// plain insert (no renaming, types are not currently hygienic....)
|
|
|
|
let name = special_names::type_self;
|
|
|
|
self_type_rib.bindings.insert(name, DlDef(self_def));
|
|
|
|
self.type_ribs.push(self_type_rib);
|
|
|
|
f(self);
|
2015-05-14 11:40:16 +00:00
|
|
|
if !self.resolved {
|
|
|
|
self.type_ribs.pop();
|
|
|
|
}
|
2015-04-03 04:13:52 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_implementation(&mut self,
|
2014-05-31 22:53:13 +00:00
|
|
|
generics: &Generics,
|
|
|
|
opt_trait_reference: &Option<TraitRef>,
|
|
|
|
self_type: &Ty,
|
2015-04-03 04:13:52 +00:00
|
|
|
item_id: NodeId,
|
2015-12-07 14:17:41 +00:00
|
|
|
impl_items: &[ImplItem]) {
|
2012-05-22 17:54:12 +00:00
|
|
|
// If applicable, create a rib for the type parameters.
|
2013-11-21 23:42:55 +00:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
2014-05-31 22:53:13 +00:00
|
|
|
TypeSpace,
|
2015-02-05 07:19:07 +00:00
|
|
|
ItemRibKind),
|
2013-11-21 23:42:55 +00:00
|
|
|
|this| {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Resolve the type parameters.
|
2015-02-05 07:19:07 +00:00
|
|
|
this.visit_generics(generics);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2012-07-31 17:27:51 +00:00
|
|
|
// Resolve the trait reference, if necessary.
|
2015-04-03 04:13:52 +00:00
|
|
|
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
|
2014-05-08 21:35:09 +00:00
|
|
|
// Resolve the self type.
|
2015-02-05 07:19:07 +00:00
|
|
|
this.visit_ty(self_type);
|
2014-05-08 21:35:09 +00:00
|
|
|
|
2016-01-20 19:31:10 +00:00
|
|
|
this.with_self_rib(Def::SelfTy(trait_id, Some((item_id, self_type.id))), |this| {
|
2015-04-03 04:13:52 +00:00
|
|
|
this.with_current_self_type(self_type, |this| {
|
|
|
|
for impl_item in impl_items {
|
|
|
|
match impl_item.node {
|
2015-11-12 14:57:51 +00:00
|
|
|
hir::ImplItemKind::Const(..) => {
|
2015-07-18 23:56:15 +00:00
|
|
|
// If this is a trait impl, ensure the const
|
2015-03-16 01:35:25 +00:00
|
|
|
// exists in trait
|
2015-09-20 01:50:30 +00:00
|
|
|
this.check_trait_item(impl_item.name,
|
2015-07-18 23:56:15 +00:00
|
|
|
impl_item.span,
|
|
|
|
|n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
|
2015-03-16 01:35:25 +00:00
|
|
|
this.with_constant_rib(|this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_impl_item(this, impl_item);
|
2015-03-16 01:35:25 +00:00
|
|
|
});
|
|
|
|
}
|
2015-11-12 14:57:51 +00:00
|
|
|
hir::ImplItemKind::Method(ref sig, _) => {
|
2015-04-03 04:13:52 +00:00
|
|
|
// If this is a trait impl, ensure the method
|
|
|
|
// exists in trait
|
2015-09-20 01:50:30 +00:00
|
|
|
this.check_trait_item(impl_item.name,
|
2015-07-18 23:56:15 +00:00
|
|
|
impl_item.span,
|
|
|
|
|n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
|
2015-04-03 04:13:52 +00:00
|
|
|
|
|
|
|
// We also need a new scope for the method-
|
|
|
|
// specific type parameters.
|
|
|
|
let type_parameters =
|
|
|
|
HasTypeParameters(&sig.generics,
|
|
|
|
FnSpace,
|
|
|
|
MethodRibKind);
|
|
|
|
this.with_type_parameter_rib(type_parameters, |this| {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_impl_item(this, impl_item);
|
2015-04-03 04:13:52 +00:00
|
|
|
});
|
|
|
|
}
|
2015-11-12 14:57:51 +00:00
|
|
|
hir::ImplItemKind::Type(ref ty) => {
|
2015-07-18 23:56:15 +00:00
|
|
|
// If this is a trait impl, ensure the type
|
2015-04-03 04:13:52 +00:00
|
|
|
// exists in trait
|
2015-09-20 01:50:30 +00:00
|
|
|
this.check_trait_item(impl_item.name,
|
2015-07-18 23:56:15 +00:00
|
|
|
impl_item.span,
|
|
|
|
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
|
2014-08-06 02:44:21 +00:00
|
|
|
|
2015-04-03 04:13:52 +00:00
|
|
|
this.visit_ty(ty);
|
|
|
|
}
|
2014-08-06 02:44:21 +00:00
|
|
|
}
|
2014-08-04 20:56:56 +00:00
|
|
|
}
|
2015-04-03 04:13:52 +00:00
|
|
|
});
|
2014-05-08 21:35:09 +00:00
|
|
|
});
|
|
|
|
});
|
2013-11-21 23:42:55 +00:00
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-07-18 23:56:15 +00:00
|
|
|
fn check_trait_item<F>(&self, name: Name, span: Span, err: F)
|
2015-10-26 19:31:11 +00:00
|
|
|
where F: FnOnce(Name, &str) -> ResolutionError
|
|
|
|
{
|
|
|
|
// If there is a TraitRef in scope for an impl, then the method must be in the
|
|
|
|
// trait.
|
2015-01-31 17:20:46 +00:00
|
|
|
if let Some((did, ref trait_ref)) = self.current_trait_ref {
|
2015-02-11 07:32:25 +00:00
|
|
|
if !self.trait_item_map.contains_key(&(name, did)) {
|
2015-03-15 21:44:19 +00:00
|
|
|
let path_str = path_names_to_string(&trait_ref.path, 0);
|
2015-10-26 19:31:11 +00:00
|
|
|
resolve_error(self, span, err(name, &*path_str));
|
2014-06-18 13:16:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
fn resolve_local(&mut self, local: &Local) {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Resolve the type.
|
2015-09-28 21:23:54 +00:00
|
|
|
walk_list!(self, visit_ty, &local.ty);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
// Resolve the initializer.
|
2015-09-28 21:23:54 +00:00
|
|
|
walk_list!(self, visit_expr, &local.init);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// Resolve the pattern.
|
2015-10-26 19:31:11 +00:00
|
|
|
self.resolve_pattern(&*local.pat, LocalIrrefutableMode, &mut HashMap::new());
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-09-05 21:15:00 +00:00
|
|
|
// build a map from pattern identifiers to binding-info's.
|
|
|
|
// this is done hygienically. This could arise for a macro
|
|
|
|
// that expands into an or-pattern where one 'x' was from the
|
|
|
|
// user and one 'x' came from the macro.
|
2014-04-14 08:30:59 +00:00
|
|
|
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
|
2013-04-03 13:28:36 +00:00
|
|
|
let mut result = HashMap::new();
|
2015-12-01 17:38:40 +00:00
|
|
|
pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
|
|
|
|
let name = path1.node;
|
2015-10-26 19:31:11 +00:00
|
|
|
result.insert(name,
|
|
|
|
BindingInfo {
|
|
|
|
span: sp,
|
|
|
|
binding_mode: binding_mode,
|
|
|
|
});
|
2013-11-21 23:42:55 +00:00
|
|
|
});
|
2012-08-06 14:20:23 +00:00
|
|
|
return result;
|
2012-07-11 01:24:41 +00:00
|
|
|
}
|
|
|
|
|
2013-09-05 21:15:00 +00:00
|
|
|
// check that all of the arms in an or-pattern have exactly the
|
|
|
|
// same set of bindings, with the same binding modes for each.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn check_consistent_bindings(&mut self, arm: &Arm) {
|
2015-03-24 23:53:34 +00:00
|
|
|
if arm.pats.is_empty() {
|
2015-10-26 19:31:11 +00:00
|
|
|
return;
|
2014-02-28 23:25:15 +00:00
|
|
|
}
|
2014-10-15 06:05:01 +00:00
|
|
|
let map_0 = self.binding_mode_map(&*arm.pats[0]);
|
2013-08-03 16:45:23 +00:00
|
|
|
for (i, p) in arm.pats.iter().enumerate() {
|
2014-05-16 17:15:33 +00:00
|
|
|
let map_i = self.binding_mode_map(&**p);
|
2012-08-06 14:20:23 +00:00
|
|
|
|
2015-01-31 17:20:46 +00:00
|
|
|
for (&key, &binding_0) in &map_0 {
|
2014-11-06 17:25:16 +00:00
|
|
|
match map_i.get(&key) {
|
2015-10-26 19:31:11 +00:00
|
|
|
None => {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
2015-10-26 19:31:11 +00:00
|
|
|
p.span,
|
|
|
|
ResolutionError::VariableNotBoundInPattern(key, i + 1));
|
|
|
|
}
|
|
|
|
Some(binding_i) => {
|
|
|
|
if binding_0.binding_mode != binding_i.binding_mode {
|
|
|
|
resolve_error(self,
|
|
|
|
binding_i.span,
|
|
|
|
ResolutionError::VariableBoundWithDifferentMode(key,
|
|
|
|
i + 1));
|
|
|
|
}
|
2014-05-28 16:24:28 +00:00
|
|
|
}
|
2012-08-06 14:20:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-31 17:20:46 +00:00
|
|
|
for (&key, &binding) in &map_i {
|
2013-02-08 22:08:02 +00:00
|
|
|
if !map_0.contains_key(&key) {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
binding.span,
|
2015-10-26 19:31:11 +00:00
|
|
|
ResolutionError::VariableNotBoundInParentPattern(key, i + 1));
|
2012-08-06 14:20:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-11 01:24:41 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_arm(&mut self, arm: &Arm) {
|
2014-09-29 23:06:13 +00:00
|
|
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2013-12-21 23:27:26 +00:00
|
|
|
let mut bindings_list = HashMap::new();
|
2015-01-31 17:20:46 +00:00
|
|
|
for pattern in &arm.pats {
|
2014-06-10 21:39:10 +00:00
|
|
|
self.resolve_pattern(&**pattern, RefutableMode, &mut bindings_list);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2012-07-11 01:24:41 +00:00
|
|
|
// This has to happen *after* we determine which
|
|
|
|
// pat_idents are variants
|
|
|
|
self.check_consistent_bindings(arm);
|
|
|
|
|
2015-09-28 21:23:54 +00:00
|
|
|
walk_list!(self, visit_expr, &arm.guard);
|
2015-02-05 07:19:07 +00:00
|
|
|
self.visit_expr(&*arm.body);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-05-14 11:40:16 +00:00
|
|
|
if !self.resolved {
|
|
|
|
self.value_ribs.pop();
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
fn resolve_block(&mut self, block: &Block) {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving block) entering block");
|
2012-05-22 17:54:12 +00:00
|
|
|
// Move down in the graph, if there's an anonymous module rooted here.
|
2016-01-11 21:19:29 +00:00
|
|
|
let orig_module = self.current_module;
|
2016-01-22 09:55:29 +00:00
|
|
|
let anonymous_module =
|
|
|
|
orig_module.anonymous_children.borrow().get(&block.id).map(|module| *module);
|
|
|
|
|
|
|
|
if let Some(anonymous_module) = anonymous_module {
|
|
|
|
debug!("(resolving block) found anonymous module, moving down");
|
|
|
|
self.value_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
|
|
|
|
self.type_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
|
|
|
|
self.current_module = anonymous_module;
|
|
|
|
} else {
|
|
|
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Descend into the block.
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_block(self, block);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// Move back up.
|
2015-05-14 11:40:16 +00:00
|
|
|
if !self.resolved {
|
2015-06-06 03:19:15 +00:00
|
|
|
self.current_module = orig_module;
|
2015-05-14 11:40:16 +00:00
|
|
|
self.value_ribs.pop();
|
2016-01-22 09:55:29 +00:00
|
|
|
if let Some(_) = anonymous_module {
|
|
|
|
self.type_ribs.pop();
|
|
|
|
}
|
2015-05-14 11:40:16 +00:00
|
|
|
}
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving block) leaving block");
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_type(&mut self, ty: &Ty) {
|
2012-08-06 19:34:08 +00:00
|
|
|
match ty.node {
|
2015-02-17 17:29:13 +00:00
|
|
|
TyPath(ref maybe_qself, ref path) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
let resolution = match self.resolve_possibly_assoc_item(ty.id,
|
|
|
|
maybe_qself.as_ref(),
|
|
|
|
path,
|
|
|
|
TypeNS,
|
|
|
|
true) {
|
|
|
|
// `<T>::a::b::c` is resolved by typeck alone.
|
|
|
|
TypecheckRequired => {
|
|
|
|
// Resolve embedded types.
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_ty(self, ty);
|
2015-10-26 19:31:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ResolveAttempt(resolution) => resolution,
|
|
|
|
};
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// This is a path in the type namespace. Walk through scopes
|
2014-03-06 07:35:12 +00:00
|
|
|
// looking for it.
|
2015-02-17 04:44:23 +00:00
|
|
|
match resolution {
|
2012-08-20 19:23:37 +00:00
|
|
|
Some(def) => {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Write the result into the def map.
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}",
|
2015-03-15 21:44:19 +00:00
|
|
|
path_names_to_string(path, 0),
|
2015-10-26 19:31:11 +00:00
|
|
|
ty.id,
|
|
|
|
def);
|
2015-01-29 19:18:17 +00:00
|
|
|
self.record_def(ty.id, def);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(ty.id, err_path_resolution());
|
|
|
|
|
2015-02-05 11:20:48 +00:00
|
|
|
// Keep reporting some errors even if they're ignored above.
|
|
|
|
self.resolve_path(ty.id, path, 0, TypeNS, true);
|
|
|
|
|
2015-02-17 17:29:13 +00:00
|
|
|
let kind = if maybe_qself.is_some() {
|
|
|
|
"associated type"
|
|
|
|
} else {
|
|
|
|
"type name"
|
2015-01-31 03:51:21 +00:00
|
|
|
};
|
2015-02-17 17:29:13 +00:00
|
|
|
|
2015-05-04 11:27:02 +00:00
|
|
|
let self_type_name = special_idents::type_self.name;
|
2015-10-26 19:31:11 +00:00
|
|
|
let is_invalid_self_type_name = path.segments.len() > 0 &&
|
|
|
|
maybe_qself.is_none() &&
|
|
|
|
path.segments[0].identifier.name ==
|
|
|
|
self_type_name;
|
2015-07-12 22:31:09 +00:00
|
|
|
if is_invalid_self_type_name {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
ty.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::SelfUsedOutsideImplOrTrait);
|
2015-05-04 11:27:02 +00:00
|
|
|
} else {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
ty.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UseOfUndeclared(
|
2015-07-14 13:37:52 +00:00
|
|
|
kind,
|
|
|
|
&*path_names_to_string(path,
|
|
|
|
0))
|
|
|
|
);
|
2015-07-12 22:31:09 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-20 20:08:48 +00:00
|
|
|
}
|
2015-02-05 07:19:07 +00:00
|
|
|
_ => {}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-02-05 07:19:07 +00:00
|
|
|
// Resolve embedded types.
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_ty(self, ty);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_pattern(&mut self,
|
2014-04-14 08:30:59 +00:00
|
|
|
pattern: &Pat,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
mode: PatternBindingMode,
|
|
|
|
// Maps idents to the node ID for the (outermost)
|
|
|
|
// pattern that binds them
|
2014-10-01 00:11:34 +00:00
|
|
|
bindings_list: &mut HashMap<Name, NodeId>) {
|
2012-07-27 20:03:04 +00:00
|
|
|
let pat_id = pattern.id;
|
2013-11-21 23:42:55 +00:00
|
|
|
walk_pat(pattern, |pattern| {
|
2012-08-06 19:34:08 +00:00
|
|
|
match pattern.node {
|
2015-07-28 13:52:54 +00:00
|
|
|
PatIdent(binding_mode, ref path1, ref at_rhs) => {
|
|
|
|
// The meaning of PatIdent with no type parameters
|
2012-10-30 22:53:06 +00:00
|
|
|
// depends on whether an enum variant or unit-like struct
|
|
|
|
// with that name is in scope. The probing lookup has to
|
|
|
|
// be careful not to emit spurious errors. Only matching
|
|
|
|
// patterns (match) can match nullary variants or
|
2015-07-28 13:52:54 +00:00
|
|
|
// unit-like structs. For binding patterns (let
|
|
|
|
// and the LHS of @-patterns), matching such a value is
|
|
|
|
// simply disallowed (since it's rarely what you want).
|
|
|
|
let const_ok = mode == RefutableMode && at_rhs.is_none();
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2014-07-01 01:02:14 +00:00
|
|
|
let ident = path1.node;
|
2015-12-01 17:38:40 +00:00
|
|
|
let renamed = ident.name;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-12-01 17:38:40 +00:00
|
|
|
match self.resolve_bare_identifier_pattern(ident.unhygienic_name,
|
|
|
|
pattern.span) {
|
2015-07-28 13:52:54 +00:00
|
|
|
FoundStructOrEnumVariant(def, lp) if const_ok => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving pattern) resolving `{}` to struct or enum variant",
|
2015-07-08 20:55:22 +00:00
|
|
|
renamed);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
self.enforce_default_binding_mode(pattern,
|
|
|
|
binding_mode,
|
|
|
|
"an enum variant");
|
|
|
|
self.record_def(pattern.id,
|
|
|
|
PathResolution {
|
|
|
|
base_def: def,
|
|
|
|
last_private: lp,
|
|
|
|
depth: 0,
|
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2013-11-28 20:22:53 +00:00
|
|
|
FoundStructOrEnumVariant(..) => {
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
2014-05-16 17:45:16 +00:00
|
|
|
pattern.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(
|
2015-07-14 13:37:52 +00:00
|
|
|
renamed)
|
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2012-07-07 02:06:58 +00:00
|
|
|
}
|
2015-11-11 19:16:57 +00:00
|
|
|
FoundConst(def, lp, _) if const_ok => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving pattern) resolving `{}` to constant", renamed);
|
|
|
|
|
|
|
|
self.enforce_default_binding_mode(pattern, binding_mode, "a constant");
|
|
|
|
self.record_def(pattern.id,
|
|
|
|
PathResolution {
|
|
|
|
base_def: def,
|
|
|
|
last_private: lp,
|
|
|
|
depth: 0,
|
|
|
|
});
|
2012-11-13 06:10:15 +00:00
|
|
|
}
|
2015-11-11 19:16:57 +00:00
|
|
|
FoundConst(def, _, name) => {
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
|
|
|
pattern.span,
|
2015-11-11 20:38:37 +00:00
|
|
|
ResolutionError::OnlyIrrefutablePatternsAllowedHere(def.def_id(),
|
|
|
|
name)
|
2015-07-14 13:37:52 +00:00
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2012-07-07 02:06:58 +00:00
|
|
|
}
|
2012-10-30 22:53:06 +00:00
|
|
|
BareIdentifierPatternUnresolved => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving pattern) binding `{}`", renamed);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-09-09 18:23:43 +00:00
|
|
|
let def_id = self.ast_map.local_def_id(pattern.id);
|
2016-01-20 19:31:10 +00:00
|
|
|
let def = Def::Local(def_id, pattern.id);
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// Record the definition so that later passes
|
|
|
|
// will be able to distinguish variants from
|
|
|
|
// locals in patterns.
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
self.record_def(pattern.id,
|
|
|
|
PathResolution {
|
|
|
|
base_def: def,
|
|
|
|
last_private: LastMod(AllPublic),
|
|
|
|
depth: 0,
|
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
|
|
|
|
// Add the binding to the local ribs, if it
|
|
|
|
// doesn't already exist in the bindings list. (We
|
|
|
|
// must not add it if it's in the bindings list
|
|
|
|
// because that breaks the assumptions later
|
|
|
|
// passes make about or-patterns.)
|
2014-06-10 21:39:10 +00:00
|
|
|
if !bindings_list.contains_key(&renamed) {
|
|
|
|
let this = &mut *self;
|
2014-09-29 23:06:13 +00:00
|
|
|
let last_rib = this.value_ribs.last_mut().unwrap();
|
|
|
|
last_rib.bindings.insert(renamed, DlDef(def));
|
2014-06-10 21:39:10 +00:00
|
|
|
bindings_list.insert(renamed, pat_id);
|
2014-10-09 04:28:50 +00:00
|
|
|
} else if mode == ArgumentIrrefutableMode &&
|
2015-10-26 19:31:11 +00:00
|
|
|
bindings_list.contains_key(&renamed) {
|
2014-10-09 04:28:50 +00:00
|
|
|
// Forbid duplicate bindings in the same
|
|
|
|
// parameter list.
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
|
|
|
pattern.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
|
2015-07-28 16:07:20 +00:00
|
|
|
&ident.name.as_str())
|
2015-07-14 13:37:52 +00:00
|
|
|
);
|
2015-10-26 19:31:11 +00:00
|
|
|
} else if bindings_list.get(&renamed) == Some(&pat_id) {
|
2014-06-10 21:39:10 +00:00
|
|
|
// Then this is a duplicate variable in the
|
|
|
|
// same disjunction, which is an error.
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
|
|
|
pattern.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
|
2015-07-28 16:07:20 +00:00
|
|
|
&ident.name.as_str())
|
2015-07-14 13:37:52 +00:00
|
|
|
);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2014-06-10 21:39:10 +00:00
|
|
|
// Else, not bound in the same pattern: do
|
|
|
|
// nothing.
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-02 01:45:37 +00:00
|
|
|
PatEnum(ref path, _) => {
|
2013-03-21 07:27:26 +00:00
|
|
|
// This must be an enum variant, struct or const.
|
2015-10-26 19:31:11 +00:00
|
|
|
let resolution = match self.resolve_possibly_assoc_item(pat_id,
|
|
|
|
None,
|
|
|
|
path,
|
|
|
|
ValueNS,
|
|
|
|
false) {
|
|
|
|
// The below shouldn't happen because all
|
|
|
|
// qualified paths should be in PatQPath.
|
|
|
|
TypecheckRequired =>
|
|
|
|
self.session.span_bug(path.span,
|
|
|
|
"resolve_possibly_assoc_item claimed
|
|
|
|
\
|
|
|
|
that a path in PatEnum requires typecheck
|
|
|
|
\
|
|
|
|
to resolve, but qualified paths should be
|
|
|
|
\
|
|
|
|
PatQPath"),
|
|
|
|
ResolveAttempt(resolution) => resolution,
|
|
|
|
};
|
2015-03-25 16:53:28 +00:00
|
|
|
if let Some(path_res) = resolution {
|
2015-02-17 04:44:23 +00:00
|
|
|
match path_res.base_def {
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::Struct(..) if path_res.depth == 0 => {
|
2016-01-20 18:08:50 +00:00
|
|
|
self.record_def(pattern.id, path_res);
|
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::Variant(..) | Def::Const(..) => {
|
2015-02-17 04:44:23 +00:00
|
|
|
self.record_def(pattern.id, path_res);
|
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::Static(..) => {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(&self,
|
|
|
|
path.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::StaticVariableReference);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2015-02-17 04:44:23 +00:00
|
|
|
}
|
2015-03-25 16:53:28 +00:00
|
|
|
_ => {
|
|
|
|
// If anything ends up here entirely resolved,
|
|
|
|
// it's an error. If anything ends up here
|
|
|
|
// partially resolved, that's OK, because it may
|
2015-05-01 03:46:37 +00:00
|
|
|
// be a `T::CONST` that typeck will resolve.
|
2015-03-25 16:53:28 +00:00
|
|
|
if path_res.depth == 0 {
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
2015-03-25 16:53:28 +00:00
|
|
|
path.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::NotAnEnumVariantStructOrConst(
|
2015-07-28 16:07:20 +00:00
|
|
|
&path.segments
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.identifier
|
|
|
|
.name
|
|
|
|
.as_str())
|
2015-07-14 13:37:52 +00:00
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2015-03-25 16:53:28 +00:00
|
|
|
} else {
|
2015-10-26 19:31:11 +00:00
|
|
|
let const_name = path.segments
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.identifier
|
|
|
|
.name;
|
2015-05-01 03:46:37 +00:00
|
|
|
let traits = self.get_traits_containing_item(const_name);
|
|
|
|
self.trait_map.insert(pattern.id, traits);
|
2015-03-25 16:53:28 +00:00
|
|
|
self.record_def(pattern.id, path_res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
|
|
|
path.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::UnresolvedEnumVariantStructOrConst(
|
2015-07-28 16:07:20 +00:00
|
|
|
&path.segments.last().unwrap().identifier.name.as_str())
|
2015-07-14 13:37:52 +00:00
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2015-03-25 16:53:28 +00:00
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_path(self, path);
|
2015-03-25 16:53:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PatQPath(ref qself, ref path) => {
|
|
|
|
// Associated constants only.
|
2015-10-26 19:31:11 +00:00
|
|
|
let resolution = match self.resolve_possibly_assoc_item(pat_id,
|
|
|
|
Some(qself),
|
|
|
|
path,
|
|
|
|
ValueNS,
|
|
|
|
false) {
|
|
|
|
TypecheckRequired => {
|
|
|
|
// All `<T>::CONST` should end up here, and will
|
|
|
|
// require use of the trait map to resolve
|
|
|
|
// during typechecking.
|
|
|
|
let const_name = path.segments
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.identifier
|
|
|
|
.name;
|
|
|
|
let traits = self.get_traits_containing_item(const_name);
|
|
|
|
self.trait_map.insert(pattern.id, traits);
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_pat(self, pattern);
|
2015-10-26 19:31:11 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
ResolveAttempt(resolution) => resolution,
|
|
|
|
};
|
2015-03-25 16:53:28 +00:00
|
|
|
if let Some(path_res) = resolution {
|
|
|
|
match path_res.base_def {
|
|
|
|
// All `<T as Trait>::CONST` should end up here, and
|
|
|
|
// have the trait already selected.
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::AssociatedConst(..) => {
|
2015-03-25 16:53:28 +00:00
|
|
|
self.record_def(pattern.id, path_res);
|
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
_ => {
|
2015-07-14 13:37:52 +00:00
|
|
|
resolve_error(
|
2015-07-14 14:32:43 +00:00
|
|
|
self,
|
|
|
|
path.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::NotAnAssociatedConst(
|
2015-07-28 16:07:20 +00:00
|
|
|
&path.segments.last().unwrap().identifier.name.as_str()
|
2015-07-14 13:37:52 +00:00
|
|
|
)
|
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2015-02-17 04:44:23 +00:00
|
|
|
}
|
2013-03-13 05:39:32 +00:00
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
} else {
|
2015-10-26 19:31:11 +00:00
|
|
|
resolve_error(self,
|
|
|
|
path.span,
|
|
|
|
ResolutionError::UnresolvedAssociatedConst(&path.segments
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.identifier
|
|
|
|
.name
|
|
|
|
.as_str()));
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2013-03-13 05:39:32 +00:00
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_pat(self, pattern);
|
2012-07-10 19:29:30 +00:00
|
|
|
}
|
|
|
|
|
2013-09-02 01:45:37 +00:00
|
|
|
PatStruct(ref path, _, _) => {
|
2015-01-31 19:20:24 +00:00
|
|
|
match self.resolve_path(pat_id, path, 0, TypeNS, false) {
|
2014-07-04 23:45:47 +00:00
|
|
|
Some(definition) => {
|
2012-08-08 02:12:58 +00:00
|
|
|
self.record_def(pattern.id, definition);
|
|
|
|
}
|
2012-12-10 20:37:50 +00:00
|
|
|
result => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving pattern) didn't find struct def: {:?}", result);
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(
|
|
|
|
self,
|
|
|
|
path.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::DoesNotNameAStruct(
|
2015-07-14 14:32:43 +00:00
|
|
|
&*path_names_to_string(path, 0))
|
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(pattern.id, err_path_resolution());
|
2012-08-07 00:01:14 +00:00
|
|
|
}
|
|
|
|
}
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_path(self, path);
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PatLit(_) | PatRange(..) => {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_pat(self, pattern);
|
2012-08-07 00:01:14 +00:00
|
|
|
}
|
|
|
|
|
2012-08-01 02:25:24 +00:00
|
|
|
_ => {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
2013-08-02 06:17:20 +00:00
|
|
|
true
|
2013-11-21 23:42:55 +00:00
|
|
|
});
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn resolve_bare_identifier_pattern(&mut self,
|
|
|
|
name: Name,
|
|
|
|
span: Span)
|
2014-04-14 08:30:59 +00:00
|
|
|
-> BareIdentifierPatternResolution {
|
2016-01-11 21:19:29 +00:00
|
|
|
let module = self.current_module;
|
2015-12-12 03:30:53 +00:00
|
|
|
match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((target, _)) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
|
|
|
|
name,
|
2016-01-14 01:42:45 +00:00
|
|
|
&target.binding);
|
2015-11-16 02:10:09 +00:00
|
|
|
match target.binding.def() {
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2015-10-26 19:31:11 +00:00
|
|
|
panic!("resolved name in the value namespace to a set of name bindings \
|
|
|
|
with no def?!");
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-11-16 02:10:09 +00:00
|
|
|
// For the two success cases, this lookup can be
|
|
|
|
// considered as not having a private component because
|
|
|
|
// the lookup happened only within the current module.
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(def @ Def::Variant(..)) | Some(def @ Def::Struct(..)) => {
|
2015-11-16 02:10:09 +00:00
|
|
|
return FoundStructOrEnumVariant(def, LastMod(AllPublic));
|
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => {
|
2015-11-16 02:10:09 +00:00
|
|
|
return FoundConst(def, LastMod(AllPublic), name);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Static(..)) => {
|
2015-11-16 02:10:09 +00:00
|
|
|
resolve_error(self, span, ResolutionError::StaticVariableReference);
|
|
|
|
return BareIdentifierPatternUnresolved;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-11-16 02:10:09 +00:00
|
|
|
_ => return BareIdentifierPatternUnresolved
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-26 08:40:42 +00:00
|
|
|
Indeterminate => return BareIdentifierPatternUnresolved,
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => {
|
|
|
|
match err {
|
|
|
|
Some((span, msg)) => {
|
2015-07-14 17:42:38 +00:00
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
|
2014-06-05 21:37:52 +00:00
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
None => (),
|
2014-06-05 21:37:52 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolve bare identifier pattern) failed to find {}", name);
|
2012-10-30 22:53:06 +00:00
|
|
|
return BareIdentifierPatternUnresolved;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-25 16:53:28 +00:00
|
|
|
/// Handles paths that may refer to associated items
|
|
|
|
fn resolve_possibly_assoc_item(&mut self,
|
|
|
|
id: NodeId,
|
2015-07-31 07:04:06 +00:00
|
|
|
maybe_qself: Option<&hir::QSelf>,
|
2015-03-25 16:53:28 +00:00
|
|
|
path: &Path,
|
|
|
|
namespace: Namespace,
|
|
|
|
check_ribs: bool)
|
2015-10-26 19:31:11 +00:00
|
|
|
-> AssocItemResolveResult {
|
2015-05-07 07:52:38 +00:00
|
|
|
let max_assoc_types;
|
|
|
|
|
2015-03-25 16:53:28 +00:00
|
|
|
match maybe_qself {
|
2015-05-07 07:52:38 +00:00
|
|
|
Some(qself) => {
|
|
|
|
if qself.position == 0 {
|
|
|
|
return TypecheckRequired;
|
|
|
|
}
|
|
|
|
max_assoc_types = path.segments.len() - qself.position;
|
|
|
|
// Make sure the trait is valid.
|
|
|
|
let _ = self.resolve_trait_reference(id, path, max_assoc_types);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
max_assoc_types = path.segments.len();
|
|
|
|
}
|
2015-03-25 16:53:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut resolution = self.with_no_errors(|this| {
|
|
|
|
this.resolve_path(id, path, 0, namespace, check_ribs)
|
|
|
|
});
|
|
|
|
for depth in 1..max_assoc_types {
|
|
|
|
if resolution.is_some() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
self.with_no_errors(|this| {
|
2015-10-26 19:31:11 +00:00
|
|
|
resolution = this.resolve_path(id, path, depth, TypeNS, true);
|
2015-03-25 16:53:28 +00:00
|
|
|
});
|
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
|
2015-03-25 16:53:28 +00:00
|
|
|
// A module is not a valid type or value.
|
|
|
|
resolution = None;
|
|
|
|
}
|
|
|
|
ResolveAttempt(resolution)
|
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
/// If `check_ribs` is true, checks the local definitions first; i.e.
|
|
|
|
/// doesn't skip straight to the containing module.
|
2015-02-17 04:44:23 +00:00
|
|
|
/// Skips `path_depth` trailing segments, which is also reflected in the
|
|
|
|
/// returned value. See `middle::def::PathResolution` for more info.
|
2015-05-14 11:40:16 +00:00
|
|
|
pub fn resolve_path(&mut self,
|
|
|
|
id: NodeId,
|
|
|
|
path: &Path,
|
|
|
|
path_depth: usize,
|
|
|
|
namespace: Namespace,
|
2015-10-26 19:31:11 +00:00
|
|
|
check_ribs: bool)
|
|
|
|
-> Option<PathResolution> {
|
2015-01-31 19:20:24 +00:00
|
|
|
let span = path.span;
|
2015-10-26 19:31:11 +00:00
|
|
|
let segments = &path.segments[..path.segments.len() - path_depth];
|
2015-01-31 19:20:24 +00:00
|
|
|
|
2015-03-29 23:21:20 +00:00
|
|
|
let mk_res = |(def, lp)| PathResolution::new(def, lp, path_depth);
|
2015-02-17 04:44:23 +00:00
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
if path.global {
|
2015-02-05 11:20:48 +00:00
|
|
|
let def = self.resolve_crate_relative_path(span, segments, namespace);
|
2015-02-17 04:44:23 +00:00
|
|
|
return def.map(mk_res);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2014-11-29 04:08:30 +00:00
|
|
|
// Try to find a path to an item in a module.
|
2015-12-12 03:30:53 +00:00
|
|
|
let last_ident = segments.last().unwrap().identifier;
|
2015-03-29 23:21:20 +00:00
|
|
|
if segments.len() <= 1 {
|
2015-12-12 03:30:53 +00:00
|
|
|
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true);
|
2015-10-26 19:31:11 +00:00
|
|
|
return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
|
|
|
|
.map(|def| {
|
|
|
|
PathResolution::new(def, LastMod(AllPublic), path_depth)
|
|
|
|
});
|
2015-03-29 23:21:20 +00:00
|
|
|
}
|
2013-08-08 18:38:10 +00:00
|
|
|
|
2015-12-12 03:30:53 +00:00
|
|
|
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false);
|
2015-03-29 23:21:20 +00:00
|
|
|
let def = self.resolve_module_relative_path(span, segments, namespace);
|
|
|
|
match (def, unqualified_def) {
|
2015-11-03 18:44:23 +00:00
|
|
|
(Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
|
2015-03-29 23:21:20 +00:00
|
|
|
self.session
|
|
|
|
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
|
2015-10-26 19:31:11 +00:00
|
|
|
id,
|
|
|
|
span,
|
2015-03-29 23:21:20 +00:00
|
|
|
"unnecessary qualification".to_string());
|
|
|
|
}
|
|
|
|
_ => {}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-03-29 23:21:20 +00:00
|
|
|
|
|
|
|
def.map(mk_res)
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-11-03 18:44:23 +00:00
|
|
|
// Resolve a single identifier
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_identifier(&mut self,
|
2015-12-01 17:38:40 +00:00
|
|
|
identifier: hir::Ident,
|
2014-11-29 04:09:12 +00:00
|
|
|
namespace: Namespace,
|
2015-12-12 03:30:53 +00:00
|
|
|
check_ribs: bool,
|
|
|
|
record_used: bool)
|
2015-11-03 18:44:23 +00:00
|
|
|
-> Option<LocalDef> {
|
2016-01-20 09:29:47 +00:00
|
|
|
if identifier.name == special_idents::invalid.name {
|
2016-01-21 19:55:54 +00:00
|
|
|
return Some(LocalDef::from_def(Def::Err));
|
2016-01-20 09:29:47 +00:00
|
|
|
}
|
|
|
|
|
2015-02-05 07:19:07 +00:00
|
|
|
// First, check to see whether the name is a primitive type.
|
|
|
|
if namespace == TypeNS {
|
|
|
|
if let Some(&prim_ty) = self.primitive_type_table
|
|
|
|
.primitive_types
|
2015-12-01 17:38:40 +00:00
|
|
|
.get(&identifier.unhygienic_name) {
|
2016-01-20 19:31:10 +00:00
|
|
|
return Some(LocalDef::from_def(Def::PrimTy(prim_ty)));
|
2015-02-05 07:19:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
if check_ribs {
|
2015-10-26 19:31:11 +00:00
|
|
|
if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, namespace) {
|
2015-11-03 18:44:23 +00:00
|
|
|
return Some(def);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-12 03:30:53 +00:00
|
|
|
let name = identifier.unhygienic_name;
|
|
|
|
self.resolve_item_by_name_in_lexical_scope(name, namespace, record_used)
|
2015-11-03 18:44:23 +00:00
|
|
|
.map(LocalDef::from_def)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve a local definition, potentially adjusting for closures.
|
2015-11-04 05:12:37 +00:00
|
|
|
fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
|
2015-11-03 18:44:23 +00:00
|
|
|
let ribs = match local_def.ribs {
|
2015-10-26 19:31:11 +00:00
|
|
|
Some((TypeNS, i)) => &self.type_ribs[i + 1..],
|
|
|
|
Some((ValueNS, i)) => &self.value_ribs[i + 1..],
|
|
|
|
_ => &[] as &[_],
|
2015-11-03 18:44:23 +00:00
|
|
|
};
|
|
|
|
let mut def = local_def.def;
|
|
|
|
match def {
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::Upvar(..) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
self.session.span_bug(span, &format!("unexpected {:?} in bindings", def))
|
2015-11-03 18:44:23 +00:00
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::Local(_, node_id) => {
|
2015-11-03 18:44:23 +00:00
|
|
|
for rib in ribs {
|
|
|
|
match rib.kind {
|
2016-01-22 09:55:29 +00:00
|
|
|
NormalRibKind | AnonymousModuleRibKind(..) => {
|
2015-11-03 18:44:23 +00:00
|
|
|
// Nothing to do. Continue.
|
|
|
|
}
|
|
|
|
ClosureRibKind(function_id) => {
|
|
|
|
let prev_def = def;
|
|
|
|
let node_def_id = self.ast_map.local_def_id(node_id);
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
let seen = self.freevars_seen
|
|
|
|
.entry(function_id)
|
|
|
|
.or_insert_with(|| NodeMap());
|
2015-11-03 18:44:23 +00:00
|
|
|
if let Some(&index) = seen.get(&node_id) {
|
2016-01-20 19:31:10 +00:00
|
|
|
def = Def::Upvar(node_def_id, node_id, index, function_id);
|
2015-11-03 18:44:23 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-10-26 19:31:11 +00:00
|
|
|
let vec = self.freevars
|
|
|
|
.entry(function_id)
|
|
|
|
.or_insert_with(|| vec![]);
|
2015-11-03 18:44:23 +00:00
|
|
|
let depth = vec.len();
|
2015-10-26 19:31:11 +00:00
|
|
|
vec.push(Freevar {
|
|
|
|
def: prev_def,
|
|
|
|
span: span,
|
|
|
|
});
|
2015-11-03 18:44:23 +00:00
|
|
|
|
2016-01-20 19:31:10 +00:00
|
|
|
def = Def::Upvar(node_def_id, node_id, depth, function_id);
|
2015-11-03 18:44:23 +00:00
|
|
|
seen.insert(node_id, depth);
|
|
|
|
}
|
|
|
|
ItemRibKind | MethodRibKind => {
|
|
|
|
// 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 19:31:11 +00:00
|
|
|
resolve_error(self,
|
|
|
|
span,
|
|
|
|
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem);
|
2015-11-03 18:44:23 +00:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
// Still doesn't deal with upvars
|
2015-10-26 19:31:11 +00:00
|
|
|
resolve_error(self,
|
|
|
|
span,
|
|
|
|
ResolutionError::AttemptToUseNonConstantValueInConstant);
|
2015-11-03 18:44:23 +00:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Def::TyParam(..) | Def::SelfTy(..) => {
|
2015-11-03 18:44:23 +00:00
|
|
|
for rib in ribs {
|
|
|
|
match rib.kind {
|
2016-01-22 09:55:29 +00:00
|
|
|
NormalRibKind | MethodRibKind | ClosureRibKind(..) |
|
|
|
|
AnonymousModuleRibKind(..) => {
|
2015-11-03 18:44:23 +00:00
|
|
|
// Nothing to do. Continue.
|
|
|
|
}
|
|
|
|
ItemRibKind => {
|
|
|
|
// This was an attempt to use a type parameter outside
|
|
|
|
// its scope.
|
|
|
|
|
|
|
|
resolve_error(self,
|
|
|
|
span,
|
|
|
|
ResolutionError::TypeParametersFromOuterFunction);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
// see #9186
|
|
|
|
resolve_error(self, span, ResolutionError::OuterTypeParameterContext);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
return Some(def);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-06-26 18:16:09 +00:00
|
|
|
// resolve a "module-relative" path, e.g. a::b::c
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_module_relative_path(&mut self,
|
2015-01-31 19:20:24 +00:00
|
|
|
span: Span,
|
2015-07-31 07:04:06 +00:00
|
|
|
segments: &[hir::PathSegment],
|
2014-11-29 04:09:12 +00:00
|
|
|
namespace: Namespace)
|
|
|
|
-> Option<(Def, LastPrivate)> {
|
2015-10-26 19:31:11 +00:00
|
|
|
let module_path = segments.split_last()
|
|
|
|
.unwrap()
|
|
|
|
.1
|
|
|
|
.iter()
|
|
|
|
.map(|ps| ps.identifier.name)
|
|
|
|
.collect::<Vec<_>>();
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2013-04-12 05:15:30 +00:00
|
|
|
let containing_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
let last_private;
|
2016-01-11 21:19:29 +00:00
|
|
|
let current_module = self.current_module;
|
2016-01-26 09:52:33 +00:00
|
|
|
match self.resolve_module_path(current_module, &module_path, UseLexicalScope, span) {
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => {
|
|
|
|
let (span, msg) = match err {
|
|
|
|
Some((span, msg)) => (span, msg),
|
|
|
|
None => {
|
2014-11-29 04:09:12 +00:00
|
|
|
let msg = format!("Use of undeclared type or module `{}`",
|
2015-03-15 21:44:19 +00:00
|
|
|
names_to_string(&module_path));
|
2015-01-31 19:20:24 +00:00
|
|
|
(span, msg)
|
2014-06-05 21:37:52 +00:00
|
|
|
}
|
|
|
|
};
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2015-07-14 17:42:38 +00:00
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
|
2014-06-05 21:37:52 +00:00
|
|
|
return None;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2016-01-26 08:40:42 +00:00
|
|
|
Indeterminate => return None,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((resulting_module, resulting_last_private)) => {
|
2012-05-22 17:54:12 +00:00
|
|
|
containing_module = resulting_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
last_private = resulting_last_private;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-31 19:20:24 +00:00
|
|
|
let name = segments.last().unwrap().identifier.name;
|
2016-01-26 09:52:33 +00:00
|
|
|
let def = match self.resolve_name_in_module(containing_module, name, namespace, false) {
|
2015-11-16 02:10:09 +00:00
|
|
|
Success((Target { binding, .. }, _)) => {
|
|
|
|
let (def, lp) = binding.def_and_lp();
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
(def, last_private.or(lp))
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-11-16 02:10:09 +00:00
|
|
|
_ => return None,
|
2013-06-03 11:31:43 +00:00
|
|
|
};
|
2015-11-16 07:59:50 +00:00
|
|
|
if let Some(DefId{krate: kid, ..}) = containing_module.def_id() {
|
2014-11-29 21:41:21 +00:00
|
|
|
self.used_crates.insert(kid);
|
2014-09-11 17:14:43 +00:00
|
|
|
}
|
2013-06-03 11:31:43 +00:00
|
|
|
return Some(def);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-03-01 18:44:43 +00:00
|
|
|
/// Invariant: This must be called only during main resolution, not during
|
|
|
|
/// import resolution.
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_crate_relative_path(&mut self,
|
2015-01-31 19:20:24 +00:00
|
|
|
span: Span,
|
2015-07-31 07:04:06 +00:00
|
|
|
segments: &[hir::PathSegment],
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
namespace: Namespace)
|
2015-10-26 19:31:11 +00:00
|
|
|
-> Option<(Def, LastPrivate)> {
|
|
|
|
let module_path = segments.split_last()
|
|
|
|
.unwrap()
|
|
|
|
.1
|
|
|
|
.iter()
|
|
|
|
.map(|ps| ps.identifier.name)
|
|
|
|
.collect::<Vec<_>>();
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
let root_module = self.graph_root;
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2013-04-12 05:15:30 +00:00
|
|
|
let containing_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
let last_private;
|
2012-08-06 19:34:08 +00:00
|
|
|
match self.resolve_module_path_from_root(root_module,
|
2015-02-18 19:48:57 +00:00
|
|
|
&module_path[..],
|
2012-12-23 22:41:37 +00:00
|
|
|
0,
|
2015-01-31 19:20:24 +00:00
|
|
|
span,
|
2014-02-11 19:19:18 +00:00
|
|
|
LastMod(AllPublic)) {
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => {
|
|
|
|
let (span, msg) = match err {
|
|
|
|
Some((span, msg)) => (span, msg),
|
|
|
|
None => {
|
|
|
|
let msg = format!("Use of undeclared module `::{}`",
|
2015-03-15 21:44:19 +00:00
|
|
|
names_to_string(&module_path[..]));
|
2015-01-31 19:20:24 +00:00
|
|
|
(span, msg)
|
2014-06-05 21:37:52 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-07-14 17:42:38 +00:00
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
|
2012-08-20 19:23:37 +00:00
|
|
|
return None;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2016-01-26 08:40:42 +00:00
|
|
|
Indeterminate => return None,
|
2012-05-22 17:54:12 +00:00
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((resulting_module, resulting_last_private)) => {
|
2012-05-22 17:54:12 +00:00
|
|
|
containing_module = resulting_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
last_private = resulting_last_private;
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-31 19:20:24 +00:00
|
|
|
let name = segments.last().unwrap().identifier.name;
|
2016-01-26 09:52:33 +00:00
|
|
|
match self.resolve_name_in_module(containing_module, name, namespace, false) {
|
2015-11-16 02:10:09 +00:00
|
|
|
Success((Target { binding, .. }, _)) => {
|
|
|
|
let (def, lp) = binding.def_and_lp();
|
|
|
|
Some((def, last_private.or(lp)))
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-11-16 02:10:09 +00:00
|
|
|
_ => None,
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn resolve_identifier_in_local_ribs(&mut self,
|
2015-12-01 17:38:40 +00:00
|
|
|
ident: hir::Ident,
|
2015-11-03 18:44:23 +00:00
|
|
|
namespace: Namespace)
|
|
|
|
-> Option<LocalDef> {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Check the local set of ribs.
|
2016-01-22 09:55:29 +00:00
|
|
|
let name = match namespace { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
|
2012-05-22 17:54:12 +00:00
|
|
|
|
2016-01-22 09:55:29 +00:00
|
|
|
for i in (0 .. self.get_ribs(namespace).len()).rev() {
|
|
|
|
if let Some(def_like) = self.get_ribs(namespace)[i].bindings.get(&name).cloned() {
|
2015-11-03 18:44:23 +00:00
|
|
|
match def_like {
|
|
|
|
DlDef(def) => {
|
|
|
|
debug!("(resolving path in local ribs) resolved `{}` to {:?} at {}",
|
2015-10-26 19:31:11 +00:00
|
|
|
name,
|
|
|
|
def,
|
|
|
|
i);
|
2015-11-03 18:44:23 +00:00
|
|
|
return Some(LocalDef {
|
|
|
|
ribs: Some((namespace, i)),
|
2015-10-26 19:31:11 +00:00
|
|
|
def: def,
|
2015-11-03 18:44:23 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
def_like => {
|
|
|
|
debug!("(resolving path in local ribs) resolved `{}` to pseudo-def {:?}",
|
2015-10-26 19:31:11 +00:00
|
|
|
name,
|
|
|
|
def_like);
|
2015-11-03 18:44:23 +00:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2016-01-22 09:55:29 +00:00
|
|
|
|
|
|
|
if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
|
|
|
|
if let Success((target, _)) = self.resolve_name_in_module(module,
|
|
|
|
ident.unhygienic_name,
|
|
|
|
namespace,
|
|
|
|
true) {
|
|
|
|
if let Some(def) = target.binding.def() {
|
|
|
|
return Some(LocalDef::from_def(def));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-11-03 18:44:23 +00:00
|
|
|
|
|
|
|
None
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2014-10-01 00:11:34 +00:00
|
|
|
fn resolve_item_by_name_in_lexical_scope(&mut self,
|
|
|
|
name: Name,
|
2015-12-12 03:30:53 +00:00
|
|
|
namespace: Namespace,
|
|
|
|
record_used: bool)
|
2015-10-26 19:31:11 +00:00
|
|
|
-> Option<Def> {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Check the items.
|
2016-01-11 21:19:29 +00:00
|
|
|
let module = self.current_module;
|
2015-12-12 03:30:53 +00:00
|
|
|
match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
Success((target, _)) => {
|
2015-11-16 02:10:09 +00:00
|
|
|
match target.binding.def() {
|
2012-08-20 19:23:37 +00:00
|
|
|
None => {
|
2012-10-15 21:56:42 +00:00
|
|
|
// This can happen if we were looking for a type and
|
|
|
|
// found a module instead. Modules don't have defs.
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item path by identifier in lexical scope) failed to \
|
|
|
|
resolve {} after success...",
|
|
|
|
name);
|
2015-11-03 18:44:23 +00:00
|
|
|
None
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2012-08-20 19:23:37 +00:00
|
|
|
Some(def) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(resolving item path in lexical scope) resolved `{}` to item",
|
2015-07-08 20:55:22 +00:00
|
|
|
name);
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 21:37:39 +00:00
|
|
|
// This lookup is "all public" because it only searched
|
|
|
|
// for one identifier in the current module (couldn't
|
|
|
|
// have passed through reexports or anything like that.
|
2015-11-03 18:44:23 +00:00
|
|
|
Some(def)
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-26 08:40:42 +00:00
|
|
|
Indeterminate => None,
|
2014-06-05 21:37:52 +00:00
|
|
|
Failed(err) => {
|
2016-02-01 03:26:16 +00:00
|
|
|
debug!("(resolving item path by identifier in lexical scope) failed to \
|
|
|
|
resolve `{}`",
|
2015-10-26 19:31:11 +00:00
|
|
|
name);
|
2015-03-29 23:21:20 +00:00
|
|
|
|
|
|
|
if let Some((span, msg)) = err {
|
2015-07-14 17:42:38 +00:00
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg))
|
2015-03-29 23:21:20 +00:00
|
|
|
}
|
|
|
|
|
2015-11-03 18:44:23 +00:00
|
|
|
None
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn with_no_errors<T, F>(&mut self, f: F) -> T
|
|
|
|
where F: FnOnce(&mut Resolver) -> T
|
2014-12-09 01:26:43 +00:00
|
|
|
{
|
2013-08-14 00:54:14 +00:00
|
|
|
self.emit_errors = false;
|
2013-09-27 02:10:16 +00:00
|
|
|
let rs = f(self);
|
2013-08-14 00:54:14 +00:00
|
|
|
self.emit_errors = true;
|
|
|
|
rs
|
|
|
|
}
|
|
|
|
|
2014-05-08 21:35:09 +00:00
|
|
|
fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
|
2015-10-26 19:31:11 +00:00
|
|
|
fn extract_path_and_node_id(t: &Ty,
|
|
|
|
allow: FallbackChecks)
|
|
|
|
-> Option<(Path, NodeId, FallbackChecks)> {
|
2014-05-19 21:27:03 +00:00
|
|
|
match t.node {
|
2015-02-17 17:29:13 +00:00
|
|
|
TyPath(None, ref path) => Some((path.clone(), t.id, allow)),
|
2014-09-07 17:09:06 +00:00
|
|
|
TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
|
|
|
|
TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
|
2014-05-19 21:27:03 +00:00
|
|
|
// This doesn't handle the remaining `Ty` variants as they are not
|
|
|
|
// that commonly the self_type, it might be interesting to provide
|
|
|
|
// support for those in future.
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
fn get_module<'a, 'tcx>(this: &mut Resolver<'a, 'tcx>,
|
|
|
|
span: Span,
|
|
|
|
name_path: &[ast::Name])
|
|
|
|
-> Option<Module<'a>> {
|
|
|
|
let root = this.current_module;
|
2014-10-01 00:11:34 +00:00
|
|
|
let last_name = name_path.last().unwrap();
|
2014-05-08 21:35:09 +00:00
|
|
|
|
2014-10-01 00:11:34 +00:00
|
|
|
if name_path.len() == 1 {
|
2014-11-06 17:25:16 +00:00
|
|
|
match this.primitive_type_table.primitive_types.get(last_name) {
|
2014-05-08 21:35:09 +00:00
|
|
|
Some(_) => None,
|
2016-01-14 01:42:45 +00:00
|
|
|
None => this.current_module.get_child(*last_name, TypeNS)
|
|
|
|
.as_ref()
|
|
|
|
.and_then(NameBinding::module)
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
} else {
|
2016-01-26 09:52:33 +00:00
|
|
|
match this.resolve_module_path(root, &name_path, UseLexicalScope, span) {
|
2014-05-08 21:35:09 +00:00
|
|
|
Success((module, _)) => Some(module),
|
2015-10-26 19:31:11 +00:00
|
|
|
_ => None,
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-11 07:32:25 +00:00
|
|
|
fn is_static_method(this: &Resolver, did: DefId) -> bool {
|
2015-09-04 17:52:28 +00:00
|
|
|
if let Some(node_id) = this.ast_map.as_local_node_id(did) {
|
|
|
|
let sig = match this.ast_map.get(node_id) {
|
2015-07-31 07:04:06 +00:00
|
|
|
hir_map::NodeTraitItem(trait_item) => match trait_item.node {
|
|
|
|
hir::MethodTraitItem(ref sig, _) => sig,
|
2015-10-26 19:31:11 +00:00
|
|
|
_ => return false,
|
2015-02-11 07:32:25 +00:00
|
|
|
},
|
2015-07-31 07:04:06 +00:00
|
|
|
hir_map::NodeImplItem(impl_item) => match impl_item.node {
|
2015-11-12 14:57:51 +00:00
|
|
|
hir::ImplItemKind::Method(ref sig, _) => sig,
|
2015-10-26 19:31:11 +00:00
|
|
|
_ => return false,
|
2015-02-11 07:32:25 +00:00
|
|
|
},
|
2015-10-26 19:31:11 +00:00
|
|
|
_ => return false,
|
2015-02-11 07:32:25 +00:00
|
|
|
};
|
2015-07-31 07:04:06 +00:00
|
|
|
sig.explicit_self.node == hir::SelfStatic
|
2015-02-11 07:32:25 +00:00
|
|
|
} else {
|
2015-11-20 15:46:39 +00:00
|
|
|
this.session.cstore.is_static_method(did)
|
2015-02-11 07:32:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-19 21:27:03 +00:00
|
|
|
let (path, node_id, allowed) = match self.current_self_type {
|
|
|
|
Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => return NoSuggestion,
|
2014-05-08 21:35:09 +00:00
|
|
|
},
|
|
|
|
None => return NoSuggestion,
|
|
|
|
};
|
|
|
|
|
2014-05-19 21:27:03 +00:00
|
|
|
if allowed == Everything {
|
|
|
|
// Look for a field with the same name in the current self_type.
|
2015-02-17 04:44:23 +00:00
|
|
|
match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Enum(did)) |
|
|
|
|
Some(Def::TyAlias(did)) |
|
|
|
|
Some(Def::Struct(did)) |
|
|
|
|
Some(Def::Variant(_, did)) => match self.structs.get(&did) {
|
2014-05-19 21:27:03 +00:00
|
|
|
None => {}
|
|
|
|
Some(fields) => {
|
|
|
|
if fields.iter().any(|&field_name| name == field_name) {
|
|
|
|
return Field;
|
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
2014-05-19 21:27:03 +00:00
|
|
|
},
|
|
|
|
_ => {} // Self type didn't resolve properly
|
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
|
2014-10-01 00:11:34 +00:00
|
|
|
let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();
|
2014-05-08 21:35:09 +00:00
|
|
|
|
|
|
|
// Look for a method in the current self type's impl module.
|
2015-02-11 07:32:25 +00:00
|
|
|
if let Some(module) = get_module(self, path.span, &name_path) {
|
2016-01-14 01:42:45 +00:00
|
|
|
if let Some(binding) = module.get_child(name, ValueNS) {
|
|
|
|
if let Some(Def::Method(did)) = binding.def() {
|
2015-02-11 07:32:25 +00:00
|
|
|
if is_static_method(self, did) {
|
2015-10-26 19:31:11 +00:00
|
|
|
return StaticMethod(path_names_to_string(&path, 0));
|
2015-02-11 07:32:25 +00:00
|
|
|
}
|
|
|
|
if self.current_trait_ref.is_some() {
|
|
|
|
return TraitItem;
|
|
|
|
} else if allowed == Everything {
|
|
|
|
return Method;
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-11 07:32:25 +00:00
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Look for a method in the current trait.
|
2015-02-11 07:32:25 +00:00
|
|
|
if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
|
|
|
|
if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) {
|
|
|
|
if is_static_method(self, did) {
|
2015-03-15 21:44:19 +00:00
|
|
|
return TraitMethod(path_names_to_string(&trait_ref.path, 0));
|
2015-02-11 07:32:25 +00:00
|
|
|
} else {
|
|
|
|
return TraitItem;
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NoSuggestion
|
|
|
|
}
|
|
|
|
|
2015-12-14 17:06:31 +00:00
|
|
|
fn find_best_match(&mut self, name: &str) -> SuggestionType {
|
2015-11-21 09:37:50 +00:00
|
|
|
if let Some(macro_name) = self.session.available_macros
|
2015-12-14 17:06:31 +00:00
|
|
|
.borrow().iter().find(|n| n.as_str() == name) {
|
2015-11-21 09:37:50 +00:00
|
|
|
return SuggestionType::Macro(format!("{}!", macro_name));
|
|
|
|
}
|
|
|
|
|
2015-12-14 17:06:31 +00:00
|
|
|
let names = self.value_ribs
|
|
|
|
.iter()
|
|
|
|
.rev()
|
|
|
|
.flat_map(|rib| rib.bindings.keys());
|
2013-02-23 08:22:51 +00:00
|
|
|
|
2015-12-14 17:06:31 +00:00
|
|
|
if let Some(found) = find_best_match_for_name(names, name, None) {
|
|
|
|
if name != &*found {
|
|
|
|
return SuggestionType::Function(found);
|
2013-02-23 08:22:51 +00:00
|
|
|
}
|
2015-12-14 17:06:31 +00:00
|
|
|
} SuggestionType::NotFound
|
2013-02-23 08:22:51 +00:00
|
|
|
}
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
fn resolve_expr(&mut self, expr: &Expr) {
|
2012-08-17 23:53:07 +00:00
|
|
|
// First, record candidate traits for this expression if it could
|
|
|
|
// result in the invocation of a method call.
|
2012-07-11 22:00:40 +00:00
|
|
|
|
|
|
|
self.record_candidate_traits_for_expr_if_necessary(expr);
|
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
// Next, resolve the node.
|
2012-08-06 19:34:08 +00:00
|
|
|
match expr.node {
|
2015-02-17 17:29:13 +00:00
|
|
|
ExprPath(ref maybe_qself, ref path) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
let resolution = match self.resolve_possibly_assoc_item(expr.id,
|
|
|
|
maybe_qself.as_ref(),
|
|
|
|
path,
|
|
|
|
ValueNS,
|
|
|
|
true) {
|
|
|
|
// `<T>::a::b::c` is resolved by typeck alone.
|
|
|
|
TypecheckRequired => {
|
|
|
|
let method_name = path.segments.last().unwrap().identifier.name;
|
|
|
|
let traits = self.get_traits_containing_item(method_name);
|
|
|
|
self.trait_map.insert(expr.id, traits);
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_expr(self, expr);
|
2015-10-26 19:31:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ResolveAttempt(resolution) => resolution,
|
|
|
|
};
|
2015-01-30 08:09:44 +00:00
|
|
|
|
2012-05-22 17:54:12 +00:00
|
|
|
// This is a local path in the value namespace. Walk through
|
|
|
|
// scopes looking for it.
|
2015-02-17 04:44:23 +00:00
|
|
|
if let Some(path_res) = resolution {
|
2014-12-10 07:11:19 +00:00
|
|
|
// Check if struct variant
|
2016-01-20 19:31:10 +00:00
|
|
|
let is_struct_variant = if let Def::Variant(_, variant_id) = path_res.base_def {
|
2016-01-17 19:57:54 +00:00
|
|
|
self.structs.contains_key(&variant_id)
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
if is_struct_variant {
|
|
|
|
let _ = self.structs.contains_key(&path_res.base_def.def_id());
|
2015-03-15 21:44:19 +00:00
|
|
|
let path_name = path_names_to_string(path, 0);
|
2015-07-13 17:32:45 +00:00
|
|
|
|
2015-12-20 21:00:43 +00:00
|
|
|
let mut err = resolve_struct_error(self,
|
|
|
|
expr.span,
|
|
|
|
ResolutionError::StructVariantUsedAsFunction(&*path_name));
|
2014-12-10 07:11:19 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
2015-02-24 14:07:54 +00:00
|
|
|
path_name);
|
|
|
|
if self.emit_errors {
|
2015-12-23 06:27:20 +00:00
|
|
|
err.fileline_help(expr.span, &msg);
|
2015-02-24 14:07:54 +00:00
|
|
|
} else {
|
2015-12-23 06:27:20 +00:00
|
|
|
err.span_help(expr.span, &msg);
|
2015-02-24 14:07:54 +00:00
|
|
|
}
|
2015-12-23 06:27:20 +00:00
|
|
|
err.emit();
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-02-17 04:44:23 +00:00
|
|
|
} else {
|
2012-05-22 17:54:12 +00:00
|
|
|
// Write the result into the def map.
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("(resolving expr) resolved `{}`",
|
2015-03-15 21:44:19 +00:00
|
|
|
path_names_to_string(path, 0));
|
2014-10-01 00:11:34 +00:00
|
|
|
|
2015-02-11 07:33:49 +00:00
|
|
|
// Partial resolutions will need the set of traits in scope,
|
|
|
|
// so they can be completed during typeck.
|
2015-02-17 04:44:23 +00:00
|
|
|
if path_res.depth != 0 {
|
2015-02-11 07:33:49 +00:00
|
|
|
let method_name = path.segments.last().unwrap().identifier.name;
|
2015-03-25 16:53:28 +00:00
|
|
|
let traits = self.get_traits_containing_item(method_name);
|
2015-02-11 07:33:49 +00:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
|
|
|
}
|
|
|
|
|
2015-02-17 04:44:23 +00:00
|
|
|
self.record_def(expr.id, path_res);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
} else {
|
|
|
|
// Be helpful if the name refers to a struct
|
|
|
|
// (The pattern matching def_tys where the id is in self.structs
|
|
|
|
// matches on regular structs while excluding tuple- and enum-like
|
|
|
|
// structs, which wouldn't result in this error.)
|
2015-03-15 21:44:19 +00:00
|
|
|
let path_name = path_names_to_string(path, 0);
|
2015-02-17 04:44:23 +00:00
|
|
|
let type_res = self.with_no_errors(|this| {
|
|
|
|
this.resolve_path(expr.id, path, 0, TypeNS, false)
|
|
|
|
});
|
2015-12-11 07:59:11 +00:00
|
|
|
|
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-02-17 04:44:23 +00:00
|
|
|
match type_res.map(|r| r.base_def) {
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Struct(..)) => {
|
2015-12-20 21:00:43 +00:00
|
|
|
let mut err = resolve_struct_error(self,
|
|
|
|
expr.span,
|
|
|
|
ResolutionError::StructVariantUsedAsFunction(&*path_name));
|
2015-02-17 04:44:23 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",
|
|
|
|
path_name);
|
|
|
|
if self.emit_errors {
|
2015-12-23 06:27:20 +00:00
|
|
|
err.fileline_help(expr.span, &msg);
|
2015-10-26 19:31:11 +00:00
|
|
|
} else {
|
2015-12-23 06:27:20 +00:00
|
|
|
err.span_help(expr.span, &msg);
|
2015-02-24 14:07:54 +00:00
|
|
|
}
|
2015-12-23 06:27:20 +00:00
|
|
|
err.emit();
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
_ => {
|
|
|
|
// Keep reporting some errors even if they're ignored above.
|
|
|
|
self.resolve_path(expr.id, path, 0, ValueNS, true);
|
|
|
|
|
|
|
|
let mut method_scope = false;
|
|
|
|
self.value_ribs.iter().rev().all(|rib| {
|
|
|
|
method_scope = match rib.kind {
|
|
|
|
MethodRibKind => true,
|
|
|
|
ItemRibKind | ConstantItemRibKind => false,
|
|
|
|
_ => return true, // Keep advancing
|
|
|
|
};
|
|
|
|
false // Stop advancing
|
|
|
|
});
|
2014-05-08 21:35:09 +00:00
|
|
|
|
2015-09-24 20:05:02 +00:00
|
|
|
if method_scope && special_names::self_.as_str() == &path_name[..] {
|
2015-10-26 19:31:11 +00:00
|
|
|
resolve_error(self,
|
|
|
|
expr.span,
|
|
|
|
ResolutionError::SelfNotAvailableInStaticMethod);
|
2015-02-17 04:44:23 +00:00
|
|
|
} else {
|
|
|
|
let last_name = path.segments.last().unwrap().identifier.name;
|
|
|
|
let mut msg = match self.find_fallback_in_self_type(last_name) {
|
|
|
|
NoSuggestion => {
|
|
|
|
// limit search to 5 to reduce the number
|
|
|
|
// of stupid suggestions
|
2015-12-14 17:06:31 +00:00
|
|
|
match self.find_best_match(&path_name) {
|
2015-11-21 09:37:50 +00:00
|
|
|
SuggestionType::Macro(s) => {
|
|
|
|
format!("the macro `{}`", s)
|
|
|
|
}
|
|
|
|
SuggestionType::Function(s) => format!("`{}`", s),
|
|
|
|
SuggestionType::NotFound => "".to_string(),
|
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
}
|
|
|
|
Field => format!("`self.{}`", path_name),
|
|
|
|
Method |
|
2015-10-26 19:31:11 +00:00
|
|
|
TraitItem => format!("to call `self.{}`", path_name),
|
2015-02-17 04:44:23 +00:00
|
|
|
TraitMethod(path_str) |
|
|
|
|
StaticMethod(path_str) =>
|
2015-10-26 19:31:11 +00:00
|
|
|
format!("to call `{}::{}`", path_str, path_name),
|
2015-02-17 04:44:23 +00:00
|
|
|
};
|
|
|
|
|
2015-12-10 23:00:17 +00:00
|
|
|
let mut context = UnresolvedNameContext::Other;
|
2015-03-24 23:54:09 +00:00
|
|
|
if !msg.is_empty() {
|
2015-12-10 23:00:17 +00:00
|
|
|
msg = format!(". Did you mean {}?", msg);
|
|
|
|
} else {
|
|
|
|
// we check if this a module and if so, we display a help
|
|
|
|
// message
|
|
|
|
let name_path = path.segments.iter()
|
|
|
|
.map(|seg| seg.identifier.name)
|
|
|
|
.collect::<Vec<_>>();
|
2016-01-11 21:19:29 +00:00
|
|
|
let current_module = self.current_module;
|
2015-12-10 23:00:17 +00:00
|
|
|
|
|
|
|
match self.resolve_module_path(current_module,
|
2016-01-26 09:52:33 +00:00
|
|
|
&name_path[..],
|
|
|
|
UseLexicalScope,
|
|
|
|
expr.span) {
|
2015-12-10 23:00:17 +00:00
|
|
|
Success(_) => {
|
|
|
|
context = UnresolvedNameContext::PathIsMod(expr.id);
|
|
|
|
},
|
|
|
|
_ => {},
|
|
|
|
};
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
2015-02-17 04:44:23 +00:00
|
|
|
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
expr.span,
|
2015-12-10 23:00:17 +00:00
|
|
|
ResolutionError::UnresolvedName(
|
|
|
|
&*path_name, &*msg, context));
|
2014-05-08 21:35:09 +00:00
|
|
|
}
|
2012-08-22 18:40:42 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_expr(self, expr);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-09-02 01:45:37 +00:00
|
|
|
ExprStruct(ref path, _, _) => {
|
2014-07-04 23:45:47 +00:00
|
|
|
// Resolve the path to the structure it goes to. We don't
|
|
|
|
// check to ensure that the path is actually a structure; that
|
|
|
|
// is checked later during typeck.
|
2015-01-31 19:20:24 +00:00
|
|
|
match self.resolve_path(expr.id, path, 0, TypeNS, false) {
|
2014-07-04 23:45:47 +00:00
|
|
|
Some(definition) => self.record_def(expr.id, definition),
|
2015-02-05 07:19:07 +00:00
|
|
|
None => {
|
|
|
|
debug!("(resolving expression) didn't find struct def",);
|
2015-07-13 17:32:45 +00:00
|
|
|
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
path.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::DoesNotNameAStruct(
|
2015-07-14 13:37:52 +00:00
|
|
|
&*path_names_to_string(path, 0))
|
|
|
|
);
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2012-07-24 01:44:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_expr(self, expr);
|
2012-07-24 01:44:59 +00:00
|
|
|
}
|
|
|
|
|
2014-07-26 00:12:51 +00:00
|
|
|
ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
|
2013-11-21 23:42:55 +00:00
|
|
|
self.with_label_rib(|this| {
|
2016-01-20 19:31:10 +00:00
|
|
|
let def_like = DlDef(Def::Label(expr.id));
|
2014-03-21 02:49:20 +00:00
|
|
|
|
2013-12-21 21:58:11 +00:00
|
|
|
{
|
2014-09-29 23:06:13 +00:00
|
|
|
let rib = this.label_ribs.last_mut().unwrap();
|
2015-12-01 17:38:40 +00:00
|
|
|
rib.bindings.insert(label.name, def_like);
|
2013-12-21 21:58:11 +00:00
|
|
|
}
|
2012-08-15 02:20:56 +00:00
|
|
|
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_expr(this, expr);
|
2013-11-21 23:42:55 +00:00
|
|
|
})
|
2012-08-15 02:20:56 +00:00
|
|
|
}
|
|
|
|
|
2013-09-02 01:45:37 +00:00
|
|
|
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
|
2015-12-01 17:38:40 +00:00
|
|
|
match self.search_label(label.node.name) {
|
2014-05-16 17:45:16 +00:00
|
|
|
None => {
|
2015-12-11 07:59:11 +00:00
|
|
|
self.record_def(expr.id, err_path_resolution());
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
2015-09-02 19:29:41 +00:00
|
|
|
label.span,
|
|
|
|
ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
|
2014-05-16 17:45:16 +00:00
|
|
|
}
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(DlDef(def @ Def::Label(_))) => {
|
2014-02-11 19:19:18 +00:00
|
|
|
// Since this def is a label, it is never read.
|
2015-10-26 19:31:11 +00:00
|
|
|
self.record_def(expr.id,
|
|
|
|
PathResolution {
|
|
|
|
base_def: def,
|
|
|
|
last_private: LastMod(AllPublic),
|
|
|
|
depth: 0,
|
|
|
|
})
|
2013-05-10 22:15:06 +00:00
|
|
|
}
|
|
|
|
Some(_) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
self.session.span_bug(expr.span, "label wasn't mapped to a label def!")
|
2013-05-10 22:15:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-04 02:59:04 +00:00
|
|
|
_ => {
|
2015-11-17 23:56:13 +00:00
|
|
|
intravisit::walk_expr(self, expr);
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 12:00:46 +00:00
|
|
|
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
|
2012-08-06 19:34:08 +00:00
|
|
|
match expr.node {
|
2015-09-20 11:00:18 +00:00
|
|
|
ExprField(_, name) => {
|
2013-06-01 22:31:56 +00:00
|
|
|
// FIXME(#6890): Even though you can't treat a method like a
|
|
|
|
// field, we need to add any trait methods we find that match
|
|
|
|
// the field name so that we can do some nice error reporting
|
|
|
|
// later on in typeck.
|
2015-09-20 11:00:18 +00:00
|
|
|
let traits = self.get_traits_containing_item(name.node);
|
2014-02-24 08:36:24 +00:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
2015-09-20 11:00:18 +00:00
|
|
|
ExprMethodCall(name, _, _) => {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(recording candidate traits for expr) recording traits for {}",
|
2013-06-18 16:39:16 +00:00
|
|
|
expr.id);
|
2015-09-20 11:00:18 +00:00
|
|
|
let traits = self.get_traits_containing_item(name.node);
|
2014-02-24 08:36:24 +00:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-11-30 19:18:25 +00:00
|
|
|
}
|
2012-07-28 02:32:42 +00:00
|
|
|
_ => {
|
2012-07-11 22:00:40 +00:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-25 16:53:28 +00:00
|
|
|
fn get_traits_containing_item(&mut self, name: Name) -> Vec<DefId> {
|
2015-10-26 19:31:11 +00:00
|
|
|
debug!("(getting traits containing item) looking for '{}'", name);
|
2014-04-22 16:06:43 +00:00
|
|
|
|
2015-10-26 19:31:11 +00:00
|
|
|
fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name) {
|
2015-09-04 17:52:28 +00:00
|
|
|
debug!("(adding trait info) found trait {:?} for method '{}'",
|
2015-10-26 19:31:11 +00:00
|
|
|
trait_def_id,
|
|
|
|
name);
|
2014-04-22 16:06:43 +00:00
|
|
|
found_traits.push(trait_def_id);
|
|
|
|
}
|
2012-10-08 19:39:30 +00:00
|
|
|
|
2014-03-04 18:02:49 +00:00
|
|
|
let mut found_traits = Vec::new();
|
2016-01-11 21:19:29 +00:00
|
|
|
let mut search_module = self.current_module;
|
2014-04-22 16:06:43 +00:00
|
|
|
loop {
|
|
|
|
// Look for the current trait.
|
2014-05-08 21:35:09 +00:00
|
|
|
match self.current_trait_ref {
|
|
|
|
Some((trait_def_id, _)) => {
|
2014-09-29 23:06:13 +00:00
|
|
|
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
2014-05-08 21:35:09 +00:00
|
|
|
add_trait_info(&mut found_traits, trait_def_id, name);
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-08 21:35:09 +00:00
|
|
|
None => {} // Nothing to do.
|
2014-04-22 16:06:43 +00:00
|
|
|
}
|
2012-07-11 22:00:40 +00:00
|
|
|
|
2014-04-22 16:06:43 +00:00
|
|
|
// Look for trait children.
|
2014-12-30 18:16:42 +00:00
|
|
|
build_reduced_graph::populate_module_if_necessary(self, &search_module);
|
2013-12-21 23:32:44 +00:00
|
|
|
|
2016-01-28 03:03:40 +00:00
|
|
|
for (&(_, ns), name_binding) in search_module.children.borrow().iter() {
|
|
|
|
if ns != TypeNS { continue }
|
|
|
|
let trait_def_id = match name_binding.def() {
|
|
|
|
Some(Def::Trait(trait_def_id)) => trait_def_id,
|
|
|
|
Some(..) | None => continue,
|
|
|
|
};
|
|
|
|
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
|
|
|
add_trait_info(&mut found_traits, trait_def_id, name);
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
2014-04-22 16:06:43 +00:00
|
|
|
}
|
2012-07-11 22:00:40 +00:00
|
|
|
|
2014-04-22 16:06:43 +00:00
|
|
|
// Look for imports.
|
2016-01-14 01:42:45 +00:00
|
|
|
for (&(_, ns), import) in search_module.import_resolutions.borrow().iter() {
|
2016-01-28 03:03:40 +00:00
|
|
|
if ns != TypeNS { continue }
|
|
|
|
let target = match import.target {
|
|
|
|
Some(ref target) => target,
|
|
|
|
None => continue,
|
2014-04-22 16:06:43 +00:00
|
|
|
};
|
2015-11-16 02:10:09 +00:00
|
|
|
let did = match target.binding.def() {
|
2016-01-20 19:31:10 +00:00
|
|
|
Some(Def::Trait(trait_def_id)) => trait_def_id,
|
2014-04-22 16:06:43 +00:00
|
|
|
Some(..) | None => continue,
|
|
|
|
};
|
2014-09-29 23:06:13 +00:00
|
|
|
if self.trait_item_map.contains_key(&(name, did)) {
|
2014-04-22 16:06:43 +00:00
|
|
|
add_trait_info(&mut found_traits, did, name);
|
2016-01-14 01:42:45 +00:00
|
|
|
let id = import.id;
|
2014-11-23 09:29:41 +00:00
|
|
|
self.used_imports.insert((id, TypeNS));
|
|
|
|
let trait_name = self.get_trait_name(did);
|
|
|
|
self.record_import_use(id, trait_name);
|
2015-11-16 07:59:50 +00:00
|
|
|
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
|
2014-11-29 21:41:21 +00:00
|
|
|
self.used_crates.insert(kid);
|
2014-09-11 17:14:43 +00:00
|
|
|
}
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
2014-04-22 16:06:43 +00:00
|
|
|
}
|
2013-05-20 16:41:20 +00:00
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
match search_module.parent_link {
|
2014-04-22 16:06:43 +00:00
|
|
|
NoParentLink | ModuleParentLink(..) => break,
|
|
|
|
BlockParentLink(parent_module, _) => {
|
2016-01-11 21:19:29 +00:00
|
|
|
search_module = parent_module;
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
2014-04-22 16:06:43 +00:00
|
|
|
}
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
|
|
|
|
2014-04-22 16:06:43 +00:00
|
|
|
found_traits
|
2012-07-11 22:00:40 +00:00
|
|
|
}
|
|
|
|
|
2015-02-17 04:44:23 +00:00
|
|
|
fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
|
|
|
|
debug!("(recording def) recording {:?} for {}", resolution, node_id);
|
2015-10-26 19:31:11 +00:00
|
|
|
assert!(match resolution.last_private {
|
|
|
|
LastImport{..} => false,
|
|
|
|
_ => true,
|
|
|
|
},
|
2014-02-11 19:19:18 +00:00
|
|
|
"Import should only be used for `use` directives");
|
2014-09-18 21:05:52 +00:00
|
|
|
|
2015-02-17 04:44:23 +00:00
|
|
|
if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
|
|
|
|
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
|
2015-10-26 19:31:11 +00:00
|
|
|
self.session.span_bug(span,
|
|
|
|
&format!("path resolved multiple times ({:?} before, {:?} now)",
|
|
|
|
prev_res,
|
|
|
|
resolution));
|
2014-09-18 21:05:52 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 12:33:01 +00:00
|
|
|
fn enforce_default_binding_mode(&mut self,
|
2015-10-26 19:31:11 +00:00
|
|
|
pat: &Pat,
|
|
|
|
pat_binding_mode: BindingMode,
|
|
|
|
descr: &str) {
|
2013-01-25 00:24:45 +00:00
|
|
|
match pat_binding_mode {
|
2013-10-20 12:31:23 +00:00
|
|
|
BindByValue(_) => {}
|
2013-11-28 20:22:53 +00:00
|
|
|
BindByRef(..) => {
|
2015-07-14 14:32:43 +00:00
|
|
|
resolve_error(self,
|
|
|
|
pat.span,
|
2015-07-14 17:42:38 +00:00
|
|
|
ResolutionError::CannotUseRefBindingModeWith(descr));
|
2013-01-25 00:24:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:44:19 +00:00
|
|
|
|
|
|
|
fn names_to_string(names: &[Name]) -> String {
|
|
|
|
let mut first = true;
|
|
|
|
let mut result = String::new();
|
|
|
|
for name in names {
|
|
|
|
if first {
|
|
|
|
first = false
|
|
|
|
} else {
|
|
|
|
result.push_str("::")
|
|
|
|
}
|
2015-07-28 16:07:20 +00:00
|
|
|
result.push_str(&name.as_str());
|
2015-10-26 19:31:11 +00:00
|
|
|
}
|
2015-03-15 21:44:19 +00:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
fn path_names_to_string(path: &Path, depth: usize) -> String {
|
2015-10-26 19:31:11 +00:00
|
|
|
let names: Vec<ast::Name> = path.segments[..path.segments.len() - depth]
|
2015-03-15 21:44:19 +00:00
|
|
|
.iter()
|
|
|
|
.map(|seg| seg.identifier.name)
|
|
|
|
.collect();
|
|
|
|
names_to_string(&names[..])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A somewhat inefficient routine to obtain the name of a module.
|
2016-01-11 21:19:29 +00:00
|
|
|
fn module_to_string<'a>(module: Module<'a>) -> String {
|
2015-03-15 21:44:19 +00:00
|
|
|
let mut names = Vec::new();
|
|
|
|
|
2016-01-11 21:19:29 +00:00
|
|
|
fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
|
2015-03-15 21:44:19 +00:00
|
|
|
match module.parent_link {
|
|
|
|
NoParentLink => {}
|
|
|
|
ModuleParentLink(ref module, name) => {
|
|
|
|
names.push(name);
|
2016-01-11 21:19:29 +00:00
|
|
|
collect_mod(names, module);
|
2015-03-15 21:44:19 +00:00
|
|
|
}
|
|
|
|
BlockParentLink(ref module, _) => {
|
|
|
|
// danger, shouldn't be ident?
|
|
|
|
names.push(special_idents::opaque.name);
|
2016-01-11 21:19:29 +00:00
|
|
|
collect_mod(names, module);
|
2015-03-15 21:44:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
collect_mod(&mut names, module);
|
|
|
|
|
2015-03-24 23:53:34 +00:00
|
|
|
if names.is_empty() {
|
2015-03-15 21:44:19 +00:00
|
|
|
return "???".to_string();
|
|
|
|
}
|
|
|
|
names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>())
|
|
|
|
}
|
|
|
|
|
2015-12-11 07:59:11 +00:00
|
|
|
fn err_path_resolution() -> PathResolution {
|
|
|
|
PathResolution {
|
2016-01-20 19:31:10 +00:00
|
|
|
base_def: Def::Err,
|
2015-12-11 07:59:11 +00:00
|
|
|
last_private: LastMod(AllPublic),
|
|
|
|
depth: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-15 21:44:19 +00:00
|
|
|
|
2013-02-19 07:40:42 +00:00
|
|
|
pub struct CrateMap {
|
2015-11-04 06:02:22 +00:00
|
|
|
pub def_map: RefCell<DefMap>,
|
2015-11-04 05:12:37 +00:00
|
|
|
pub freevars: FreevarMap,
|
2014-12-18 18:27:17 +00:00
|
|
|
pub export_map: ExportMap,
|
2014-03-28 17:05:27 +00:00
|
|
|
pub trait_map: TraitMap,
|
|
|
|
pub external_exports: ExternalExports,
|
2015-10-26 19:31:11 +00:00
|
|
|
pub glob_map: Option<GlobMap>,
|
2014-11-23 09:29:41 +00:00
|
|
|
}
|
|
|
|
|
2015-03-30 13:38:44 +00:00
|
|
|
#[derive(PartialEq,Copy, Clone)]
|
2014-11-23 09:29:41 +00:00
|
|
|
pub enum MakeGlobMap {
|
|
|
|
Yes,
|
2015-10-26 19:31:11 +00:00
|
|
|
No,
|
2013-02-19 07:40:42 +00:00
|
|
|
}
|
|
|
|
|
2012-07-04 21:53:12 +00:00
|
|
|
/// Entry point to crate resolution.
|
2014-11-23 09:29:41 +00:00
|
|
|
pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
|
2015-07-31 07:04:06 +00:00
|
|
|
ast_map: &'a hir_map::Map<'tcx>,
|
2014-11-23 09:29:41 +00:00
|
|
|
make_glob_map: MakeGlobMap)
|
|
|
|
-> CrateMap {
|
2015-06-13 23:35:18 +00:00
|
|
|
let krate = ast_map.krate();
|
2016-01-11 21:19:29 +00:00
|
|
|
let arenas = Resolver::arenas();
|
|
|
|
let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas, None);
|
2014-12-19 07:13:54 +00:00
|
|
|
|
|
|
|
resolver.resolve_crate(krate);
|
|
|
|
|
|
|
|
check_unused::check_crate(&mut resolver, krate);
|
|
|
|
|
2013-02-19 07:40:42 +00:00
|
|
|
CrateMap {
|
2014-09-18 02:45:21 +00:00
|
|
|
def_map: resolver.def_map,
|
|
|
|
freevars: resolver.freevars,
|
2014-12-18 18:27:17 +00:00
|
|
|
export_map: resolver.export_map,
|
2014-09-18 02:45:21 +00:00
|
|
|
trait_map: resolver.trait_map,
|
|
|
|
external_exports: resolver.external_exports,
|
2014-11-23 09:29:41 +00:00
|
|
|
glob_map: if resolver.make_glob_map {
|
2015-10-26 19:31:11 +00:00
|
|
|
Some(resolver.glob_map)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
},
|
2013-02-19 07:40:42 +00:00
|
|
|
}
|
2012-05-22 17:54:12 +00:00
|
|
|
}
|
2015-04-28 02:48:22 +00:00
|
|
|
|
2015-08-09 09:09:55 +00:00
|
|
|
/// Builds a name resolution walker to be used within this module,
|
|
|
|
/// or used externally, with an optional callback function.
|
|
|
|
///
|
|
|
|
/// The callback takes a &mut bool which allows callbacks to end a
|
|
|
|
/// walk when set to true, passing through the rest of the walk, while
|
|
|
|
/// preserving the ribs + current module. This allows resolve_path
|
|
|
|
/// calls to be made with the correct scope info. The node in the
|
|
|
|
/// callback corresponds to the current node in the walk.
|
2015-05-14 11:40:16 +00:00
|
|
|
pub fn create_resolver<'a, 'tcx>(session: &'a Session,
|
2015-07-31 07:04:06 +00:00
|
|
|
ast_map: &'a hir_map::Map<'tcx>,
|
2015-05-14 11:40:16 +00:00
|
|
|
krate: &'a Crate,
|
|
|
|
make_glob_map: MakeGlobMap,
|
2016-01-11 21:19:29 +00:00
|
|
|
arenas: &'a ResolverArenas<'a>,
|
2015-07-31 07:04:06 +00:00
|
|
|
callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>)
|
2015-05-14 11:40:16 +00:00
|
|
|
-> Resolver<'a, 'tcx> {
|
2016-01-11 21:19:29 +00:00
|
|
|
let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas);
|
2015-05-14 11:40:16 +00:00
|
|
|
|
|
|
|
resolver.callback = callback;
|
|
|
|
|
|
|
|
build_reduced_graph::build_reduced_graph(&mut resolver, krate);
|
|
|
|
|
|
|
|
resolve_imports::resolve_imports(&mut resolver);
|
|
|
|
|
|
|
|
resolver
|
|
|
|
}
|
|
|
|
|
2015-04-28 02:48:22 +00:00
|
|
|
__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
|