@@ -83,6 +83,7 @@ pub struct LoweringContext<'a> {
83
83
trait_impls : BTreeMap < DefId , Vec < NodeId > > ,
84
84
trait_default_impl : BTreeMap < DefId , NodeId > ,
85
85
86
+ catch_scopes : Vec < NodeId > ,
86
87
loop_scopes : Vec < NodeId > ,
87
88
is_in_loop_condition : bool ,
88
89
@@ -121,6 +122,7 @@ pub fn lower_crate(sess: &Session,
121
122
bodies : BTreeMap :: new ( ) ,
122
123
trait_impls : BTreeMap :: new ( ) ,
123
124
trait_default_impl : BTreeMap :: new ( ) ,
125
+ catch_scopes : Vec :: new ( ) ,
124
126
loop_scopes : Vec :: new ( ) ,
125
127
is_in_loop_condition : false ,
126
128
type_def_lifetime_params : DefIdMap ( ) ,
@@ -259,6 +261,21 @@ impl<'a> LoweringContext<'a> {
259
261
span
260
262
}
261
263
264
+ fn with_catch_scope < T , F > ( & mut self , catch_id : NodeId , f : F ) -> T
265
+ where F : FnOnce ( & mut LoweringContext ) -> T
266
+ {
267
+ let len = self . catch_scopes . len ( ) ;
268
+ self . catch_scopes . push ( catch_id) ;
269
+
270
+ let result = f ( self ) ;
271
+ assert_eq ! ( len + 1 , self . catch_scopes. len( ) ,
272
+ "catch scopes should be added and removed in stack order" ) ;
273
+
274
+ self . catch_scopes . pop ( ) . unwrap ( ) ;
275
+
276
+ result
277
+ }
278
+
262
279
fn with_loop_scope < T , F > ( & mut self , loop_id : NodeId , f : F ) -> T
263
280
where F : FnOnce ( & mut LoweringContext ) -> T
264
281
{
@@ -293,15 +310,17 @@ impl<'a> LoweringContext<'a> {
293
310
result
294
311
}
295
312
296
- fn with_new_loop_scopes < T , F > ( & mut self , f : F ) -> T
313
+ fn with_new_scopes < T , F > ( & mut self , f : F ) -> T
297
314
where F : FnOnce ( & mut LoweringContext ) -> T
298
315
{
299
316
let was_in_loop_condition = self . is_in_loop_condition ;
300
317
self . is_in_loop_condition = false ;
301
318
319
+ let catch_scopes = mem:: replace ( & mut self . catch_scopes , Vec :: new ( ) ) ;
302
320
let loop_scopes = mem:: replace ( & mut self . loop_scopes , Vec :: new ( ) ) ;
303
321
let result = f ( self ) ;
304
- mem:: replace ( & mut self . loop_scopes , loop_scopes) ;
322
+ self . catch_scopes = catch_scopes;
323
+ self . loop_scopes = loop_scopes;
305
324
306
325
self . is_in_loop_condition = was_in_loop_condition;
307
326
@@ -1063,7 +1082,7 @@ impl<'a> LoweringContext<'a> {
1063
1082
self . record_body ( value, None ) )
1064
1083
}
1065
1084
ItemKind :: Fn ( ref decl, unsafety, constness, abi, ref generics, ref body) => {
1066
- self . with_new_loop_scopes ( |this| {
1085
+ self . with_new_scopes ( |this| {
1067
1086
let body = this. lower_block ( body) ;
1068
1087
let body = this. expr_block ( body, ThinVec :: new ( ) ) ;
1069
1088
let body_id = this. record_body ( body, Some ( decl) ) ;
@@ -1660,13 +1679,17 @@ impl<'a> LoweringContext<'a> {
1660
1679
this. lower_opt_sp_ident ( opt_ident) ,
1661
1680
hir:: LoopSource :: Loop ) )
1662
1681
}
1682
+ ExprKind :: Catch ( ref body) => {
1683
+ // FIXME(cramertj): Add catch to HIR
1684
+ self . with_catch_scope ( e. id , |this| hir:: ExprBlock ( this. lower_block ( body) ) )
1685
+ }
1663
1686
ExprKind :: Match ( ref expr, ref arms) => {
1664
1687
hir:: ExprMatch ( P ( self . lower_expr ( expr) ) ,
1665
1688
arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
1666
1689
hir:: MatchSource :: Normal )
1667
1690
}
1668
1691
ExprKind :: Closure ( capture_clause, ref decl, ref body, fn_decl_span) => {
1669
- self . with_new_loop_scopes ( |this| {
1692
+ self . with_new_scopes ( |this| {
1670
1693
this. with_parent_def ( e. id , |this| {
1671
1694
let expr = this. lower_expr ( body) ;
1672
1695
hir:: ExprClosure ( this. lower_capture_clause ( capture_clause) ,
@@ -2064,6 +2087,12 @@ impl<'a> LoweringContext<'a> {
2064
2087
// Err(err) => #[allow(unreachable_code)]
2065
2088
// return Carrier::from_error(From::from(err)),
2066
2089
// }
2090
+
2091
+ // FIXME(cramertj): implement breaking to catch
2092
+ if !self . catch_scopes . is_empty ( ) {
2093
+ bug ! ( "`?` in catch scopes is unimplemented" )
2094
+ }
2095
+
2067
2096
let unstable_span = self . allow_internal_unstable ( "?" , e. span ) ;
2068
2097
2069
2098
// Carrier::translate(<expr>)
0 commit comments