@@ -83,6 +83,7 @@ pub struct LoweringContext<'a> {
8383 trait_impls : BTreeMap < DefId , Vec < NodeId > > ,
8484 trait_default_impl : BTreeMap < DefId , NodeId > ,
8585
86+ catch_scopes : Vec < NodeId > ,
8687 loop_scopes : Vec < NodeId > ,
8788 is_in_loop_condition : bool ,
8889
@@ -121,6 +122,7 @@ pub fn lower_crate(sess: &Session,
121122 bodies : BTreeMap :: new ( ) ,
122123 trait_impls : BTreeMap :: new ( ) ,
123124 trait_default_impl : BTreeMap :: new ( ) ,
125+ catch_scopes : Vec :: new ( ) ,
124126 loop_scopes : Vec :: new ( ) ,
125127 is_in_loop_condition : false ,
126128 type_def_lifetime_params : DefIdMap ( ) ,
@@ -259,6 +261,21 @@ impl<'a> LoweringContext<'a> {
259261 span
260262 }
261263
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+
262279 fn with_loop_scope < T , F > ( & mut self , loop_id : NodeId , f : F ) -> T
263280 where F : FnOnce ( & mut LoweringContext ) -> T
264281 {
@@ -293,15 +310,17 @@ impl<'a> LoweringContext<'a> {
293310 result
294311 }
295312
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
297314 where F : FnOnce ( & mut LoweringContext ) -> T
298315 {
299316 let was_in_loop_condition = self . is_in_loop_condition ;
300317 self . is_in_loop_condition = false ;
301318
319+ let catch_scopes = mem:: replace ( & mut self . catch_scopes , Vec :: new ( ) ) ;
302320 let loop_scopes = mem:: replace ( & mut self . loop_scopes , Vec :: new ( ) ) ;
303321 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;
305324
306325 self . is_in_loop_condition = was_in_loop_condition;
307326
@@ -1063,7 +1082,7 @@ impl<'a> LoweringContext<'a> {
10631082 self . record_body ( value, None ) )
10641083 }
10651084 ItemKind :: Fn ( ref decl, unsafety, constness, abi, ref generics, ref body) => {
1066- self . with_new_loop_scopes ( |this| {
1085+ self . with_new_scopes ( |this| {
10671086 let body = this. lower_block ( body) ;
10681087 let body = this. expr_block ( body, ThinVec :: new ( ) ) ;
10691088 let body_id = this. record_body ( body, Some ( decl) ) ;
@@ -1660,13 +1679,17 @@ impl<'a> LoweringContext<'a> {
16601679 this. lower_opt_sp_ident ( opt_ident) ,
16611680 hir:: LoopSource :: Loop ) )
16621681 }
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+ }
16631686 ExprKind :: Match ( ref expr, ref arms) => {
16641687 hir:: ExprMatch ( P ( self . lower_expr ( expr) ) ,
16651688 arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
16661689 hir:: MatchSource :: Normal )
16671690 }
16681691 ExprKind :: Closure ( capture_clause, ref decl, ref body, fn_decl_span) => {
1669- self . with_new_loop_scopes ( |this| {
1692+ self . with_new_scopes ( |this| {
16701693 this. with_parent_def ( e. id , |this| {
16711694 let expr = this. lower_expr ( body) ;
16721695 hir:: ExprClosure ( this. lower_capture_clause ( capture_clause) ,
@@ -2064,6 +2087,12 @@ impl<'a> LoweringContext<'a> {
20642087 // Err(err) => #[allow(unreachable_code)]
20652088 // return Carrier::from_error(From::from(err)),
20662089 // }
2090+
2091+ // FIXME(cramertj): implement breaking to catch
2092+ if !self . catch_scopes . is_empty ( ) {
2093+ bug ! ( "`?` in catch scopes is unimplemented" )
2094+ }
2095+
20672096 let unstable_span = self . allow_internal_unstable ( "?" , e. span ) ;
20682097
20692098 // Carrier::translate(<expr>)
0 commit comments