@@ -14,13 +14,14 @@ use crate::tokenstream::*;
1414
1515use rustc_data_structures:: map_in_place:: MapInPlace ;
1616use rustc_data_structures:: sync:: Lrc ;
17+ use rustc_data_structures:: thin_vec:: ThinVec ;
1718use rustc_span:: source_map:: Spanned ;
1819use rustc_span:: symbol:: Ident ;
1920use rustc_span:: Span ;
2021
2122use smallvec:: { smallvec, Array , SmallVec } ;
2223use std:: ops:: DerefMut ;
23- use std:: { panic, process , ptr} ;
24+ use std:: { panic, ptr} ;
2425
2526pub trait ExpectOne < A : Array > {
2627 fn expect_one ( self , err : & ' static str ) -> A :: Item ;
@@ -283,23 +284,21 @@ pub trait MutVisitor: Sized {
283284
284285/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
285286/// 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.
291288//
292289// 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 ) {
297291 unsafe {
298292 // Safe because `t` is used in a read-only fashion by `read()` before
299293 // being overwritten by `write()`.
300294 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+ } ) ;
303302 ptr:: write ( t, new_t) ;
304303 }
305304}
@@ -1454,3 +1453,108 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
14541453 }
14551454 vis. visit_span ( & mut visibility. span ) ;
14561455}
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