@@ -21,6 +21,7 @@ use self::SawTyComponent::*;
21
21
use self :: SawTraitOrImplItemComponent :: * ;
22
22
use syntax:: abi:: Abi ;
23
23
use syntax:: ast:: { self , Name , NodeId } ;
24
+ use syntax:: attr;
24
25
use syntax:: parse:: token;
25
26
use syntax_pos:: { Span , NO_EXPANSION , COMMAND_LINE_EXPN , BytePos } ;
26
27
use rustc:: hir;
@@ -53,6 +54,7 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
53
54
def_path_hashes : & ' a mut DefPathHashes < ' hash , ' tcx > ,
54
55
hash_spans : bool ,
55
56
codemap : & ' a mut CachingCodemapView < ' tcx > ,
57
+ overflow_checks_enabled : bool ,
56
58
}
57
59
58
60
impl < ' a , ' hash , ' tcx > StrictVersionHashVisitor < ' a , ' hash , ' tcx > {
@@ -62,12 +64,16 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
62
64
codemap : & ' a mut CachingCodemapView < ' tcx > ,
63
65
hash_spans : bool )
64
66
-> Self {
67
+ let check_overflow = tcx. sess . opts . debugging_opts . force_overflow_checks
68
+ . unwrap_or ( tcx. sess . opts . debug_assertions ) ;
69
+
65
70
StrictVersionHashVisitor {
66
71
st : st,
67
72
tcx : tcx,
68
73
def_path_hashes : def_path_hashes,
69
74
hash_spans : hash_spans,
70
75
codemap : codemap,
76
+ overflow_checks_enabled : check_overflow,
71
77
}
72
78
}
73
79
@@ -83,7 +89,6 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
83
89
// Also note that we are hashing byte offsets for the column, not unicode
84
90
// codepoint offsets. For the purpose of the hash that's sufficient.
85
91
fn hash_span ( & mut self , span : Span ) {
86
- debug_assert ! ( self . hash_spans) ;
87
92
debug ! ( "hash_span: st={:?}" , self . st) ;
88
93
89
94
// If this is not an empty or invalid span, we want to hash the last
@@ -241,37 +246,80 @@ enum SawExprComponent<'a> {
241
246
SawExprRepeat ,
242
247
}
243
248
244
- fn saw_expr < ' a > ( node : & ' a Expr_ ) -> SawExprComponent < ' a > {
249
+ // The boolean returned indicates whether the span of this expression is always
250
+ // significant, regardless of debuginfo.
251
+ fn saw_expr < ' a > ( node : & ' a Expr_ ,
252
+ overflow_checks_enabled : bool )
253
+ -> ( SawExprComponent < ' a > , bool ) {
254
+ let binop_can_panic_at_runtime = |binop| {
255
+ match binop {
256
+ BiAdd |
257
+ BiSub |
258
+ BiMul => overflow_checks_enabled,
259
+
260
+ BiDiv |
261
+ BiRem => true ,
262
+
263
+ BiAnd |
264
+ BiOr |
265
+ BiBitXor |
266
+ BiBitAnd |
267
+ BiBitOr |
268
+ BiShl |
269
+ BiShr |
270
+ BiEq |
271
+ BiLt |
272
+ BiLe |
273
+ BiNe |
274
+ BiGe |
275
+ BiGt => false
276
+ }
277
+ } ;
278
+
279
+ let unop_can_panic_at_runtime = |unop| {
280
+ match unop {
281
+ UnDeref |
282
+ UnNot => false ,
283
+ UnNeg => overflow_checks_enabled,
284
+ }
285
+ } ;
286
+
245
287
match * node {
246
- ExprBox ( ..) => SawExprBox ,
247
- ExprArray ( ..) => SawExprArray ,
248
- ExprCall ( ..) => SawExprCall ,
249
- ExprMethodCall ( ..) => SawExprMethodCall ,
250
- ExprTup ( ..) => SawExprTup ,
251
- ExprBinary ( op, ..) => SawExprBinary ( op. node ) ,
252
- ExprUnary ( op, _) => SawExprUnary ( op) ,
253
- ExprLit ( ref lit) => SawExprLit ( lit. node . clone ( ) ) ,
254
- ExprCast ( ..) => SawExprCast ,
255
- ExprType ( ..) => SawExprType ,
256
- ExprIf ( ..) => SawExprIf ,
257
- ExprWhile ( ..) => SawExprWhile ,
258
- ExprLoop ( _, id) => SawExprLoop ( id. map ( |id| id. node . as_str ( ) ) ) ,
259
- ExprMatch ( ..) => SawExprMatch ,
260
- ExprClosure ( cc, _, _, _) => SawExprClosure ( cc) ,
261
- ExprBlock ( ..) => SawExprBlock ,
262
- ExprAssign ( ..) => SawExprAssign ,
263
- ExprAssignOp ( op, ..) => SawExprAssignOp ( op. node ) ,
264
- ExprField ( _, name) => SawExprField ( name. node . as_str ( ) ) ,
265
- ExprTupField ( _, id) => SawExprTupField ( id. node ) ,
266
- ExprIndex ( ..) => SawExprIndex ,
267
- ExprPath ( ref qself, _) => SawExprPath ( qself. as_ref ( ) . map ( |q| q. position ) ) ,
268
- ExprAddrOf ( m, _) => SawExprAddrOf ( m) ,
269
- ExprBreak ( id) => SawExprBreak ( id. map ( |id| id. node . as_str ( ) ) ) ,
270
- ExprAgain ( id) => SawExprAgain ( id. map ( |id| id. node . as_str ( ) ) ) ,
271
- ExprRet ( ..) => SawExprRet ,
272
- ExprInlineAsm ( ref a, ..) => SawExprInlineAsm ( a) ,
273
- ExprStruct ( ..) => SawExprStruct ,
274
- ExprRepeat ( ..) => SawExprRepeat ,
288
+ ExprBox ( ..) => ( SawExprBox , false ) ,
289
+ ExprArray ( ..) => ( SawExprArray , false ) ,
290
+ ExprCall ( ..) => ( SawExprCall , false ) ,
291
+ ExprMethodCall ( ..) => ( SawExprMethodCall , false ) ,
292
+ ExprTup ( ..) => ( SawExprTup , false ) ,
293
+ ExprBinary ( op, ..) => {
294
+ ( SawExprBinary ( op. node ) , binop_can_panic_at_runtime ( op. node ) )
295
+ }
296
+ ExprUnary ( op, _) => {
297
+ ( SawExprUnary ( op) , unop_can_panic_at_runtime ( op) )
298
+ }
299
+ ExprLit ( ref lit) => ( SawExprLit ( lit. node . clone ( ) ) , false ) ,
300
+ ExprCast ( ..) => ( SawExprCast , false ) ,
301
+ ExprType ( ..) => ( SawExprType , false ) ,
302
+ ExprIf ( ..) => ( SawExprIf , false ) ,
303
+ ExprWhile ( ..) => ( SawExprWhile , false ) ,
304
+ ExprLoop ( _, id) => ( SawExprLoop ( id. map ( |id| id. node . as_str ( ) ) ) , false ) ,
305
+ ExprMatch ( ..) => ( SawExprMatch , false ) ,
306
+ ExprClosure ( cc, _, _, _) => ( SawExprClosure ( cc) , false ) ,
307
+ ExprBlock ( ..) => ( SawExprBlock , false ) ,
308
+ ExprAssign ( ..) => ( SawExprAssign , false ) ,
309
+ ExprAssignOp ( op, ..) => {
310
+ ( SawExprAssignOp ( op. node ) , binop_can_panic_at_runtime ( op. node ) )
311
+ }
312
+ ExprField ( _, name) => ( SawExprField ( name. node . as_str ( ) ) , false ) ,
313
+ ExprTupField ( _, id) => ( SawExprTupField ( id. node ) , false ) ,
314
+ ExprIndex ( ..) => ( SawExprIndex , true ) ,
315
+ ExprPath ( ref qself, _) => ( SawExprPath ( qself. as_ref ( ) . map ( |q| q. position ) ) , false ) ,
316
+ ExprAddrOf ( m, _) => ( SawExprAddrOf ( m) , false ) ,
317
+ ExprBreak ( id) => ( SawExprBreak ( id. map ( |id| id. node . as_str ( ) ) ) , false ) ,
318
+ ExprAgain ( id) => ( SawExprAgain ( id. map ( |id| id. node . as_str ( ) ) ) , false ) ,
319
+ ExprRet ( ..) => ( SawExprRet , false ) ,
320
+ ExprInlineAsm ( ref a, ..) => ( SawExprInlineAsm ( a) , false ) ,
321
+ ExprStruct ( ..) => ( SawExprStruct , false ) ,
322
+ ExprRepeat ( ..) => ( SawExprRepeat , false ) ,
275
323
}
276
324
}
277
325
@@ -421,10 +469,13 @@ macro_rules! hash_attrs {
421
469
422
470
macro_rules! hash_span {
423
471
( $visitor: expr, $span: expr) => ( {
424
- if $visitor. hash_spans {
472
+ hash_span!( $visitor, $span, false )
473
+ } ) ;
474
+ ( $visitor: expr, $span: expr, $force: expr) => ( {
475
+ if $force || $visitor. hash_spans {
425
476
$visitor. hash_span( $span) ;
426
477
}
427
- } )
478
+ } ) ;
428
479
}
429
480
430
481
impl < ' a , ' hash , ' tcx > visit:: Visitor < ' tcx > for StrictVersionHashVisitor < ' a , ' hash , ' tcx > {
@@ -474,10 +525,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
474
525
475
526
fn visit_expr ( & mut self , ex : & ' tcx Expr ) {
476
527
debug ! ( "visit_expr: st={:?}" , self . st) ;
477
- SawExpr ( saw_expr ( & ex. node ) ) . hash ( self . st ) ;
528
+ let ( saw_expr, force_span) = saw_expr ( & ex. node ,
529
+ self . overflow_checks_enabled ) ;
530
+ SawExpr ( saw_expr) . hash ( self . st ) ;
478
531
// No need to explicitly hash the discriminant here, since we are
479
532
// implicitly hashing the discriminant of SawExprComponent.
480
- hash_span ! ( self , ex. span) ;
533
+ hash_span ! ( self , ex. span, force_span ) ;
481
534
hash_attrs ! ( self , & ex. attrs) ;
482
535
visit:: walk_expr ( self , ex)
483
536
}
@@ -519,6 +572,9 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
519
572
520
573
fn visit_item ( & mut self , i : & ' tcx Item ) {
521
574
debug ! ( "visit_item: {:?} st={:?}" , i, self . st) ;
575
+
576
+ self . maybe_enable_overflow_checks ( & i. attrs ) ;
577
+
522
578
SawItem ( saw_item ( & i. node ) ) . hash ( self . st ) ;
523
579
hash_span ! ( self , i. span) ;
524
580
hash_attrs ! ( self , & i. attrs) ;
@@ -545,6 +601,9 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
545
601
546
602
fn visit_trait_item ( & mut self , ti : & ' tcx TraitItem ) {
547
603
debug ! ( "visit_trait_item: st={:?}" , self . st) ;
604
+
605
+ self . maybe_enable_overflow_checks ( & ti. attrs ) ;
606
+
548
607
SawTraitItem ( saw_trait_item ( & ti. node ) ) . hash ( self . st ) ;
549
608
hash_span ! ( self , ti. span) ;
550
609
hash_attrs ! ( self , & ti. attrs) ;
@@ -553,6 +612,9 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
553
612
554
613
fn visit_impl_item ( & mut self , ii : & ' tcx ImplItem ) {
555
614
debug ! ( "visit_impl_item: st={:?}" , self . st) ;
615
+
616
+ self . maybe_enable_overflow_checks ( & ii. attrs ) ;
617
+
556
618
SawImplItem ( saw_impl_item ( & ii. node ) ) . hash ( self . st ) ;
557
619
hash_span ! ( self , ii. span) ;
558
620
hash_attrs ! ( self , & ii. attrs) ;
@@ -842,4 +904,10 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
842
904
indices. sort_by_key ( |index| get_key ( & items[ * index] ) ) ;
843
905
indices
844
906
}
907
+
908
+ fn maybe_enable_overflow_checks ( & mut self , item_attrs : & [ ast:: Attribute ] ) {
909
+ if attr:: contains_name ( item_attrs, "rustc_inherit_overflow_checks" ) {
910
+ self . overflow_checks_enabled = true ;
911
+ }
912
+ }
845
913
}
0 commit comments