Skip to content

Commit

Permalink
rustc_resolve: don't handle impl items as if they were modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Feb 24, 2015
1 parent 6700166 commit 06f362a
Show file tree
Hide file tree
Showing 24 changed files with 156 additions and 384 deletions.
4 changes: 4 additions & 0 deletions src/librustc/middle/ty.rs
Expand Up @@ -51,6 +51,7 @@ use middle::dependency_format;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
use middle::mem_categorization as mc;
use middle::privacy::LastPrivateMap;
use middle::region;
use middle::resolve_lifetime;
use middle::infer;
Expand Down Expand Up @@ -683,6 +684,7 @@ pub struct ctxt<'tcx> {
pub sess: Session,
pub def_map: DefMap,
pub partial_def_map: PartialDefMap,
pub last_private_map: RefCell<LastPrivateMap>,

pub named_region_map: resolve_lifetime::NamedRegionMap,

Expand Down Expand Up @@ -2426,6 +2428,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
arenas: &'tcx CtxtArenas<'tcx>,
def_map: DefMap,
partial_def_map: PartialDefMap,
last_private_map: LastPrivateMap,
named_region_map: resolve_lifetime::NamedRegionMap,
map: ast_map::Map<'tcx>,
freevars: RefCell<FreevarMap>,
Expand All @@ -2449,6 +2452,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
sess: s,
def_map: def_map,
partial_def_map: partial_def_map,
last_private_map: RefCell::new(last_private_map),
region_maps: region_maps,
node_types: RefCell::new(FnvHashMap()),
item_substs: RefCell::new(NodeMap()),
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_driver/driver.rs
Expand Up @@ -609,6 +609,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
arenas,
def_map,
partial_def_map,
last_private_map,
named_region_map,
ast_map,
freevars,
Expand All @@ -622,10 +623,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
time(time_passes, "const checking", (), |_|
middle::check_const::check_crate(&ty_cx));

let maps = (external_exports, last_private_map);
let (exported_items, public_items) =
time(time_passes, "privacy checking", maps, |(a, b)|
rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
time(time_passes, "privacy checking", (), |_|
rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));

// Do not move this check past lint
time(time_passes, "stability index", (), |_|
Expand Down
10 changes: 3 additions & 7 deletions src/librustc_privacy/lib.rs
Expand Up @@ -38,8 +38,7 @@ use rustc::middle::def;
use rustc::middle::privacy::ImportUse::*;
use rustc::middle::privacy::LastPrivate::*;
use rustc::middle::privacy::PrivateDep::*;
use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
use rustc::middle::privacy::{ExternalExports};
use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
use rustc::middle::ty::{MethodTypeParam, MethodStatic};
use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
use rustc::middle::ty::{MethodStaticClosure, MethodObject};
Expand Down Expand Up @@ -379,7 +378,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
in_foreign: bool,
parents: NodeMap<ast::NodeId>,
external_exports: ExternalExports,
last_private_map: LastPrivateMap,
}

enum PrivacyResult {
Expand Down Expand Up @@ -730,7 +728,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
&format!("{} `{}`", tyname, name))
};

match self.last_private_map[path_id] {
match self.tcx.last_private_map.borrow()[path_id] {
LastMod(AllPublic) => {},
LastMod(DependsOn(def)) => {
self.report_error(ck_public(def));
Expand Down Expand Up @@ -1500,8 +1498,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {

pub fn check_crate(tcx: &ty::ctxt,
export_map: &def::ExportMap,
external_exports: ExternalExports,
last_private_map: LastPrivateMap)
external_exports: ExternalExports)
-> (ExportedItems, PublicItems) {
let krate = tcx.map.krate();

Expand All @@ -1519,7 +1516,6 @@ pub fn check_crate(tcx: &ty::ctxt,
tcx: tcx,
parents: visitor.parents,
external_exports: external_exports,
last_private_map: last_private_map,
};
visit::walk_crate(&mut visitor, krate);

Expand Down
238 changes: 10 additions & 228 deletions src/librustc_resolve/build_reduced_graph.rs
Expand Up @@ -39,18 +39,16 @@ use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
use syntax::ast::{Name, NamedField, NodeId};
use syntax::ast::{PathListIdent, PathListMod, Public};
use syntax::ast::StmtDecl;
use syntax::ast::StructVariantKind;
use syntax::ast::TupleVariantKind;
use syntax::ast::TyObjectSum;
use syntax::ast::{TypeImplItem, UnnamedField};
use syntax::ast::UnnamedField;
use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::ast::{Visibility};
use syntax::ast::TyPath;
use syntax::ast;
use syntax::ast_util::{self, PostExpansionMethod, local_def};
use syntax::ast_util::{self, local_def};
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::{self, special_idents};
use syntax::codemap::{Span, DUMMY_SP};
Expand Down Expand Up @@ -177,12 +175,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
Some(TypeNS)
}
ForbidDuplicateTypesAndModules => {
match child.def_for_namespace(TypeNS) {
None => {}
Some(_) if child.get_module_if_available()
.map(|m| m.kind.get()) ==
Some(ImplModuleKind) => {}
Some(_) => duplicate_type = TypeError
if child.defined_in_namespace(TypeNS) {
duplicate_type = TypeError;
}
Some(TypeNS)
}
Expand Down Expand Up @@ -461,9 +455,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);

let parent_link = self.get_parent_link(parent, name);
// We want to make sure the module type is EnumModuleKind
// even if there's already an ImplModuleKind module defined,
// since that's how we prevent duplicate enum definitions
name_bindings.set_module_kind(parent_link,
Some(local_def(item.id)),
EnumModuleKind,
Expand Down Expand Up @@ -513,133 +504,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent.clone()
}

ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
// If this implements an anonymous trait, then add all the
// methods within to a new module, if the type was defined
// within this module.

let mod_name = match ty.node {
TyPath(ref path) if path.segments.len() == 1 => {
// FIXME(18446) we should distinguish between the name of
// a trait and the name of an impl of that trait.
Some(path.segments.last().unwrap().identifier.name)
}
TyObjectSum(ref lhs_ty, _) => {
match lhs_ty.node {
TyPath(ref path) if path.segments.len() == 1 => {
Some(path.segments.last().unwrap().identifier.name)
}
_ => {
None
}
}
}
_ => {
None
}
};

let mod_name = match mod_name {
Some(mod_name) => mod_name,
None => {
self.resolve_error(ty.span,
"inherent implementations may \
only be implemented in the same \
module as the type they are \
implemented for");
return parent.clone();
}
};
// Create the module and add all methods.
let child_opt = parent.children.borrow().get(&mod_name)
.and_then(|m| m.get_module_if_available());
let new_parent = match child_opt {
// It already exists
Some(ref child) if (child.kind.get() == ImplModuleKind ||
child.kind.get() == TraitModuleKind) => {
child.clone()
}
Some(ref child) if child.kind.get() == EnumModuleKind ||
child.kind.get() == TypeModuleKind => {
child.clone()
}
// Create the module
_ => {
let name_bindings =
self.add_child(mod_name, parent, ForbidDuplicateModules, sp);

let parent_link = self.get_parent_link(parent, name);
let def_id = local_def(item.id);
let ns = TypeNS;
let is_public =
!name_bindings.defined_in_namespace(ns) ||
name_bindings.defined_in_public_namespace(ns);

name_bindings.define_module(parent_link,
Some(def_id),
ImplModuleKind,
false,
is_public,
sp);

name_bindings.get_module()
}
};

// For each implementation item...
for impl_item in impl_items {
match *impl_item {
MethodImplItem(ref method) => {
// Add the method to the module.
let name = method.pe_ident().name;
let method_name_bindings =
self.add_child(name,
&new_parent,
ForbidDuplicateValues,
method.span);
let def = DefMethod(local_def(method.id),
FromImpl(local_def(item.id)));

// NB: not IMPORTABLE
let modifiers = if method.pe_vis() == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
method_name_bindings.define_value(
def,
method.span,
modifiers);
}
TypeImplItem(ref typedef) => {
// Add the typedef to the module.
let name = typedef.ident.name;
let typedef_name_bindings =
self.add_child(
name,
&new_parent,
ForbidDuplicateTypesAndModules,
typedef.span);
let def = DefAssociatedTy(local_def(item.id),
local_def(typedef.id));
// NB: not IMPORTABLE
let modifiers = if typedef.vis == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
typedef_name_bindings.define_type(
def,
typedef.span,
modifiers);
}
}
}
parent.clone()
}

ItemImpl(..) => parent.clone(),
ItemDefaultImpl(_, _) |
ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),

ItemTrait(_, _, _, ref items) => {
let name_bindings =
Expand Down Expand Up @@ -805,8 +671,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {

let kind = match def {
DefTy(_, true) => EnumModuleKind,
DefTy(_, false) => TypeModuleKind,
DefStruct(..) => ImplModuleKind,
DefTy(_, false) | DefStruct(..) => TypeModuleKind,
_ => NormalModuleKind
};

Expand Down Expand Up @@ -980,92 +845,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
}
}
}
DlImpl(def) => {
match csearch::get_type_name_if_impl(&self.session.cstore, def) {
None => {}
Some(final_name) => {
let methods_opt =
csearch::get_methods_if_impl(&self.session.cstore, def);
match methods_opt {
Some(ref methods) if
methods.len() >= 1 => {
debug!("(building reduced graph for \
external crate) processing \
static methods for type name {}",
token::get_name(final_name));

let child_name_bindings =
self.add_child(
final_name,
root,
OverwriteDuplicates,
DUMMY_SP);

// Process the static methods. First,
// create the module.
let type_module;
let type_def = child_name_bindings.type_def.borrow().clone();
match type_def {
Some(TypeNsDef {
module_def: Some(module_def),
..
}) => {
// We already have a module. This
// is OK.
type_module = module_def;

// Mark it as an impl module if
// necessary.
type_module.kind.set(ImplModuleKind);
}
Some(_) | None => {
let parent_link =
self.get_parent_link(root, final_name);
child_name_bindings.define_module(
parent_link,
Some(def),
ImplModuleKind,
true,
true,
DUMMY_SP);
type_module =
child_name_bindings.
get_module();
}
}

// Add each static method to the module.
let new_parent = type_module;
for method_info in methods {
let name = method_info.name;
debug!("(building reduced graph for \
external crate) creating \
static method '{}'",
token::get_name(name));

let method_name_bindings =
self.add_child(name,
&new_parent,
OverwriteDuplicates,
DUMMY_SP);
let def = DefFn(method_info.def_id, false);

// NB: not IMPORTABLE
let modifiers = if method_info.vis == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
method_name_bindings.define_value(
def, DUMMY_SP, modifiers);
}
}

// Otherwise, do nothing.
Some(_) | None => {}
}
}
}
DlImpl(_) => {
debug!("(building reduced graph for external crate) \
ignoring impl");
}
DlField => {
debug!("(building reduced graph for external crate) \
Expand Down

0 comments on commit 06f362a

Please sign in to comment.