@@ -15,6 +15,7 @@ use la_arena::Arena;
15
15
use once_cell:: unsync:: OnceCell ;
16
16
use profile:: Count ;
17
17
use rustc_hash:: FxHashMap ;
18
+ use smallvec:: SmallVec ;
18
19
use syntax:: {
19
20
ast:: {
20
21
self , ArrayExprKind , AstChildren , HasArgList , HasLoopBody , HasName , LiteralKind ,
@@ -30,9 +31,9 @@ use crate::{
30
31
builtin_type:: { BuiltinFloat , BuiltinInt , BuiltinUint } ,
31
32
db:: DefDatabase ,
32
33
expr:: {
33
- dummy_expr_id, Array , BindingAnnotation , ClosureKind , Expr , ExprId , FloatTypeWrapper ,
34
- Label , LabelId , Literal , MatchArm , Movability , Pat , PatId , RecordFieldPat , RecordLitField ,
35
- Statement ,
34
+ dummy_expr_id, Array , Binding , BindingAnnotation , BindingId , ClosureKind , Expr , ExprId ,
35
+ FloatTypeWrapper , Label , LabelId , Literal , MatchArm , Movability , Pat , PatId ,
36
+ RecordFieldPat , RecordLitField , Statement ,
36
37
} ,
37
38
item_scope:: BuiltinShadowMode ,
38
39
path:: { GenericArgs , Path } ,
@@ -87,6 +88,7 @@ pub(super) fn lower(
87
88
body : Body {
88
89
exprs : Arena :: default ( ) ,
89
90
pats : Arena :: default ( ) ,
91
+ bindings : Arena :: default ( ) ,
90
92
labels : Arena :: default ( ) ,
91
93
params : Vec :: new ( ) ,
92
94
body_expr : dummy_expr_id ( ) ,
@@ -116,6 +118,22 @@ struct ExprCollector<'a> {
116
118
is_lowering_generator : bool ,
117
119
}
118
120
121
+ #[ derive( Debug , Default ) ]
122
+ struct BindingList {
123
+ map : FxHashMap < Name , BindingId > ,
124
+ }
125
+
126
+ impl BindingList {
127
+ fn find (
128
+ & mut self ,
129
+ ec : & mut ExprCollector < ' _ > ,
130
+ name : Name ,
131
+ mode : BindingAnnotation ,
132
+ ) -> BindingId {
133
+ * self . map . entry ( name) . or_insert_with_key ( |n| ec. alloc_binding ( n. clone ( ) , mode) )
134
+ }
135
+ }
136
+
119
137
impl ExprCollector < ' _ > {
120
138
fn collect (
121
139
mut self ,
@@ -127,17 +145,16 @@ impl ExprCollector<'_> {
127
145
param_list. self_param ( ) . filter ( |_| attr_enabled. next ( ) . unwrap_or ( false ) )
128
146
{
129
147
let ptr = AstPtr :: new ( & self_param) ;
130
- let param_pat = self . alloc_pat (
131
- Pat :: Bind {
132
- name : name ! [ self ] ,
133
- mode : BindingAnnotation :: new (
134
- self_param. mut_token ( ) . is_some ( ) && self_param. amp_token ( ) . is_none ( ) ,
135
- false ,
136
- ) ,
137
- subpat : None ,
138
- } ,
139
- Either :: Right ( ptr) ,
148
+ let binding_id = self . alloc_binding (
149
+ name ! [ self ] ,
150
+ BindingAnnotation :: new (
151
+ self_param. mut_token ( ) . is_some ( ) && self_param. amp_token ( ) . is_none ( ) ,
152
+ false ,
153
+ ) ,
140
154
) ;
155
+ let param_pat =
156
+ self . alloc_pat ( Pat :: Bind { id : binding_id, subpat : None } , Either :: Right ( ptr) ) ;
157
+ self . add_definition_to_binding ( binding_id, param_pat) ;
141
158
self . body . params . push ( param_pat) ;
142
159
}
143
160
@@ -179,6 +196,9 @@ impl ExprCollector<'_> {
179
196
id
180
197
}
181
198
199
+ fn alloc_binding ( & mut self , name : Name , mode : BindingAnnotation ) -> BindingId {
200
+ self . body . bindings . alloc ( Binding { name, mode, definitions : SmallVec :: new ( ) } )
201
+ }
182
202
fn alloc_pat ( & mut self , pat : Pat , ptr : PatPtr ) -> PatId {
183
203
let src = self . expander . to_source ( ptr) ;
184
204
let id = self . make_pat ( pat, src. clone ( ) ) ;
@@ -804,7 +824,7 @@ impl ExprCollector<'_> {
804
824
}
805
825
806
826
fn collect_pat ( & mut self , pat : ast:: Pat ) -> PatId {
807
- let pat_id = self . collect_pat_ ( pat) ;
827
+ let pat_id = self . collect_pat_ ( pat, & mut BindingList :: default ( ) ) ;
808
828
for ( _, pats) in self . name_to_pat_grouping . drain ( ) {
809
829
let pats = Arc :: < [ _ ] > :: from ( pats) ;
810
830
self . body . or_pats . extend ( pats. iter ( ) . map ( |& pat| ( pat, pats. clone ( ) ) ) ) ;
@@ -820,16 +840,18 @@ impl ExprCollector<'_> {
820
840
}
821
841
}
822
842
823
- fn collect_pat_ ( & mut self , pat : ast:: Pat ) -> PatId {
843
+ fn collect_pat_ ( & mut self , pat : ast:: Pat , binding_list : & mut BindingList ) -> PatId {
824
844
let pattern = match & pat {
825
845
ast:: Pat :: IdentPat ( bp) => {
826
846
let name = bp. name ( ) . map ( |nr| nr. as_name ( ) ) . unwrap_or_else ( Name :: missing) ;
827
847
828
848
let key = self . is_lowering_inside_or_pat . then ( || name. clone ( ) ) ;
829
849
let annotation =
830
850
BindingAnnotation :: new ( bp. mut_token ( ) . is_some ( ) , bp. ref_token ( ) . is_some ( ) ) ;
831
- let subpat = bp. pat ( ) . map ( |subpat| self . collect_pat_ ( subpat) ) ;
832
- let pattern = if annotation == BindingAnnotation :: Unannotated && subpat. is_none ( ) {
851
+ let subpat = bp. pat ( ) . map ( |subpat| self . collect_pat_ ( subpat, binding_list) ) ;
852
+ let ( binding, pattern) = if annotation == BindingAnnotation :: Unannotated
853
+ && subpat. is_none ( )
854
+ {
833
855
// This could also be a single-segment path pattern. To
834
856
// decide that, we need to try resolving the name.
835
857
let ( resolved, _) = self . expander . def_map . resolve_path (
@@ -839,30 +861,37 @@ impl ExprCollector<'_> {
839
861
BuiltinShadowMode :: Other ,
840
862
) ;
841
863
match resolved. take_values ( ) {
842
- Some ( ModuleDefId :: ConstId ( _) ) => Pat :: Path ( name. into ( ) ) ,
864
+ Some ( ModuleDefId :: ConstId ( _) ) => ( None , Pat :: Path ( name. into ( ) ) ) ,
843
865
Some ( ModuleDefId :: EnumVariantId ( _) ) => {
844
866
// this is only really valid for unit variants, but
845
867
// shadowing other enum variants with a pattern is
846
868
// an error anyway
847
- Pat :: Path ( name. into ( ) )
869
+ ( None , Pat :: Path ( name. into ( ) ) )
848
870
}
849
871
Some ( ModuleDefId :: AdtId ( AdtId :: StructId ( s) ) )
850
872
if self . db . struct_data ( s) . variant_data . kind ( ) != StructKind :: Record =>
851
873
{
852
874
// Funnily enough, record structs *can* be shadowed
853
875
// by pattern bindings (but unit or tuple structs
854
876
// can't).
855
- Pat :: Path ( name. into ( ) )
877
+ ( None , Pat :: Path ( name. into ( ) ) )
856
878
}
857
879
// shadowing statics is an error as well, so we just ignore that case here
858
- _ => Pat :: Bind { name, mode : annotation, subpat } ,
880
+ _ => {
881
+ let id = binding_list. find ( self , name, annotation) ;
882
+ ( Some ( id) , Pat :: Bind { id, subpat } )
883
+ }
859
884
}
860
885
} else {
861
- Pat :: Bind { name, mode : annotation, subpat }
886
+ let id = binding_list. find ( self , name, annotation) ;
887
+ ( Some ( id) , Pat :: Bind { id, subpat } )
862
888
} ;
863
889
864
890
let ptr = AstPtr :: new ( & pat) ;
865
891
let pat = self . alloc_pat ( pattern, Either :: Left ( ptr) ) ;
892
+ if let Some ( binding_id) = binding {
893
+ self . add_definition_to_binding ( binding_id, pat) ;
894
+ }
866
895
if let Some ( key) = key {
867
896
self . name_to_pat_grouping . entry ( key) . or_default ( ) . push ( pat) ;
868
897
}
@@ -871,11 +900,11 @@ impl ExprCollector<'_> {
871
900
ast:: Pat :: TupleStructPat ( p) => {
872
901
let path =
873
902
p. path ( ) . and_then ( |path| self . expander . parse_path ( self . db , path) ) . map ( Box :: new) ;
874
- let ( args, ellipsis) = self . collect_tuple_pat ( p. fields ( ) ) ;
903
+ let ( args, ellipsis) = self . collect_tuple_pat ( p. fields ( ) , binding_list ) ;
875
904
Pat :: TupleStruct { path, args, ellipsis }
876
905
}
877
906
ast:: Pat :: RefPat ( p) => {
878
- let pat = self . collect_pat_opt ( p. pat ( ) ) ;
907
+ let pat = self . collect_pat_opt_ ( p. pat ( ) , binding_list ) ;
879
908
let mutability = Mutability :: from_mutable ( p. mut_token ( ) . is_some ( ) ) ;
880
909
Pat :: Ref { pat, mutability }
881
910
}
@@ -886,12 +915,12 @@ impl ExprCollector<'_> {
886
915
}
887
916
ast:: Pat :: OrPat ( p) => {
888
917
self . is_lowering_inside_or_pat = true ;
889
- let pats = p. pats ( ) . map ( |p| self . collect_pat_ ( p) ) . collect ( ) ;
918
+ let pats = p. pats ( ) . map ( |p| self . collect_pat_ ( p, binding_list ) ) . collect ( ) ;
890
919
Pat :: Or ( pats)
891
920
}
892
- ast:: Pat :: ParenPat ( p) => return self . collect_pat_opt_ ( p. pat ( ) ) ,
921
+ ast:: Pat :: ParenPat ( p) => return self . collect_pat_opt_ ( p. pat ( ) , binding_list ) ,
893
922
ast:: Pat :: TuplePat ( p) => {
894
- let ( args, ellipsis) = self . collect_tuple_pat ( p. fields ( ) ) ;
923
+ let ( args, ellipsis) = self . collect_tuple_pat ( p. fields ( ) , binding_list ) ;
895
924
Pat :: Tuple { args, ellipsis }
896
925
}
897
926
ast:: Pat :: WildcardPat ( _) => Pat :: Wild ,
@@ -904,7 +933,7 @@ impl ExprCollector<'_> {
904
933
. fields ( )
905
934
. filter_map ( |f| {
906
935
let ast_pat = f. pat ( ) ?;
907
- let pat = self . collect_pat_ ( ast_pat) ;
936
+ let pat = self . collect_pat_ ( ast_pat, binding_list ) ;
908
937
let name = f. field_name ( ) ?. as_name ( ) ;
909
938
Some ( RecordFieldPat { name, pat } )
910
939
} )
@@ -923,9 +952,15 @@ impl ExprCollector<'_> {
923
952
924
953
// FIXME properly handle `RestPat`
925
954
Pat :: Slice {
926
- prefix : prefix. into_iter ( ) . map ( |p| self . collect_pat_ ( p) ) . collect ( ) ,
927
- slice : slice. map ( |p| self . collect_pat_ ( p) ) ,
928
- suffix : suffix. into_iter ( ) . map ( |p| self . collect_pat_ ( p) ) . collect ( ) ,
955
+ prefix : prefix
956
+ . into_iter ( )
957
+ . map ( |p| self . collect_pat_ ( p, binding_list) )
958
+ . collect ( ) ,
959
+ slice : slice. map ( |p| self . collect_pat_ ( p, binding_list) ) ,
960
+ suffix : suffix
961
+ . into_iter ( )
962
+ . map ( |p| self . collect_pat_ ( p, binding_list) )
963
+ . collect ( ) ,
929
964
}
930
965
}
931
966
ast:: Pat :: LiteralPat ( lit) => {
@@ -948,7 +983,7 @@ impl ExprCollector<'_> {
948
983
Pat :: Missing
949
984
}
950
985
ast:: Pat :: BoxPat ( boxpat) => {
951
- let inner = self . collect_pat_opt_ ( boxpat. pat ( ) ) ;
986
+ let inner = self . collect_pat_opt_ ( boxpat. pat ( ) , binding_list ) ;
952
987
Pat :: Box { inner }
953
988
}
954
989
ast:: Pat :: ConstBlockPat ( const_block_pat) => {
@@ -965,7 +1000,7 @@ impl ExprCollector<'_> {
965
1000
let src = self . expander . to_source ( Either :: Left ( AstPtr :: new ( & pat) ) ) ;
966
1001
let pat =
967
1002
self . collect_macro_call ( call, macro_ptr, true , |this, expanded_pat| {
968
- this. collect_pat_opt_ ( expanded_pat)
1003
+ this. collect_pat_opt_ ( expanded_pat, binding_list )
969
1004
} ) ;
970
1005
self . source_map . pat_map . insert ( src, pat) ;
971
1006
return pat;
@@ -979,21 +1014,25 @@ impl ExprCollector<'_> {
979
1014
self . alloc_pat ( pattern, Either :: Left ( ptr) )
980
1015
}
981
1016
982
- fn collect_pat_opt_ ( & mut self , pat : Option < ast:: Pat > ) -> PatId {
1017
+ fn collect_pat_opt_ ( & mut self , pat : Option < ast:: Pat > , binding_list : & mut BindingList ) -> PatId {
983
1018
match pat {
984
- Some ( pat) => self . collect_pat_ ( pat) ,
1019
+ Some ( pat) => self . collect_pat_ ( pat, binding_list ) ,
985
1020
None => self . missing_pat ( ) ,
986
1021
}
987
1022
}
988
1023
989
- fn collect_tuple_pat ( & mut self , args : AstChildren < ast:: Pat > ) -> ( Box < [ PatId ] > , Option < usize > ) {
1024
+ fn collect_tuple_pat (
1025
+ & mut self ,
1026
+ args : AstChildren < ast:: Pat > ,
1027
+ binding_list : & mut BindingList ,
1028
+ ) -> ( Box < [ PatId ] > , Option < usize > ) {
990
1029
// Find the location of the `..`, if there is one. Note that we do not
991
1030
// consider the possibility of there being multiple `..` here.
992
1031
let ellipsis = args. clone ( ) . position ( |p| matches ! ( p, ast:: Pat :: RestPat ( _) ) ) ;
993
1032
// We want to skip the `..` pattern here, since we account for it above.
994
1033
let args = args
995
1034
. filter ( |p| !matches ! ( p, ast:: Pat :: RestPat ( _) ) )
996
- . map ( |p| self . collect_pat_ ( p) )
1035
+ . map ( |p| self . collect_pat_ ( p, binding_list ) )
997
1036
. collect ( ) ;
998
1037
999
1038
( args, ellipsis)
@@ -1022,6 +1061,10 @@ impl ExprCollector<'_> {
1022
1061
None => Some ( ( ) ) ,
1023
1062
}
1024
1063
}
1064
+
1065
+ fn add_definition_to_binding ( & mut self , binding_id : BindingId , pat_id : PatId ) {
1066
+ self . body . bindings [ binding_id] . definitions . push ( pat_id) ;
1067
+ }
1025
1068
}
1026
1069
1027
1070
impl From < ast:: LiteralKind > for Literal {
0 commit comments