@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
88use crate :: {
99 body:: Body ,
1010 db:: DefDatabase ,
11- expr:: { Expr , ExprId , Pat , PatId , Statement } ,
11+ expr:: { Expr , ExprId , LabelId , Pat , PatId , Statement } ,
1212 BlockId , DefWithBodyId ,
1313} ;
1414
@@ -40,6 +40,7 @@ impl ScopeEntry {
4040pub struct ScopeData {
4141 parent : Option < ScopeId > ,
4242 block : Option < BlockId > ,
43+ label : Option < ( LabelId , Name ) > ,
4344 entries : Vec < ScopeEntry > ,
4445}
4546
@@ -67,6 +68,11 @@ impl ExprScopes {
6768 self . scopes [ scope] . block
6869 }
6970
71+ /// If `scope` refers to a labeled expression scope, returns the corresponding `Label`.
72+ pub fn label ( & self , scope : ScopeId ) -> Option < ( LabelId , Name ) > {
73+ self . scopes [ scope] . label . clone ( )
74+ }
75+
7076 pub fn scope_chain ( & self , scope : Option < ScopeId > ) -> impl Iterator < Item = ScopeId > + ' _ {
7177 std:: iter:: successors ( scope, move |& scope| self . scopes [ scope] . parent )
7278 }
@@ -85,15 +91,34 @@ impl ExprScopes {
8591 }
8692
8793 fn root_scope ( & mut self ) -> ScopeId {
88- self . scopes . alloc ( ScopeData { parent : None , block : None , entries : vec ! [ ] } )
94+ self . scopes . alloc ( ScopeData { parent : None , block : None , label : None , entries : vec ! [ ] } )
8995 }
9096
9197 fn new_scope ( & mut self , parent : ScopeId ) -> ScopeId {
92- self . scopes . alloc ( ScopeData { parent : Some ( parent) , block : None , entries : vec ! [ ] } )
98+ self . scopes . alloc ( ScopeData {
99+ parent : Some ( parent) ,
100+ block : None ,
101+ label : None ,
102+ entries : vec ! [ ] ,
103+ } )
93104 }
94105
95- fn new_block_scope ( & mut self , parent : ScopeId , block : BlockId ) -> ScopeId {
96- self . scopes . alloc ( ScopeData { parent : Some ( parent) , block : Some ( block) , entries : vec ! [ ] } )
106+ fn new_labeled_scope ( & mut self , parent : ScopeId , label : Option < ( LabelId , Name ) > ) -> ScopeId {
107+ self . scopes . alloc ( ScopeData { parent : Some ( parent) , block : None , label, entries : vec ! [ ] } )
108+ }
109+
110+ fn new_block_scope (
111+ & mut self ,
112+ parent : ScopeId ,
113+ block : BlockId ,
114+ label : Option < ( LabelId , Name ) > ,
115+ ) -> ScopeId {
116+ self . scopes . alloc ( ScopeData {
117+ parent : Some ( parent) ,
118+ block : Some ( block) ,
119+ label,
120+ entries : vec ! [ ] ,
121+ } )
97122 }
98123
99124 fn add_bindings ( & mut self , body : & Body , scope : ScopeId , pat : PatId ) {
@@ -144,21 +169,33 @@ fn compute_block_scopes(
144169}
145170
146171fn compute_expr_scopes ( expr : ExprId , body : & Body , scopes : & mut ExprScopes , scope : ScopeId ) {
172+ let make_label =
173+ |label : & Option < _ > | label. map ( |label| ( label, body. labels [ label] . name . clone ( ) ) ) ;
174+
147175 scopes. set_scope ( expr, scope) ;
148176 match & body[ expr] {
149- Expr :: Block { statements, tail, id, .. } => {
150- let scope = scopes. new_block_scope ( scope, * id) ;
177+ Expr :: Block { statements, tail, id, label } => {
178+ let scope = scopes. new_block_scope ( scope, * id, make_label ( label ) ) ;
151179 // Overwrite the old scope for the block expr, so that every block scope can be found
152180 // via the block itself (important for blocks that only contain items, no expressions).
153181 scopes. set_scope ( expr, scope) ;
154- compute_block_scopes ( & statements, * tail, body, scopes, scope) ;
182+ compute_block_scopes ( statements, * tail, body, scopes, scope) ;
155183 }
156- Expr :: For { iterable, pat, body : body_expr, .. } => {
184+ Expr :: For { iterable, pat, body : body_expr, label } => {
157185 compute_expr_scopes ( * iterable, body, scopes, scope) ;
158- let scope = scopes. new_scope ( scope) ;
186+ let scope = scopes. new_labeled_scope ( scope, make_label ( label ) ) ;
159187 scopes. add_bindings ( body, scope, * pat) ;
160188 compute_expr_scopes ( * body_expr, body, scopes, scope) ;
161189 }
190+ Expr :: While { condition, body : body_expr, label } => {
191+ let scope = scopes. new_labeled_scope ( scope, make_label ( label) ) ;
192+ compute_expr_scopes ( * condition, body, scopes, scope) ;
193+ compute_expr_scopes ( * body_expr, body, scopes, scope) ;
194+ }
195+ Expr :: Loop { body : body_expr, label } => {
196+ let scope = scopes. new_labeled_scope ( scope, make_label ( label) ) ;
197+ compute_expr_scopes ( * body_expr, body, scopes, scope) ;
198+ }
162199 Expr :: Lambda { args, body : body_expr, .. } => {
163200 let scope = scopes. new_scope ( scope) ;
164201 scopes. add_params_bindings ( body, scope, & args) ;
0 commit comments