diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e8186477877f4..1dc30d2221da8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -87,6 +87,7 @@ use syntax::parse::token::{special_idents}; use syntax::print::pprust::stmt_to_str; use syntax::{ast, ast_util, codemap, ast_map}; use syntax::abi::{X86, X86_64, Arm, Mips}; +use syntax::visit::Visitor; pub use middle::trans::context::task_llcx; @@ -2162,6 +2163,14 @@ pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def, } } +pub struct TransItemVisitor; + +impl Visitor<@mut CrateContext> for TransItemVisitor { + fn visit_item(&mut self, i: @ast::item, ccx: @mut CrateContext) { + trans_item(ccx, i); + } +} + pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { let _icx = push_ctxt("trans_item"); let path = match ccx.tcx.items.get_copy(&item.id) { @@ -2193,15 +2202,10 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { item.id, item.attrs); } else { - for stmt in body.stmts.iter() { - match stmt.node { - ast::stmt_decl(@codemap::spanned { node: ast::decl_item(i), - _ }, _) => { - trans_item(ccx, i); - } - _ => () - } - } + // Be sure to travel more than just one layer deep to catch nested + // items in blocks and such. + let mut v = TransItemVisitor; + v.visit_block(body, ccx); } } ast::item_impl(ref generics, _, _, ref ms) => { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 717dfbb678453..fb4dd8a74fb61 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -37,6 +37,7 @@ use std::vec; use syntax::ast_map::{path, path_mod, path_name}; use syntax::ast_util; use syntax::{ast, ast_map}; +use syntax::visit; /** The main "translation" pass for methods. Generates code @@ -56,7 +57,15 @@ pub fn trans_impl(ccx: @mut CrateContext, debug!("trans_impl(path=%s, name=%s, id=%?)", path.repr(tcx), name.repr(tcx), id); - if !generics.ty_params.is_empty() { return; } + // Both here and below with generic methods, be sure to recurse and look for + // items that we need to translate. + if !generics.ty_params.is_empty() { + let mut v = TransItemVisitor; + for method in methods.iter() { + visit::walk_method_helper(&mut v, *method, ccx); + } + return; + } let sub_path = vec::append_one(path, path_name(name)); for method in methods.iter() { if method.generics.ty_params.len() == 0u { @@ -69,6 +78,9 @@ pub fn trans_impl(ccx: @mut CrateContext, *method, None, llfn); + } else { + let mut v = TransItemVisitor; + visit::walk_method_helper(&mut v, *method, ccx); } } } diff --git a/src/test/auxiliary/nested_item.rs b/src/test/auxiliary/nested_item.rs new file mode 100644 index 0000000000000..e9dde0d14a399 --- /dev/null +++ b/src/test/auxiliary/nested_item.rs @@ -0,0 +1,40 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// original problem +fn foo() -> int { + { + static foo: int = 2; + foo + } +} + +// issue 8134 +struct Foo; +impl Foo { + pub fn foo(&self) { + static X: uint = 1; + } +} + +// issue 8134 +pub struct Parser; +impl> Parser { + fn in_doctype(&mut self) { + static DOCTYPEPattern: [char, ..6] = ['O', 'C', 'T', 'Y', 'P', 'E']; + } +} + +struct Bar; +impl Foo { + pub fn bar(&self) { + static X: uint = 1; + } +} diff --git a/src/test/run-pass/nested_item_main.rs b/src/test/run-pass/nested_item_main.rs new file mode 100644 index 0000000000000..5ce05fea568b3 --- /dev/null +++ b/src/test/run-pass/nested_item_main.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:nested_item.rs +// xfail-fast + +extern mod nested_item; + +pub fn main() { + assert_eq!(2, nested_item::foo::<()>()); + assert_eq!(2, nested_item::foo::()); +}