@@ -1080,6 +1080,7 @@ fn variant_arg_types(ccx: &@crate_ctxt, sp: &span, vid: &ast::def_id,
1080
1080
mod writeback {
1081
1081
1082
1082
export resolve_type_vars_in_block;
1083
+ export resolve_type_vars_in_expr;
1083
1084
1084
1085
fn resolve_type_vars_in_type ( fcx : & @fn_ctxt , sp : & span , typ : ty:: t ) ->
1085
1086
option:: t [ ty:: t ] {
@@ -1168,6 +1169,20 @@ mod writeback {
1168
1169
// Ignore items
1169
1170
}
1170
1171
1172
+ fn resolve_type_vars_in_expr ( fcx : & @fn_ctxt , e : & @ast:: expr ) -> bool {
1173
+ let wbcx = { fcx: fcx, mutable success: true } ;
1174
+ let visit = visit:: mk_vt
1175
+ ( @{ visit_item: visit_item,
1176
+ visit_stmt: visit_stmt,
1177
+ visit_expr: visit_expr,
1178
+ visit_block: visit_block,
1179
+ visit_pat: visit_pat,
1180
+ visit_local: visit_local
1181
+ with * visit:: default_visitor ( ) } ) ;
1182
+ visit:: visit_expr ( e, wbcx, visit) ;
1183
+ ret wbcx. success ;
1184
+ }
1185
+
1171
1186
fn resolve_type_vars_in_block ( fcx : & @fn_ctxt , blk : & ast:: blk ) -> bool {
1172
1187
let wbcx = { fcx: fcx, mutable success: true } ;
1173
1188
let visit = visit:: mk_vt
@@ -2651,13 +2666,23 @@ fn check_fn(ccx: &@crate_ctxt, f: &ast::_fn, id: &ast::node_id,
2651
2666
_ { }
2652
2667
}
2653
2668
2654
- if option:: is_some ( body. node . expr ) {
2669
+ // For non-iterator fns, we unify the tail expr's type with the
2670
+ // function result type, if there is a tail expr.
2671
+ // We don't do this check for an iterator, as the tail expr doesn't
2672
+ // have to have the result type of the iterator.
2673
+ if option:: is_some ( body. node . expr ) && f. proto != ast:: proto_iter {
2655
2674
let tail_expr = option:: get ( body. node . expr ) ;
2656
- let tail_expr_ty = expr_ty ( ccx. tcx , tail_expr) ;
2657
- // Have to exclude ty_nil to allow functions to end in
2658
- // while expressions, etc.
2659
- let nil = ty:: mk_nil ( fcx. ccx . tcx ) ;
2660
- if !are_compatible ( fcx, nil, tail_expr_ty) {
2675
+ // The use of resolve_type_vars_if_possible makes me very
2676
+ // afraid :-(
2677
+ let tail_expr_ty = resolve_type_vars_if_possible (
2678
+ fcx, expr_ty ( ccx. tcx , tail_expr) ) ;
2679
+ // Hacky compromise: use eq and not are_compatible
2680
+ // This allows things like while loops and ifs with no
2681
+ // else to appear in tail position without a trailing
2682
+ // semicolon when the return type is non-nil, while
2683
+ // making sure to unify the tailexpr-type with the result
2684
+ // type when the tailexpr-type is just a type variable.
2685
+ if !ty:: eq_ty ( tail_expr_ty, ty:: mk_nil ( ccx. tcx ) ) {
2661
2686
demand:: simple ( fcx, tail_expr. span , fcx. ret_ty , tail_expr_ty) ;
2662
2687
}
2663
2688
}
0 commit comments