Fix a bug with region-parameterized enums etc where trans considered

them to be non-monomorphic.  Merely having lifetime parameters
is not enough to qualify for that status.  Fixes #5243.
This commit is contained in:
Niko Matsakis 2013-03-06 12:27:23 -05:00
parent 67100ddb35
commit 704cd648ac
8 changed files with 56 additions and 21 deletions

View File

@ -178,12 +178,14 @@ fn is_test_fn(i: @ast::item) -> bool {
fn has_test_signature(i: @ast::item) -> bool {
match &i.node {
&ast::item_fn(ref decl, _, ref tps, _) => {
&ast::item_fn(ref decl, _, ref generics, _) => {
let no_output = match decl.output.node {
ast::ty_nil => true,
_ => false
};
decl.inputs.is_empty() && no_output && tps.is_empty()
decl.inputs.is_empty()
&& no_output
&& !generics.is_parameterized()
}
_ => false
}

View File

@ -228,14 +228,16 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) {
fn encode_symbol(ecx: @EncodeContext, ebml_w: writer::Encoder, id: node_id) {
ebml_w.start_tag(tag_items_data_item_symbol);
let sym = match ecx.item_symbols.find(&id) {
Some(ref x) => (/*bad*/copy *x),
None => {
ecx.diag.handler().bug(
fmt!("encode_symbol: id not found %d", id));
}
};
ebml_w.writer.write(str::to_bytes(sym));
match ecx.item_symbols.find(&id) {
Some(ref x) => {
debug!("encode_symbol(id=%?, str=%s)", id, *x);
ebml_w.writer.write(str::to_bytes(*x));
}
None => {
ecx.diag.handler().bug(
fmt!("encode_symbol: id not found %d", id));
}
}
ebml_w.end_tag();
}
@ -264,6 +266,8 @@ fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder,
path: &[ast_map::path_elt],
index: @mut ~[entry<int>],
generics: &ast::Generics) {
debug!("encode_enum_variant_info(id=%?)", id);
let mut disr_val = 0;
let mut i = 0;
let vi = ty::enum_variants(ecx.tcx,

View File

@ -2079,7 +2079,7 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) {
_ => fail!(~"trans_item"),
};
match /*bad*/copy item.node {
ast::item_fn(ref decl, purity, ref tps, ref body) => {
ast::item_fn(ref decl, purity, ref generics, ref body) => {
if purity == ast::extern_fn {
let llfndecl = get_item_val(ccx, item.id);
foreign::trans_foreign_fn(ccx,
@ -2087,7 +2087,7 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) {
/*bad*/copy *path,
~[path_name(item.ident)]),
decl, body, llfndecl, item.id);
} else if tps.is_empty() {
} else if !generics.is_type_parameterized() {
let llfndecl = get_item_val(ccx, item.id);
trans_fn(ccx,
vec::append(/*bad*/copy *path, ~[path_name(item.ident)]),
@ -2111,8 +2111,8 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) {
ast::item_mod(ref m) => {
trans_mod(ccx, m);
}
ast::item_enum(ref enum_definition, ref tps) => {
if tps.is_empty() {
ast::item_enum(ref enum_definition, ref generics) => {
if !generics.is_type_parameterized() {
let degen = (*enum_definition).variants.len() == 1u;
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
let mut i = 0;
@ -2128,8 +2128,8 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) {
};
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
}
ast::item_struct(struct_def, tps) => {
if tps.is_empty() {
ast::item_struct(struct_def, generics) => {
if !generics.is_type_parameterized() {
trans_struct_def(ccx, struct_def, path, item.id);
}
}

View File

@ -861,7 +861,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
// like "foo<X>". This is because otherwise ty_to_str will
// print the name as merely "foo", as it has no way to
// reconstruct the value of X.
if !generics.is_empty() { t0 } else {
if generics.is_parameterized() { t0 } else {
ty::mk_with_id(tcx, t0, def_id)
}
};

View File

@ -315,7 +315,7 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt,
Some(ast_map::node_item(it,_)) => {
match it.node {
ast::item_fn(_, _, ref ps, _)
if !ps.is_empty() => {
if ps.is_parameterized() => {
tcx.sess.span_err(
main_span,
~"main function is not allowed \

View File

@ -161,8 +161,14 @@ pub struct Generics {
}
pub impl Generics {
fn is_empty(&self) -> bool {
self.lifetimes.len() + self.ty_params.len() == 0
fn is_parameterized(&self) -> bool {
self.lifetimes.len() + self.ty_params.len() > 0
}
fn is_lt_parameterized(&self) -> bool {
self.lifetimes.len() > 0
}
fn is_type_parameterized(&self) -> bool {
self.ty_params.len() > 0
}
}

View File

@ -567,7 +567,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
ast::item_impl(ref generics, opt_trait, ty, ref methods) => {
head(s, visibility_qualified(item.vis, ~"impl"));
if !generics.is_empty() {
if generics.is_parameterized() {
print_generics(s, generics);
space(s.s);
}

View File

@ -0,0 +1,23 @@
// Copyright 2012-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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that merely have lifetime parameters is not
// enough for trans to consider this as non-monomorphic,
// which led to various assertions and failures in turn.
struct S<'self> {
v: &'self int
}
fn f<'lt>(_s: &S<'lt>) {}
fn main() {
f(& S { v: &42 });
}