@@ -15,6 +15,7 @@ use la_arena::Arena;
1515use once_cell:: unsync:: OnceCell ;
1616use profile:: Count ;
1717use rustc_hash:: FxHashMap ;
18+ use smallvec:: SmallVec ;
1819use syntax:: {
1920 ast:: {
2021 self , ArrayExprKind , AstChildren , HasArgList , HasLoopBody , HasName , LiteralKind ,
@@ -30,9 +31,9 @@ use crate::{
3031 builtin_type:: { BuiltinFloat , BuiltinInt , BuiltinUint } ,
3132 db:: DefDatabase ,
3233 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 ,
3637 } ,
3738 item_scope:: BuiltinShadowMode ,
3839 path:: { GenericArgs , Path } ,
@@ -87,6 +88,7 @@ pub(super) fn lower(
8788 body : Body {
8889 exprs : Arena :: default ( ) ,
8990 pats : Arena :: default ( ) ,
91+ bindings : Arena :: default ( ) ,
9092 labels : Arena :: default ( ) ,
9193 params : Vec :: new ( ) ,
9294 body_expr : dummy_expr_id ( ) ,
@@ -116,6 +118,22 @@ struct ExprCollector<'a> {
116118 is_lowering_generator : bool ,
117119}
118120
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+
119137impl ExprCollector < ' _ > {
120138 fn collect (
121139 mut self ,
@@ -127,17 +145,16 @@ impl ExprCollector<'_> {
127145 param_list. self_param ( ) . filter ( |_| attr_enabled. next ( ) . unwrap_or ( false ) )
128146 {
129147 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+ ) ,
140154 ) ;
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) ;
141158 self . body . params . push ( param_pat) ;
142159 }
143160
@@ -179,6 +196,9 @@ impl ExprCollector<'_> {
179196 id
180197 }
181198
199+ fn alloc_binding ( & mut self , name : Name , mode : BindingAnnotation ) -> BindingId {
200+ self . body . bindings . alloc ( Binding { name, mode, definitions : SmallVec :: new ( ) } )
201+ }
182202 fn alloc_pat ( & mut self , pat : Pat , ptr : PatPtr ) -> PatId {
183203 let src = self . expander . to_source ( ptr) ;
184204 let id = self . make_pat ( pat, src. clone ( ) ) ;
@@ -804,7 +824,7 @@ impl ExprCollector<'_> {
804824 }
805825
806826 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 ( ) ) ;
808828 for ( _, pats) in self . name_to_pat_grouping . drain ( ) {
809829 let pats = Arc :: < [ _ ] > :: from ( pats) ;
810830 self . body . or_pats . extend ( pats. iter ( ) . map ( |& pat| ( pat, pats. clone ( ) ) ) ) ;
@@ -820,16 +840,18 @@ impl ExprCollector<'_> {
820840 }
821841 }
822842
823- fn collect_pat_ ( & mut self , pat : ast:: Pat ) -> PatId {
843+ fn collect_pat_ ( & mut self , pat : ast:: Pat , binding_list : & mut BindingList ) -> PatId {
824844 let pattern = match & pat {
825845 ast:: Pat :: IdentPat ( bp) => {
826846 let name = bp. name ( ) . map ( |nr| nr. as_name ( ) ) . unwrap_or_else ( Name :: missing) ;
827847
828848 let key = self . is_lowering_inside_or_pat . then ( || name. clone ( ) ) ;
829849 let annotation =
830850 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+ {
833855 // This could also be a single-segment path pattern. To
834856 // decide that, we need to try resolving the name.
835857 let ( resolved, _) = self . expander . def_map . resolve_path (
@@ -839,30 +861,37 @@ impl ExprCollector<'_> {
839861 BuiltinShadowMode :: Other ,
840862 ) ;
841863 match resolved. take_values ( ) {
842- Some ( ModuleDefId :: ConstId ( _) ) => Pat :: Path ( name. into ( ) ) ,
864+ Some ( ModuleDefId :: ConstId ( _) ) => ( None , Pat :: Path ( name. into ( ) ) ) ,
843865 Some ( ModuleDefId :: EnumVariantId ( _) ) => {
844866 // this is only really valid for unit variants, but
845867 // shadowing other enum variants with a pattern is
846868 // an error anyway
847- Pat :: Path ( name. into ( ) )
869+ ( None , Pat :: Path ( name. into ( ) ) )
848870 }
849871 Some ( ModuleDefId :: AdtId ( AdtId :: StructId ( s) ) )
850872 if self . db . struct_data ( s) . variant_data . kind ( ) != StructKind :: Record =>
851873 {
852874 // Funnily enough, record structs *can* be shadowed
853875 // by pattern bindings (but unit or tuple structs
854876 // can't).
855- Pat :: Path ( name. into ( ) )
877+ ( None , Pat :: Path ( name. into ( ) ) )
856878 }
857879 // 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+ }
859884 }
860885 } else {
861- Pat :: Bind { name, mode : annotation, subpat }
886+ let id = binding_list. find ( self , name, annotation) ;
887+ ( Some ( id) , Pat :: Bind { id, subpat } )
862888 } ;
863889
864890 let ptr = AstPtr :: new ( & pat) ;
865891 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+ }
866895 if let Some ( key) = key {
867896 self . name_to_pat_grouping . entry ( key) . or_default ( ) . push ( pat) ;
868897 }
@@ -871,11 +900,11 @@ impl ExprCollector<'_> {
871900 ast:: Pat :: TupleStructPat ( p) => {
872901 let path =
873902 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 ) ;
875904 Pat :: TupleStruct { path, args, ellipsis }
876905 }
877906 ast:: Pat :: RefPat ( p) => {
878- let pat = self . collect_pat_opt ( p. pat ( ) ) ;
907+ let pat = self . collect_pat_opt_ ( p. pat ( ) , binding_list ) ;
879908 let mutability = Mutability :: from_mutable ( p. mut_token ( ) . is_some ( ) ) ;
880909 Pat :: Ref { pat, mutability }
881910 }
@@ -886,12 +915,12 @@ impl ExprCollector<'_> {
886915 }
887916 ast:: Pat :: OrPat ( p) => {
888917 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 ( ) ;
890919 Pat :: Or ( pats)
891920 }
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 ) ,
893922 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 ) ;
895924 Pat :: Tuple { args, ellipsis }
896925 }
897926 ast:: Pat :: WildcardPat ( _) => Pat :: Wild ,
@@ -904,7 +933,7 @@ impl ExprCollector<'_> {
904933 . fields ( )
905934 . filter_map ( |f| {
906935 let ast_pat = f. pat ( ) ?;
907- let pat = self . collect_pat_ ( ast_pat) ;
936+ let pat = self . collect_pat_ ( ast_pat, binding_list ) ;
908937 let name = f. field_name ( ) ?. as_name ( ) ;
909938 Some ( RecordFieldPat { name, pat } )
910939 } )
@@ -923,9 +952,15 @@ impl ExprCollector<'_> {
923952
924953 // FIXME properly handle `RestPat`
925954 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 ( ) ,
929964 }
930965 }
931966 ast:: Pat :: LiteralPat ( lit) => {
@@ -948,7 +983,7 @@ impl ExprCollector<'_> {
948983 Pat :: Missing
949984 }
950985 ast:: Pat :: BoxPat ( boxpat) => {
951- let inner = self . collect_pat_opt_ ( boxpat. pat ( ) ) ;
986+ let inner = self . collect_pat_opt_ ( boxpat. pat ( ) , binding_list ) ;
952987 Pat :: Box { inner }
953988 }
954989 ast:: Pat :: ConstBlockPat ( const_block_pat) => {
@@ -965,7 +1000,7 @@ impl ExprCollector<'_> {
9651000 let src = self . expander . to_source ( Either :: Left ( AstPtr :: new ( & pat) ) ) ;
9661001 let pat =
9671002 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 )
9691004 } ) ;
9701005 self . source_map . pat_map . insert ( src, pat) ;
9711006 return pat;
@@ -979,21 +1014,25 @@ impl ExprCollector<'_> {
9791014 self . alloc_pat ( pattern, Either :: Left ( ptr) )
9801015 }
9811016
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 {
9831018 match pat {
984- Some ( pat) => self . collect_pat_ ( pat) ,
1019+ Some ( pat) => self . collect_pat_ ( pat, binding_list ) ,
9851020 None => self . missing_pat ( ) ,
9861021 }
9871022 }
9881023
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 > ) {
9901029 // Find the location of the `..`, if there is one. Note that we do not
9911030 // consider the possibility of there being multiple `..` here.
9921031 let ellipsis = args. clone ( ) . position ( |p| matches ! ( p, ast:: Pat :: RestPat ( _) ) ) ;
9931032 // We want to skip the `..` pattern here, since we account for it above.
9941033 let args = args
9951034 . filter ( |p| !matches ! ( p, ast:: Pat :: RestPat ( _) ) )
996- . map ( |p| self . collect_pat_ ( p) )
1035+ . map ( |p| self . collect_pat_ ( p, binding_list ) )
9971036 . collect ( ) ;
9981037
9991038 ( args, ellipsis)
@@ -1022,6 +1061,10 @@ impl ExprCollector<'_> {
10221061 None => Some ( ( ) ) ,
10231062 }
10241063 }
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+ }
10251068}
10261069
10271070impl From < ast:: LiteralKind > for Literal {
0 commit comments