Skip to content

Commit cd8fddd

Browse files
authored
Merge pull request #27145 from slavapestov/refactor-type-check-checked-cast
Refactor typeCheckCheckedCast() and a few other things
2 parents d67443f + de4b63d commit cd8fddd

File tree

10 files changed

+82
-129
lines changed

10 files changed

+82
-129
lines changed

include/swift/Sema/IDETypeChecking.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ namespace swift {
4747
/// \returns true on convertible, false on not.
4848
bool isConvertibleTo(Type T1, Type T2, bool openArchetypes, DeclContext &DC);
4949

50-
bool isEqual(Type T1, Type T2, DeclContext &DC);
51-
52-
bool canPossiblyEqual(Type T1, Type T2, DeclContext &DC);
53-
5450
void collectDefaultImplementationForProtocolMembers(ProtocolDecl *PD,
5551
llvm::SmallDenseMap<ValueDecl*, ValueDecl*> &DefaultMap);
5652

include/swift/Sema/IDETypeCheckingRequests.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ class IsDeclApplicableRequest:
8787
// Type relation checking
8888
//----------------------------------------------------------------------------//
8989
enum class TypeRelation: uint8_t {
90-
EqualTo,
91-
PossiblyEqualTo,
9290
ConvertTo,
9391
};
9492

@@ -158,8 +156,6 @@ struct TypeRelationCheckInput {
158156
out << " is ";
159157
switch(owner.Relation) {
160158
#define CASE(NAME) case TypeRelation::NAME: out << #NAME << " "; break;
161-
CASE(EqualTo)
162-
CASE(PossiblyEqualTo)
163159
CASE(ConvertTo)
164160
#undef CASE
165161
}

lib/AST/Type.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,7 +1479,11 @@ bool TypeBase::isExactSuperclassOf(Type ty) {
14791479
ty->getSuperclass()->getAnyNominal()->hasClangNode())))
14801480
return false;
14811481

1482+
SmallPtrSet<ClassDecl *, 8> seen;
14821483
do {
1484+
if (auto *classDecl = ty->getClassOrBoundGenericClass())
1485+
if (!seen.insert(classDecl).second)
1486+
return false;
14831487
if (ty->isEqual(this))
14841488
return true;
14851489
} while ((ty = ty->getSuperclass()));
@@ -1510,6 +1514,10 @@ bool TypeBase::isBindableTo(Type b) {
15101514
if (orig->requiresClass() && !subst->satisfiesClassConstraint())
15111515
return false;
15121516

1517+
if (auto superclass = orig->getSuperclass())
1518+
if (!superclass->isBindableToSuperclassOf(subst))
1519+
return false;
1520+
15131521
// TODO: If the archetype has a superclass constraint, check that the
15141522
// substitution is a subclass.
15151523

@@ -1528,7 +1536,7 @@ bool TypeBase::isBindableTo(Type b) {
15281536
if (CanType(orig) == subst)
15291537
return true;
15301538

1531-
llvm_unreachable("not a valid canonical type substitution");
1539+
return false;
15321540
}
15331541

15341542
bool visitNominalType(NominalType *nom, CanType subst) {
@@ -1580,17 +1588,20 @@ bool TypeBase::isBindableTo(Type b) {
15801588
}
15811589

15821590
bool visitDependentMemberType(DependentMemberType *dt, CanType subst) {
1583-
llvm_unreachable("can't visit dependent types");
1591+
return true;
15841592
}
15851593
bool visitGenericTypeParamType(GenericTypeParamType *dt, CanType subst) {
1586-
llvm_unreachable("can't visit dependent types");
1594+
return true;
15871595
}
15881596

15891597
bool visitFunctionType(FunctionType *func, CanType subst) {
15901598
if (auto substFunc = dyn_cast<FunctionType>(subst)) {
15911599
if (func->getExtInfo() != substFunc->getExtInfo())
15921600
return false;
15931601

1602+
if (func->getParams().size() != substFunc->getParams().size())
1603+
return false;
1604+
15941605
for (unsigned i : indices(func->getParams())) {
15951606
if (!visit(func->getParams()[i].getOldType(),
15961607
substFunc.getParams()[i].getOldType()))
@@ -1708,20 +1719,13 @@ bool TypeBase::isBindableToSuperclassOf(Type ty) {
17081719
if (!ty->mayHaveSuperclass())
17091720
return false;
17101721

1711-
// If the type is itself an archetype, we could always potentially bind it
1712-
// to the superclass (via external retroactive conformance, even if the
1713-
// type isn't statically known to conform).
1714-
//
1715-
// We could theoretically reject cases where the set of conformances is known
1716-
// (say the protocol or classes are private or internal).
1717-
if (is<ArchetypeType>())
1718-
return true;
1719-
1722+
SmallPtrSet<ClassDecl *, 8> seen;
17201723
do {
1724+
if (auto *classDecl = ty->getClassOrBoundGenericClass())
1725+
if (!seen.insert(classDecl).second)
1726+
return false;
17211727
if (isBindableTo(ty))
17221728
return true;
1723-
if (ty->getAnyNominal() && ty->getAnyNominal()->isInvalid())
1724-
return false;
17251729
} while ((ty = ty->getSuperclass()));
17261730
return false;
17271731
}

lib/IDE/IDETypeChecking.cpp

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -88,25 +88,6 @@ PrintOptions PrintOptions::printDocInterface() {
8888
return result;
8989
}
9090

91-
/// Erase any associated types within dependent member types, so we'll resolve
92-
/// them again.
93-
static Type eraseAssociatedTypes(Type type) {
94-
if (!type->hasTypeParameter()) return type;
95-
96-
return type.transformRec([](TypeBase *type) -> Optional<Type> {
97-
if (auto depMemType = dyn_cast<DependentMemberType>(type)) {
98-
auto newBase = eraseAssociatedTypes(depMemType->getBase());
99-
if (newBase.getPointer() == depMemType->getBase().getPointer() &&
100-
!depMemType->getAssocType())
101-
return None;
102-
103-
return Type(DependentMemberType::get(newBase, depMemType->getName()));
104-
}
105-
106-
return None;
107-
});
108-
}
109-
11091
struct SynthesizedExtensionAnalyzer::Implementation {
11192
static bool isMemberFavored(const NominalTypeDecl* Target, const Decl* D) {
11293
DeclContext* DC = Target->getInnermostDeclContext();
@@ -186,11 +167,9 @@ struct SynthesizedExtensionAnalyzer::Implementation {
186167
std::set<Requirement> Requirements;
187168
void addRequirement(GenericSignature *GenericSig,
188169
Type First, Type Second, RequirementKind Kind) {
189-
CanType CanFirst =
190-
GenericSig->getCanonicalTypeInContext(eraseAssociatedTypes(First));
170+
CanType CanFirst = GenericSig->getCanonicalTypeInContext(First);
191171
CanType CanSecond;
192-
if (Second) CanSecond =
193-
GenericSig->getCanonicalTypeInContext(eraseAssociatedTypes(Second));
172+
if (Second) CanSecond = GenericSig->getCanonicalTypeInContext(Second);
194173

195174
Requirements.insert({First, Second, Kind, CanFirst, CanSecond});
196175
}
@@ -325,7 +304,6 @@ struct SynthesizedExtensionAnalyzer::Implementation {
325304

326305
switch (Kind) {
327306
case RequirementKind::Conformance:
328-
case RequirementKind::Superclass:
329307
// FIXME: This could be more accurate; check
330308
// conformance instead of subtyping
331309
if (!isConvertibleTo(First, Second, /*openArchetypes=*/true, *DC))
@@ -335,8 +313,17 @@ struct SynthesizedExtensionAnalyzer::Implementation {
335313
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
336314
break;
337315

316+
case RequirementKind::Superclass:
317+
if (!Second->isBindableToSuperclassOf(First)) {
318+
return true;
319+
} else if (!Second->isExactSuperclassOf(Second)) {
320+
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
321+
}
322+
break;
323+
338324
case RequirementKind::SameType:
339-
if (!canPossiblyEqual(First, Second, *DC)) {
325+
if (!First->isBindableTo(Second) &&
326+
!Second->isBindableTo(First)) {
340327
return true;
341328
} else if (!First->isEqual(Second)) {
342329
MergeInfo.addRequirement(GenericSig, First, Second, Kind);
@@ -753,19 +740,6 @@ bool swift::isMemberDeclApplied(const DeclContext *DC, Type BaseTy,
753740
IsDeclApplicableRequest(DeclApplicabilityOwner(DC, BaseTy, VD)), false);
754741
}
755742

756-
bool swift::canPossiblyEqual(Type T1, Type T2, DeclContext &DC) {
757-
return evaluateOrDefault(DC.getASTContext().evaluator,
758-
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
759-
TypeRelation::PossiblyEqualTo, true)), false);
760-
}
761-
762-
763-
bool swift::isEqual(Type T1, Type T2, DeclContext &DC) {
764-
return evaluateOrDefault(DC.getASTContext().evaluator,
765-
TypeRelationCheckRequest(TypeRelationCheckInput(&DC, T1, T2,
766-
TypeRelation::EqualTo, true)), false);
767-
}
768-
769743
bool swift::isConvertibleTo(Type T1, Type T2, bool openArchetypes,
770744
DeclContext &DC) {
771745
return evaluateOrDefault(DC.getASTContext().evaluator,

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7163,6 +7163,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
71637163
// T1 <c T2 && T2 : Hashable ===> T1 <c AnyHashable
71647164
case ConversionRestrictionKind::HashableToAnyHashable: {
71657165
// We never want to do this if the LHS is already AnyHashable.
7166+
type1 = simplifyType(type1);
71667167
if (isAnyHashableType(
71677168
type1->getRValueType()->lookThroughAllOptionalTypes())) {
71687169
return SolutionKind::Error;

lib/Sema/ConstraintSystem.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -728,8 +728,8 @@ Optional<Type> ConstraintSystem::isSetType(Type type) {
728728
}
729729

730730
bool ConstraintSystem::isCollectionType(Type type) {
731-
auto &ctx = type->getASTContext();
732731
if (auto *structType = type->getAs<BoundGenericStructType>()) {
732+
auto &ctx = type->getASTContext();
733733
auto *decl = structType->getDecl();
734734
if (decl == ctx.getArrayDecl() || decl == ctx.getDictionaryDecl() ||
735735
decl == ctx.getSetDecl())
@@ -740,13 +740,9 @@ bool ConstraintSystem::isCollectionType(Type type) {
740740
}
741741

742742
bool ConstraintSystem::isAnyHashableType(Type type) {
743-
if (auto tv = type->getAs<TypeVariableType>()) {
744-
auto fixedType = getFixedType(tv);
745-
return fixedType && isAnyHashableType(fixedType);
746-
}
747-
748743
if (auto st = type->getAs<StructType>()) {
749-
return st->getDecl() == TC.Context.getAnyHashableDecl();
744+
auto &ctx = type->getASTContext();
745+
return st->getDecl() == ctx.getAnyHashableDecl();
750746
}
751747

752748
return false;

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2491,7 +2491,7 @@ class ConstraintSystem {
24912491
static bool isCollectionType(Type t);
24922492

24932493
/// Determine if the type in question is AnyHashable.
2494-
bool isAnyHashableType(Type t);
2494+
static bool isAnyHashableType(Type t);
24952495

24962496
/// Call Expr::isTypeReference on the given expression, using a
24972497
/// custom accessor for the type on the expression that reads the

lib/Sema/IDETypeCheckingRequests.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ TypeRelationCheckRequest::evaluate(Evaluator &evaluator,
104104
TypeRelationCheckInput Owner) const {
105105
Optional<constraints::ConstraintKind> CKind;
106106
switch (Owner.Relation) {
107-
case TypeRelation::EqualTo:
108-
return Owner.Pair.FirstTy->isEqual(Owner.Pair.SecondTy);
109-
case TypeRelation::PossiblyEqualTo:
110-
CKind = constraints::ConstraintKind::Bind;
111-
break;
112107
case TypeRelation::ConvertTo:
113108
CKind = constraints::ConstraintKind::Conversion;
114109
break;

0 commit comments

Comments
 (0)