Skip to content

Commit f10e50a

Browse files
committed
auto merge of #8843 : alexcrichton/rust/fix-bug, r=huonw
Whenever a generic function was encountered, only the top-level items were recursed upon, even though the function could contain items inside blocks or nested inside of other expressions. This fixes the existing code from traversing just the top level items to using a Visitor to deeply recurse and find any items which need to be translated. This was uncovered when building code with --lib, because the encode_symbol function would panic once it found that an item hadn't been translated. Closes #8134
2 parents f94844c + 2c1d656 commit f10e50a

File tree

4 files changed

+85
-10
lines changed

4 files changed

+85
-10
lines changed

src/librustc/middle/trans/base.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ use syntax::parse::token::{special_idents};
8787
use syntax::print::pprust::stmt_to_str;
8888
use syntax::{ast, ast_util, codemap, ast_map};
8989
use syntax::abi::{X86, X86_64, Arm, Mips};
90+
use syntax::visit::Visitor;
9091

9192
pub use middle::trans::context::task_llcx;
9293

@@ -2162,6 +2163,14 @@ pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
21622163
}
21632164
}
21642165

2166+
pub struct TransItemVisitor;
2167+
2168+
impl Visitor<@mut CrateContext> for TransItemVisitor {
2169+
fn visit_item(&mut self, i: @ast::item, ccx: @mut CrateContext) {
2170+
trans_item(ccx, i);
2171+
}
2172+
}
2173+
21652174
pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
21662175
let _icx = push_ctxt("trans_item");
21672176
let path = match ccx.tcx.items.get_copy(&item.id) {
@@ -2193,15 +2202,10 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
21932202
item.id,
21942203
item.attrs);
21952204
} else {
2196-
for stmt in body.stmts.iter() {
2197-
match stmt.node {
2198-
ast::stmt_decl(@codemap::spanned { node: ast::decl_item(i),
2199-
_ }, _) => {
2200-
trans_item(ccx, i);
2201-
}
2202-
_ => ()
2203-
}
2204-
}
2205+
// Be sure to travel more than just one layer deep to catch nested
2206+
// items in blocks and such.
2207+
let mut v = TransItemVisitor;
2208+
v.visit_block(body, ccx);
22052209
}
22062210
}
22072211
ast::item_impl(ref generics, _, _, ref ms) => {

src/librustc/middle/trans/meth.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use std::vec;
3737
use syntax::ast_map::{path, path_mod, path_name};
3838
use syntax::ast_util;
3939
use syntax::{ast, ast_map};
40+
use syntax::visit;
4041

4142
/**
4243
The main "translation" pass for methods. Generates code
@@ -56,7 +57,15 @@ pub fn trans_impl(ccx: @mut CrateContext,
5657
debug!("trans_impl(path=%s, name=%s, id=%?)",
5758
path.repr(tcx), name.repr(tcx), id);
5859

59-
if !generics.ty_params.is_empty() { return; }
60+
// Both here and below with generic methods, be sure to recurse and look for
61+
// items that we need to translate.
62+
if !generics.ty_params.is_empty() {
63+
let mut v = TransItemVisitor;
64+
for method in methods.iter() {
65+
visit::walk_method_helper(&mut v, *method, ccx);
66+
}
67+
return;
68+
}
6069
let sub_path = vec::append_one(path, path_name(name));
6170
for method in methods.iter() {
6271
if method.generics.ty_params.len() == 0u {
@@ -69,6 +78,9 @@ pub fn trans_impl(ccx: @mut CrateContext,
6978
*method,
7079
None,
7180
llfn);
81+
} else {
82+
let mut v = TransItemVisitor;
83+
visit::walk_method_helper(&mut v, *method, ccx);
7284
}
7385
}
7486
}

src/test/auxiliary/nested_item.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// original problem
12+
fn foo<T>() -> int {
13+
{
14+
static foo: int = 2;
15+
foo
16+
}
17+
}
18+
19+
// issue 8134
20+
struct Foo;
21+
impl<T> Foo {
22+
pub fn foo(&self) {
23+
static X: uint = 1;
24+
}
25+
}
26+
27+
// issue 8134
28+
pub struct Parser<T>;
29+
impl<T: std::iterator::Iterator<char>> Parser<T> {
30+
fn in_doctype(&mut self) {
31+
static DOCTYPEPattern: [char, ..6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
32+
}
33+
}
34+
35+
struct Bar;
36+
impl<T> Foo {
37+
pub fn bar(&self) {
38+
static X: uint = 1;
39+
}
40+
}

src/test/run-pass/nested_item_main.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:nested_item.rs
12+
// xfail-fast
13+
14+
extern mod nested_item;
15+
16+
pub fn main() {
17+
assert_eq!(2, nested_item::foo::<()>());
18+
assert_eq!(2, nested_item::foo::<int>());
19+
}

0 commit comments

Comments
 (0)