@@ -14,13 +14,14 @@ use crate::tokenstream::*;
14
14
15
15
use rustc_data_structures:: map_in_place:: MapInPlace ;
16
16
use rustc_data_structures:: sync:: Lrc ;
17
+ use rustc_data_structures:: thin_vec:: ThinVec ;
17
18
use rustc_span:: source_map:: Spanned ;
18
19
use rustc_span:: symbol:: Ident ;
19
20
use rustc_span:: Span ;
20
21
21
22
use smallvec:: { smallvec, Array , SmallVec } ;
22
23
use std:: ops:: DerefMut ;
23
- use std:: { panic, process , ptr} ;
24
+ use std:: { panic, ptr} ;
24
25
25
26
pub trait ExpectOne < A : Array > {
26
27
fn expect_one ( self , err : & ' static str ) -> A :: Item ;
@@ -283,23 +284,21 @@ pub trait MutVisitor: Sized {
283
284
284
285
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
285
286
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
286
- /// method. Abort the program if the closure panics.
287
- ///
288
- /// FIXME: Abort on panic means that any fatal error inside `visit_clobber` will abort the compiler.
289
- /// Instead of aborting on catching a panic we need to reset the visited node to some valid but
290
- /// possibly meaningless value and rethrow the panic.
287
+ /// method.
291
288
//
292
289
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
293
- pub fn visit_clobber < T , F > ( t : & mut T , f : F )
294
- where
295
- F : FnOnce ( T ) -> T ,
296
- {
290
+ pub fn visit_clobber < T : DummyAstNode > ( t : & mut T , f : impl FnOnce ( T ) -> T ) {
297
291
unsafe {
298
292
// Safe because `t` is used in a read-only fashion by `read()` before
299
293
// being overwritten by `write()`.
300
294
let old_t = ptr:: read ( t) ;
301
- let new_t = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || f ( old_t) ) )
302
- . unwrap_or_else ( |_| process:: abort ( ) ) ;
295
+ let new_t =
296
+ panic:: catch_unwind ( panic:: AssertUnwindSafe ( || f ( old_t) ) ) . unwrap_or_else ( |err| {
297
+ // Set `t` to some valid but possible meaningless value,
298
+ // and pass the fatal error further.
299
+ ptr:: write ( t, T :: dummy ( ) ) ;
300
+ panic:: resume_unwind ( err) ;
301
+ } ) ;
303
302
ptr:: write ( t, new_t) ;
304
303
}
305
304
}
@@ -1454,3 +1453,108 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
1454
1453
}
1455
1454
vis. visit_span ( & mut visibility. span ) ;
1456
1455
}
1456
+
1457
+ /// Some value for the AST node that is valid but possibly meaningless.
1458
+ pub trait DummyAstNode {
1459
+ fn dummy ( ) -> Self ;
1460
+ }
1461
+
1462
+ impl < T > DummyAstNode for Option < T > {
1463
+ fn dummy ( ) -> Self {
1464
+ Default :: default ( )
1465
+ }
1466
+ }
1467
+
1468
+ impl < T : DummyAstNode + ' static > DummyAstNode for P < T > {
1469
+ fn dummy ( ) -> Self {
1470
+ P ( DummyAstNode :: dummy ( ) )
1471
+ }
1472
+ }
1473
+
1474
+ impl < T > DummyAstNode for ThinVec < T > {
1475
+ fn dummy ( ) -> Self {
1476
+ Default :: default ( )
1477
+ }
1478
+ }
1479
+
1480
+ impl DummyAstNode for Item {
1481
+ fn dummy ( ) -> Self {
1482
+ Item {
1483
+ attrs : Default :: default ( ) ,
1484
+ id : DUMMY_NODE_ID ,
1485
+ span : Default :: default ( ) ,
1486
+ vis : Visibility {
1487
+ kind : VisibilityKind :: Public ,
1488
+ span : Default :: default ( ) ,
1489
+ tokens : Default :: default ( ) ,
1490
+ } ,
1491
+ ident : Ident :: empty ( ) ,
1492
+ kind : ItemKind :: ExternCrate ( None ) ,
1493
+ tokens : Default :: default ( ) ,
1494
+ }
1495
+ }
1496
+ }
1497
+
1498
+ impl DummyAstNode for Expr {
1499
+ fn dummy ( ) -> Self {
1500
+ Expr {
1501
+ id : DUMMY_NODE_ID ,
1502
+ kind : ExprKind :: Err ,
1503
+ span : Default :: default ( ) ,
1504
+ attrs : Default :: default ( ) ,
1505
+ tokens : Default :: default ( ) ,
1506
+ }
1507
+ }
1508
+ }
1509
+
1510
+ impl DummyAstNode for Ty {
1511
+ fn dummy ( ) -> Self {
1512
+ Ty {
1513
+ id : DUMMY_NODE_ID ,
1514
+ kind : TyKind :: Err ,
1515
+ span : Default :: default ( ) ,
1516
+ tokens : Default :: default ( ) ,
1517
+ }
1518
+ }
1519
+ }
1520
+
1521
+ impl DummyAstNode for Pat {
1522
+ fn dummy ( ) -> Self {
1523
+ Pat {
1524
+ id : DUMMY_NODE_ID ,
1525
+ kind : PatKind :: Wild ,
1526
+ span : Default :: default ( ) ,
1527
+ tokens : Default :: default ( ) ,
1528
+ }
1529
+ }
1530
+ }
1531
+
1532
+ impl DummyAstNode for Stmt {
1533
+ fn dummy ( ) -> Self {
1534
+ Stmt { id : DUMMY_NODE_ID , kind : StmtKind :: Empty , span : Default :: default ( ) }
1535
+ }
1536
+ }
1537
+
1538
+ impl DummyAstNode for Block {
1539
+ fn dummy ( ) -> Self {
1540
+ Block {
1541
+ stmts : Default :: default ( ) ,
1542
+ id : DUMMY_NODE_ID ,
1543
+ rules : BlockCheckMode :: Default ,
1544
+ span : Default :: default ( ) ,
1545
+ tokens : Default :: default ( ) ,
1546
+ could_be_bare_literal : Default :: default ( ) ,
1547
+ }
1548
+ }
1549
+ }
1550
+
1551
+ impl DummyAstNode for Crate {
1552
+ fn dummy ( ) -> Self {
1553
+ Crate {
1554
+ attrs : Default :: default ( ) ,
1555
+ items : Default :: default ( ) ,
1556
+ span : Default :: default ( ) ,
1557
+ is_placeholder : Default :: default ( ) ,
1558
+ }
1559
+ }
1560
+ }
0 commit comments