rustc: Implement intra-crate static methods on anonymous trait implementations.
This commit is contained in:
parent
b38092e9a2
commit
4dc67c5e6a
2 changed files with 312 additions and 109 deletions
|
@ -9,9 +9,8 @@ use syntax::ast::{_mod, add, arm};
|
||||||
use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value};
|
use syntax::ast::{bind_by_ref, bind_by_implicit_ref, bind_by_value};
|
||||||
use syntax::ast::{bitand, bitor, bitxor};
|
use syntax::ast::{bitand, bitor, bitxor};
|
||||||
use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
|
use syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
|
||||||
use syntax::ast::{bound_trait, binding_mode,
|
use syntax::ast::{bound_trait, binding_mode, capture_clause, class_ctor};
|
||||||
capture_clause, class_ctor, class_dtor};
|
use syntax::ast::{class_dtor, crate, crate_num, decl_item};
|
||||||
use syntax::ast::{crate, crate_num, decl_item};
|
|
||||||
use syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
|
use syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
|
||||||
use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod};
|
use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod};
|
||||||
use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
|
use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
|
||||||
|
@ -294,6 +293,35 @@ enum EnumVariantOrConstResolution {
|
||||||
EnumVariantOrConstNotFound
|
EnumVariantOrConstNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Specifies how duplicates should be handled when adding a child item if
|
||||||
|
// another item exists with the same name in some namespace.
|
||||||
|
enum DuplicateCheckingMode {
|
||||||
|
ForbidDuplicateModules,
|
||||||
|
ForbidDuplicateTypes,
|
||||||
|
ForbidDuplicateValues,
|
||||||
|
ForbidDuplicateTypesAndValues,
|
||||||
|
OverwriteDuplicates
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DuplicateCheckingMode : cmp::Eq {
|
||||||
|
pure fn eq(other: &DuplicateCheckingMode) -> bool {
|
||||||
|
(self as uint) == (*other as uint)
|
||||||
|
}
|
||||||
|
pure fn ne(other: &DuplicateCheckingMode) -> bool { !self.eq(other) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the namespace associated with the given duplicate checking mode,
|
||||||
|
// or fails for OverwriteDuplicates. This is used for error messages.
|
||||||
|
fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode) ->
|
||||||
|
Namespace {
|
||||||
|
match mode {
|
||||||
|
ForbidDuplicateModules | ForbidDuplicateTypes |
|
||||||
|
ForbidDuplicateTypesAndValues => TypeNS,
|
||||||
|
ForbidDuplicateValues => ValueNS,
|
||||||
|
OverwriteDuplicates => fail ~"OverwriteDuplicates has no namespace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// One local scope.
|
/// One local scope.
|
||||||
struct Rib {
|
struct Rib {
|
||||||
bindings: HashMap<ident,def_like>,
|
bindings: HashMap<ident,def_like>,
|
||||||
|
@ -490,9 +518,10 @@ impl Privacy : cmp::Eq {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Records a possibly-private type definition.
|
// Records a possibly-private type definition.
|
||||||
enum TypeNsDef {
|
struct TypeNsDef {
|
||||||
ModuleDef(Privacy, @Module),
|
mut privacy: Privacy,
|
||||||
TypeDef(Privacy, def)
|
mut module_def: Option<@Module>,
|
||||||
|
mut type_def: Option<def>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Records a possibly-private value definition.
|
// Records a possibly-private value definition.
|
||||||
|
@ -508,7 +537,7 @@ struct NameBindings {
|
||||||
mut value_def: Option<ValueNsDef>, //< Meaning in value namespace.
|
mut value_def: Option<ValueNsDef>, //< Meaning in value namespace.
|
||||||
|
|
||||||
// For error reporting
|
// For error reporting
|
||||||
// XXX: Merge me into TypeDef and ValueDef.
|
// FIXME (#3783): Merge me into TypeNsDef and ValueNsDef.
|
||||||
mut type_span: Option<span>,
|
mut type_span: Option<span>,
|
||||||
mut value_span: Option<span>,
|
mut value_span: Option<span>,
|
||||||
}
|
}
|
||||||
|
@ -521,16 +550,46 @@ impl NameBindings {
|
||||||
def_id: Option<def_id>,
|
def_id: Option<def_id>,
|
||||||
legacy_exports: bool,
|
legacy_exports: bool,
|
||||||
sp: span) {
|
sp: span) {
|
||||||
if self.type_def.is_none() {
|
// Merges the module with the existing type def or creates a new one.
|
||||||
let module_ = @Module(parent_link, def_id, legacy_exports);
|
let module_ = @Module(parent_link, def_id, legacy_exports);
|
||||||
self.type_def = Some(ModuleDef(privacy, module_));
|
match self.type_def {
|
||||||
self.type_span = Some(sp);
|
None => {
|
||||||
|
self.type_def = Some(TypeNsDef {
|
||||||
|
privacy: privacy,
|
||||||
|
module_def: Some(module_),
|
||||||
|
type_def: None
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Some(copy type_def) => {
|
||||||
|
self.type_def = Some(TypeNsDef {
|
||||||
|
privacy: privacy,
|
||||||
|
module_def: Some(module_),
|
||||||
|
.. type_def
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
self.type_span = Some(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Records a type definition.
|
/// Records a type definition.
|
||||||
fn define_type(privacy: Privacy, def: def, sp: span) {
|
fn define_type(privacy: Privacy, def: def, sp: span) {
|
||||||
self.type_def = Some(TypeDef(privacy, def));
|
// Merges the type with the existing type def or creates a new one.
|
||||||
|
match self.type_def {
|
||||||
|
None => {
|
||||||
|
self.type_def = Some(TypeNsDef {
|
||||||
|
privacy: privacy,
|
||||||
|
module_def: None,
|
||||||
|
type_def: Some(def)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Some(copy type_def) => {
|
||||||
|
self.type_def = Some(TypeNsDef {
|
||||||
|
privacy: privacy,
|
||||||
|
type_def: Some(def),
|
||||||
|
.. type_def
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
self.type_span = Some(sp);
|
self.type_span = Some(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,8 +602,8 @@ impl NameBindings {
|
||||||
/// Returns the module node if applicable.
|
/// Returns the module node if applicable.
|
||||||
fn get_module_if_available() -> Option<@Module> {
|
fn get_module_if_available() -> Option<@Module> {
|
||||||
match self.type_def {
|
match self.type_def {
|
||||||
Some(ModuleDef(_, module_)) => return Some(module_),
|
Some(type_def) => type_def.module_def,
|
||||||
None | Some(TypeDef(_, _)) => return None,
|
None => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,12 +612,12 @@ impl NameBindings {
|
||||||
* definition.
|
* definition.
|
||||||
*/
|
*/
|
||||||
fn get_module() -> @Module {
|
fn get_module() -> @Module {
|
||||||
match self.type_def {
|
match self.get_module_if_available() {
|
||||||
None | Some(TypeDef(*)) => {
|
None => {
|
||||||
fail ~"get_module called on a node with no module \
|
fail ~"get_module called on a node with no module \
|
||||||
definition!"
|
definition!"
|
||||||
}
|
}
|
||||||
Some(ModuleDef(_, module_)) => module_
|
Some(module_def) => module_def
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,10 +633,23 @@ impl NameBindings {
|
||||||
TypeNS => {
|
TypeNS => {
|
||||||
match self.type_def {
|
match self.type_def {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ModuleDef(_, module_)) => {
|
Some(type_def) => {
|
||||||
module_.def_id.map(|def_id| def_mod(*def_id))
|
// FIXME (#3784): This is reallllly questionable.
|
||||||
|
// Perhaps the right thing to do is to merge def_mod
|
||||||
|
// and def_ty.
|
||||||
|
match type_def.type_def {
|
||||||
|
Some(type_def) => Some(type_def),
|
||||||
|
None => {
|
||||||
|
match type_def.module_def {
|
||||||
|
Some(module_def) => {
|
||||||
|
module_def.def_id.map(|def_id|
|
||||||
|
def_mod(*def_id))
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(TypeDef(_, def)) => Some(def)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNS => {
|
ValueNS => {
|
||||||
|
@ -594,8 +666,7 @@ impl NameBindings {
|
||||||
TypeNS => {
|
TypeNS => {
|
||||||
match self.type_def {
|
match self.type_def {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ModuleDef(privacy, _)) | Some(TypeDef(privacy, _)) =>
|
Some(type_def) => Some(type_def.privacy)
|
||||||
Some(privacy)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNS => {
|
ValueNS => {
|
||||||
|
@ -882,9 +953,7 @@ impl Resolver {
|
||||||
*/
|
*/
|
||||||
fn add_child(name: ident,
|
fn add_child(name: ident,
|
||||||
reduced_graph_parent: ReducedGraphParent,
|
reduced_graph_parent: ReducedGraphParent,
|
||||||
// Pass in the namespaces for the child item so that we can
|
duplicate_checking_mode: DuplicateCheckingMode,
|
||||||
// check for duplicate items in the same namespace
|
|
||||||
ns: ~[Namespace],
|
|
||||||
// For printing errors
|
// For printing errors
|
||||||
sp: span)
|
sp: span)
|
||||||
-> (@NameBindings, ReducedGraphParent) {
|
-> (@NameBindings, ReducedGraphParent) {
|
||||||
|
@ -904,29 +973,67 @@ impl Resolver {
|
||||||
let new_parent = ModuleReducedGraphParent(module_);
|
let new_parent = ModuleReducedGraphParent(module_);
|
||||||
match module_.children.find(name) {
|
match module_.children.find(name) {
|
||||||
None => {
|
None => {
|
||||||
let child = @NameBindings();
|
let child = @NameBindings();
|
||||||
module_.children.insert(name, child);
|
module_.children.insert(name, child);
|
||||||
return (child, new_parent);
|
return (child, new_parent);
|
||||||
}
|
}
|
||||||
Some(child) => {
|
Some(child) => {
|
||||||
// We don't want to complain if the multiple definitions
|
// Enforce the duplicate checking mode. If we're requesting
|
||||||
// are in different namespaces.
|
// duplicate module checking, check that there isn't a module
|
||||||
match ns.find(|n| child.defined_in_namespace(n)) {
|
// in the module with the same name. If we're requesting
|
||||||
Some(ns) => {
|
// duplicate type checking, check that there isn't a type in
|
||||||
self.session.span_err(sp,
|
// the module with the same name. If we're requesting
|
||||||
fmt!("Duplicate definition of %s %s",
|
// duplicate value checking, check that there isn't a value in
|
||||||
namespace_to_str(ns),
|
// the module with the same name. If we're requesting
|
||||||
self.session.str_of(name)));
|
// duplicate type checking and duplicate value checking, check
|
||||||
do child.span_for_namespace(ns).iter() |sp| {
|
// that there isn't a duplicate type and a duplicate value
|
||||||
self.session.span_note(*sp,
|
// with the same name. If no duplicate checking was requested
|
||||||
fmt!("First definition of %s %s here:",
|
// at all, do nothing.
|
||||||
namespace_to_str(ns),
|
|
||||||
self.session.str_of(name)));
|
let mut is_duplicate = false;
|
||||||
}
|
match duplicate_checking_mode {
|
||||||
|
ForbidDuplicateModules => {
|
||||||
|
is_duplicate =
|
||||||
|
child.get_module_if_available().is_some();
|
||||||
|
}
|
||||||
|
ForbidDuplicateTypes => {
|
||||||
|
match child.def_for_namespace(TypeNS) {
|
||||||
|
Some(def_mod(_)) | None => {}
|
||||||
|
Some(_) => is_duplicate = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ForbidDuplicateValues => {
|
||||||
|
is_duplicate = child.defined_in_namespace(ValueNS);
|
||||||
|
}
|
||||||
|
ForbidDuplicateTypesAndValues => {
|
||||||
|
match child.def_for_namespace(TypeNS) {
|
||||||
|
Some(def_mod(_)) | None => {}
|
||||||
|
Some(_) => is_duplicate = true
|
||||||
|
};
|
||||||
|
if child.defined_in_namespace(ValueNS) {
|
||||||
|
is_duplicate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OverwriteDuplicates => {}
|
||||||
}
|
}
|
||||||
_ => {}
|
if duplicate_checking_mode != OverwriteDuplicates &&
|
||||||
}
|
is_duplicate {
|
||||||
return (child, new_parent);
|
// Return an error here by looking up the namespace that
|
||||||
|
// had the duplicate.
|
||||||
|
let ns = namespace_for_duplicate_checking_mode(
|
||||||
|
duplicate_checking_mode);
|
||||||
|
self.session.span_err(sp,
|
||||||
|
fmt!("duplicate definition of %s %s",
|
||||||
|
namespace_to_str(ns),
|
||||||
|
self.session.str_of(name)));
|
||||||
|
do child.span_for_namespace(ns).iter() |sp| {
|
||||||
|
self.session.span_note(*sp,
|
||||||
|
fmt!("first definition of %s %s here:",
|
||||||
|
namespace_to_str(ns),
|
||||||
|
self.session.str_of(name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (child, new_parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -987,7 +1094,7 @@ impl Resolver {
|
||||||
item_mod(module_) => {
|
item_mod(module_) => {
|
||||||
let legacy = has_legacy_export_attr(item.attrs);
|
let legacy = has_legacy_export_attr(item.attrs);
|
||||||
let (name_bindings, new_parent) =
|
let (name_bindings, new_parent) =
|
||||||
self.add_child(ident, parent, ~[TypeNS], sp);
|
self.add_child(ident, parent, ForbidDuplicateModules, sp);
|
||||||
|
|
||||||
let parent_link = self.get_parent_link(new_parent, ident);
|
let parent_link = self.get_parent_link(new_parent, ident);
|
||||||
let def_id = { crate: 0, node: item.id };
|
let def_id = { crate: 0, node: item.id };
|
||||||
|
@ -999,12 +1106,14 @@ impl Resolver {
|
||||||
|
|
||||||
visit_mod(module_, sp, item.id, new_parent, visitor);
|
visit_mod(module_, sp, item.id, new_parent, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
item_foreign_mod(fm) => {
|
item_foreign_mod(fm) => {
|
||||||
let legacy = has_legacy_export_attr(item.attrs);
|
let legacy = has_legacy_export_attr(item.attrs);
|
||||||
let new_parent = match fm.sort {
|
let new_parent = match fm.sort {
|
||||||
named => {
|
named => {
|
||||||
let (name_bindings, new_parent) =
|
let (name_bindings, new_parent) =
|
||||||
self.add_child(ident, parent, ~[TypeNS], sp);
|
self.add_child(ident, parent,
|
||||||
|
ForbidDuplicateModules, sp);
|
||||||
|
|
||||||
let parent_link = self.get_parent_link(new_parent,
|
let parent_link = self.get_parent_link(new_parent,
|
||||||
ident);
|
ident);
|
||||||
|
@ -1028,15 +1137,15 @@ impl Resolver {
|
||||||
|
|
||||||
// These items live in the value namespace.
|
// These items live in the value namespace.
|
||||||
item_const(*) => {
|
item_const(*) => {
|
||||||
let (name_bindings, _) = self.add_child(ident, parent,
|
let (name_bindings, _) =
|
||||||
~[ValueNS], sp);
|
self.add_child(ident, parent, ForbidDuplicateValues, sp);
|
||||||
|
|
||||||
(*name_bindings).define_value
|
(*name_bindings).define_value
|
||||||
(privacy, def_const(local_def(item.id)), sp);
|
(privacy, def_const(local_def(item.id)), sp);
|
||||||
}
|
}
|
||||||
item_fn(_, purity, _, _) => {
|
item_fn(_, purity, _, _) => {
|
||||||
let (name_bindings, new_parent) = self.add_child(ident, parent,
|
let (name_bindings, new_parent) =
|
||||||
~[ValueNS], sp);
|
self.add_child(ident, parent, ForbidDuplicateValues, sp);
|
||||||
|
|
||||||
let def = def_fn(local_def(item.id), purity);
|
let def = def_fn(local_def(item.id), purity);
|
||||||
(*name_bindings).define_value(privacy, def, sp);
|
(*name_bindings).define_value(privacy, def, sp);
|
||||||
|
@ -1045,17 +1154,16 @@ impl Resolver {
|
||||||
|
|
||||||
// These items live in the type namespace.
|
// These items live in the type namespace.
|
||||||
item_ty(*) => {
|
item_ty(*) => {
|
||||||
let (name_bindings, _) = self.add_child(ident, parent,
|
let (name_bindings, _) =
|
||||||
~[TypeNS], sp);
|
self.add_child(ident, parent, ForbidDuplicateTypes, sp);
|
||||||
|
|
||||||
(*name_bindings).define_type
|
(*name_bindings).define_type
|
||||||
(privacy, def_ty(local_def(item.id)), sp);
|
(privacy, def_ty(local_def(item.id)), sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
item_enum(enum_definition, _) => {
|
item_enum(enum_definition, _) => {
|
||||||
|
let (name_bindings, new_parent) =
|
||||||
let (name_bindings, new_parent) = self.add_child(ident, parent,
|
self.add_child(ident, parent, ForbidDuplicateTypes, sp);
|
||||||
~[TypeNS], sp);
|
|
||||||
|
|
||||||
(*name_bindings).define_type
|
(*name_bindings).define_type
|
||||||
(privacy, def_ty(local_def(item.id)), sp);
|
(privacy, def_ty(local_def(item.id)), sp);
|
||||||
|
@ -1072,7 +1180,7 @@ impl Resolver {
|
||||||
// These items live in both the type and value namespaces.
|
// These items live in both the type and value namespaces.
|
||||||
item_class(*) => {
|
item_class(*) => {
|
||||||
let (name_bindings, new_parent) =
|
let (name_bindings, new_parent) =
|
||||||
self.add_child(ident, parent, ~[TypeNS], sp);
|
self.add_child(ident, parent, ForbidDuplicateTypes, sp);
|
||||||
|
|
||||||
(*name_bindings).define_type
|
(*name_bindings).define_type
|
||||||
(privacy, def_ty(local_def(item.id)), sp);
|
(privacy, def_ty(local_def(item.id)), sp);
|
||||||
|
@ -1083,13 +1191,75 @@ impl Resolver {
|
||||||
visit_item(item, new_parent, visitor);
|
visit_item(item, new_parent, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
item_impl(*) => {
|
item_impl(_, trait_ref_opt, ty, methods) => {
|
||||||
|
// If this implements an anonymous trait and it has static
|
||||||
|
// methods, then add all the static methods within to a new
|
||||||
|
// module, if the type was defined within this module.
|
||||||
|
//
|
||||||
|
// FIXME (#3785): This is quite unsatisfactory. Perhaps we
|
||||||
|
// should modify anonymous traits to only be implementable in
|
||||||
|
// the same module that declared the type.
|
||||||
|
|
||||||
|
// Bail out early if there are no static methods.
|
||||||
|
let mut has_static_methods = false;
|
||||||
|
for methods.each |method| {
|
||||||
|
match method.self_ty.node {
|
||||||
|
sty_static => has_static_methods = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are static methods, then create the module
|
||||||
|
// and add them.
|
||||||
|
match (trait_ref_opt, ty) {
|
||||||
|
(None, @{ id: _, node: ty_path(path, _), span: _ }) if
|
||||||
|
has_static_methods && path.idents.len() == 1 => {
|
||||||
|
// Create the module.
|
||||||
|
let name = path_to_ident(path);
|
||||||
|
let (name_bindings, new_parent) =
|
||||||
|
self.add_child(name,
|
||||||
|
parent,
|
||||||
|
ForbidDuplicateModules,
|
||||||
|
sp);
|
||||||
|
|
||||||
|
let parent_link = self.get_parent_link(new_parent,
|
||||||
|
ident);
|
||||||
|
let def_id = local_def(item.id);
|
||||||
|
name_bindings.define_module(privacy, parent_link,
|
||||||
|
Some(def_id), false, sp);
|
||||||
|
|
||||||
|
let new_parent = ModuleReducedGraphParent(
|
||||||
|
name_bindings.get_module());
|
||||||
|
|
||||||
|
// For each static method...
|
||||||
|
for methods.each |method| {
|
||||||
|
match method.self_ty.node {
|
||||||
|
sty_static => {
|
||||||
|
// Add the static method to the module.
|
||||||
|
let ident = method.ident;
|
||||||
|
let (method_name_bindings, _) =
|
||||||
|
self.add_child(ident,
|
||||||
|
new_parent,
|
||||||
|
ForbidDuplicateValues,
|
||||||
|
method.span);
|
||||||
|
let def = def_fn(local_def(method.id),
|
||||||
|
method.purity);
|
||||||
|
method_name_bindings.define_value(
|
||||||
|
Public, def, method.span);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
visit_item(item, parent, visitor);
|
visit_item(item, parent, visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
item_trait(_, _, methods) => {
|
item_trait(_, _, methods) => {
|
||||||
let (name_bindings, new_parent) = self.add_child(ident, parent,
|
let (name_bindings, new_parent) =
|
||||||
~[TypeNS], sp);
|
self.add_child(ident, parent, ForbidDuplicateTypes, sp);
|
||||||
|
|
||||||
// Add the names of all the methods to the trait info.
|
// Add the names of all the methods to the trait info.
|
||||||
let method_names = @HashMap();
|
let method_names = @HashMap();
|
||||||
|
@ -1103,8 +1273,8 @@ impl Resolver {
|
||||||
sty_static => {
|
sty_static => {
|
||||||
// which parent to use??
|
// which parent to use??
|
||||||
let (method_name_bindings, _) =
|
let (method_name_bindings, _) =
|
||||||
self.add_child(ident, new_parent, ~[ValueNS],
|
self.add_child(ident, new_parent,
|
||||||
ty_m.span);
|
ForbidDuplicateValues, ty_m.span);
|
||||||
let def = def_static_method(local_def(ty_m.id),
|
let def = def_static_method(local_def(ty_m.id),
|
||||||
local_def(item.id),
|
local_def(item.id),
|
||||||
ty_m.purity);
|
ty_m.purity);
|
||||||
|
@ -1142,7 +1312,7 @@ impl Resolver {
|
||||||
&&visitor: vt<ReducedGraphParent>) {
|
&&visitor: vt<ReducedGraphParent>) {
|
||||||
|
|
||||||
let ident = variant.node.name;
|
let ident = variant.node.name;
|
||||||
let (child, _) = self.add_child(ident, parent, ~[ValueNS],
|
let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues,
|
||||||
variant.span);
|
variant.span);
|
||||||
|
|
||||||
let privacy;
|
let privacy;
|
||||||
|
@ -1324,7 +1494,7 @@ impl Resolver {
|
||||||
match find_use_stmt_cnum(self.session.cstore, node_id) {
|
match find_use_stmt_cnum(self.session.cstore, node_id) {
|
||||||
Some(crate_id) => {
|
Some(crate_id) => {
|
||||||
let (child_name_bindings, new_parent) =
|
let (child_name_bindings, new_parent) =
|
||||||
self.add_child(name, parent, ~[TypeNS],
|
self.add_child(name, parent, ForbidDuplicateTypes,
|
||||||
view_item.span);
|
view_item.span);
|
||||||
|
|
||||||
let def_id = { crate: crate_id, node: 0 };
|
let def_id = { crate: crate_id, node: 0 };
|
||||||
|
@ -1355,7 +1525,8 @@ impl Resolver {
|
||||||
|
|
||||||
let name = foreign_item.ident;
|
let name = foreign_item.ident;
|
||||||
let (name_bindings, new_parent) =
|
let (name_bindings, new_parent) =
|
||||||
self.add_child(name, parent, ~[ValueNS], foreign_item.span);
|
self.add_child(name, parent, ForbidDuplicateValues,
|
||||||
|
foreign_item.span);
|
||||||
|
|
||||||
match foreign_item.node {
|
match foreign_item.node {
|
||||||
foreign_item_fn(_, purity, type_parameters) => {
|
foreign_item_fn(_, purity, type_parameters) => {
|
||||||
|
@ -1408,7 +1579,13 @@ impl Resolver {
|
||||||
match def {
|
match def {
|
||||||
def_mod(def_id) | def_foreign_mod(def_id) => {
|
def_mod(def_id) | def_foreign_mod(def_id) => {
|
||||||
match copy child_name_bindings.type_def {
|
match copy child_name_bindings.type_def {
|
||||||
None => {
|
Some(TypeNsDef { module_def: Some(copy module_def), _ }) => {
|
||||||
|
debug!("(building reduced graph for external crate) \
|
||||||
|
already created module");
|
||||||
|
module_def.def_id = Some(def_id);
|
||||||
|
modules.insert(def_id, module_def);
|
||||||
|
}
|
||||||
|
Some(_) | None => {
|
||||||
debug!("(building reduced graph for \
|
debug!("(building reduced graph for \
|
||||||
external crate) building module \
|
external crate) building module \
|
||||||
%s", final_ident);
|
%s", final_ident);
|
||||||
|
@ -1451,16 +1628,6 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ModuleDef(_, module_)) => {
|
|
||||||
debug!("(building reduced graph for \
|
|
||||||
external crate) already created \
|
|
||||||
module");
|
|
||||||
module_.def_id = Some(def_id);
|
|
||||||
modules.insert(def_id, module_);
|
|
||||||
}
|
|
||||||
Some(TypeDef(*)) => {
|
|
||||||
self.session.bug(~"external module def overwriting type def");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def_fn(*) | def_static_method(*) | def_const(*) |
|
def_fn(*) | def_static_method(*) | def_const(*) |
|
||||||
|
@ -1476,8 +1643,7 @@ impl Resolver {
|
||||||
// If this is a trait, add all the method names
|
// If this is a trait, add all the method names
|
||||||
// to the trait info.
|
// to the trait info.
|
||||||
|
|
||||||
match get_method_names_if_trait(self.session.cstore,
|
match get_method_names_if_trait(self.session.cstore, def_id) {
|
||||||
def_id) {
|
|
||||||
None => {
|
None => {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
@ -1547,8 +1713,8 @@ impl Resolver {
|
||||||
let (child_name_bindings, new_parent) =
|
let (child_name_bindings, new_parent) =
|
||||||
self.add_child(ident,
|
self.add_child(ident,
|
||||||
ModuleReducedGraphParent(current_module),
|
ModuleReducedGraphParent(current_module),
|
||||||
// May want a better span
|
OverwriteDuplicates,
|
||||||
~[], dummy_sp());
|
dummy_sp());
|
||||||
|
|
||||||
// Define or reuse the module node.
|
// Define or reuse the module node.
|
||||||
match child_name_bindings.type_def {
|
match child_name_bindings.type_def {
|
||||||
|
@ -1572,7 +1738,8 @@ impl Resolver {
|
||||||
let (child_name_bindings, new_parent) =
|
let (child_name_bindings, new_parent) =
|
||||||
self.add_child(final_ident,
|
self.add_child(final_ident,
|
||||||
ModuleReducedGraphParent(current_module),
|
ModuleReducedGraphParent(current_module),
|
||||||
~[], dummy_sp());
|
OverwriteDuplicates,
|
||||||
|
dummy_sp());
|
||||||
|
|
||||||
match path_entry.def_like {
|
match path_entry.def_like {
|
||||||
dl_def(def) => {
|
dl_def(def) => {
|
||||||
|
@ -1582,12 +1749,12 @@ impl Resolver {
|
||||||
final_ident, new_parent);
|
final_ident, new_parent);
|
||||||
}
|
}
|
||||||
dl_impl(_) => {
|
dl_impl(_) => {
|
||||||
// Because of the infelicitous way the metadata is
|
// We only process static methods of impls here.
|
||||||
// written, we can't process this impl now. We'll get it
|
|
||||||
// later.
|
|
||||||
|
|
||||||
debug!("(building reduced graph for external crate) \
|
debug!("(building reduced graph for external crate) \
|
||||||
ignoring impl %s", final_ident_str);
|
processing impl %s", final_ident_str);
|
||||||
|
|
||||||
|
// FIXME (#3786): Cross-crate static methods in anonymous
|
||||||
|
// traits.
|
||||||
}
|
}
|
||||||
dl_field => {
|
dl_field => {
|
||||||
debug!("(building reduced graph for external crate) \
|
debug!("(building reduced graph for external crate) \
|
||||||
|
@ -2310,18 +2477,34 @@ impl Resolver {
|
||||||
return Indeterminate;
|
return Indeterminate;
|
||||||
}
|
}
|
||||||
Success(target) => {
|
Success(target) => {
|
||||||
|
// Check to see whether there are type bindings, and, if
|
||||||
|
// so, whether there is a module within.
|
||||||
match target.bindings.type_def {
|
match target.bindings.type_def {
|
||||||
None | Some(TypeDef(*)) => {
|
Some(copy type_def) => {
|
||||||
// Not a module.
|
match type_def.module_def {
|
||||||
|
None => {
|
||||||
|
// Not a module.
|
||||||
|
self.session.span_err(span,
|
||||||
|
fmt!("not a \
|
||||||
|
module: %s",
|
||||||
|
self.session.
|
||||||
|
str_of(
|
||||||
|
name)));
|
||||||
|
return Failed;
|
||||||
|
}
|
||||||
|
Some(copy module_def) => {
|
||||||
|
search_module = module_def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// There are no type bindings at all.
|
||||||
self.session.span_err(span,
|
self.session.span_err(span,
|
||||||
fmt!("not a module: %s",
|
fmt!("not a module: %s",
|
||||||
self.session.
|
self.session.str_of(
|
||||||
str_of(name)));
|
name)));
|
||||||
return Failed;
|
return Failed;
|
||||||
}
|
}
|
||||||
Some(ModuleDef(_, copy module_)) => {
|
|
||||||
search_module = module_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2469,14 +2652,24 @@ impl Resolver {
|
||||||
match self.resolve_item_in_lexical_scope(module_, name, TypeNS) {
|
match self.resolve_item_in_lexical_scope(module_, name, TypeNS) {
|
||||||
Success(target) => {
|
Success(target) => {
|
||||||
match target.bindings.type_def {
|
match target.bindings.type_def {
|
||||||
None | Some(TypeDef(*)) => {
|
Some(type_def) => {
|
||||||
|
match type_def.module_def {
|
||||||
|
None => {
|
||||||
|
error!("!!! (resolving module in lexical \
|
||||||
|
scope) module wasn't actually a \
|
||||||
|
module!");
|
||||||
|
return Failed;
|
||||||
|
}
|
||||||
|
Some(module_def) => {
|
||||||
|
return Success(module_def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
error!("!!! (resolving module in lexical scope) module
|
error!("!!! (resolving module in lexical scope) module
|
||||||
wasn't actually a module!");
|
wasn't actually a module!");
|
||||||
return Failed;
|
return Failed;
|
||||||
}
|
}
|
||||||
Some(ModuleDef(_, module_)) => {
|
|
||||||
return Success(module_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Indeterminate => {
|
Indeterminate => {
|
||||||
|
@ -3403,7 +3596,6 @@ impl Resolver {
|
||||||
self_binding: SelfBinding,
|
self_binding: SelfBinding,
|
||||||
capture_clause: CaptureClause,
|
capture_clause: CaptureClause,
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
|
|
||||||
// Check each element of the capture clause.
|
// Check each element of the capture clause.
|
||||||
match capture_clause {
|
match capture_clause {
|
||||||
NoCaptureClause => {
|
NoCaptureClause => {
|
||||||
|
@ -3495,7 +3687,6 @@ impl Resolver {
|
||||||
|
|
||||||
fn resolve_type_parameters(type_parameters: ~[ty_param],
|
fn resolve_type_parameters(type_parameters: ~[ty_param],
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
|
|
||||||
for type_parameters.each |type_parameter| {
|
for type_parameters.each |type_parameter| {
|
||||||
for type_parameter.bounds.each |bound| {
|
for type_parameter.bounds.each |bound| {
|
||||||
match *bound {
|
match *bound {
|
||||||
|
@ -3517,7 +3708,6 @@ impl Resolver {
|
||||||
methods: ~[@method],
|
methods: ~[@method],
|
||||||
optional_destructor: Option<class_dtor>,
|
optional_destructor: Option<class_dtor>,
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
|
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
let outer_type_parameter_count = (*type_parameters).len();
|
let outer_type_parameter_count = (*type_parameters).len();
|
||||||
let borrowed_type_parameters: &~[ty_param] = &*type_parameters;
|
let borrowed_type_parameters: &~[ty_param] = &*type_parameters;
|
||||||
|
@ -3619,23 +3809,21 @@ impl Resolver {
|
||||||
self_type: @Ty,
|
self_type: @Ty,
|
||||||
methods: ~[@method],
|
methods: ~[@method],
|
||||||
visitor: ResolveVisitor) {
|
visitor: ResolveVisitor) {
|
||||||
|
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
let outer_type_parameter_count = type_parameters.len();
|
let outer_type_parameter_count = type_parameters.len();
|
||||||
let borrowed_type_parameters: &~[ty_param] = &type_parameters;
|
let borrowed_type_parameters: &~[ty_param] = &type_parameters;
|
||||||
do self.with_type_parameter_rib(HasTypeParameters
|
do self.with_type_parameter_rib(HasTypeParameters
|
||||||
(borrowed_type_parameters, id, 0u,
|
(borrowed_type_parameters, id, 0u,
|
||||||
NormalRibKind)) {
|
NormalRibKind)) {
|
||||||
|
|
||||||
// Resolve the type parameters.
|
// Resolve the type parameters.
|
||||||
self.resolve_type_parameters(type_parameters, visitor);
|
self.resolve_type_parameters(type_parameters, visitor);
|
||||||
|
|
||||||
// Resolve the trait reference, if necessary.
|
// Resolve the trait reference, if necessary.
|
||||||
let original_trait_refs = self.current_trait_refs;
|
let original_trait_refs = self.current_trait_refs;
|
||||||
match opt_trait_reference {
|
match opt_trait_reference {
|
||||||
Some(trait_reference) => {
|
Some(trait_reference) => {
|
||||||
let new_trait_refs = @DVec();
|
let new_trait_refs = @DVec();
|
||||||
match self.resolve_path(
|
match self.resolve_path(
|
||||||
trait_reference.path, TypeNS, true, visitor) {
|
trait_reference.path, TypeNS, true, visitor) {
|
||||||
None => {
|
None => {
|
||||||
self.session.span_err(span,
|
self.session.span_err(span,
|
||||||
|
@ -3649,10 +3837,10 @@ impl Resolver {
|
||||||
(*new_trait_refs).push(def_id_of_def(def));
|
(*new_trait_refs).push(def_id_of_def(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Record the current set of trait references.
|
// Record the current set of trait references.
|
||||||
self.current_trait_refs = Some(new_trait_refs);
|
self.current_trait_refs = Some(new_trait_refs);
|
||||||
}
|
}
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the self type.
|
// Resolve the self type.
|
||||||
|
|
15
src/test/run-pass/anon-trait-static-method.rs
Normal file
15
src/test/run-pass/anon-trait-static-method.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
struct Foo {
|
||||||
|
x: int
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
static fn new() -> Foo {
|
||||||
|
Foo { x: 3 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = Foo::new();
|
||||||
|
io::println(x.x.to_str());
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue