@@ -941,7 +941,15 @@ fn place_from_bindings_impl<'db>(
941
941
942
942
if let Some ( first) = types. next ( ) {
943
943
let ty = if let Some ( second) = types. next ( ) {
944
- UnionType :: from_elements ( db, [ first, second] . into_iter ( ) . chain ( types) )
944
+ let mut builder = PublicTypeBuilder :: new ( db) ;
945
+ builder. add ( first) ;
946
+ builder. add ( second) ;
947
+
948
+ for ty in types {
949
+ builder. add ( ty) ;
950
+ }
951
+
952
+ builder. build ( )
945
953
} else {
946
954
first
947
955
} ;
@@ -969,73 +977,103 @@ fn place_from_bindings_impl<'db>(
969
977
}
970
978
}
971
979
972
- /// Accumulates multiple (potentially conflicting) declared types and type qualifiers,
973
- /// and eventually builds a union from them.
980
+ /// Accumulates types from multiple bindings or declarations, and eventually builds a
981
+ /// union type from them.
974
982
///
975
983
/// `@overload`ed function literal types are discarded if they are immediately followed
976
984
/// by their implementation. This is to ensure that we do not merge all of them into the
977
985
/// union type. The last one will include the other overloads already.
978
986
struct PublicTypeBuilder < ' db > {
979
- queue : Option < TypeAndQualifiers < ' db > > ,
987
+ db : & ' db dyn Db ,
988
+ queue : Option < Type < ' db > > ,
980
989
builder : UnionBuilder < ' db > ,
981
- qualifiers : TypeQualifiers ,
982
- first_type : Option < Type < ' db > > ,
983
- conflicting_types : FxOrderSet < Type < ' db > > ,
984
990
}
985
991
986
992
impl < ' db > PublicTypeBuilder < ' db > {
987
993
fn new ( db : & ' db dyn Db ) -> Self {
988
994
PublicTypeBuilder {
995
+ db,
989
996
queue : None ,
990
997
builder : UnionBuilder :: new ( db) ,
991
- qualifiers : TypeQualifiers :: empty ( ) ,
992
- first_type : None ,
993
- conflicting_types : FxOrderSet :: default ( ) ,
994
998
}
995
999
}
996
1000
997
- fn push_element ( & mut self , db : & ' db dyn Db , element : TypeAndQualifiers < ' db > ) {
998
- let element_ty = element. inner_type ( ) ;
999
-
1000
- if let Some ( first_ty) = self . first_type {
1001
- if !first_ty. is_equivalent_to ( db, element_ty) {
1002
- self . conflicting_types . insert ( element_ty) ;
1003
- }
1004
- } else {
1005
- self . first_type = Some ( element_ty) ;
1006
- }
1007
-
1008
- self . builder . add_in_place ( element_ty) ;
1009
- self . qualifiers = self . qualifiers . union ( element. qualifiers ( ) ) ;
1001
+ fn add_to_union ( & mut self , element : Type < ' db > ) {
1002
+ self . builder . add_in_place ( element) ;
1010
1003
}
1011
1004
1012
- fn drain_queue ( & mut self , db : & ' db dyn Db ) {
1005
+ fn drain_queue ( & mut self ) {
1013
1006
if let Some ( queued_element) = self . queue . take ( ) {
1014
- self . push_element ( db , queued_element) ;
1007
+ self . add_to_union ( queued_element) ;
1015
1008
}
1016
1009
}
1017
1010
1018
- fn add ( & mut self , db : & ' db dyn Db , element : TypeAndQualifiers < ' db > ) {
1019
- let element_type = element. inner_type ( ) ;
1020
- match element_type {
1011
+ fn add ( & mut self , element : Type < ' db > ) -> bool {
1012
+ match element {
1021
1013
Type :: FunctionLiteral ( function) => {
1022
- if function. literal ( db) . last_definition ( db) . is_overload ( db) {
1014
+ if function
1015
+ . literal ( self . db )
1016
+ . last_definition ( self . db )
1017
+ . is_overload ( self . db )
1018
+ {
1023
1019
self . queue = Some ( element) ;
1020
+ false
1024
1021
} else {
1025
1022
self . queue = None ;
1026
- self . push_element ( db, element) ;
1023
+ self . add_to_union ( element) ;
1024
+ true
1027
1025
}
1028
1026
}
1029
1027
_ => {
1030
- self . drain_queue ( db) ;
1031
- self . push_element ( db, element) ;
1028
+ self . drain_queue ( ) ;
1029
+ self . add_to_union ( element) ;
1030
+ true
1032
1031
}
1033
1032
}
1034
1033
}
1035
1034
1036
- fn build ( mut self , db : & ' db dyn Db ) -> DeclaredTypeAndConflictingTypes < ' db > {
1037
- self . drain_queue ( db) ;
1035
+ fn build ( mut self ) -> Type < ' db > {
1036
+ self . drain_queue ( ) ;
1037
+ self . builder . build ( )
1038
+ }
1039
+ }
1040
+
1041
+ /// Accumulates multiple (potentially conflicting) declared types and type qualifiers,
1042
+ /// and eventually builds a union from them.
1043
+ struct DeclaredTypeBuilder < ' db > {
1044
+ inner : PublicTypeBuilder < ' db > ,
1045
+ qualifiers : TypeQualifiers ,
1046
+ first_type : Option < Type < ' db > > ,
1047
+ conflicting_types : FxOrderSet < Type < ' db > > ,
1048
+ }
1049
+
1050
+ impl < ' db > DeclaredTypeBuilder < ' db > {
1051
+ fn new ( db : & ' db dyn Db ) -> Self {
1052
+ DeclaredTypeBuilder {
1053
+ inner : PublicTypeBuilder :: new ( db) ,
1054
+ qualifiers : TypeQualifiers :: empty ( ) ,
1055
+ first_type : None ,
1056
+ conflicting_types : FxOrderSet :: default ( ) ,
1057
+ }
1058
+ }
1059
+
1060
+ fn add ( & mut self , element : TypeAndQualifiers < ' db > ) {
1061
+ let element_ty = element. inner_type ( ) ;
1062
+
1063
+ if self . inner . add ( element_ty) {
1064
+ if let Some ( first_ty) = self . first_type {
1065
+ if !first_ty. is_equivalent_to ( self . inner . db , element_ty) {
1066
+ self . conflicting_types . insert ( element_ty) ;
1067
+ }
1068
+ } else {
1069
+ self . first_type = Some ( element_ty) ;
1070
+ }
1071
+ }
1072
+
1073
+ self . qualifiers = self . qualifiers . union ( element. qualifiers ( ) ) ;
1074
+ }
1038
1075
1076
+ fn build ( mut self ) -> DeclaredTypeAndConflictingTypes < ' db > {
1039
1077
if !self . conflicting_types . is_empty ( ) {
1040
1078
self . conflicting_types . insert_before (
1041
1079
0 ,
@@ -1045,7 +1083,7 @@ impl<'db> PublicTypeBuilder<'db> {
1045
1083
}
1046
1084
1047
1085
(
1048
- TypeAndQualifiers :: new ( self . builder . build ( ) , self . qualifiers ) ,
1086
+ TypeAndQualifiers :: new ( self . inner . build ( ) , self . qualifiers ) ,
1049
1087
self . conflicting_types . into_boxed_slice ( ) ,
1050
1088
)
1051
1089
}
@@ -1112,11 +1150,11 @@ fn place_from_declarations_impl<'db>(
1112
1150
let mut types = types. peekable ( ) ;
1113
1151
1114
1152
if types. peek ( ) . is_some ( ) {
1115
- let mut builder = PublicTypeBuilder :: new ( db) ;
1153
+ let mut builder = DeclaredTypeBuilder :: new ( db) ;
1116
1154
for element in types {
1117
- builder. add ( db , element) ;
1155
+ builder. add ( element) ;
1118
1156
}
1119
- let ( declared, conflicting) = builder. build ( db ) ;
1157
+ let ( declared, conflicting) = builder. build ( ) ;
1120
1158
1121
1159
if !conflicting. is_empty ( ) {
1122
1160
return Err ( ( declared, conflicting) ) ;
0 commit comments