@@ -50,6 +50,7 @@ use util::nodemap::{DefIdMap, NodeMap, FxHashMap};
50
50
51
51
use std:: collections:: BTreeMap ;
52
52
use std:: iter;
53
+ use std:: mem;
53
54
54
55
use syntax:: attr;
55
56
use syntax:: ast:: * ;
@@ -79,6 +80,8 @@ pub struct LoweringContext<'a> {
79
80
impl_items : BTreeMap < hir:: ImplItemId , hir:: ImplItem > ,
80
81
bodies : FxHashMap < hir:: BodyId , hir:: Body > ,
81
82
83
+ loop_scopes : Vec < NodeId > ,
84
+
82
85
type_def_lifetime_params : DefIdMap < usize > ,
83
86
}
84
87
@@ -112,6 +115,7 @@ pub fn lower_crate(sess: &Session,
112
115
trait_items : BTreeMap :: new ( ) ,
113
116
impl_items : BTreeMap :: new ( ) ,
114
117
bodies : FxHashMap ( ) ,
118
+ loop_scopes : Vec :: new ( ) ,
115
119
type_def_lifetime_params : DefIdMap ( ) ,
116
120
} . lower_crate ( krate)
117
121
}
@@ -244,6 +248,27 @@ impl<'a> LoweringContext<'a> {
244
248
span
245
249
}
246
250
251
+ fn with_loop_scope < T , F > ( & mut self , loop_id : NodeId , f : F ) -> T
252
+ where F : FnOnce ( & mut LoweringContext ) -> T
253
+ {
254
+ let len = self . loop_scopes . len ( ) ;
255
+ self . loop_scopes . push ( loop_id) ;
256
+ let result = f ( self ) ;
257
+ assert_eq ! ( len + 1 , self . loop_scopes. len( ) ,
258
+ "Loop scopes should be added and removed in stack order" ) ;
259
+ self . loop_scopes . pop ( ) . unwrap ( ) ;
260
+ result
261
+ }
262
+
263
+ fn with_new_loop_scopes < T , F > ( & mut self , f : F ) -> T
264
+ where F : FnOnce ( & mut LoweringContext ) -> T
265
+ {
266
+ let loop_scopes = mem:: replace ( & mut self . loop_scopes , Vec :: new ( ) ) ;
267
+ let result = f ( self ) ;
268
+ mem:: replace ( & mut self . loop_scopes , loop_scopes) ;
269
+ result
270
+ }
271
+
247
272
fn with_parent_def < T , F > ( & mut self , parent_id : NodeId , f : F ) -> T
248
273
where F : FnOnce ( & mut LoweringContext ) -> T
249
274
{
@@ -271,17 +296,23 @@ impl<'a> LoweringContext<'a> {
271
296
o_id. map ( |sp_ident| respan ( sp_ident. span , sp_ident. node . name ) )
272
297
}
273
298
274
- fn lower_label ( & mut self , id : NodeId , label : Option < Spanned < Ident > > ) -> Option < hir:: Label > {
275
- label. map ( |sp_ident| {
276
- hir:: Label {
277
- span : sp_ident. span ,
278
- name : sp_ident. node . name ,
299
+ fn lower_label ( & mut self , label : Option < ( NodeId , Spanned < Ident > ) > ) -> hir:: Label {
300
+ match label {
301
+ Some ( ( id, label_ident) ) => hir:: Label {
302
+ ident : Some ( label_ident) ,
279
303
loop_id : match self . expect_full_def ( id) {
280
304
Def :: Label ( loop_id) => loop_id,
281
305
_ => DUMMY_NODE_ID
282
306
}
307
+ } ,
308
+ None => hir:: Label {
309
+ ident : None ,
310
+ loop_id : match self . loop_scopes . last ( ) {
311
+ Some ( innermost_loop_id) => * innermost_loop_id,
312
+ _ => DUMMY_NODE_ID
313
+ }
283
314
}
284
- } )
315
+ }
285
316
}
286
317
287
318
fn lower_attrs ( & mut self , attrs : & Vec < Attribute > ) -> hir:: HirVec < Attribute > {
@@ -992,15 +1023,17 @@ impl<'a> LoweringContext<'a> {
992
1023
self . record_body ( value, None ) )
993
1024
}
994
1025
ItemKind :: Fn ( ref decl, unsafety, constness, abi, ref generics, ref body) => {
995
- let body = self . lower_block ( body) ;
996
- let body = self . expr_block ( body, ThinVec :: new ( ) ) ;
997
- let body_id = self . record_body ( body, Some ( decl) ) ;
998
- hir:: ItemFn ( self . lower_fn_decl ( decl) ,
999
- self . lower_unsafety ( unsafety) ,
1000
- self . lower_constness ( constness) ,
1001
- abi,
1002
- self . lower_generics ( generics) ,
1003
- body_id)
1026
+ self . with_new_loop_scopes ( |this| {
1027
+ let body = this. lower_block ( body) ;
1028
+ let body = this. expr_block ( body, ThinVec :: new ( ) ) ;
1029
+ let body_id = this. record_body ( body, Some ( decl) ) ;
1030
+ hir:: ItemFn ( this. lower_fn_decl ( decl) ,
1031
+ this. lower_unsafety ( unsafety) ,
1032
+ this. lower_constness ( constness) ,
1033
+ abi,
1034
+ this. lower_generics ( generics) ,
1035
+ body_id)
1036
+ } )
1004
1037
}
1005
1038
ItemKind :: Mod ( ref m) => hir:: ItemMod ( self . lower_mod ( m) ) ,
1006
1039
ItemKind :: ForeignMod ( ref nm) => hir:: ItemForeignMod ( self . lower_foreign_mod ( nm) ) ,
@@ -1562,26 +1595,32 @@ impl<'a> LoweringContext<'a> {
1562
1595
hir:: ExprIf ( P ( self . lower_expr ( cond) ) , self . lower_block ( blk) , else_opt)
1563
1596
}
1564
1597
ExprKind :: While ( ref cond, ref body, opt_ident) => {
1565
- hir:: ExprWhile ( P ( self . lower_expr ( cond) ) , self . lower_block ( body) ,
1566
- self . lower_opt_sp_ident ( opt_ident) )
1598
+ self . with_loop_scope ( e. id , |this|
1599
+ hir:: ExprWhile (
1600
+ P ( this. lower_expr ( cond) ) ,
1601
+ this. lower_block ( body) ,
1602
+ this. lower_opt_sp_ident ( opt_ident) ) )
1567
1603
}
1568
1604
ExprKind :: Loop ( ref body, opt_ident) => {
1569
- hir:: ExprLoop ( self . lower_block ( body) ,
1570
- self . lower_opt_sp_ident ( opt_ident) ,
1571
- hir:: LoopSource :: Loop )
1605
+ self . with_loop_scope ( e. id , |this|
1606
+ hir:: ExprLoop ( this. lower_block ( body) ,
1607
+ this. lower_opt_sp_ident ( opt_ident) ,
1608
+ hir:: LoopSource :: Loop ) )
1572
1609
}
1573
1610
ExprKind :: Match ( ref expr, ref arms) => {
1574
1611
hir:: ExprMatch ( P ( self . lower_expr ( expr) ) ,
1575
1612
arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
1576
1613
hir:: MatchSource :: Normal )
1577
1614
}
1578
1615
ExprKind :: Closure ( capture_clause, ref decl, ref body, fn_decl_span) => {
1579
- self . with_parent_def ( e. id , |this| {
1580
- let expr = this. lower_expr ( body) ;
1581
- hir:: ExprClosure ( this. lower_capture_clause ( capture_clause) ,
1582
- this. lower_fn_decl ( decl) ,
1583
- this. record_body ( expr, Some ( decl) ) ,
1584
- fn_decl_span)
1616
+ self . with_new_loop_scopes ( |this| {
1617
+ this. with_parent_def ( e. id , |this| {
1618
+ let expr = this. lower_expr ( body) ;
1619
+ hir:: ExprClosure ( this. lower_capture_clause ( capture_clause) ,
1620
+ this. lower_fn_decl ( decl) ,
1621
+ this. record_body ( expr, Some ( decl) ) ,
1622
+ fn_decl_span)
1623
+ } )
1585
1624
} )
1586
1625
}
1587
1626
ExprKind :: Block ( ref blk) => hir:: ExprBlock ( self . lower_block ( blk) ) ,
@@ -1660,10 +1699,13 @@ impl<'a> LoweringContext<'a> {
1660
1699
hir:: ExprPath ( self . lower_qpath ( e. id , qself, path, ParamMode :: Optional ) )
1661
1700
}
1662
1701
ExprKind :: Break ( opt_ident, ref opt_expr) => {
1663
- hir:: ExprBreak ( self . lower_label ( e. id , opt_ident) ,
1702
+ hir:: ExprBreak (
1703
+ self . lower_label ( opt_ident. map ( |ident| ( e. id , ident) ) ) ,
1664
1704
opt_expr. as_ref ( ) . map ( |x| P ( self . lower_expr ( x) ) ) )
1665
1705
}
1666
- ExprKind :: Continue ( opt_ident) => hir:: ExprAgain ( self . lower_label ( e. id , opt_ident) ) ,
1706
+ ExprKind :: Continue ( opt_ident) =>
1707
+ hir:: ExprAgain (
1708
+ self . lower_label ( opt_ident. map ( |ident| ( e. id , ident) ) ) ) ,
1667
1709
ExprKind :: Ret ( ref e) => hir:: ExprRet ( e. as_ref ( ) . map ( |x| P ( self . lower_expr ( x) ) ) ) ,
1668
1710
ExprKind :: InlineAsm ( ref asm) => {
1669
1711
let hir_asm = hir:: InlineAsm {
@@ -1804,9 +1846,14 @@ impl<'a> LoweringContext<'a> {
1804
1846
// }
1805
1847
// }
1806
1848
1849
+ let ( body, break_expr, sub_expr) = self . with_loop_scope ( e. id , |this| (
1850
+ this. lower_block ( body) ,
1851
+ this. expr_break ( e. span , ThinVec :: new ( ) ) ,
1852
+ P ( this. lower_expr ( sub_expr) ) ,
1853
+ ) ) ;
1854
+
1807
1855
// `<pat> => <body>`
1808
1856
let pat_arm = {
1809
- let body = self . lower_block ( body) ;
1810
1857
let body_expr = P ( self . expr_block ( body, ThinVec :: new ( ) ) ) ;
1811
1858
let pat = self . lower_pat ( pat) ;
1812
1859
self . arm ( hir_vec ! [ pat] , body_expr)
@@ -1815,13 +1862,11 @@ impl<'a> LoweringContext<'a> {
1815
1862
// `_ => break`
1816
1863
let break_arm = {
1817
1864
let pat_under = self . pat_wild ( e. span ) ;
1818
- let break_expr = self . expr_break ( e. span , ThinVec :: new ( ) ) ;
1819
1865
self . arm ( hir_vec ! [ pat_under] , break_expr)
1820
1866
} ;
1821
1867
1822
1868
// `match <sub_expr> { ... }`
1823
1869
let arms = hir_vec ! [ pat_arm, break_arm] ;
1824
- let sub_expr = P ( self . lower_expr ( sub_expr) ) ;
1825
1870
let match_expr = self . expr ( e. span ,
1826
1871
hir:: ExprMatch ( sub_expr,
1827
1872
arms,
@@ -1863,7 +1908,7 @@ impl<'a> LoweringContext<'a> {
1863
1908
1864
1909
// `::std::option::Option::Some(<pat>) => <body>`
1865
1910
let pat_arm = {
1866
- let body_block = self . lower_block ( body) ;
1911
+ let body_block = self . with_loop_scope ( e . id , |this| this . lower_block ( body) ) ;
1867
1912
let body_expr = P ( self . expr_block ( body_block, ThinVec :: new ( ) ) ) ;
1868
1913
let pat = self . lower_pat ( pat) ;
1869
1914
let some_pat = self . pat_some ( e. span , pat) ;
@@ -1873,7 +1918,8 @@ impl<'a> LoweringContext<'a> {
1873
1918
1874
1919
// `::std::option::Option::None => break`
1875
1920
let break_arm = {
1876
- let break_expr = self . expr_break ( e. span , ThinVec :: new ( ) ) ;
1921
+ let break_expr = self . with_loop_scope ( e. id , |this|
1922
+ this. expr_break ( e. span , ThinVec :: new ( ) ) ) ;
1877
1923
let pat = self . pat_none ( e. span ) ;
1878
1924
self . arm ( hir_vec ! [ pat] , break_expr)
1879
1925
} ;
@@ -2151,7 +2197,8 @@ impl<'a> LoweringContext<'a> {
2151
2197
}
2152
2198
2153
2199
fn expr_break ( & mut self , span : Span , attrs : ThinVec < Attribute > ) -> P < hir:: Expr > {
2154
- P ( self . expr ( span, hir:: ExprBreak ( None , None ) , attrs) )
2200
+ let expr_break = hir:: ExprBreak ( self . lower_label ( None ) , None ) ;
2201
+ P ( self . expr ( span, expr_break, attrs) )
2155
2202
}
2156
2203
2157
2204
fn expr_call ( & mut self , span : Span , e : P < hir:: Expr > , args : hir:: HirVec < hir:: Expr > )
0 commit comments