@@ -206,6 +206,25 @@ bool ConstraintSystem::PotentialBindings::isViable(
206
206
return true ;
207
207
}
208
208
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
+
209
228
Optional<ConstraintSystem::PotentialBinding>
210
229
ConstraintSystem::getPotentialBindingForRelationalConstraint (
211
230
PotentialBindings &result, Constraint *constraint,
@@ -291,22 +310,27 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
291
310
292
311
// Check whether we can perform this binding.
293
312
// 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)) {
299
314
type = *boundType;
300
315
if (type->hasTypeVariable ())
301
316
result.InvolvesTypeVariables = true ;
302
317
} 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)
306
321
return None;
307
- }
308
322
309
323
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
+
310
334
return None;
311
335
}
312
336
@@ -724,6 +748,46 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
724
748
return result;
725
749
}
726
750
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
+
727
791
// Given a possibly-Optional type, return the direct superclass of the
728
792
// (underlying) type wrapped in the same number of optional levels as
729
793
// type.
0 commit comments