@@ -992,6 +992,84 @@ fn place_from_bindings_impl<'db>(
992992 }
993993}
994994
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+
9951073/// Implementation of [`place_from_declarations`].
9961074///
9971075/// ## Implementation Note
@@ -1048,79 +1126,30 @@ fn place_from_declarations_impl<'db>(
10481126 let mut types = types. peekable ( ) ;
10491127
10501128 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) ;
10701132 }
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) ;
10791134
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+ }
10841138
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+ )
10901146 }
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+ } ,
10971150 } ;
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- } ;
11111151
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 ( ) ) )
11241153 } else {
11251154 Ok ( Place :: Unbound . into ( ) )
11261155 }
0 commit comments