@@ -1845,31 +1845,25 @@ mod unify {
1845
1845
fn record_var_binding_for_expected (
1846
1846
cx : @ctxt , key : int , typ : t , variance : variance ) -> result {
1847
1847
record_var_binding (
1848
- cx, key, typ,
1849
- lambda ( cx: @ctxt, old_type: t, new_type: t) -> result {
1850
- unify_step( cx, old_type, new_type, variance)
1851
- } )
1848
+ cx, key, typ, variance_transform ( variance, covariant) )
1852
1849
}
1853
1850
1854
1851
fn record_var_binding_for_actual (
1855
1852
cx : @ctxt , key : int , typ : t , variance : variance ) -> result {
1853
+ // Unifying in 'the other direction' so flip the variance
1856
1854
record_var_binding (
1857
- cx, key, typ,
1858
- lambda ( cx: @ctxt, old_type: t, new_type: t) -> result {
1859
- unify_step( cx, new_type, old_type, variance)
1860
- } )
1855
+ cx, key, typ, variance_transform ( variance, contravariant) )
1861
1856
}
1862
1857
1863
1858
fn record_var_binding (
1864
- cx : @ctxt , key : int , typ : t ,
1865
- unify_types : fn ( @ctxt , t , t ) -> result ) -> result {
1859
+ cx : @ctxt , key : int , typ : t , variance : variance ) -> result {
1866
1860
1867
1861
ufind:: grow ( cx. vb . sets , ( key as uint ) + 1 u) ;
1868
1862
let root = ufind:: find ( cx. vb . sets , key as uint ) ;
1869
1863
let result_type = typ;
1870
1864
alt smallintmap:: find :: < t > ( cx. vb . types , root) {
1871
1865
some ( old_type) {
1872
- alt unify_types ( cx, old_type, typ) {
1866
+ alt unify_step ( cx, old_type, typ, variance ) {
1873
1867
ures_ok ( unified_type) { result_type = unified_type; }
1874
1868
rs { ret rs; }
1875
1869
}
@@ -1949,10 +1943,24 @@ mod unify {
1949
1943
}
1950
1944
1951
1945
// Unifies two mutability flags.
1952
- fn unify_mut ( expected : ast:: mutability , actual : ast:: mutability ) ->
1953
- option:: t < ast:: mutability > {
1954
- if expected == actual { ret some ( expected) ; }
1955
- if expected == ast:: maybe_mut { ret some ( actual) ; }
1946
+ fn unify_mut ( expected : ast:: mutability , actual : ast:: mutability ,
1947
+ variance : variance ) ->
1948
+ option:: t < ( ast:: mutability , variance ) > {
1949
+
1950
+ // If you're unifying mutability then the thing inside
1951
+ // will be invariant on anything it contains
1952
+ let newvariance = variance_transform ( variance, invariant) ;
1953
+
1954
+ if expected == actual { ret some ( ( expected, newvariance) ) ; }
1955
+ if variance == covariant {
1956
+ if expected == ast:: maybe_mut {
1957
+ ret some ( ( actual, newvariance) ) ;
1958
+ }
1959
+ } else if variance == contravariant {
1960
+ if actual == ast:: maybe_mut {
1961
+ ret some ( ( expected, newvariance) ) ;
1962
+ }
1963
+ }
1956
1964
ret none;
1957
1965
}
1958
1966
tag fn_common_res {
@@ -2258,13 +2266,13 @@ mod unify {
2258
2266
ty:: ty_box ( expected_mt) {
2259
2267
alt struct( cx. tcx , actual) {
2260
2268
ty:: ty_box ( actual_mt) {
2261
- let mut ;
2262
- alt unify_mut ( expected_mt. mut , actual_mt. mut ) {
2269
+ let ( mut , var ) = alt unify_mut (
2270
+ expected_mt. mut , actual_mt. mut , variance ) {
2263
2271
none. { ret ures_err ( terr_box_mutability) ; }
2264
- some ( m ) { mut = m ; }
2265
- }
2272
+ some ( mv ) { mv }
2273
+ } ;
2266
2274
let result = unify_step (
2267
- cx, expected_mt. ty , actual_mt. ty , variance ) ;
2275
+ cx, expected_mt. ty , actual_mt. ty , var ) ;
2268
2276
alt result {
2269
2277
ures_ok( result_sub) {
2270
2278
let mt = { ty: result_sub, mut : mut } ;
@@ -2279,13 +2287,13 @@ mod unify {
2279
2287
ty:: ty_uniq ( expected_mt) {
2280
2288
alt struct( cx. tcx , actual) {
2281
2289
ty:: ty_uniq ( actual_mt) {
2282
- let mut = expected_mt . mut ;
2283
- alt unify_mut ( expected_mt. mut , actual_mt. mut ) {
2290
+ let ( mut , var ) = alt unify_mut (
2291
+ expected_mt. mut , actual_mt. mut , variance ) {
2284
2292
none. { ret ures_err ( terr_box_mutability) ; }
2285
- some ( m ) { mut = m ; }
2286
- }
2293
+ some ( mv ) { mv }
2294
+ } ;
2287
2295
let result = unify_step (
2288
- cx, expected_mt. ty , actual_mt. ty , variance ) ;
2296
+ cx, expected_mt. ty , actual_mt. ty , var ) ;
2289
2297
alt result {
2290
2298
ures_ok( result_mt) {
2291
2299
let mt = { ty: result_mt, mut : mut } ;
@@ -2300,13 +2308,13 @@ mod unify {
2300
2308
ty:: ty_vec ( expected_mt) {
2301
2309
alt struct( cx. tcx , actual) {
2302
2310
ty:: ty_vec ( actual_mt) {
2303
- let mut ;
2304
- alt unify_mut ( expected_mt. mut , actual_mt. mut ) {
2311
+ let ( mut , var ) = alt unify_mut (
2312
+ expected_mt. mut , actual_mt. mut , variance ) {
2305
2313
none. { ret ures_err ( terr_vec_mutability) ; }
2306
- some ( m ) { mut = m ; }
2307
- }
2314
+ some ( mv ) { mv }
2315
+ } ;
2308
2316
let result = unify_step (
2309
- cx, expected_mt. ty , actual_mt. ty , variance ) ;
2317
+ cx, expected_mt. ty , actual_mt. ty , var ) ;
2310
2318
alt result {
2311
2319
ures_ok( result_sub) {
2312
2320
let mt = { ty: result_sub, mut : mut } ;
@@ -2321,13 +2329,13 @@ mod unify {
2321
2329
ty:: ty_ptr ( expected_mt) {
2322
2330
alt struct( cx. tcx , actual) {
2323
2331
ty:: ty_ptr ( actual_mt) {
2324
- let mut ;
2325
- alt unify_mut ( expected_mt. mut , actual_mt. mut ) {
2332
+ let ( mut , var ) = alt unify_mut (
2333
+ expected_mt. mut , actual_mt. mut , variance ) {
2326
2334
none. { ret ures_err ( terr_vec_mutability) ; }
2327
- some ( m ) { mut = m ; }
2328
- }
2335
+ some ( mv ) { mv }
2336
+ } ;
2329
2337
let result = unify_step (
2330
- cx, expected_mt. ty , actual_mt. ty , variance ) ;
2338
+ cx, expected_mt. ty , actual_mt. ty , var ) ;
2331
2339
alt result {
2332
2340
ures_ok( result_sub) {
2333
2341
let mt = { ty: result_sub, mut : mut } ;
@@ -2385,12 +2393,12 @@ mod unify {
2385
2393
while i < expected_len {
2386
2394
let expected_field = expected_fields[ i] ;
2387
2395
let actual_field = actual_fields[ i] ;
2388
- let mut ;
2389
- alt unify_mut ( expected_field. mt. mut , actual_field. mt. mut )
2396
+ let ( mut , var ) = alt unify_mut (
2397
+ expected_field. mt . mut , actual_field. mt . mut , variance )
2390
2398
{
2391
2399
none. { ret ures_err ( terr_record_mutability) ; }
2392
- some ( m ) { mut = m ; }
2393
- }
2400
+ some ( mv ) { mv }
2401
+ } ;
2394
2402
if !str:: eq ( expected_field. ident , actual_field. ident ) {
2395
2403
let err =
2396
2404
terr_record_fields ( expected_field. ident ,
@@ -2399,7 +2407,7 @@ mod unify {
2399
2407
}
2400
2408
let result =
2401
2409
unify_step ( cx, expected_field. mt . ty ,
2402
- actual_field. mt . ty , variance ) ;
2410
+ actual_field. mt . ty , var ) ;
2403
2411
alt result {
2404
2412
ures_ok( rty) {
2405
2413
let mt = { ty: rty, mut : mut } ;
0 commit comments