@@ -40,6 +40,9 @@ use rustc_data_structures::sync::Lrc;
40
40
use syntax:: ast;
41
41
use syntax:: attr;
42
42
use syntax_pos:: { Span , DUMMY_SP } ;
43
+ use self :: Promotability :: * ;
44
+ use std:: ops:: { BitAnd , BitOr } ;
45
+
43
46
44
47
pub fn provide ( providers : & mut Providers ) {
45
48
* providers = Providers {
@@ -84,7 +87,6 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
84
87
tables : & ty:: TypeckTables :: empty ( None ) ,
85
88
in_fn : false ,
86
89
in_static : false ,
87
- promotable : false ,
88
90
mut_rvalue_borrows : NodeSet ( ) ,
89
91
param_env : ty:: ParamEnv :: empty ( ) ,
90
92
identity_substs : Substs :: empty ( ) ,
@@ -95,7 +97,7 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
95
97
let node_id = tcx. hir . as_local_node_id ( def_id)
96
98
. expect ( "rvalue_promotable_map invoked with non-local def-id" ) ;
97
99
let body_id = tcx. hir . body_owned_by ( node_id) ;
98
- visitor. visit_nested_body ( body_id) ;
100
+ let _ = visitor. check_nested_body ( body_id) ;
99
101
100
102
Lrc :: new ( visitor. result )
101
103
}
@@ -104,38 +106,83 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
104
106
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
105
107
in_fn : bool ,
106
108
in_static : bool ,
107
- promotable : bool ,
108
109
mut_rvalue_borrows : NodeSet ,
109
110
param_env : ty:: ParamEnv < ' tcx > ,
110
111
identity_substs : & ' tcx Substs < ' tcx > ,
111
112
tables : & ' a ty:: TypeckTables < ' tcx > ,
112
113
result : ItemLocalSet ,
113
114
}
114
115
116
+ #[ must_use]
117
+ #[ derive( Debug , PartialEq ) ]
118
+ enum Promotability {
119
+ Promotable ,
120
+ NotPromotable
121
+ }
122
+
123
+ impl BitAnd for Promotability {
124
+ type Output = Self ;
125
+
126
+ fn bitand ( self , rhs : Self ) -> Self {
127
+ match ( self , rhs) {
128
+ ( Promotable , NotPromotable ) => NotPromotable ,
129
+ ( NotPromotable , Promotable ) => NotPromotable ,
130
+ ( NotPromotable , NotPromotable ) => NotPromotable ,
131
+ ( Promotable , Promotable ) => Promotable ,
132
+ }
133
+ }
134
+ }
135
+
136
+ impl BitOr for Promotability {
137
+ type Output = Self ;
138
+
139
+ fn bitor ( self , rhs : Self ) -> Self {
140
+ match ( self , rhs) {
141
+ ( Promotable , NotPromotable ) => Promotable ,
142
+ ( NotPromotable , Promotable ) => Promotable ,
143
+ ( NotPromotable , NotPromotable ) => NotPromotable ,
144
+ ( Promotable , Promotable ) => Promotable ,
145
+ }
146
+ }
147
+ }
148
+
115
149
impl < ' a , ' gcx > CheckCrateVisitor < ' a , ' gcx > {
116
150
// Returns true iff all the values of the type are promotable.
117
- fn type_has_only_promotable_values ( & mut self , ty : Ty < ' gcx > ) -> bool {
118
- ty. is_freeze ( self . tcx , self . param_env , DUMMY_SP ) &&
119
- !ty. needs_drop ( self . tcx , self . param_env )
151
+ fn type_promotability ( & mut self , ty : Ty < ' gcx > ) -> Promotability {
152
+ debug ! ( "type_promotability({})" , ty) ;
153
+
154
+ if ty. is_freeze ( self . tcx , self . param_env , DUMMY_SP ) &&
155
+ !ty. needs_drop ( self . tcx , self . param_env ) {
156
+ Promotable
157
+ } else {
158
+ NotPromotable
159
+ }
120
160
}
121
161
122
- fn handle_const_fn_call ( & mut self , def_id : DefId , ret_ty : Ty < ' gcx > , span : Span ) {
123
- self . promotable &= self . type_has_only_promotable_values ( ret_ty) ;
162
+ fn handle_const_fn_call ( & mut self , def_id : DefId ,
163
+ ret_ty : Ty < ' gcx > , span : Span ) -> Promotability {
164
+ if let NotPromotable = self . type_promotability ( ret_ty) {
165
+ return NotPromotable ;
166
+ }
124
167
125
- self . promotable & = if let Some ( fn_id) = self . tcx . hir . as_local_node_id ( def_id) {
168
+ let node_check = if let Some ( fn_id) = self . tcx . hir . as_local_node_id ( def_id) {
126
169
FnLikeNode :: from_node ( self . tcx . hir . get ( fn_id) ) . map_or ( false , |fn_like| {
127
170
fn_like. constness ( ) == hir:: Constness :: Const
128
171
} )
129
172
} else {
130
173
self . tcx . is_const_fn ( def_id)
131
174
} ;
132
175
176
+ if !node_check {
177
+ return NotPromotable
178
+ }
179
+
133
180
if let Some ( & attr:: Stability {
134
181
rustc_const_unstable : Some ( attr:: RustcConstUnstable {
135
182
feature : ref feature_name
136
183
} ) ,
137
184
.. } ) = self . tcx . lookup_stability ( def_id) {
138
- self . promotable & =
185
+ let stable_check =
139
186
// feature-gate is enabled,
140
187
self . tcx . features ( )
141
188
. declared_lib_features
@@ -147,7 +194,11 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
147
194
148
195
// this comes from a macro that has #[allow_internal_unstable]
149
196
span. allows_unstable ( ) ;
150
- }
197
+ if !stable_check {
198
+ return NotPromotable
199
+ }
200
+ } ;
201
+ Promotable
151
202
}
152
203
153
204
/// While the `ExprUseVisitor` walks, we will identify which
@@ -169,7 +220,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
169
220
}
170
221
171
222
impl < ' a , ' tcx > CheckCrateVisitor < ' a , ' tcx > {
172
- fn visit_nested_body ( & mut self , body_id : hir:: BodyId ) {
223
+ fn check_nested_body ( & mut self , body_id : hir:: BodyId ) -> Promotability {
173
224
let item_id = self . tcx . hir . body_owner ( body_id) ;
174
225
let item_def_id = self . tcx . hir . local_def_id ( item_id) ;
175
226
@@ -200,68 +251,67 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
200
251
euv:: ExprUseVisitor :: new ( self , tcx, param_env, & region_scope_tree, self . tables , None )
201
252
. consume_body ( body) ;
202
253
203
- self . visit_expr ( & body. value ) ;
254
+ let body_promotable = self . check_expr ( & body. value ) ;
204
255
self . in_fn = outer_in_fn;
205
256
self . tables = outer_tables;
206
257
self . param_env = outer_param_env;
207
258
self . identity_substs = outer_identity_substs;
259
+ body_promotable
208
260
}
209
261
210
- fn visit_stmt ( & mut self , stmt : & ' tcx hir:: Stmt ) {
262
+ fn check_stmt ( & mut self , stmt : & ' tcx hir:: Stmt ) -> Promotability {
211
263
match stmt. node {
212
264
hir:: StmtDecl ( ref decl, _node_id) => {
213
265
match & decl. node {
214
266
hir:: DeclLocal ( local) => {
215
- self . promotable = false ;
216
267
if self . remove_mut_rvalue_borrow ( & local. pat ) {
217
268
if let Some ( init) = & local. init {
218
269
self . mut_rvalue_borrows . insert ( init. id ) ;
219
270
}
220
271
}
221
272
222
273
match local. init {
223
- Some ( ref expr) => self . visit_expr ( & expr) ,
274
+ Some ( ref expr) => { let _ = self . check_expr ( & expr) ; } ,
224
275
None => { } ,
225
276
}
277
+ NotPromotable
226
278
}
227
279
// Item statements are allowed
228
- hir:: DeclItem ( _) => { }
280
+ hir:: DeclItem ( _) => Promotable
229
281
}
230
282
}
231
283
hir:: StmtExpr ( ref box_expr, _node_id) |
232
284
hir:: StmtSemi ( ref box_expr, _node_id) => {
233
- self . visit_expr ( box_expr) ;
234
- self . promotable = false ;
285
+ let _ = self . check_expr ( box_expr) ;
286
+ NotPromotable
235
287
}
236
288
}
237
289
}
238
290
239
- fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr ) {
240
- let outer = self . promotable ;
241
- self . promotable = true ;
242
-
291
+ fn check_expr ( & mut self , ex : & ' tcx hir:: Expr ) -> Promotability {
243
292
let node_ty = self . tables . node_id_to_type ( ex. hir_id ) ;
244
- check_expr ( self , ex, node_ty) ;
245
- check_adjustments ( self , ex) ;
293
+ let mut outer = check_expr_kind ( self , ex, node_ty) ;
294
+ outer = outer & check_adjustments ( self , ex) ;
246
295
247
296
// Handle borrows on (or inside the autorefs of) this expression.
248
297
if self . mut_rvalue_borrows . remove ( & ex. id ) {
249
- self . promotable = false ;
298
+ outer = NotPromotable
250
299
}
251
300
252
- if self . promotable {
301
+ if outer == Promotable {
253
302
self . result . insert ( ex. hir_id . local_id ) ;
254
303
}
255
- self . promotable &= outer;
304
+ outer
256
305
}
257
306
258
- fn visit_block ( & mut self , block : & ' tcx hir:: Block ) {
307
+ fn check_block ( & mut self , block : & ' tcx hir:: Block ) -> Promotability {
308
+ let mut iter_result = Promotable ;
259
309
for index in block. stmts . iter ( ) {
260
- self . visit_stmt ( index)
310
+ iter_result = iter_result & self . check_stmt ( index) ;
261
311
}
262
312
match block. expr {
263
- Some ( ref box_expr) => { self . visit_expr ( & * box_expr) } ,
264
- None => { } ,
313
+ Some ( ref box_expr) => iter_result & self . check_expr ( & * box_expr) ,
314
+ None => iter_result ,
265
315
}
266
316
}
267
317
}
@@ -272,63 +322,68 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
272
322
/// every nested expression. If the expression is not part
273
323
/// of a const/static item, it is qualified for promotion
274
324
/// instead of producing errors.
275
- fn check_expr < ' a , ' tcx > (
325
+ fn check_expr_kind < ' a , ' tcx > (
276
326
v : & mut CheckCrateVisitor < ' a , ' tcx > ,
277
- e : & ' tcx hir:: Expr , node_ty : Ty < ' tcx > ) {
278
- match node_ty. sty {
327
+ e : & ' tcx hir:: Expr , node_ty : Ty < ' tcx > ) -> Promotability {
328
+
329
+ let ty_result = match node_ty. sty {
279
330
ty:: TyAdt ( def, _) if def. has_dtor ( v. tcx ) => {
280
- v . promotable = false ;
331
+ NotPromotable
281
332
}
282
- _ => { }
283
- }
333
+ _ => Promotable
334
+ } ;
284
335
285
- match e. node {
336
+ let node_result = match e. node {
286
337
hir:: ExprBox ( ref expr) => {
287
- v . visit_expr ( & expr) ;
288
- v . promotable = false ;
338
+ let _ = v . check_expr ( & expr) ;
339
+ NotPromotable
289
340
}
290
341
hir:: ExprUnary ( op, ref expr) => {
342
+ let expr_promotability = v. check_expr ( expr) ;
291
343
if v. tables . is_method_call ( e) {
292
- v . promotable = false ;
344
+ return NotPromotable ;
293
345
}
294
346
if op == hir:: UnDeref {
295
- v . promotable = false ;
347
+ return NotPromotable ;
296
348
}
297
- v . visit_expr ( expr ) ;
349
+ expr_promotability
298
350
}
299
351
hir:: ExprBinary ( op, ref lhs, ref rhs) => {
352
+ let lefty = v. check_expr ( lhs) ;
353
+ let righty = v. check_expr ( rhs) ;
300
354
if v. tables . is_method_call ( e) {
301
- v . promotable = false ;
355
+ return NotPromotable ;
302
356
}
303
- v. visit_expr ( lhs) ;
304
- v. visit_expr ( rhs) ;
305
357
match v. tables . node_id_to_type ( lhs. hir_id ) . sty {
306
358
ty:: TyRawPtr ( _) => {
307
359
assert ! ( op. node == hir:: BiEq || op. node == hir:: BiNe ||
308
360
op. node == hir:: BiLe || op. node == hir:: BiLt ||
309
361
op. node == hir:: BiGe || op. node == hir:: BiGt ) ;
310
362
311
- v . promotable = false ;
363
+ NotPromotable
312
364
}
313
- _ => { }
365
+ _ => lefty & righty
314
366
}
315
367
}
316
368
hir:: ExprCast ( ref from, _) => {
317
- v . visit_expr ( from) ;
369
+ let expr_promotability = v . check_expr ( from) ;
318
370
debug ! ( "Checking const cast(id={})" , from. id) ;
319
371
match v. tables . cast_kinds ( ) . get ( from. hir_id ) {
320
- None => v. tcx . sess . delay_span_bug ( e. span , "no kind for cast" ) ,
372
+ None => {
373
+ v. tcx . sess . delay_span_bug ( e. span , "no kind for cast" ) ;
374
+ NotPromotable
375
+ } ,
321
376
Some ( & CastKind :: PtrAddrCast ) | Some ( & CastKind :: FnPtrAddrCast ) => {
322
- v . promotable = false ;
377
+ NotPromotable
323
378
}
324
- _ => { }
379
+ _ => expr_promotability
325
380
}
326
381
}
327
382
hir:: ExprPath ( ref qpath) => {
328
383
let def = v. tables . qpath_def ( qpath, e. hir_id ) ;
329
384
match def {
330
385
Def :: VariantCtor ( ..) | Def :: StructCtor ( ..) |
331
- Def :: Fn ( ..) | Def :: Method ( ..) => { }
386
+ Def :: Fn ( ..) | Def :: Method ( ..) => Promotable ,
332
387
333
388
// References to a static that are themselves within a static
334
389
// are inherently promotable with the exception
@@ -337,25 +392,18 @@ fn check_expr<'a, 'tcx>(
337
392
Def :: Static ( did, _) => {
338
393
339
394
if v. in_static {
340
- let mut thread_local = false ;
341
-
342
395
for attr in & v. tcx . get_attrs ( did) [ ..] {
343
396
if attr. check_name ( "thread_local" ) {
344
397
debug ! ( "Reference to Static(id={:?}) is unpromotable \
345
398
due to a #[thread_local] attribute", did) ;
346
- v. promotable = false ;
347
- thread_local = true ;
348
- break ;
399
+ return NotPromotable ;
349
400
}
350
401
}
351
-
352
- if !thread_local {
353
- debug ! ( "Allowing promotion of reference to Static(id={:?})" , did) ;
354
- }
402
+ Promotable
355
403
} else {
356
404
debug ! ( "Reference to Static(id={:?}) is unpromotable as it is not \
357
405
referenced from a static", did) ;
358
- v . promotable = false ;
406
+ NotPromotable
359
407
360
408
}
361
409
}
@@ -364,26 +412,24 @@ fn check_expr<'a, 'tcx>(
364
412
Def :: AssociatedConst ( did) => {
365
413
let promotable = if v. tcx . trait_of_item ( did) . is_some ( ) {
366
414
// Don't peek inside trait associated constants.
367
- false
415
+ NotPromotable
416
+ } else if v. tcx . at ( e. span ) . const_is_rvalue_promotable_to_static ( did) {
417
+ Promotable
368
418
} else {
369
- v . tcx . at ( e . span ) . const_is_rvalue_promotable_to_static ( did )
419
+ NotPromotable
370
420
} ;
371
-
372
421
// Just in case the type is more specific than the definition,
373
422
// e.g. impl associated const with type parameters, check it.
374
423
// Also, trait associated consts are relaxed by this.
375
- v. promotable &= promotable || v. type_has_only_promotable_values ( node_ty) ;
376
- }
377
-
378
- _ => {
379
- v. promotable = false ;
424
+ promotable | v. type_promotability ( node_ty)
380
425
}
426
+ _ => NotPromotable
381
427
}
382
428
}
383
429
hir:: ExprCall ( ref callee, ref hirvec) => {
384
- v . visit_expr ( callee) ;
430
+ let mut call_result = v . check_expr ( callee) ;
385
431
for index in hirvec. iter ( ) {
386
- v . visit_expr ( index)
432
+ call_result = call_result & v . check_expr ( index) ;
387
433
}
388
434
let mut callee = & * * callee;
389
435
loop {
@@ -401,9 +447,9 @@ fn check_expr<'a, 'tcx>(
401
447
} else {
402
448
Def :: Err
403
449
} ;
404
- match def {
450
+ let def_result = match def {
405
451
Def :: StructCtor ( _, CtorKind :: Fn ) |
406
- Def :: VariantCtor ( _, CtorKind :: Fn ) => { }
452
+ Def :: VariantCtor ( _, CtorKind :: Fn ) => Promotable ,
407
453
Def :: Fn ( did) => {
408
454
v. handle_const_fn_call ( did, node_ty, e. span )
409
455
}
@@ -412,94 +458,110 @@ fn check_expr<'a, 'tcx>(
412
458
ty:: ImplContainer ( _) => {
413
459
v. handle_const_fn_call ( did, node_ty, e. span )
414
460
}
415
- ty:: TraitContainer ( _) => v . promotable = false
461
+ ty:: TraitContainer ( _) => NotPromotable ,
416
462
}
417
463
}
418
- _ => v. promotable = false
419
- }
464
+ _ => NotPromotable ,
465
+ } ;
466
+ def_result & call_result
420
467
}
421
468
hir:: ExprMethodCall ( ref _pathsegment, ref _span, ref hirvec) => {
469
+ let mut method_call_result = Promotable ;
422
470
for index in hirvec. iter ( ) {
423
- v . visit_expr ( index)
471
+ method_call_result = method_call_result & v . check_expr ( index) ;
424
472
}
425
473
if let Some ( def) = v. tables . type_dependent_defs ( ) . get ( e. hir_id ) {
426
474
let def_id = def. def_id ( ) ;
427
475
match v. tcx . associated_item ( def_id) . container {
428
- ty:: ImplContainer ( _) => v. handle_const_fn_call ( def_id, node_ty, e. span ) ,
429
- ty:: TraitContainer ( _) => v. promotable = false
430
- }
476
+ ty:: ImplContainer ( _) => {
477
+ method_call_result = method_call_result
478
+ & v. handle_const_fn_call ( def_id, node_ty, e. span ) ;
479
+ }
480
+ ty:: TraitContainer ( _) => return NotPromotable ,
481
+ } ;
431
482
} else {
432
483
v. tcx . sess . delay_span_bug ( e. span , "no type-dependent def for method call" ) ;
433
484
}
485
+ method_call_result
434
486
}
435
487
hir:: ExprStruct ( ref _qpath, ref hirvec, ref option_expr) => {
488
+ let mut struct_result = Promotable ;
436
489
for index in hirvec. iter ( ) {
437
- v . visit_expr ( & index. expr ) ;
490
+ struct_result = struct_result & v . check_expr ( & index. expr ) ;
438
491
}
439
492
match * option_expr {
440
- Some ( ref expr) => { v . visit_expr ( & expr) } ,
493
+ Some ( ref expr) => { struct_result = struct_result & v . check_expr ( & expr) ; } ,
441
494
None => { } ,
442
495
}
443
496
if let ty:: TyAdt ( adt, ..) = v. tables . expr_ty ( e) . sty {
444
497
// unsafe_cell_type doesn't necessarily exist with no_core
445
498
if Some ( adt. did ) == v. tcx . lang_items ( ) . unsafe_cell_type ( ) {
446
- v . promotable = false ;
499
+ return NotPromotable ;
447
500
}
448
501
}
502
+ struct_result
449
503
}
450
504
451
- hir:: ExprLit ( _) => { }
505
+ hir:: ExprLit ( _) => Promotable ,
452
506
453
507
hir:: ExprAddrOf ( _, ref expr) |
454
508
hir:: ExprRepeat ( ref expr, _) => {
455
- v. visit_expr ( expr) ;
509
+ v. check_expr ( & expr)
456
510
}
457
511
458
512
hir:: ExprClosure ( _capture_clause, ref _box_fn_decl,
459
513
body_id, _span, _option_generator_movability) => {
460
- v . visit_nested_body ( body_id) ;
514
+ let nested_body_promotable = v . check_nested_body ( body_id) ;
461
515
// Paths in constant contexts cannot refer to local variables,
462
516
// as there are none, and thus closures can't have upvars there.
463
517
if v. tcx . with_freevars ( e. id , |fv| !fv. is_empty ( ) ) {
464
- v. promotable = false ;
518
+ NotPromotable
519
+ } else {
520
+ nested_body_promotable
465
521
}
466
522
}
467
523
468
524
hir:: ExprField ( ref expr, _ident) => {
469
- v . visit_expr ( expr) ;
525
+ let expr_promotability = v . check_expr ( & expr) ;
470
526
if let Some ( def) = v. tables . expr_ty ( expr) . ty_adt_def ( ) {
471
527
if def. is_union ( ) {
472
- v . promotable = false
528
+ return NotPromotable ;
473
529
}
474
530
}
531
+ expr_promotability
475
532
}
476
533
477
534
hir:: ExprBlock ( ref box_block, ref _option_label) => {
478
- v. visit_block ( box_block) ;
535
+ v. check_block ( box_block)
479
536
}
480
537
481
538
hir:: ExprIndex ( ref lhs, ref rhs) => {
539
+ let lefty = v. check_expr ( lhs) ;
540
+ let righty = v. check_expr ( rhs) ;
482
541
if v. tables . is_method_call ( e) {
483
- v . promotable = false ;
542
+ return NotPromotable ;
484
543
}
485
- v. visit_expr ( lhs) ;
486
- v. visit_expr ( rhs) ;
544
+ lefty & righty
487
545
}
488
546
489
547
hir:: ExprArray ( ref hirvec) => {
548
+ let mut array_result = Promotable ;
490
549
for index in hirvec. iter ( ) {
491
- v . visit_expr ( index)
550
+ array_result = array_result & v . check_expr ( index) ;
492
551
}
552
+ array_result
493
553
}
494
554
495
555
hir:: ExprType ( ref expr, ref _ty) => {
496
- v. visit_expr ( expr) ;
556
+ v. check_expr ( & expr)
497
557
}
498
558
499
559
hir:: ExprTup ( ref hirvec) => {
560
+ let mut tup_result = Promotable ;
500
561
for index in hirvec. iter ( ) {
501
- v . visit_expr ( index)
562
+ tup_result = tup_result & v . check_expr ( index) ;
502
563
}
564
+ tup_result
503
565
}
504
566
505
567
@@ -515,79 +577,84 @@ fn check_expr<'a, 'tcx>(
515
577
v. mut_rvalue_borrows . insert ( expr. id ) ;
516
578
}
517
579
518
- v . visit_expr ( expr) ;
580
+ let _ = v . check_expr ( expr) ;
519
581
for index in hirvec_arm. iter ( ) {
520
- v . visit_expr ( & * index. body ) ;
582
+ let _ = v . check_expr ( & * index. body ) ;
521
583
match index. guard {
522
- Some ( ref expr) => v. visit_expr ( & expr) ,
584
+ Some ( ref expr) => {
585
+ let _ = v. check_expr ( & expr) ;
586
+ } ,
523
587
None => { } ,
524
- }
588
+ } ;
525
589
}
526
- v . promotable = false ;
590
+ NotPromotable
527
591
}
528
592
529
593
hir:: ExprIf ( ref lhs, ref rhs, ref option_expr) => {
530
- v . visit_expr ( lhs) ;
531
- v . visit_expr ( rhs) ;
594
+ let _ = v . check_expr ( lhs) ;
595
+ let _ = v . check_expr ( rhs) ;
532
596
match option_expr {
533
- Some ( ref expr) => v . visit_expr ( & expr) ,
597
+ Some ( ref expr) => { let _ = v . check_expr ( & expr) ; } ,
534
598
None => { } ,
535
- }
536
- v . promotable = false ;
599
+ } ;
600
+ NotPromotable
537
601
}
538
602
539
603
// Loops (not very meaningful in constants).
540
604
hir:: ExprWhile ( ref expr, ref box_block, ref _option_label) => {
541
- v . visit_expr ( expr) ;
542
- v . visit_block ( box_block) ;
543
- v . promotable = false ;
605
+ let _ = v . check_expr ( expr) ;
606
+ let _ = v . check_block ( box_block) ;
607
+ NotPromotable
544
608
}
545
609
546
610
hir:: ExprLoop ( ref box_block, ref _option_label, ref _loop_source) => {
547
- v . visit_block ( box_block) ;
548
- v . promotable = false ;
611
+ let _ = v . check_block ( box_block) ;
612
+ NotPromotable
549
613
}
550
614
551
615
// More control flow (also not very meaningful).
552
616
hir:: ExprBreak ( _, ref option_expr) | hir:: ExprRet ( ref option_expr) => {
553
617
match * option_expr {
554
- Some ( ref expr) => { v . visit_expr ( & expr) } ,
618
+ Some ( ref expr) => { let _ = v . check_expr ( & expr) ; } ,
555
619
None => { } ,
556
620
}
557
- v . promotable = false ;
621
+ NotPromotable
558
622
}
559
623
560
624
hir:: ExprContinue ( _) => {
561
- v . promotable = false ;
625
+ NotPromotable
562
626
}
563
627
564
628
// Generator expressions
565
629
hir:: ExprYield ( ref expr) => {
566
- v . visit_expr ( & expr) ;
567
- v . promotable = false ;
630
+ let _ = v . check_expr ( & expr) ;
631
+ NotPromotable
568
632
}
569
633
570
634
// Expressions with side-effects.
571
635
hir:: ExprAssignOp ( _, ref lhs, ref rhs) | hir:: ExprAssign ( ref lhs, ref rhs) => {
572
- v . visit_expr ( lhs) ;
573
- v . visit_expr ( rhs) ;
574
- v . promotable = false ;
636
+ let _ = v . check_expr ( lhs) ;
637
+ let _ = v . check_expr ( rhs) ;
638
+ NotPromotable
575
639
}
576
640
577
641
hir:: ExprInlineAsm ( ref _inline_asm, ref hirvec_lhs, ref hirvec_rhs) => {
578
642
for index in hirvec_lhs. iter ( ) {
579
- v . visit_expr ( index)
643
+ let _ = v . check_expr ( index) ;
580
644
}
581
645
for index in hirvec_rhs. iter ( ) {
582
- v . visit_expr ( index)
646
+ let _ = v . check_expr ( index) ;
583
647
}
584
- v . promotable = false ;
648
+ NotPromotable
585
649
}
586
- }
650
+ } ;
651
+ ty_result & node_result
587
652
}
588
653
589
654
/// Check the adjustments of an expression
590
- fn check_adjustments < ' a , ' tcx > ( v : & mut CheckCrateVisitor < ' a , ' tcx > , e : & hir:: Expr ) {
655
+ fn check_adjustments < ' a , ' tcx > (
656
+ v : & mut CheckCrateVisitor < ' a , ' tcx > ,
657
+ e : & hir:: Expr ) -> Promotability {
591
658
use rustc:: ty:: adjustment:: * ;
592
659
593
660
let mut adjustments = v. tables . expr_adjustments ( e) . iter ( ) . peekable ( ) ;
@@ -607,11 +674,11 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
607
674
continue ;
608
675
}
609
676
}
610
- v. promotable = false ;
611
- break ;
677
+ return NotPromotable ;
612
678
}
613
679
}
614
680
}
681
+ Promotable
615
682
}
616
683
617
684
impl < ' a , ' gcx , ' tcx > euv:: Delegate < ' tcx > for CheckCrateVisitor < ' a , ' gcx > {
0 commit comments