Skip to content

Commit bc03c82

Browse files
committedSep 16, 2010
Check for infinitely sized tags. Un-XFAIL test/compile-fail/infinite-tag-type-recursion.rs.
1 parent 659d1e1 commit bc03c82

File tree

3 files changed

+78
-5
lines changed

3 files changed

+78
-5
lines changed
 

‎src/Makefile

-2
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ TEST_XFAILS_X86 := $(TASK_XFAILS) \
419419
test/run-fail/task-comm-14.rs \
420420
test/compile-fail/bad-recv.rs \
421421
test/compile-fail/bad-send.rs \
422-
test/compile-fail/infinite-tag-type-recursion.rs \
423422
test/compile-fail/infinite-vec-type-recursion.rs \
424423
test/compile-fail/writing-through-read-alias.rs
425424

@@ -591,7 +590,6 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
591590
$(addprefix test/compile-fail/, \
592591
bad-recv.rs \
593592
bad-send.rs \
594-
infinite-tag-type-recursion.rs \
595593
infinite-vec-type-recursion.rs \
596594
rec-missing-fields.rs \
597595
writing-through-read-alias.rs \

‎src/boot/me/type.ml

+73-1
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,75 @@ let populate_tag_graph_node (cx:Semant.ctxt) (id:Common.opaque_id) (n:int) =
10241024
in
10251025
Array.iter add_ty ty_tup
10261026

1027+
let stack_contains (stack:'a Stack.t) (elem:'a) : bool =
1028+
try
1029+
Stack.iter (fun elem' -> if elem = elem' then raise Exit) stack; false
1030+
with Exit -> true
1031+
1032+
let report_infinitely_sized_tag
1033+
(id:Common.opaque_id)
1034+
(stack:Common.opaque_id Stack.t)
1035+
: unit =
1036+
let string_of_tag_id tag_id =
1037+
let ty = Ast.TY_tag { Ast.tag_id = tag_id; Ast.tag_args = [| |] } in
1038+
Ast.sprintf_ty () ty
1039+
in
1040+
let msg = Buffer.create 0 in
1041+
Buffer.add_string msg "found tag of infinite size: ";
1042+
while not (Stack.is_empty stack) do
1043+
Buffer.add_string msg (string_of_tag_id (Stack.pop stack));
1044+
Buffer.add_string msg " <- "
1045+
done;
1046+
Buffer.add_string msg (string_of_tag_id id);
1047+
Buffer.add_string msg "; use '@' for recursive references";
1048+
Common.err None "%s" (Buffer.contents msg)
1049+
1050+
let check_for_tag_cycles (cx:Semant.ctxt) =
1051+
(* Find cycles in tags using Tarjan's strongly connected components
1052+
* algorithm. *)
1053+
let lowlinks = Hashtbl.create 0 in
1054+
let next_index, stack = ref 0, Stack.create () in
1055+
1056+
let rec check_node id node =
1057+
if node.Semant.tgn_index = None then begin
1058+
let index = !next_index in
1059+
incr next_index;
1060+
node.Semant.tgn_index <- Some index;
1061+
1062+
Stack.push id stack;
1063+
1064+
Hashtbl.add lowlinks id max_int;
1065+
1066+
let check_outgoing_edge id' =
1067+
let node' = Hashtbl.find cx.Semant.ctxt_tag_containment id' in
1068+
if node'.Semant.tgn_index = None then begin
1069+
check_node id' node';
1070+
let lowlink = Hashtbl.find lowlinks id in
1071+
let lowlink' = Hashtbl.find lowlinks id' in
1072+
Hashtbl.replace lowlinks id (min lowlink lowlink')
1073+
end else if stack_contains stack id' then
1074+
let lowlink = Hashtbl.find lowlinks id in
1075+
let index' =
1076+
match node'.Semant.tgn_index with
1077+
Some index' -> index'
1078+
| None ->
1079+
Common.bug
1080+
()
1081+
"check_for_tag_cycles: node in stack without index"
1082+
in
1083+
Hashtbl.replace lowlinks id (min lowlink index')
1084+
in
1085+
1086+
Queue.iter check_outgoing_edge node.Semant.tgn_children;
1087+
1088+
if index == Hashtbl.find lowlinks id then
1089+
report_infinitely_sized_tag id stack;
1090+
1091+
ignore (Stack.pop stack)
1092+
end
1093+
in
1094+
Hashtbl.iter check_node cx.Semant.ctxt_tag_containment
1095+
10271096
let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
10281097
let path = Stack.create () in
10291098
let fn_ctx_stack = Stack.create () in
@@ -1139,7 +1208,10 @@ let process_crate (cx:Semant.ctxt) (crate:Ast.crate) : unit =
11391208
if not (Hashtbl.mem cx.Semant.ctxt_auto_deref_lval lval_id) then
11401209
Hashtbl.add cx.Semant.ctxt_auto_deref_lval lval_id false
11411210
in
1142-
Hashtbl.iter fill cx.Semant.ctxt_all_lvals
1211+
Hashtbl.iter fill cx.Semant.ctxt_all_lvals;
1212+
1213+
(* Check for tag cycles. *)
1214+
check_for_tag_cycles cx
11431215
in
11441216

11451217
{

‎src/test/compile-fail/infinite-tag-type-recursion.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// -*- rust -*-
22

3-
// error-pattern: Infinite type recursion
3+
// error-pattern: tag of infinite size
44

5-
type mlist = tag(cons(int,mlist), nil());
5+
tag mlist {
6+
cons(int, mlist);
7+
nil();
8+
}
69

710
fn main() {
811
auto a = cons(10, cons(11, nil()));

0 commit comments

Comments
 (0)
Please sign in to comment.