mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-25 14:13:38 +00:00
Guard against infinitely expanding generic/inline functions
Closes #2220 Test case disabled until a memory-leak issue is resolved.
This commit is contained in:
parent
2782cfb783
commit
68f8812511
@ -1938,7 +1938,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
|||||||
|
|
||||||
let map_node = ccx.tcx.items.get(fn_id.node);
|
let map_node = ccx.tcx.items.get(fn_id.node);
|
||||||
// Get the path so that we can create a symbol
|
// Get the path so that we can create a symbol
|
||||||
let (pt, name) = alt map_node {
|
let (pt, name, span) = alt map_node {
|
||||||
ast_map::node_item(i, pt) {
|
ast_map::node_item(i, pt) {
|
||||||
alt i.node {
|
alt i.node {
|
||||||
ast::item_res(_, _, _, dtor_id, _, _) {
|
ast::item_res(_, _, _, dtor_id, _, _) {
|
||||||
@ -1946,23 +1946,33 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
|||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
(pt, i.ident)
|
(pt, i.ident, i.span)
|
||||||
}
|
}
|
||||||
ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
|
ast_map::node_variant(v, enm, pt) { (pt, v.node.name, enm.span) }
|
||||||
ast_map::node_method(m, _, pt) { (pt, m.ident) }
|
ast_map::node_method(m, _, pt) { (pt, m.ident, m.span) }
|
||||||
ast_map::node_native_item(i, ast::native_abi_rust_intrinsic, pt)
|
ast_map::node_native_item(i, ast::native_abi_rust_intrinsic, pt)
|
||||||
{ (pt, i.ident) }
|
{ (pt, i.ident, i.span) }
|
||||||
ast_map::node_native_item(_, abi, _) {
|
ast_map::node_native_item(_, abi, _) {
|
||||||
// Natives don't have to be monomorphized.
|
// Natives don't have to be monomorphized.
|
||||||
ret {val: get_item_val(ccx, fn_id.node),
|
ret {val: get_item_val(ccx, fn_id.node),
|
||||||
must_cast: true};
|
must_cast: true};
|
||||||
}
|
}
|
||||||
ast_map::node_ctor(nm, _, _, pt) { (pt, nm) }
|
ast_map::node_ctor(nm, _, _, pt) { (pt, nm, ast_util::dummy_sp()) }
|
||||||
_ { fail "unexpected node type"; }
|
_ { fail "unexpected node type"; }
|
||||||
};
|
};
|
||||||
let mono_ty = ty::subst_tps(ccx.tcx, substs, item_ty);
|
let mono_ty = ty::subst_tps(ccx.tcx, substs, item_ty);
|
||||||
let llfty = type_of_fn_from_ty(ccx, mono_ty);
|
let llfty = type_of_fn_from_ty(ccx, mono_ty);
|
||||||
|
|
||||||
|
let depth = option::get_or_default(ccx.monomorphizing.find(fn_id), 0u);
|
||||||
|
// Random cut-off -- code that needs to instantiate the same function
|
||||||
|
// recursively more than ten times can probably safely be assumed to be
|
||||||
|
// causing an infinite expansion.
|
||||||
|
if depth > 10u {
|
||||||
|
ccx.sess.span_fatal(
|
||||||
|
span, "overly deep expansion of inlined function");
|
||||||
|
}
|
||||||
|
ccx.monomorphizing.insert(fn_id, depth + 1u);
|
||||||
|
|
||||||
let pt = *pt + [path_name(ccx.names(name))];
|
let pt = *pt + [path_name(ccx.names(name))];
|
||||||
let s = mangle_exported_name(ccx, pt, mono_ty);
|
let s = mangle_exported_name(ccx, pt, mono_ty);
|
||||||
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty);
|
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty);
|
||||||
@ -2014,6 +2024,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, real_substs: [ty::t],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ccx.monomorphizing.insert(fn_id, depth);
|
||||||
{val: lldecl, must_cast: must_cast}
|
{val: lldecl, must_cast: must_cast}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5022,6 +5033,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
|||||||
tydescs: ty::new_ty_hash(),
|
tydescs: ty::new_ty_hash(),
|
||||||
external: util::common::new_def_hash(),
|
external: util::common::new_def_hash(),
|
||||||
monomorphized: map::hashmap(hash_mono_id, {|a, b| a == b}),
|
monomorphized: map::hashmap(hash_mono_id, {|a, b| a == b}),
|
||||||
|
monomorphizing: ast_util::new_def_id_hash(),
|
||||||
type_use_cache: util::common::new_def_hash(),
|
type_use_cache: util::common::new_def_hash(),
|
||||||
vtables: map::hashmap(hash_mono_id, {|a, b| a == b}),
|
vtables: map::hashmap(hash_mono_id, {|a, b| a == b}),
|
||||||
const_cstr_cache: map::str_hash(),
|
const_cstr_cache: map::str_hash(),
|
||||||
|
@ -95,6 +95,7 @@ type crate_ctxt = {
|
|||||||
external: hashmap<ast::def_id, option<ast::node_id>>,
|
external: hashmap<ast::def_id, option<ast::node_id>>,
|
||||||
// Cache instances of monomorphized functions
|
// Cache instances of monomorphized functions
|
||||||
monomorphized: hashmap<mono_id, ValueRef>,
|
monomorphized: hashmap<mono_id, ValueRef>,
|
||||||
|
monomorphizing: hashmap<ast::def_id, uint>,
|
||||||
// Cache computed type parameter uses (see type_use.rs)
|
// Cache computed type parameter uses (see type_use.rs)
|
||||||
type_use_cache: hashmap<ast::def_id, [type_use::type_uses]>,
|
type_use_cache: hashmap<ast::def_id, [type_use::type_uses]>,
|
||||||
// Cache generated vtables
|
// Cache generated vtables
|
||||||
|
30
src/test/compile-fail/infinite-instantiation.rs
Normal file
30
src/test/compile-fail/infinite-instantiation.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// error-pattern: overly deep expansion
|
||||||
|
// issue 2258
|
||||||
|
// This is currently exposing a memory leak, and xfailed for that reason
|
||||||
|
// xfail-test
|
||||||
|
|
||||||
|
iface to_opt {
|
||||||
|
fn to_option() -> option<self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl of to_opt for uint {
|
||||||
|
fn to_option() -> option<uint> {
|
||||||
|
some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:copy> of to_opt for option<T> {
|
||||||
|
fn to_option() -> option<option<T>> {
|
||||||
|
some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function<T:to_opt>(counter: uint, t: T) {
|
||||||
|
if counter > 0u {
|
||||||
|
function(counter - 1u, t.to_option());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
function(22u, 22u);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user