@@ -184,6 +184,7 @@ export type_param;
184
184
export unify;
185
185
export variant_info;
186
186
export walk_ty;
187
+ export occurs_check_fails;
187
188
188
189
// Data types
189
190
tag mode { mo_val; mo_alias ( bool) ; }
@@ -655,6 +656,7 @@ fn walk_ty(cx: &ctxt, walker: ty_walk, ty: t) {
655
656
ty_str. { /* no-op */ }
656
657
ty_istr. { /* no-op */ }
657
658
ty_type. { /* no-op */ }
659
+ ty_task. { /* no-op */ }
658
660
ty_native ( _) { /* no-op */ }
659
661
ty_box ( tm) { walk_ty ( cx, walker, tm. ty ) ; }
660
662
ty_vec ( tm) { walk_ty ( cx, walker, tm. ty ) ; }
@@ -686,6 +688,9 @@ fn walk_ty(cx: &ctxt, walker: ty_walk, ty: t) {
686
688
walk_ty ( cx, walker, sub) ;
687
689
for tp: t in tps { walk_ty ( cx, walker, tp) ; }
688
690
}
691
+ ty_constr ( sub, _) {
692
+ walk_ty ( cx, walker, sub) ;
693
+ }
689
694
ty_var ( _) { /* no-op */ }
690
695
ty_param ( _, _) { /* no-op */ }
691
696
}
@@ -1393,6 +1398,24 @@ fn type_param(cx: &ctxt, ty: &t) -> option::t[uint] {
1393
1398
ret none;
1394
1399
}
1395
1400
1401
+ // Returns an ivec of all the type variables
1402
+ // occurring in t. It may contain duplicates.
1403
+ fn vars_in_type ( cx : & ctxt , ty : & t ) -> int [ ] {
1404
+ fn collect_var ( cx : & ctxt , vars : & @mutable int[ ] , ty : t ) {
1405
+ alt struct( cx, ty) {
1406
+ ty_var ( v) {
1407
+ * vars += ~[ v] ;
1408
+ }
1409
+ _ { }
1410
+ }
1411
+ }
1412
+ let rslt: @mutable int[ ] = @mutable ( ~[ ] ) ;
1413
+ walk_ty ( cx, bind collect_var ( cx, rslt, _) , ty) ;
1414
+ // Works because of a "convenient" bug that lets us
1415
+ // return a mutable ivec as if it's immutable
1416
+ ret * rslt;
1417
+ }
1418
+
1396
1419
fn type_autoderef ( cx : & ctxt , t : & ty:: t ) -> ty:: t {
1397
1420
let t1: ty:: t = t;
1398
1421
while true {
@@ -1990,6 +2013,28 @@ fn is_lval(expr: &@ast::expr) -> bool {
1990
2013
}
1991
2014
}
1992
2015
2016
+ fn occurs_check_fails ( tcx : & ctxt , sp : & option:: t [ span ] , vid : int , rt : & t )
2017
+ -> bool {
2018
+ // Occurs check!
2019
+ if ivec:: member ( vid, vars_in_type ( tcx, rt) ) {
2020
+ alt sp {
2021
+ some ( s) {
2022
+ // Maybe this should be span_err -- however, there's an
2023
+ // assertion later on that the type doesn't contain
2024
+ // variables, so in this case we have to be sure to die.
2025
+ tcx. sess . span_fatal ( s,
2026
+ "Type inference failed because I \
2027
+ could not find a type\n that's both of the form " +
2028
+ ty_to_str ( tcx, ty:: mk_var ( tcx, ( vid) ) )
2029
+ + " and of the form " + ty_to_str ( tcx, rt)
2030
+ + ". Such a type would have to be infinitely \
2031
+ large.") ;
2032
+ }
2033
+ _ { ret true; }
2034
+ }
2035
+ }
2036
+ else { ret false; }
2037
+ }
1993
2038
1994
2039
// Type unification via Robinson's algorithm (Robinson 1965). Implemented as
1995
2040
// described in Hoder and Voronkov:
@@ -2318,9 +2363,6 @@ mod unify {
2318
2363
// TODO: rewrite this using tuple pattern matching when available, to
2319
2364
// avoid all this rightward drift and spikiness.
2320
2365
2321
- // TODO: occurs check, to make sure we don't loop forever when
2322
- // unifying e.g. 'a and option['a]
2323
-
2324
2366
// Fast path.
2325
2367
2326
2368
if eq_ty ( expected, actual) { ret ures_ok ( expected) ; }
@@ -2694,9 +2736,15 @@ mod unify {
2694
2736
}
2695
2737
2696
2738
// Fixups and substitutions
2697
- fn fixup_vars ( tcx : ty_ctxt , vb : @var_bindings , typ : t ) -> fixup_result {
2698
- fn subst_vars ( tcx : ty_ctxt , vb : @var_bindings ,
2739
+ // Takes an optional span - complain about occurs check violations
2740
+ // iff the span is present (so that if we already know we're going
2741
+ // to error anyway, we don't complain)
2742
+ fn fixup_vars ( tcx : ty_ctxt , sp : & option:: t [ span ] ,
2743
+ vb : @var_bindings , typ : t ) -> fixup_result {
2744
+ fn subst_vars ( tcx : ty_ctxt , sp : & option:: t [ span ] , vb : @var_bindings ,
2699
2745
unresolved : @mutable option:: t [ int ] , vid : int ) -> t {
2746
+ // Should really return a fixup_result instead of a t, but fold_ty
2747
+ // doesn't allow returning anything but a t.
2700
2748
if vid as uint >= ufindivec:: set_count ( vb. sets ) {
2701
2749
* unresolved = some ( vid) ;
2702
2750
ret ty:: mk_var ( tcx, vid) ;
@@ -2705,29 +2753,33 @@ mod unify {
2705
2753
alt smallintmap:: find[ t] ( vb. types , root_id) {
2706
2754
none. { * unresolved = some ( vid) ; ret ty:: mk_var ( tcx, vid) ; }
2707
2755
some ( rt) {
2756
+ if occurs_check_fails ( tcx, sp, vid, rt) {
2757
+ // Return the type unchanged, so we can error out downstream
2758
+ ret rt;
2759
+ }
2708
2760
ret fold_ty( tcx,
2709
- fm_var ( bind subst_vars ( tcx, vb, unresolved, _) ) ,
2710
- rt) ;
2761
+ fm_var ( bind subst_vars ( tcx, sp, vb, unresolved, _) ) , rt) ;
2711
2762
}
2712
2763
}
2713
2764
}
2714
2765
let unresolved = @mutable none[ int] ;
2715
2766
let rty =
2716
- fold_ty ( tcx, fm_var ( bind subst_vars ( tcx, vb, unresolved, _) ) ,
2767
+ fold_ty ( tcx, fm_var ( bind subst_vars ( tcx, sp , vb, unresolved, _) ) ,
2717
2768
typ) ;
2718
2769
let ur = * unresolved;
2719
2770
alt ur {
2720
2771
none. { ret fix_ok( rty) ; }
2721
2772
some ( var_id) { ret fix_err( var_id) ; }
2722
2773
}
2723
2774
}
2724
- fn resolve_type_var ( tcx : & ty_ctxt , vb : & @var_bindings , vid : int ) ->
2775
+ fn resolve_type_var ( tcx : & ty_ctxt , sp : & option:: t [ span ] ,
2776
+ vb : & @var_bindings , vid : int ) ->
2725
2777
fixup_result {
2726
2778
if vid as uint >= ufindivec:: set_count ( vb. sets ) { ret fix_err ( vid) ; }
2727
2779
let root_id = ufindivec:: find ( vb. sets , vid as uint ) ;
2728
2780
alt smallintmap:: find[ t] ( vb. types , root_id) {
2729
2781
none. { ret fix_err ( vid) ; }
2730
- some ( rt) { ret fixup_vars ( tcx, vb, rt) ; }
2782
+ some ( rt) { ret fixup_vars ( tcx, sp , vb, rt) ; }
2731
2783
}
2732
2784
}
2733
2785
}
0 commit comments