@@ -60,6 +60,8 @@ tag type_err {
60
60
terr_record_size ( uint, uint) ;
61
61
terr_record_mutability;
62
62
terr_record_fields ( ast. ident , ast. ident ) ;
63
+ terr_meth_count;
64
+ terr_obj_meths ( ast. ident , ast. ident ) ;
63
65
terr_arg_count;
64
66
}
65
67
@@ -724,6 +726,67 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
724
726
725
727
}
726
728
729
+ fn unify_obj( & hashmap[ int, @ty. t] bindings,
730
+ @ty. t expected,
731
+ @ty. t actual,
732
+ & unify_handler handler,
733
+ vec[ method] expected_meths,
734
+ vec[ method] actual_meths) -> unify_result {
735
+ let vec[ method] result_meths = vec( ) ;
736
+ let uint i = 0 u;
737
+ let uint expected_len = _vec. len[ method] ( expected_meths) ;
738
+ let uint actual_len = _vec. len[ method] ( actual_meths) ;
739
+
740
+ if ( expected_len != actual_len) {
741
+ ret ures_err( terr_meth_count, expected, actual) ;
742
+ }
743
+
744
+ // FIXME: work around buggy typestate logic for 'alt', sigh.
745
+ fn is_ok( & unify_result r) -> bool {
746
+ alt ( r) {
747
+ case ( ures_ok( ?tfn) ) {
748
+ ret true;
749
+ }
750
+ case ( _) { }
751
+ }
752
+ ret false;
753
+ }
754
+
755
+ fn append_if_ok( & method e_meth,
756
+ & unify_result r, & mutable vec[ method] result_meths) {
757
+ alt ( r) {
758
+ case ( ures_ok( ?tfn) ) {
759
+ alt ( tfn. struct ) {
760
+ case ( ty_fn( ?ins, ?out) ) {
761
+ result_meths += vec( rec( inputs = ins,
762
+ output = out
763
+ with e_meth) ) ;
764
+ }
765
+ }
766
+ }
767
+ }
768
+ }
769
+
770
+ while ( i < expected_len) {
771
+ auto e_meth = expected_meths. ( i) ;
772
+ auto a_meth = actual_meths. ( i) ;
773
+ if ( ! _str. eq( e_meth. ident, a_meth. ident) ) {
774
+ ret ures_err( terr_obj_meths( e_meth. ident, a_meth. ident) ,
775
+ expected, actual) ;
776
+ }
777
+ auto r = unify_fn( bindings, expected, actual, handler,
778
+ e_meth. inputs, e_meth. output,
779
+ a_meth. inputs, a_meth. output) ;
780
+ if ( !is_ok( r) ) {
781
+ ret r;
782
+ }
783
+ append_if_ok( e_meth, r, result_meths) ;
784
+ i += 1 u;
785
+ }
786
+ auto t = plain_ty( ty_obj( result_meths) ) ;
787
+ ret ures_ok( t) ;
788
+ }
789
+
727
790
fn unify_step( & hashmap[ int, @ty. t] bindings, @ty. t expected, @ty. t actual,
728
791
& unify_handler handler) -> unify_result {
729
792
// TODO: rewrite this using tuple pattern matching when available, to
@@ -961,6 +1024,18 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
961
1024
}
962
1025
}
963
1026
1027
+ case ( ty. ty_obj( ?expected_meths) ) {
1028
+ alt ( actual. struct ) {
1029
+ case ( ty. ty_obj( ?actual_meths) ) {
1030
+ ret unify_obj( bindings, expected, actual, handler,
1031
+ expected_meths, actual_meths) ;
1032
+ }
1033
+ case ( _) {
1034
+ ret ures_err( terr_mismatch, expected, actual) ;
1035
+ }
1036
+ }
1037
+ }
1038
+
964
1039
case ( ty. ty_var( ?expected_id) ) {
965
1040
alt ( bindings. find( expected_id) ) {
966
1041
case ( some[ @ty. t] ( ?expected_ty) ) {
@@ -1042,6 +1117,14 @@ fn type_err_to_str(&ty.type_err err) -> str {
1042
1117
case ( terr_arg_count) {
1043
1118
ret "incorrect number of function parameters";
1044
1119
}
1120
+ case ( terr_meth_count) {
1121
+ ret "incorrect number of object methods";
1122
+ }
1123
+ case ( terr_obj_meths( ?e_meth, ?a_meth) ) {
1124
+ ret "expected an obj with method ' " + e_meth +
1125
+ "' but found one with method ' " + a_meth +
1126
+ "' ";
1127
+ }
1045
1128
}
1046
1129
}
1047
1130
0 commit comments