@@ -2371,15 +2371,16 @@ fn require_pure_call(ccx: @crate_ctxt, caller_purity: ast::purity,
2371
2371
}
2372
2372
}
2373
2373
2374
- fn check_expr( fcx: @fn_ctxt, expr: @ast:: expr) -> bool {
2375
- ret check_expr_with_unifier( fcx, expr, ty:: mk_nil( fcx. ccx. tcx) ) { ||
2376
- /* do not take any action on unify */
2377
- } ;
2374
+ fn check_expr_with( fcx: @fn_ctxt, expr: @ast:: expr, expected: ty:: t) -> bool {
2375
+ check_expr( fcx, expr, some( expected) )
2378
2376
}
2379
2377
2380
- fn check_expr_with( fcx: @fn_ctxt, expr: @ast:: expr, expected: ty:: t) -> bool {
2378
+ fn check_expr( fcx: @fn_ctxt, expr: @ast:: expr,
2379
+ expected: option<ty:: t>) -> bool {
2381
2380
ret check_expr_with_unifier( fcx, expr, expected) { ||
2382
- demand:: suptype( fcx, expr. span, expected, fcx. expr_ty( expr) ) ;
2381
+ for expected. each { |t|
2382
+ demand:: suptype( fcx, expr. span, t, fcx. expr_ty( expr) ) ;
2383
+ }
2383
2384
} ;
2384
2385
}
2385
2386
@@ -2790,7 +2791,7 @@ fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
2790
2791
2791
2792
fn check_expr_with_unifier( fcx: @fn_ctxt,
2792
2793
expr: @ast:: expr,
2793
- expected: ty:: t,
2794
+ expected: option< ty:: t> ,
2794
2795
unifier: fn ( ) ) -> bool {
2795
2796
2796
2797
#debug( ">> typechecking expr %d ( %s) ",
@@ -2861,7 +2862,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
2861
2862
} ;
2862
2863
if is_block == check_blocks {
2863
2864
let arg_ty = arg_tys[ i] ;
2864
- bot |= check_expr_with_unifier( fcx, a, arg_ty) { ||
2865
+ bot |= check_expr_with_unifier(
2866
+ fcx, a, some( arg_ty) ) { ||
2865
2867
demand:: assign( fcx, a. span, arg_ty, a) ;
2866
2868
} ;
2867
2869
}
@@ -2881,7 +2883,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
2881
2883
// A generic function for checking assignment expressions
2882
2884
fn check_assignment( fcx: @fn_ctxt, _sp: span, lhs: @ast:: expr,
2883
2885
rhs: @ast:: expr, id: ast:: node_id) -> bool {
2884
- let mut bot = check_expr( fcx, lhs) ;
2886
+ let mut bot = check_expr( fcx, lhs, none ) ;
2885
2887
bot |= check_expr_with( fcx, rhs, fcx. expr_ty( lhs) ) ;
2886
2888
fcx. write_ty( id, ty:: mk_nil( fcx. ccx. tcx) ) ;
2887
2889
ret bot;
@@ -2891,7 +2893,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
2891
2893
fn check_call( fcx: @fn_ctxt, sp: span, call_expr_id: ast:: node_id,
2892
2894
f: @ast:: expr, args: [ @ast:: expr] ) -> bool {
2893
2895
2894
- let mut bot = check_expr( fcx, f) ;
2896
+ let mut bot = check_expr( fcx, f, none ) ;
2895
2897
let fn_ty = fcx. expr_ty( f) ;
2896
2898
2897
2899
// Call the generic checker.
@@ -2992,7 +2994,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
2992
2994
lhs: @ast:: expr,
2993
2995
rhs: @ast:: expr) -> bool {
2994
2996
let tcx = fcx. ccx. tcx;
2995
- let lhs_bot = check_expr( fcx, lhs) ;
2997
+ let lhs_bot = check_expr( fcx, lhs, none ) ;
2996
2998
let lhs_t = fcx. expr_ty( lhs) ;
2997
2999
let lhs_t = structurally_resolved_type( fcx, lhs. span, lhs_t) ;
2998
3000
ret alt ( op, ty:: get( lhs_t) . struct ) {
@@ -3015,7 +3017,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3015
3017
( _, _) if ty:: type_is_integral( lhs_t) &&
3016
3018
ast_util:: is_shift_binop( op) {
3017
3019
// Shift is a special case: rhs can be any integral type
3018
- let rhs_bot = check_expr( fcx, rhs) ;
3020
+ let rhs_bot = check_expr( fcx, rhs, none ) ;
3019
3021
let rhs_t = fcx. expr_ty( rhs) ;
3020
3022
require_integral( fcx, rhs. span, rhs_t) ;
3021
3023
fcx. write_ty( expr. id, lhs_t) ;
@@ -3063,7 +3065,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3063
3065
}
3064
3066
_ { }
3065
3067
}
3066
- check_expr( fcx, rhs) ;
3068
+ check_expr( fcx, rhs, none ) ;
3067
3069
tcx. sess. span_err(
3068
3070
ex. span, "binary operation " + ast_util:: binop_to_str( op) +
3069
3071
" cannot be applied to type `" +
@@ -3083,6 +3085,19 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3083
3085
}
3084
3086
}
3085
3087
}
3088
+ fn unpack_expected<O : copy>( fcx: @fn_ctxt, expected: option<ty:: t>,
3089
+ unpack: fn ( ty:: sty) -> option<O >)
3090
+ -> option<O > {
3091
+ alt expected {
3092
+ some( t) {
3093
+ alt infer:: resolve_shallow( fcx. infcx, t, true) {
3094
+ result:: ok( t) { unpack( ty:: get( t) . struct ) }
3095
+ _ { none }
3096
+ }
3097
+ }
3098
+ _ { none }
3099
+ }
3100
+ }
3086
3101
3087
3102
let tcx = fcx. ccx. tcx;
3088
3103
let id = expr. id;
@@ -3147,7 +3162,19 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3147
3162
fcx. write_nil( expr. id) ;
3148
3163
}
3149
3164
ast:: expr_unary( unop, oper) {
3150
- bot = check_expr( fcx, oper) ;
3165
+ let exp_inner = unpack_expected( fcx, expected) { |sty|
3166
+ alt unop {
3167
+ ast:: box( _) | ast:: uniq( _) {
3168
+ alt sty {
3169
+ ty:: ty_box( mt) | ty:: ty_uniq( mt) { some( mt. ty) }
3170
+ _ { none }
3171
+ }
3172
+ }
3173
+ ast:: not | ast:: neg { some( expected. get( ) ) }
3174
+ ast:: deref { none }
3175
+ }
3176
+ } ;
3177
+ bot = check_expr( fcx, oper, exp_inner) ;
3151
3178
let mut oper_t = fcx. expr_ty( oper) ;
3152
3179
alt unop {
3153
3180
ast:: box( mutbl) {
@@ -3202,12 +3229,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3202
3229
fcx. write_ty( id, oper_t) ;
3203
3230
}
3204
3231
ast:: expr_addr_of( mutbl, oper) {
3205
- bot = check_expr( fcx, oper) ;
3206
- let mut oper_t = fcx . expr_ty ( oper ) ;
3207
-
3232
+ bot = check_expr( fcx, oper, unpack_expected ( fcx , expected ) { |ty|
3233
+ alt ty { ty :: ty_rptr ( _ , mt ) { some ( mt . ty ) } _ { none } }
3234
+ } ) ;
3208
3235
let region = region_of( fcx, oper) ;
3209
- let tm = { ty: oper_t , mutbl: mutbl } ;
3210
- oper_t = ty:: mk_rptr( tcx, region, tm) ;
3236
+ let tm = { ty: fcx . expr_ty ( oper ) , mutbl: mutbl } ;
3237
+ let oper_t = ty:: mk_rptr( tcx, region, tm) ;
3211
3238
fcx. write_ty( id, oper_t) ;
3212
3239
}
3213
3240
ast:: expr_path( pth) {
@@ -3255,7 +3282,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3255
3282
ast:: expr_log( _, lv, e) {
3256
3283
bot = check_expr_with( fcx, lv, ty:: mk_mach_uint( tcx, ast:: ty_u32) ) ;
3257
3284
// Note: this does not always execute, so do not propagate bot:
3258
- check_expr( fcx, e) ;
3285
+ check_expr( fcx, e, none ) ;
3259
3286
fcx. write_nil( id) ;
3260
3287
}
3261
3288
ast:: expr_check( _, e) {
@@ -3272,7 +3299,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3272
3299
fcx. write_nil( id) ;
3273
3300
}
3274
3301
ast:: expr_copy( a) {
3275
- bot = check_expr_with ( fcx, a, expected) ;
3302
+ bot = check_expr ( fcx, a, expected) ;
3276
3303
fcx. write_ty( id, fcx. expr_ty( a) ) ;
3277
3304
}
3278
3305
ast:: expr_move( lhs, rhs) {
@@ -3348,26 +3375,22 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3348
3375
}
3349
3376
ast:: expr_fn_block( decl, body) {
3350
3377
// Take the prototype from the expected type, but default to block:
3351
- let proto = alt ty:: get( expected) . struct {
3352
- ty:: ty_fn( { proto, _} ) { proto }
3353
- _ { ast:: proto_box }
3354
- } ;
3355
- #debug( "checking expr_fn_block %s expected=%s",
3356
- expr_to_str( expr) ,
3357
- ty_to_str( tcx, expected) ) ;
3378
+ let proto = unpack_expected( fcx, expected, { |sty|
3379
+ alt sty { ty:: ty_fn( { proto, _} ) { some( proto) } _ { none } }
3380
+ } ) . get_default( ast:: proto_box) ;
3358
3381
check_expr_fn_with_unifier( fcx, expr, proto, decl, body,
3359
3382
false, unifier) ;
3360
3383
}
3361
3384
ast:: expr_loop_body( b) {
3362
- let rty = structurally_resolved_type ( fcx, expr . span , expected ) ;
3363
- let ( inner_ty, proto) = alt check ty :: get ( rty ) . struct {
3385
+ let expected_sty = unpack_expected ( fcx, expected , { |x|some ( x ) } ) . get ( ) ;
3386
+ let ( inner_ty, proto) = alt expected_sty {
3364
3387
ty:: ty_fn( fty) {
3365
3388
alt infer:: mk_subty( fcx. infcx, fty. output, ty:: mk_bool( tcx) ) {
3366
3389
result:: ok( _) { }
3367
3390
result:: err( err) {
3368
3391
tcx. sess. span_fatal(
3369
- expr. span, #fmt( "a loop function' s last argument should \
3370
- return `bool `, not `%s`",
3392
+ expr. span, #fmt( "a loop function' s last argument \
3393
+ should return `bool `, not `%s`",
3371
3394
ty_to_str( tcx, fty. output) ) ) ;
3372
3395
}
3373
3396
}
@@ -3406,7 +3429,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3406
3429
}
3407
3430
ast:: expr_bind( f, args) {
3408
3431
// Call the generic checker.
3409
- bot = check_expr( fcx, f) ;
3432
+ bot = check_expr( fcx, f, none ) ;
3410
3433
3411
3434
let { fty, bot: ccob_bot} = {
3412
3435
let fn_ty = fcx. expr_ty( f) ;
@@ -3465,7 +3488,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3465
3488
bot = check_call( fcx, expr. span, expr. id, f, args) ;
3466
3489
}
3467
3490
ast:: expr_cast( e, t) {
3468
- bot = check_expr( fcx, e) ;
3491
+ bot = check_expr( fcx, e, none ) ;
3469
3492
let t_1 = fcx. to_ty( t) ;
3470
3493
let t_e = fcx. expr_ty( e) ;
3471
3494
@@ -3506,18 +3529,29 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3506
3529
ast:: expr_tup( elts) {
3507
3530
let mut elt_ts = [ ] ;
3508
3531
vec:: reserve( elt_ts, vec:: len( elts) ) ;
3509
- for elts. each { |e|
3510
- check_expr( fcx, e) ;
3532
+ let flds = unpack_expected( fcx, expected) { |sty|
3533
+ alt sty { ty:: ty_tup( flds) { some( flds) } _ { none } }
3534
+ } ;
3535
+ for elts. eachi { |i, e|
3536
+ check_expr( fcx, e, flds. map { |fs| fs[ i] } ) ;
3511
3537
let ety = fcx. expr_ty( e) ;
3512
3538
elt_ts += [ ety] ;
3513
3539
}
3514
3540
let typ = ty:: mk_tup( tcx, elt_ts) ;
3515
3541
fcx. write_ty( id, typ) ;
3516
3542
}
3517
3543
ast:: expr_rec( fields, base) {
3518
- option:: iter( base) { |b| check_expr( fcx, b) ; }
3544
+ option:: iter( base) { |b| check_expr( fcx, b, expected) ; }
3545
+ let expected = if expected == none && base != none {
3546
+ some( fcx. expr_ty( base. get( ) ) )
3547
+ } else { expected } ;
3548
+ let flds = unpack_expected( fcx, expected) { |sty|
3549
+ alt sty { ty:: ty_rec( flds) { some( flds) } _ { none } }
3550
+ } ;
3519
3551
let fields_t = vec:: map( fields, { |f|
3520
- bot |= check_expr( fcx, f. node. expr) ;
3552
+ bot |= check_expr( fcx, f. node. expr, flds. chain { |flds|
3553
+ vec:: find( flds) { |tf| tf. ident == f. node. ident}
3554
+ } . map { |tf| tf. mt. ty} ) ;
3521
3555
let expr_t = fcx. expr_ty( f. node. expr) ;
3522
3556
let expr_mt = { ty: expr_t, mutbl: f. node. mutbl} ;
3523
3557
// for the most precise error message,
@@ -3531,7 +3565,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3531
3565
fcx. write_ty( id, typ) ;
3532
3566
}
3533
3567
some( bexpr) {
3534
- bot |= check_expr( fcx, bexpr) ;
3535
3568
let bexpr_t = fcx. expr_ty( bexpr) ;
3536
3569
let mut base_fields: [ field] = [ ] ;
3537
3570
alt structure_of( fcx, expr. span, bexpr_t) {
@@ -3560,7 +3593,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3560
3593
}
3561
3594
}
3562
3595
ast:: expr_field( base, field, tys) {
3563
- bot |= check_expr( fcx, base) ;
3596
+ bot |= check_expr( fcx, base, none ) ;
3564
3597
let expr_t = structurally_resolved_type( fcx, expr. span,
3565
3598
fcx. expr_ty( base) ) ;
3566
3599
let base_t = do_autoderef( fcx, expr. span, expr_t) ;
@@ -3638,10 +3671,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3638
3671
}
3639
3672
}
3640
3673
ast:: expr_index( base, idx) {
3641
- bot |= check_expr( fcx, base) ;
3674
+ bot |= check_expr( fcx, base, none ) ;
3642
3675
let raw_base_t = fcx. expr_ty( base) ;
3643
3676
let base_t = do_autoderef( fcx, expr. span, raw_base_t) ;
3644
- bot |= check_expr( fcx, idx) ;
3677
+ bot |= check_expr( fcx, idx, none ) ;
3645
3678
let idx_t = fcx. expr_ty( idx) ;
3646
3679
alt structure_of( fcx, expr. span, base_t) {
3647
3680
ty:: ty_evec( mt, _) |
@@ -3671,8 +3704,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3671
3704
}
3672
3705
}
3673
3706
ast:: expr_new( p, alloc_id, v) {
3674
- bot |= check_expr( fcx, p) ;
3675
- bot |= check_expr( fcx, v) ;
3707
+ bot |= check_expr( fcx, p, none ) ;
3708
+ bot |= check_expr( fcx, v, none ) ;
3676
3709
3677
3710
let p_ty = fcx. expr_ty( p) ;
3678
3711
@@ -3728,7 +3761,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3728
3761
#debug( "type of expr %s is %s, expected is %s",
3729
3762
syntax:: print:: pprust:: expr_to_str( expr) ,
3730
3763
ty_to_str( tcx, fcx. expr_ty( expr) ) ,
3731
- ty_to_str( tcx, expected) ) ;
3764
+ alt expected {
3765
+ some( t) { ty_to_str( tcx, t) }
3766
+ _ { "empty" }
3767
+ } ) ;
3732
3768
3733
3769
unifier( ) ;
3734
3770
@@ -3739,7 +3775,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
3739
3775
fn require_integral( fcx: @fn_ctxt, sp: span, t: ty:: t) {
3740
3776
if !type_is_integral( fcx, sp, t) {
3741
3777
fcx. ccx. tcx. sess. span_err( sp, "mismatched types: expected \
3742
- `integer` but found `"
3778
+ integral type but found `"
3743
3779
+ fcx. ty_to_str( t) + "`") ;
3744
3780
}
3745
3781
}
@@ -3796,7 +3832,7 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool {
3796
3832
}
3797
3833
ast:: stmt_semi( expr, id) {
3798
3834
node_id = id;
3799
- bot = check_expr( fcx, expr) ;
3835
+ bot = check_expr( fcx, expr, none ) ;
3800
3836
}
3801
3837
}
3802
3838
fcx. write_nil( node_id) ;
@@ -3841,7 +3877,7 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
3841
3877
if bot && !warned {
3842
3878
fcx. ccx. tcx. sess. span_warn( e. span, "unreachable expression") ;
3843
3879
}
3844
- bot |= check_expr( fcx, e) ;
3880
+ bot |= check_expr( fcx, e, none ) ;
3845
3881
let ety = fcx. expr_ty( e) ;
3846
3882
fcx. write_ty( blk. node. id, ety) ;
3847
3883
}
@@ -3870,7 +3906,7 @@ fn check_const(ccx: @crate_ctxt, _sp: span, e: @ast::expr, id: ast::node_id) {
3870
3906
node_types: smallintmap:: mk( ) ,
3871
3907
node_type_substs: map:: int_hash( ) ,
3872
3908
ccx: ccx} ;
3873
- check_expr( fcx, e) ;
3909
+ check_expr( fcx, e, none ) ;
3874
3910
let cty = fcx. expr_ty( e) ;
3875
3911
let declty = fcx. ccx. tcx. tcache. get( local_def( id) ) . ty;
3876
3912
demand:: suptype( fcx, e. span, declty, cty) ;
@@ -3915,7 +3951,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
3915
3951
for vs. each { |v|
3916
3952
alt v. node. disr_expr {
3917
3953
some( e) {
3918
- check_expr( fcx, e) ;
3954
+ check_expr( fcx, e, none ) ;
3919
3955
let cty = fcx. expr_ty( e) ;
3920
3956
let declty = ty:: mk_int( ccx. tcx) ;
3921
3957
demand:: suptype( fcx, e. span, declty, cty) ;
0 commit comments