@@ -84,6 +84,7 @@ pub struct LoweringContext<'a> {
84
84
trait_impls : BTreeMap < DefId , Vec < NodeId > > ,
85
85
trait_default_impl : BTreeMap < DefId , NodeId > ,
86
86
87
+ catch_scopes : Vec < NodeId > ,
87
88
loop_scopes : Vec < NodeId > ,
88
89
is_in_loop_condition : bool ,
89
90
@@ -123,6 +124,7 @@ pub fn lower_crate(sess: &Session,
123
124
trait_impls : BTreeMap :: new ( ) ,
124
125
trait_default_impl : BTreeMap :: new ( ) ,
125
126
exported_macros : Vec :: new ( ) ,
127
+ catch_scopes : Vec :: new ( ) ,
126
128
loop_scopes : Vec :: new ( ) ,
127
129
is_in_loop_condition : false ,
128
130
type_def_lifetime_params : DefIdMap ( ) ,
@@ -261,6 +263,21 @@ impl<'a> LoweringContext<'a> {
261
263
span
262
264
}
263
265
266
+ fn with_catch_scope < T , F > ( & mut self , catch_id : NodeId , f : F ) -> T
267
+ where F : FnOnce ( & mut LoweringContext ) -> T
268
+ {
269
+ let len = self . catch_scopes . len ( ) ;
270
+ self . catch_scopes . push ( catch_id) ;
271
+
272
+ let result = f ( self ) ;
273
+ assert_eq ! ( len + 1 , self . catch_scopes. len( ) ,
274
+ "catch scopes should be added and removed in stack order" ) ;
275
+
276
+ self . catch_scopes . pop ( ) . unwrap ( ) ;
277
+
278
+ result
279
+ }
280
+
264
281
fn with_loop_scope < T , F > ( & mut self , loop_id : NodeId , f : F ) -> T
265
282
where F : FnOnce ( & mut LoweringContext ) -> T
266
283
{
@@ -295,15 +312,17 @@ impl<'a> LoweringContext<'a> {
295
312
result
296
313
}
297
314
298
- fn with_new_loop_scopes < T , F > ( & mut self , f : F ) -> T
315
+ fn with_new_scopes < T , F > ( & mut self , f : F ) -> T
299
316
where F : FnOnce ( & mut LoweringContext ) -> T
300
317
{
301
318
let was_in_loop_condition = self . is_in_loop_condition ;
302
319
self . is_in_loop_condition = false ;
303
320
321
+ let catch_scopes = mem:: replace ( & mut self . catch_scopes , Vec :: new ( ) ) ;
304
322
let loop_scopes = mem:: replace ( & mut self . loop_scopes , Vec :: new ( ) ) ;
305
323
let result = f ( self ) ;
306
- mem:: replace ( & mut self . loop_scopes , loop_scopes) ;
324
+ self . catch_scopes = catch_scopes;
325
+ self . loop_scopes = loop_scopes;
307
326
308
327
self . is_in_loop_condition = was_in_loop_condition;
309
328
@@ -1065,7 +1084,7 @@ impl<'a> LoweringContext<'a> {
1065
1084
self . record_body ( value, None ) )
1066
1085
}
1067
1086
ItemKind :: Fn ( ref decl, unsafety, constness, abi, ref generics, ref body) => {
1068
- self . with_new_loop_scopes ( |this| {
1087
+ self . with_new_scopes ( |this| {
1069
1088
let body = this. lower_block ( body) ;
1070
1089
let body = this. expr_block ( body, ThinVec :: new ( ) ) ;
1071
1090
let body_id = this. record_body ( body, Some ( decl) ) ;
@@ -1665,13 +1684,17 @@ impl<'a> LoweringContext<'a> {
1665
1684
this. lower_opt_sp_ident ( opt_ident) ,
1666
1685
hir:: LoopSource :: Loop ) )
1667
1686
}
1687
+ ExprKind :: Catch ( ref body) => {
1688
+ // FIXME(cramertj): Add catch to HIR
1689
+ self . with_catch_scope ( e. id , |this| hir:: ExprBlock ( this. lower_block ( body) ) )
1690
+ }
1668
1691
ExprKind :: Match ( ref expr, ref arms) => {
1669
1692
hir:: ExprMatch ( P ( self . lower_expr ( expr) ) ,
1670
1693
arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
1671
1694
hir:: MatchSource :: Normal )
1672
1695
}
1673
1696
ExprKind :: Closure ( capture_clause, ref decl, ref body, fn_decl_span) => {
1674
- self . with_new_loop_scopes ( |this| {
1697
+ self . with_new_scopes ( |this| {
1675
1698
this. with_parent_def ( e. id , |this| {
1676
1699
let expr = this. lower_expr ( body) ;
1677
1700
hir:: ExprClosure ( this. lower_capture_clause ( capture_clause) ,
@@ -2069,6 +2092,12 @@ impl<'a> LoweringContext<'a> {
2069
2092
// Err(err) => #[allow(unreachable_code)]
2070
2093
// return Carrier::from_error(From::from(err)),
2071
2094
// }
2095
+
2096
+ // FIXME(cramertj): implement breaking to catch
2097
+ if !self . catch_scopes . is_empty ( ) {
2098
+ bug ! ( "`?` in catch scopes is unimplemented" )
2099
+ }
2100
+
2072
2101
let unstable_span = self . allow_internal_unstable ( "?" , e. span ) ;
2073
2102
2074
2103
// Carrier::translate(<expr>)
0 commit comments