Skip to content

Commit 918d0c6

Browse files
authored
Merge pull request swiftlang#11913 from rudkx/join
Start implementing a more complete Type::join.
2 parents 7e37ac2 + 20a4ecf commit 918d0c6

File tree

1 file changed

+166
-69
lines changed

1 file changed

+166
-69
lines changed

lib/AST/TypeJoinMeet.cpp

Lines changed: 166 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -17,100 +17,197 @@
1717
#include "swift/AST/ASTContext.h"
1818
#include "swift/AST/Decl.h"
1919
#include "swift/AST/Type.h"
20+
#include "swift/AST/TypeVisitor.h"
2021
#include "swift/AST/Types.h"
2122
#include "llvm/ADT/SmallPtrSet.h"
2223
using namespace swift;
2324

24-
Type Type::join(Type type1, Type type2) {
25-
assert(!type1->hasTypeVariable() && !type2->hasTypeVariable() &&
26-
"Cannot compute join of types involving type variables");
27-
28-
assert(type1->getWithoutSpecifierType()->isEqual(type1) &&
29-
"Expected simple type!");
30-
assert(type2->getWithoutSpecifierType()->isEqual(type2) &&
31-
"Expected simple type!");
32-
33-
// FIXME: This algorithm is woefully incomplete, and is only currently used
34-
// for optimizing away extra exploratory work in the constraint solver. It
35-
// should eventually encompass all of the subtyping rules of the language.
36-
37-
// If the types are equivalent, the join is obvious.
38-
if (type1->isEqual(type2))
39-
return type1;
40-
41-
// If both are class metatypes, compute the join of the instance type and
42-
// wrap the result in a metatype.
43-
if (auto *metatype1 = type1->getAs<MetatypeType>()) {
44-
if (auto *metatype2 = type2->getAs<MetatypeType>()) {
45-
auto instance1 = metatype1->getInstanceType();
46-
auto instance2 = metatype2->getInstanceType();
47-
if (instance1->mayHaveSuperclass() &&
48-
instance2->mayHaveSuperclass()) {
49-
auto result = Type::join(instance1, instance2);
50-
if (!result)
51-
return result;
52-
return MetatypeType::get(result);
53-
}
54-
}
25+
// FIXME: This is currently woefully incomplete, and is only currently
26+
// used for optimizing away extra exploratory work in the constraint
27+
// solver. It should eventually encompass all of the subtyping rules
28+
// of the language.
29+
struct TypeJoin : TypeVisitor<TypeJoin, Type> {
30+
Type First;
31+
32+
TypeJoin(Type First) : First(First) {
33+
assert(First && "Unexpected null type!");
5534
}
5635

57-
// If both are existential metatypes, compute the join of the instance type
58-
// and wrap the result in an existential metatype.
59-
if (auto *metatype1 = type1->getAs<ExistentialMetatypeType>()) {
60-
if (auto *metatype2 = type2->getAs<ExistentialMetatypeType>()) {
61-
auto instance1 = metatype1->getInstanceType();
62-
auto instance2 = metatype2->getInstanceType();
63-
auto result = Type::join(instance1, instance2);
64-
if (!result)
65-
return result;
66-
return ExistentialMetatypeType::get(result);
67-
}
36+
static Type getSuperclassJoin(Type first, Type second);
37+
38+
Type visitClassType(Type second);
39+
Type visitBoundGenericClassType(Type second);
40+
Type visitArchetypeType(Type second);
41+
Type visitDynamicSelfType(Type second);
42+
Type visitMetatypeType(Type second);
43+
Type visitExistentialMetatypeType(Type second);
44+
Type visitBoundGenericEnumType(Type second);
45+
46+
Type visitOptionalType(Type second);
47+
48+
Type visitType(Type second) {
49+
// FIXME: Implement all the visitors.
50+
// llvm_unreachable("Unimplemented type visitor!");
51+
// return First->getASTContext().TheAnyType;
52+
return nullptr;
6853
}
6954

70-
// If both are class types or opaque types that potentially have superclasses,
71-
// find the common superclass.
72-
if (type1->mayHaveSuperclass() && type2->mayHaveSuperclass()) {
73-
/// Walk the superclasses of type1 looking for type2. Record them for our
74-
/// second step.
75-
llvm::SmallPtrSet<CanType, 8> superclassesOfType1;
76-
CanType canType2 = type2->getCanonicalType();
77-
for (Type super1 = type1; super1; super1 = super1->getSuperclass()) {
78-
CanType canSuper1 = super1->getCanonicalType();
55+
public:
56+
static Type join(Type first, Type second) {
57+
if (!first || !second) {
58+
if (first)
59+
return ErrorType::get(first->getASTContext());
7960

80-
// If we have found the second type, we're done.
81-
if (canSuper1 == canType2) return super1;
61+
if (second)
62+
return ErrorType::get(second->getASTContext());
8263

83-
superclassesOfType1.insert(canSuper1);
64+
return Type();
8465
}
8566

86-
// Look through the superclasses of type2 to determine if any were also
87-
// superclasses of type1.
88-
for (Type super2 = type2; super2; super2 = super2->getSuperclass()) {
89-
CanType canSuper2 = super2->getCanonicalType();
67+
assert(!first->hasTypeVariable() && !second->hasTypeVariable() &&
68+
"Cannot compute join of types involving type variables");
9069

91-
// If we found the first type, we're done.
92-
if (superclassesOfType1.count(canSuper2)) return super2;
93-
}
70+
assert(first->getWithoutSpecifierType()->isEqual(first) &&
71+
"Expected simple type!");
72+
assert(second->getWithoutSpecifierType()->isEqual(second) &&
73+
"Expected simple type!");
74+
75+
// If the types are equivalent, the join is obvious.
76+
if (first->isEqual(second))
77+
return first;
9478

95-
// There is no common superclass; we're done.
79+
// Until we handle all the combinations of joins, we need to make
80+
// sure we visit the optional side.
81+
OptionalTypeKind otk;
82+
if (second->getAnyOptionalObjectType(otk))
83+
return TypeJoin(first).visit(second);
84+
85+
return TypeJoin(second).visit(first);
86+
}
87+
};
88+
89+
Type TypeJoin::getSuperclassJoin(Type first, Type second) {
90+
if (!first || !second)
91+
return TypeJoin::join(first, second);
92+
93+
// FIXME: Return Any
94+
if (!first->mayHaveSuperclass() || !second->mayHaveSuperclass())
9695
return nullptr;
96+
97+
/// Walk the superclasses of `first` looking for `second`. Record them
98+
/// for our second step.
99+
llvm::SmallPtrSet<CanType, 8> superclassesOfFirst;
100+
CanType canSecond = second->getCanonicalType();
101+
for (Type super = first; super; super = super->getSuperclass()) {
102+
CanType canSuper = super->getCanonicalType();
103+
104+
// If we have found the second type, we're done.
105+
if (canSuper == canSecond) return super;
106+
107+
superclassesOfFirst.insert(canSuper);
97108
}
98109

99-
// If one or both of the types are optional types, look at the underlying
100-
// object type.
110+
// Look through the superclasses of second to determine if any were also
111+
// superclasses of first.
112+
for (Type super = second; super; super = super->getSuperclass()) {
113+
CanType canSuper = super->getCanonicalType();
114+
115+
// If we found the first type, we're done.
116+
if (superclassesOfFirst.count(canSuper)) return super;
117+
}
118+
119+
// FIXME: Return Any
120+
// There is no common superclass; we're done.
121+
return nullptr;
122+
}
123+
124+
Type TypeJoin::visitClassType(Type second) {
125+
return getSuperclassJoin(First, second);
126+
}
127+
128+
Type TypeJoin::visitBoundGenericClassType(Type second) {
129+
return getSuperclassJoin(First, second);
130+
}
131+
132+
Type TypeJoin::visitArchetypeType(Type second) {
133+
return getSuperclassJoin(First, second);
134+
}
135+
136+
Type TypeJoin::visitDynamicSelfType(Type second) {
137+
return getSuperclassJoin(First, second);
138+
}
139+
140+
Type TypeJoin::visitMetatypeType(Type second) {
141+
assert(!First->mayHaveSuperclass() && !second->mayHaveSuperclass());
142+
143+
// FIXME: Return Any
144+
if (First->getKind() != second->getKind())
145+
return nullptr;
146+
147+
auto firstInstance = First->castTo<AnyMetatypeType>()->getInstanceType();
148+
auto secondInstance = second->castTo<AnyMetatypeType>()->getInstanceType();
149+
150+
auto joinInstance = join(firstInstance, secondInstance);
151+
152+
// FIXME: Return Any
153+
if (!joinInstance)
154+
return nullptr;
155+
156+
return MetatypeType::get(joinInstance);
157+
}
158+
159+
Type TypeJoin::visitExistentialMetatypeType(Type second) {
160+
assert(!First->mayHaveSuperclass() && !second->mayHaveSuperclass());
161+
162+
// FIXME: Return Any
163+
if (First->getKind() != second->getKind())
164+
return nullptr;
165+
166+
auto firstInstance = First->castTo<AnyMetatypeType>()->getInstanceType();
167+
auto secondInstance = second->castTo<AnyMetatypeType>()->getInstanceType();
168+
169+
auto joinInstance = join(firstInstance, secondInstance);
170+
171+
// FIXME: Return Any
172+
if (!joinInstance)
173+
return nullptr;
174+
175+
return ExistentialMetatypeType::get(joinInstance);
176+
}
177+
178+
Type TypeJoin::visitBoundGenericEnumType(Type second) {
179+
// FIXME: Return Any
180+
if (First->getKind() != second->getKind())
181+
return nullptr;
182+
101183
OptionalTypeKind otk1, otk2;
102-
Type objectType1 = type1->getAnyOptionalObjectType(otk1);
103-
Type objectType2 = type2->getAnyOptionalObjectType(otk2);
184+
Type objectType1 = First->getAnyOptionalObjectType(otk1);
185+
Type objectType2 = second->getAnyOptionalObjectType(otk2);
104186
if (otk1 == OTK_Optional || otk2 == OTK_Optional) {
105187
// Compute the join of the unwrapped type. If there is none, we're done.
106-
Type unwrappedJoin = join(objectType1 ? objectType1 : type1,
107-
objectType2 ? objectType2 : type2);
188+
Type unwrappedJoin = join(objectType1 ? objectType1 : First,
189+
objectType2 ? objectType2 : second);
190+
// FIXME: More general joins of enums need to be handled.
108191
if (!unwrappedJoin) return nullptr;
109192

110193
return OptionalType::get(unwrappedJoin);
111194
}
112195

113-
// The join can only be an existential.
196+
// FIXME: More general joins of enums need to be handled, and
197+
// then Any should be returned when there is no better
198+
// choice.
114199
return nullptr;
115200
}
116201

202+
Type TypeJoin::visitOptionalType(Type second) {
203+
auto canFirst = First->getCanonicalType();
204+
auto canSecond = second->getCanonicalType();
205+
206+
return TypeJoin::join(canFirst, canSecond);
207+
}
208+
209+
Type Type::join(Type type1, Type type2) {
210+
assert(type1 && type2 && "Unexpected null type!");
211+
212+
return TypeJoin::join(type1, type2);
213+
}

0 commit comments

Comments
 (0)