Skip to content

Commit e1fd5de

Browse files
committed
---
yaml --- r: 4425 b: refs/heads/master c: d7ee55b h: refs/heads/master i: 4423: 740af79 v: v3
1 parent c05c170 commit e1fd5de

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: c5d55ef9181b1a0987045183093742a2d360c07e
2+
refs/heads/master: d7ee55bfd0240095d0614ec5d33774171a177d86

trunk/src/comp/middle/typeck.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,7 @@ fn variant_arg_types(ccx: &@crate_ctxt, sp: &span, vid: &ast::def_id,
10801080
mod writeback {
10811081

10821082
export resolve_type_vars_in_block;
1083+
export resolve_type_vars_in_expr;
10831084

10841085
fn resolve_type_vars_in_type(fcx: &@fn_ctxt, sp: &span, typ: ty::t) ->
10851086
option::t[ty::t] {
@@ -1168,6 +1169,20 @@ mod writeback {
11681169
// Ignore items
11691170
}
11701171

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+
11711186
fn resolve_type_vars_in_block(fcx: &@fn_ctxt, blk: &ast::blk) -> bool {
11721187
let wbcx = {fcx: fcx, mutable success: true};
11731188
let visit = visit::mk_vt
@@ -2651,13 +2666,23 @@ fn check_fn(ccx: &@crate_ctxt, f: &ast::_fn, id: &ast::node_id,
26512666
_ { }
26522667
}
26532668

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 {
26552674
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)) {
26612686
demand::simple(fcx, tail_expr.span, fcx.ret_ty, tail_expr_ty);
26622687
}
26632688
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Tests that the tail expr in null() has its type
2+
// unified with the type *T, and so the type variable
3+
// in that type gets resolved.
4+
use std;
5+
import std::unsafe;
6+
7+
fn null[T]() -> *T { unsafe::reinterpret_cast(0) }
8+
9+
fn main() {
10+
null[int]();
11+
}

0 commit comments

Comments
 (0)