@@ -14,14 +14,14 @@ import std::option::some;
14
14
import std:: option:: none;
15
15
import std:: option:: is_none;
16
16
17
-
18
17
// This is not an alias-analyser (though it would merit from becoming one, or
19
- // at getting input from one, to be more precise). It is a pass that checks
18
+ // getting input from one, to be more precise). It is a pass that checks
20
19
// whether aliases are used in a safe way. Beyond that, though it doesn't have
21
20
// a lot to do with aliases, it also checks whether assignments are valid
22
21
// (using an lval, which is actually mutable), since it already has all the
23
22
// information needed to do that (and the typechecker, which would be a
24
23
// logical place for such a check, doesn't).
24
+
25
25
tag valid { valid; overwritten ( span, ast:: path) ; val_taken ( span, ast:: path) ; }
26
26
27
27
type restrict =
@@ -40,12 +40,10 @@ type ctx = rec(@ty::ctxt tcx,
40
40
std:: map:: hashmap[ node_id, local_info] local_map ) ;
41
41
42
42
fn check_crate ( @ty:: ctxt tcx, & @ast:: crate crate) {
43
- auto cx =
44
- @rec ( tcx=tcx,
45
-
46
- // Stores information about object fields and function
47
- // arguments that's otherwise not easily available.
48
- local_map=std:: map:: new_int_hash ( ) ) ;
43
+ auto cx = @rec ( tcx=tcx,
44
+ // Stores information about object fields and function
45
+ // arguments that's otherwise not easily available.
46
+ local_map=std:: map:: new_int_hash ( ) ) ;
49
47
auto v =
50
48
@rec ( visit_fn=bind visit_fn ( cx, _, _, _, _, _, _, _) ,
51
49
visit_item=bind visit_item ( cx, _, _, _) ,
@@ -117,9 +115,11 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
117
115
case ( ast:: expr_swap ( ?lhs, ?rhs) ) {
118
116
check_lval ( cx, lhs, sc, v) ;
119
117
check_lval ( cx, rhs, sc, v) ;
118
+ handled = false ;
120
119
}
121
120
case ( ast:: expr_move ( ?dest, ?src) ) {
122
121
check_assign ( cx, dest, src, sc, v) ;
122
+ check_move_rhs ( cx, src, sc, v) ;
123
123
}
124
124
case ( ast:: expr_assign ( ?dest, ?src) ) {
125
125
check_assign ( cx, dest, src, sc, v) ;
@@ -369,7 +369,6 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::node_id id,
369
369
auto my_defnum = ast:: def_id_of_def( def) . _1;
370
370
auto var_t = ty:: expr_ty( * cx. tcx, ex) ;
371
371
for ( restrict r in sc) {
372
-
373
372
// excludes variables introduced since the alias was made
374
373
if ( my_defnum < r. block_defnum) {
375
374
for ( ty:: t t in r. tys) {
@@ -399,7 +398,6 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
399
398
r. ok = overwritten ( dest. span , p) ;
400
399
}
401
400
}
402
- check_var ( * cx, dest, p, dest. id , true , sc) ;
403
401
}
404
402
case ( _) {
405
403
auto root = expr_root ( * cx, dest, false ) ;
@@ -420,6 +418,22 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
420
418
}
421
419
}
422
420
421
+ fn check_move_rhs ( & @ctx cx , & @ast:: expr src, & scope sc, & vt[ scope] v ) {
422
+ alt ( src. node ) {
423
+ case ( ast:: expr_path ( ?p) ) {
424
+ check_lval ( cx, src, sc, v) ;
425
+ }
426
+ case ( _) {
427
+ auto root = expr_root ( * cx, src, false ) ;
428
+ // Not a path and no-derefs means this is a temporary.
429
+ if ( vec:: len ( root. ds ) != 0 u) {
430
+ cx. tcx . sess . span_err
431
+ ( src. span , "moving out of a data structure" ) ;
432
+ }
433
+ }
434
+ }
435
+ }
436
+
423
437
fn check_assign ( & @ctx cx , & @ast:: expr dest, & @ast:: expr src, & scope sc,
424
438
& vt[ scope] v ) {
425
439
visit_expr ( cx, src, sc, v) ;
0 commit comments