1
Fork 0

rustc: Implement intra-crate static methods on anonymous trait implementations.

This commit is contained in:
Patrick Walton 2012-10-15 18:04:15 -07:00
parent b38092e9a2
commit 4dc67c5e6a
2 changed files with 312 additions and 109 deletions

View file

@ -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.

View 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());
}