Skip to content

Commit 0ffc988

Browse files
authored
Merge pull request swiftlang#20907 from rudkx/refactor-checkTypeOfBinding
Refactor checkTypeOfBinding
2 parents 01bfdc1 + e0847c5 commit 0ffc988

File tree

3 files changed

+74
-78
lines changed

3 files changed

+74
-78
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,25 @@ bool ConstraintSystem::PotentialBindings::isViable(
206206
return true;
207207
}
208208

209+
static bool hasNilLiteralConstraint(TypeVariableType *typeVar,
210+
ConstraintSystem &CS) {
211+
// Look for a literal-conformance constraint on the type variable.
212+
llvm::SetVector<Constraint *> constraints;
213+
CS.getConstraintGraph().gatherConstraints(
214+
typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
215+
[](Constraint *constraint) -> bool {
216+
return constraint->getKind() == ConstraintKind::LiteralConformsTo &&
217+
constraint->getProtocol()->isSpecificProtocol(
218+
KnownProtocolKind::ExpressibleByNilLiteral);
219+
});
220+
221+
for (auto constraint : constraints)
222+
if (CS.simplifyType(constraint->getFirstType())->isEqual(typeVar))
223+
return true;
224+
225+
return false;
226+
}
227+
209228
Optional<ConstraintSystem::PotentialBinding>
210229
ConstraintSystem::getPotentialBindingForRelationalConstraint(
211230
PotentialBindings &result, Constraint *constraint,
@@ -291,22 +310,27 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
291310

292311
// Check whether we can perform this binding.
293312
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
294-
bool isNilLiteral = false;
295-
bool *isNilLiteralPtr = nullptr;
296-
if (!addOptionalSupertypeBindings && kind == AllowedBindingKind::Supertypes)
297-
isNilLiteralPtr = &isNilLiteral;
298-
if (auto boundType = checkTypeOfBinding(typeVar, type, isNilLiteralPtr)) {
313+
if (auto boundType = checkTypeOfBinding(typeVar, type)) {
299314
type = *boundType;
300315
if (type->hasTypeVariable())
301316
result.InvolvesTypeVariables = true;
302317
} else {
303-
// If the bound is a 'nil' literal type, add optional supertype bindings.
304-
if (isNilLiteral) {
305-
addOptionalSupertypeBindings = true;
318+
auto *bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>();
319+
320+
if (!bindingTypeVar)
306321
return None;
307-
}
308322

309323
result.InvolvesTypeVariables = true;
324+
325+
// If we've already set addOptionalSupertypeBindings, or we aren't
326+
// allowing supertype bindings, we're done.
327+
if (addOptionalSupertypeBindings || kind != AllowedBindingKind::Supertypes)
328+
return None;
329+
330+
// If the bound is a 'nil' literal type, add optional supertype bindings.
331+
if (hasNilLiteralConstraint(bindingTypeVar, *this))
332+
addOptionalSupertypeBindings = true;
333+
310334
return None;
311335
}
312336

@@ -724,6 +748,46 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
724748
return result;
725749
}
726750

751+
/// \brief Check whether the given type can be used as a binding for the given
752+
/// type variable.
753+
///
754+
/// \returns the type to bind to, if the binding is okay.
755+
Optional<Type> ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar,
756+
Type type) {
757+
// Simplify the type.
758+
type = simplifyType(type);
759+
760+
// If the type references the type variable, don't permit the binding.
761+
SmallVector<TypeVariableType *, 4> referencedTypeVars;
762+
type->getTypeVariables(referencedTypeVars);
763+
if (count(referencedTypeVars, typeVar))
764+
return None;
765+
766+
// If type variable is not allowed to bind to `lvalue`,
767+
// let's check if type of potential binding has any
768+
// type variables, which are allowed to bind to `lvalue`,
769+
// and postpone such type from consideration.
770+
if (!typeVar->getImpl().canBindToLValue()) {
771+
for (auto *typeVar : referencedTypeVars) {
772+
if (typeVar->getImpl().canBindToLValue())
773+
return None;
774+
}
775+
}
776+
777+
// If the type is a type variable itself, don't permit the binding.
778+
if (auto *bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>())
779+
return None;
780+
781+
// Don't bind to a dependent member type, even if it's currently
782+
// wrapped in any number of optionals, because binding producer
783+
// might unwrap and try to attempt it directly later.
784+
if (type->lookThroughAllOptionalTypes()->is<DependentMemberType>())
785+
return None;
786+
787+
// Okay, allow the binding (with the simplified type).
788+
return type;
789+
}
790+
727791
// Given a possibly-Optional type, return the direct superclass of the
728792
// (underlying) type wrapped in the same number of optional levels as
729793
// type.

lib/Sema/CSSolver.cpp

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -61,73 +61,6 @@ TypeVariableType *ConstraintSystem::createTypeVariable(
6161
return tv;
6262
}
6363

64-
/// \brief Check whether the given type can be used as a binding for the given
65-
/// type variable.
66-
///
67-
/// \returns the type to bind to, if the binding is okay.
68-
Optional<Type> ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar,
69-
Type type,
70-
bool *isNilLiteral) {
71-
if (!type)
72-
return None;
73-
74-
// Simplify the type.
75-
type = simplifyType(type);
76-
77-
// If the type references the type variable, don't permit the binding.
78-
SmallVector<TypeVariableType *, 4> referencedTypeVars;
79-
type->getTypeVariables(referencedTypeVars);
80-
if (count(referencedTypeVars, typeVar))
81-
return None;
82-
83-
// If type variable is not allowed to bind to `lvalue`,
84-
// let's check if type of potential binding has any
85-
// type variables, which are allowed to bind to `lvalue`,
86-
// and postpone such type from consideration.
87-
if (!typeVar->getImpl().canBindToLValue()) {
88-
for (auto *typeVar : referencedTypeVars) {
89-
if (typeVar->getImpl().canBindToLValue())
90-
return None;
91-
}
92-
}
93-
94-
// If the type is a type variable itself, don't permit the binding.
95-
if (auto bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>()) {
96-
if (isNilLiteral) {
97-
*isNilLiteral = false;
98-
99-
// Look for a literal-conformance constraint on the type variable.
100-
llvm::SetVector<Constraint *> constraints;
101-
getConstraintGraph().gatherConstraints(
102-
bindingTypeVar, constraints,
103-
ConstraintGraph::GatheringKind::EquivalenceClass,
104-
[](Constraint *constraint) -> bool {
105-
return constraint->getKind() == ConstraintKind::LiteralConformsTo &&
106-
constraint->getProtocol()->isSpecificProtocol(
107-
KnownProtocolKind::ExpressibleByNilLiteral);
108-
});
109-
110-
for (auto constraint : constraints) {
111-
if (simplifyType(constraint->getFirstType())->isEqual(bindingTypeVar)) {
112-
*isNilLiteral = true;
113-
break;
114-
}
115-
}
116-
}
117-
118-
return None;
119-
}
120-
121-
// Don't bind to a dependent member type, even if it's currently
122-
// wrapped in any number of optionals, because binding producer
123-
// might unwrap and try to attempt it directly later.
124-
if (type->lookThroughAllOptionalTypes()->is<DependentMemberType>())
125-
return None;
126-
127-
// Okay, allow the binding (with the simplified type).
128-
return type;
129-
}
130-
13164
Solution ConstraintSystem::finalize() {
13265
assert(solverState);
13366

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2984,8 +2984,7 @@ class ConstraintSystem {
29842984
}
29852985
};
29862986

2987-
Optional<Type> checkTypeOfBinding(TypeVariableType *typeVar, Type type,
2988-
bool *isNilLiteral = nullptr);
2987+
Optional<Type> checkTypeOfBinding(TypeVariableType *typeVar, Type type);
29892988
Optional<PotentialBindings> determineBestBindings();
29902989
Optional<ConstraintSystem::PotentialBinding>
29912990
getPotentialBindingForRelationalConstraint(

0 commit comments

Comments
 (0)