@@ -21,6 +21,7 @@ use self::SawTyComponent::*;
2121use self :: SawTraitOrImplItemComponent :: * ;
2222use syntax:: abi:: Abi ;
2323use syntax:: ast:: { self , Name , NodeId } ;
24+ use syntax:: attr;
2425use syntax:: parse:: token;
2526use syntax_pos:: { Span , NO_EXPANSION , COMMAND_LINE_EXPN , BytePos } ;
2627use rustc:: hir;
@@ -53,6 +54,7 @@ pub struct StrictVersionHashVisitor<'a, 'hash: 'a, 'tcx: 'hash> {
5354 def_path_hashes : & ' a mut DefPathHashes < ' hash , ' tcx > ,
5455 hash_spans : bool ,
5556 codemap : & ' a mut CachingCodemapView < ' tcx > ,
57+ overflow_checks_enabled : bool ,
5658}
5759
5860impl < ' a , ' hash , ' tcx > StrictVersionHashVisitor < ' a , ' hash , ' tcx > {
@@ -62,12 +64,16 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
6264 codemap : & ' a mut CachingCodemapView < ' tcx > ,
6365 hash_spans : bool )
6466 -> Self {
67+ let check_overflow = tcx. sess . opts . debugging_opts . force_overflow_checks
68+ . unwrap_or ( tcx. sess . opts . debug_assertions ) ;
69+
6570 StrictVersionHashVisitor {
6671 st : st,
6772 tcx : tcx,
6873 def_path_hashes : def_path_hashes,
6974 hash_spans : hash_spans,
7075 codemap : codemap,
76+ overflow_checks_enabled : check_overflow,
7177 }
7278 }
7379
@@ -83,7 +89,6 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
8389 // Also note that we are hashing byte offsets for the column, not unicode
8490 // codepoint offsets. For the purpose of the hash that's sufficient.
8591 fn hash_span ( & mut self , span : Span ) {
86- debug_assert ! ( self . hash_spans) ;
8792 debug ! ( "hash_span: st={:?}" , self . st) ;
8893
8994 // If this is not an empty or invalid span, we want to hash the last
@@ -241,37 +246,80 @@ enum SawExprComponent<'a> {
241246 SawExprRepeat ,
242247}
243248
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+
245287 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 ) ,
275323 }
276324}
277325
@@ -421,10 +469,13 @@ macro_rules! hash_attrs {
421469
422470macro_rules! hash_span {
423471 ( $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 {
425476 $visitor. hash_span( $span) ;
426477 }
427- } )
478+ } ) ;
428479}
429480
430481impl < ' 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
474525
475526 fn visit_expr ( & mut self , ex : & ' tcx Expr ) {
476527 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 ) ;
478531 // No need to explicitly hash the discriminant here, since we are
479532 // implicitly hashing the discriminant of SawExprComponent.
480- hash_span ! ( self , ex. span) ;
533+ hash_span ! ( self , ex. span, force_span ) ;
481534 hash_attrs ! ( self , & ex. attrs) ;
482535 visit:: walk_expr ( self , ex)
483536 }
@@ -519,6 +572,9 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
519572
520573 fn visit_item ( & mut self , i : & ' tcx Item ) {
521574 debug ! ( "visit_item: {:?} st={:?}" , i, self . st) ;
575+
576+ self . maybe_enable_overflow_checks ( & i. attrs ) ;
577+
522578 SawItem ( saw_item ( & i. node ) ) . hash ( self . st ) ;
523579 hash_span ! ( self , i. span) ;
524580 hash_attrs ! ( self , & i. attrs) ;
@@ -545,6 +601,9 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
545601
546602 fn visit_trait_item ( & mut self , ti : & ' tcx TraitItem ) {
547603 debug ! ( "visit_trait_item: st={:?}" , self . st) ;
604+
605+ self . maybe_enable_overflow_checks ( & ti. attrs ) ;
606+
548607 SawTraitItem ( saw_trait_item ( & ti. node ) ) . hash ( self . st ) ;
549608 hash_span ! ( self , ti. span) ;
550609 hash_attrs ! ( self , & ti. attrs) ;
@@ -553,6 +612,9 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
553612
554613 fn visit_impl_item ( & mut self , ii : & ' tcx ImplItem ) {
555614 debug ! ( "visit_impl_item: st={:?}" , self . st) ;
615+
616+ self . maybe_enable_overflow_checks ( & ii. attrs ) ;
617+
556618 SawImplItem ( saw_impl_item ( & ii. node ) ) . hash ( self . st ) ;
557619 hash_span ! ( self , ii. span) ;
558620 hash_attrs ! ( self , & ii. attrs) ;
@@ -842,4 +904,10 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
842904 indices. sort_by_key ( |index| get_key ( & items[ * index] ) ) ;
843905 indices
844906 }
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+ }
845913}
0 commit comments