@@ -992,6 +992,84 @@ fn place_from_bindings_impl<'db>(
992
992
}
993
993
}
994
994
995
+ struct PublicTypeBuilder < ' db > {
996
+ queue : Vec < TypeAndQualifiers < ' db > > ,
997
+ builder : UnionBuilder < ' db > ,
998
+ qualifiers : TypeQualifiers ,
999
+ first_type : Option < Type < ' db > > ,
1000
+ conflicting_types : Vec < Type < ' db > > ,
1001
+ }
1002
+
1003
+ impl < ' db > PublicTypeBuilder < ' db > {
1004
+ fn new ( db : & ' db dyn Db ) -> Self {
1005
+ PublicTypeBuilder {
1006
+ queue : vec ! [ ] ,
1007
+ builder : UnionBuilder :: new ( db) ,
1008
+ qualifiers : TypeQualifiers :: empty ( ) ,
1009
+ first_type : None ,
1010
+ conflicting_types : vec ! [ ] ,
1011
+ }
1012
+ }
1013
+
1014
+ fn push_element ( & mut self , db : & ' db dyn Db , element : TypeAndQualifiers < ' db > ) {
1015
+ let element_ty = element. inner_type ( ) ;
1016
+
1017
+ if let Some ( first_ty) = self . first_type {
1018
+ if !first_ty. is_equivalent_to ( db, element_ty) {
1019
+ self . conflicting_types . push ( element_ty) ;
1020
+ }
1021
+ } else {
1022
+ self . first_type = Some ( element_ty) ;
1023
+ }
1024
+
1025
+ self . builder . add_in_place ( element_ty) ;
1026
+ self . qualifiers = self . qualifiers . union ( element. qualifiers ( ) ) ;
1027
+ }
1028
+
1029
+ fn drain_queue ( & mut self , db : & ' db dyn Db ) {
1030
+ let mut queue = vec ! [ ] ;
1031
+ std:: mem:: swap ( & mut queue, & mut self . queue ) ;
1032
+ for queued_element in queue {
1033
+ self . push_element ( db, queued_element) ;
1034
+ }
1035
+ }
1036
+
1037
+ fn add ( & mut self , db : & ' db dyn Db , element : TypeAndQualifiers < ' db > ) {
1038
+ let element_type = element. inner_type ( ) ;
1039
+ match element_type {
1040
+ Type :: FunctionLiteral ( function) => {
1041
+ if function. literal ( db) . last_definition ( db) . is_overload ( db) {
1042
+ self . queue . push ( element) ;
1043
+ } else {
1044
+ self . queue . clear ( ) ;
1045
+ self . push_element ( db, element) ;
1046
+ }
1047
+ }
1048
+ _ => {
1049
+ self . drain_queue ( db) ;
1050
+ self . push_element ( db, element) ;
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ fn build ( mut self , db : & ' db dyn Db ) -> ( TypeAndQualifiers < ' db > , Box < [ Type < ' db > ] > ) {
1056
+ self . drain_queue ( db) ;
1057
+
1058
+ if !self . conflicting_types . is_empty ( ) {
1059
+ self . conflicting_types . insert (
1060
+ 0 ,
1061
+ self . first_type
1062
+ . expect ( "there must be a first type if there are conflicting types" ) ,
1063
+ ) ;
1064
+ }
1065
+
1066
+ (
1067
+ TypeAndQualifiers :: new ( self . builder . build ( ) , self . qualifiers ) ,
1068
+ self . conflicting_types . into_boxed_slice ( ) ,
1069
+ )
1070
+ }
1071
+ }
1072
+
995
1073
/// Implementation of [`place_from_declarations`].
996
1074
///
997
1075
/// ## Implementation Note
@@ -1048,79 +1126,30 @@ fn place_from_declarations_impl<'db>(
1048
1126
let mut types = types. peekable ( ) ;
1049
1127
1050
1128
if types. peek ( ) . is_some ( ) {
1051
- let mut union_elements = vec ! [ ] ;
1052
- let mut queue = vec ! [ ] ;
1053
-
1054
- for ty in types {
1055
- match ty. inner_type ( ) {
1056
- Type :: FunctionLiteral ( function) => {
1057
- if function. literal ( db) . last_definition ( db) . is_overload ( db) {
1058
- queue. push ( ty) ;
1059
- } else {
1060
- queue. clear ( ) ;
1061
- union_elements. push ( ty) ;
1062
- }
1063
- }
1064
- _ => {
1065
- union_elements. append ( & mut queue) ;
1066
-
1067
- union_elements. push ( ty) ;
1068
- }
1069
- }
1129
+ let mut builder = PublicTypeBuilder :: new ( db) ;
1130
+ for element in types {
1131
+ builder. add ( db, element) ;
1070
1132
}
1071
- union_elements. append ( & mut queue) ;
1072
- // dbg!(&union_elements);
1073
-
1074
- let mut union_elements = union_elements. into_iter ( ) ;
1075
-
1076
- let first = union_elements
1077
- . next ( )
1078
- . expect ( "At least one type must be present" ) ;
1133
+ let ( declared, conflicting) = builder. build ( db) ;
1079
1134
1080
- let mut conflicting: Vec < Type < ' db > > = vec ! [ ] ;
1081
- let declared = if let Some ( second) = union_elements. next ( ) {
1082
- let ty_first = first. inner_type ( ) ;
1083
- let mut qualifiers = first. qualifiers ( ) ;
1135
+ if !conflicting. is_empty ( ) {
1136
+ return Err ( ( declared, conflicting) ) ;
1137
+ }
1084
1138
1085
- let mut builder = UnionBuilder :: new ( db) . add ( ty_first) ;
1086
- for other in std:: iter:: once ( second) . chain ( union_elements) {
1087
- let other_ty = other. inner_type ( ) ;
1088
- if !ty_first. is_equivalent_to ( db, other_ty) {
1089
- conflicting. push ( other_ty) ;
1139
+ let boundness = match considered_definitions {
1140
+ ConsideredDefinitions :: AllReachable => Boundness :: Bound ,
1141
+ ConsideredDefinitions :: AllLiveAtUse => match undeclared_reachability {
1142
+ Truthiness :: AlwaysTrue => {
1143
+ unreachable ! (
1144
+ "If we have at least one declaration, the implicit `unbound` binding should not be definitely visible"
1145
+ )
1090
1146
}
1091
- builder = builder. add ( other_ty) ;
1092
- qualifiers = qualifiers. union ( other. qualifiers ( ) ) ;
1093
- }
1094
- TypeAndQualifiers :: new ( builder. build ( ) , qualifiers)
1095
- } else {
1096
- first
1147
+ Truthiness :: AlwaysFalse => Boundness :: Bound ,
1148
+ Truthiness :: Ambiguous => Boundness :: PossiblyUnbound ,
1149
+ } ,
1097
1150
} ;
1098
- if conflicting. is_empty ( ) {
1099
- let boundness = match considered_definitions {
1100
- ConsideredDefinitions :: AllReachable => Boundness :: Bound ,
1101
- ConsideredDefinitions :: AllLiveAtUse => match undeclared_reachability {
1102
- Truthiness :: AlwaysTrue => {
1103
- unreachable ! (
1104
- "If we have at least one declaration, the implicit `unbound` binding should not be definitely visible"
1105
- )
1106
- }
1107
- Truthiness :: AlwaysFalse => Boundness :: Bound ,
1108
- Truthiness :: Ambiguous => Boundness :: PossiblyUnbound ,
1109
- } ,
1110
- } ;
1111
1151
1112
- Ok (
1113
- Place :: Type ( declared. inner_type ( ) , boundness)
1114
- . with_qualifiers ( declared. qualifiers ( ) ) ,
1115
- )
1116
- } else {
1117
- Err ( (
1118
- declared,
1119
- std:: iter:: once ( first. inner_type ( ) )
1120
- . chain ( conflicting)
1121
- . collect ( ) ,
1122
- ) )
1123
- }
1152
+ Ok ( Place :: Type ( declared. inner_type ( ) , boundness) . with_qualifiers ( declared. qualifiers ( ) ) )
1124
1153
} else {
1125
1154
Ok ( Place :: Unbound . into ( ) )
1126
1155
}
0 commit comments