mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +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);
|
||||
// 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) {
|
||||
alt i.node {
|
||||
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_method(m, _, pt) { (pt, m.ident) }
|
||||
ast_map::node_variant(v, enm, pt) { (pt, v.node.name, enm.span) }
|
||||
ast_map::node_method(m, _, pt) { (pt, m.ident, m.span) }
|
||||
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, _) {
|
||||
// Natives don't have to be monomorphized.
|
||||
ret {val: get_item_val(ccx, fn_id.node),
|
||||
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"; }
|
||||
};
|
||||
let mono_ty = ty::subst_tps(ccx.tcx, substs, item_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 s = mangle_exported_name(ccx, pt, mono_ty);
|
||||
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}
|
||||
}
|
||||
|
||||
@ -5022,6 +5033,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
||||
tydescs: ty::new_ty_hash(),
|
||||
external: util::common::new_def_hash(),
|
||||
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(),
|
||||
vtables: map::hashmap(hash_mono_id, {|a, b| a == b}),
|
||||
const_cstr_cache: map::str_hash(),
|
||||
|
@ -95,6 +95,7 @@ type crate_ctxt = {
|
||||
external: hashmap<ast::def_id, option<ast::node_id>>,
|
||||
// Cache instances of monomorphized functions
|
||||
monomorphized: hashmap<mono_id, ValueRef>,
|
||||
monomorphizing: hashmap<ast::def_id, uint>,
|
||||
// Cache computed type parameter uses (see type_use.rs)
|
||||
type_use_cache: hashmap<ast::def_id, [type_use::type_uses]>,
|
||||
// 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