@@ -84,6 +84,7 @@ pub struct LoweringContext<'a> {
8484 trait_impls : BTreeMap < DefId , Vec < NodeId > > ,
8585 trait_default_impl : BTreeMap < DefId , NodeId > ,
8686
87+ catch_scopes : Vec < NodeId > ,
8788 loop_scopes : Vec < NodeId > ,
8889 is_in_loop_condition : bool ,
8990
@@ -123,6 +124,7 @@ pub fn lower_crate(sess: &Session,
123124 trait_impls : BTreeMap :: new ( ) ,
124125 trait_default_impl : BTreeMap :: new ( ) ,
125126 exported_macros : Vec :: new ( ) ,
127+ catch_scopes : Vec :: new ( ) ,
126128 loop_scopes : Vec :: new ( ) ,
127129 is_in_loop_condition : false ,
128130 type_def_lifetime_params : DefIdMap ( ) ,
@@ -261,6 +263,21 @@ impl<'a> LoweringContext<'a> {
261263 span
262264 }
263265
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+
264281 fn with_loop_scope < T , F > ( & mut self , loop_id : NodeId , f : F ) -> T
265282 where F : FnOnce ( & mut LoweringContext ) -> T
266283 {
@@ -295,15 +312,17 @@ impl<'a> LoweringContext<'a> {
295312 result
296313 }
297314
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
299316 where F : FnOnce ( & mut LoweringContext ) -> T
300317 {
301318 let was_in_loop_condition = self . is_in_loop_condition ;
302319 self . is_in_loop_condition = false ;
303320
321+ let catch_scopes = mem:: replace ( & mut self . catch_scopes , Vec :: new ( ) ) ;
304322 let loop_scopes = mem:: replace ( & mut self . loop_scopes , Vec :: new ( ) ) ;
305323 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;
307326
308327 self . is_in_loop_condition = was_in_loop_condition;
309328
@@ -1065,7 +1084,7 @@ impl<'a> LoweringContext<'a> {
10651084 self . record_body ( value, None ) )
10661085 }
10671086 ItemKind :: Fn ( ref decl, unsafety, constness, abi, ref generics, ref body) => {
1068- self . with_new_loop_scopes ( |this| {
1087+ self . with_new_scopes ( |this| {
10691088 let body = this. lower_block ( body) ;
10701089 let body = this. expr_block ( body, ThinVec :: new ( ) ) ;
10711090 let body_id = this. record_body ( body, Some ( decl) ) ;
@@ -1665,13 +1684,17 @@ impl<'a> LoweringContext<'a> {
16651684 this. lower_opt_sp_ident ( opt_ident) ,
16661685 hir:: LoopSource :: Loop ) )
16671686 }
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+ }
16681691 ExprKind :: Match ( ref expr, ref arms) => {
16691692 hir:: ExprMatch ( P ( self . lower_expr ( expr) ) ,
16701693 arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
16711694 hir:: MatchSource :: Normal )
16721695 }
16731696 ExprKind :: Closure ( capture_clause, ref decl, ref body, fn_decl_span) => {
1674- self . with_new_loop_scopes ( |this| {
1697+ self . with_new_scopes ( |this| {
16751698 this. with_parent_def ( e. id , |this| {
16761699 let expr = this. lower_expr ( body) ;
16771700 hir:: ExprClosure ( this. lower_capture_clause ( capture_clause) ,
@@ -2069,6 +2092,12 @@ impl<'a> LoweringContext<'a> {
20692092 // Err(err) => #[allow(unreachable_code)]
20702093 // return Carrier::from_error(From::from(err)),
20712094 // }
2095+
2096+ // FIXME(cramertj): implement breaking to catch
2097+ if !self . catch_scopes . is_empty ( ) {
2098+ bug ! ( "`?` in catch scopes is unimplemented" )
2099+ }
2100+
20722101 let unstable_span = self . allow_internal_unstable ( "?" , e. span ) ;
20732102
20742103 // Carrier::translate(<expr>)
0 commit comments