Check for infinitely sized tags. Un-XFAIL test/compile-fail/infinite-tag-type-recursion.rs.

This commit is contained in:
Patrick Walton 2010-09-16 16:24:19 -07:00
parent 659d1e1b7d
commit bc03c82c79
3 changed files with 78 additions and 5 deletions

View File

@ -419,7 +419,6 @@ TEST_XFAILS_X86 := $(TASK_XFAILS) \
test/run-fail/task-comm-14.rs \
test/compile-fail/bad-recv.rs \
test/compile-fail/bad-send.rs \
test/compile-fail/infinite-tag-type-recursion.rs \
test/compile-fail/infinite-vec-type-recursion.rs \
test/compile-fail/writing-through-read-alias.rs
@ -591,7 +590,6 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
$(addprefix test/compile-fail/, \
bad-recv.rs \
bad-send.rs \
infinite-tag-type-recursion.rs \
infinite-vec-type-recursion.rs \
rec-missing-fields.rs \
writing-through-read-alias.rs \

View File

@ -1024,6 +1024,75 @@ let populate_tag_graph_node (cx:Semant.ctxt) (id:Common.opaque_id) (n:int) =
in
Array.iter add_ty ty_tup
let stack_contains (stack:'a Stack.t) (elem:'a) : bool =
try
Stack.iter (fun elem' -> if elem = elem' then raise Exit) stack; false
with Exit -> true
let report_infinitely_sized_tag
(id:Common.opaque_id)
(stack:Common.opaque_id Stack.t)
: unit =
let string_of_tag_id tag_id =
let ty = Ast.TY_tag { Ast.tag_id = tag_id; Ast.tag_args = [| |] } in
Ast.sprintf_ty () ty
in
let msg = Buffer.create 0 in
Buffer.add_string msg "found tag of infinite size: ";
while not (Stack.is_empty stack) do
Buffer.add_string msg (string_of_tag_id (Stack.pop stack));
Buffer.add_string msg " <- "
done;
Buffer.add_string msg (string_of_tag_id id);
Buffer.add_string msg "; use '@' for recursive references";
Common.err None "%s" (Buffer.contents msg)
let check_for_tag_cycles (cx:Semant.ctxt) =
(* Find cycles in tags using Tarjan's strongly connected components
* algorithm. *)
let lowlinks = Hashtbl.create 0 in
let next_index, stack = ref 0, Stack.create () in
let rec check_node id node =
if node.Semant.tgn_index = None then begin
let index = !next_index in
incr next_index;
node.Semant.tgn_index <- Some index;
Stack.push id stack;
Hashtbl.add lowlinks id max_int;
let check_outgoing_edge id' =
let node' = Hashtbl.find cx.Semant.ctxt_tag_containment id' in
if node'.Semant.tgn_index = None then begin
check_node id' node';
let lowlink = Hashtbl.find lowlinks id in
let lowlink' = Hashtbl.find lowlinks id' in
Hashtbl.replace lowlinks id (min lowlink lowlink')
end else if stack_contains stack id' then
let lowlink = Hashtbl.find lowlinks id in
let index' =
match node'.Semant.tgn_index with
Some index' -> index'
| None ->
Common.bug
()
"check_for_tag_cycles: node in stack without index"
in
Hashtbl.replace lowlinks id (min lowlink index')
in
Queue.iter check_outgoing_edge node.Semant.tgn_children;
if index == Hashtbl.find lowlinks id then
report_infinitely_sized_tag id stack;
ignore (Stack.pop stack)
end
in
Hashtbl.iter check_node cx.Semant.ctxt_tag_containment
let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
let path = Stack.create () in
let fn_ctx_stack = Stack.create () in
@ -1139,7 +1208,10 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
if not (Hashtbl.mem cx.Semant.ctxt_auto_deref_lval lval_id) then
Hashtbl.add cx.Semant.ctxt_auto_deref_lval lval_id false
in
Hashtbl.iter fill cx.Semant.ctxt_all_lvals
Hashtbl.iter fill cx.Semant.ctxt_all_lvals;
(* Check for tag cycles. *)
check_for_tag_cycles cx
in
{

View File

@ -1,8 +1,11 @@
// -*- rust -*-
// error-pattern: Infinite type recursion
// error-pattern: tag of infinite size
type mlist = tag(cons(int,mlist), nil());
tag mlist {
cons(int, mlist);
nil();
}
fn main() {
auto a = cons(10, cons(11, nil()));