@@ -104,6 +104,41 @@ void ConstraintSystem::PotentialBindings::finalize(
104
104
existingTypes.insert (binding.BindingType ->getCanonicalType ());
105
105
106
106
inferTransitiveBindings (cs, existingTypes, inferredBindings);
107
+
108
+ // Adjust optionality of existing bindings based on presence of
109
+ // `ExpressibleByNilLiteral` requirement.
110
+ if (llvm::any_of (Protocols, [](Constraint *constraint) {
111
+ auto *protocol = constraint->getProtocol ();
112
+ return protocol->isSpecificProtocol (
113
+ KnownProtocolKind::ExpressibleByNilLiteral);
114
+ })) {
115
+ for (auto &binding : Bindings) {
116
+ bool wrapInOptional = false ;
117
+ if (binding.Kind == AllowedBindingKind::Supertypes) {
118
+ auto type = binding.BindingType ->getRValueType ();
119
+ // If the type doesn't conform to ExpressibleByNilLiteral,
120
+ // produce an optional of that type as a potential binding. We
121
+ // overwrite the binding in place because the non-optional type
122
+ // will fail to type-check against the nil-literal conformance.
123
+ bool conformsToExprByNilLiteral = false ;
124
+ if (auto *nominalBindingDecl = type->getAnyNominal ()) {
125
+ SmallVector<ProtocolConformance *, 2 > conformances;
126
+ conformsToExprByNilLiteral = nominalBindingDecl->lookupConformance (
127
+ cs.DC ->getParentModule (),
128
+ cs.getASTContext ().getProtocol (
129
+ KnownProtocolKind::ExpressibleByNilLiteral),
130
+ conformances);
131
+ }
132
+ wrapInOptional = !conformsToExprByNilLiteral;
133
+ } else if (binding.isDefaultableBinding () &&
134
+ binding.BindingType ->isAny ()) {
135
+ wrapInOptional = true ;
136
+ }
137
+
138
+ if (wrapInOptional)
139
+ binding.BindingType = OptionalType::get (binding.BindingType );
140
+ }
141
+ }
107
142
}
108
143
109
144
Optional<ConstraintSystem::PotentialBindings>
@@ -114,11 +149,8 @@ ConstraintSystem::determineBestBindings() {
114
149
115
150
// First, let's collect all of the possible bindings.
116
151
for (auto *typeVar : getTypeVariables ()) {
117
- if (typeVar->getImpl ().hasRepresentativeOrFixed ())
118
- continue ;
119
-
120
- if (auto bindings = getPotentialBindings (typeVar))
121
- cache.insert ({typeVar, std::move (bindings)});
152
+ if (!typeVar->getImpl ().hasRepresentativeOrFixed ())
153
+ cache.insert ({typeVar, getPotentialBindings (typeVar)});
122
154
}
123
155
124
156
// Now let's see if we could infer something for related type
@@ -132,6 +164,9 @@ ConstraintSystem::determineBestBindings() {
132
164
133
165
bindings.finalize (*this , cache);
134
166
167
+ if (!bindings)
168
+ continue ;
169
+
135
170
if (isDebugMode ()) {
136
171
bindings.dump (typeVar, llvm::errs (), solverState->depth * 2 );
137
172
}
@@ -283,31 +318,11 @@ bool ConstraintSystem::PotentialBindings::favoredOverDisjunction(
283
318
return !InvolvesTypeVariables;
284
319
}
285
320
286
- static bool hasNilLiteralConstraint (TypeVariableType *typeVar,
287
- const ConstraintSystem &CS) {
288
- // Look for a literal-conformance constraint on the type variable.
289
- auto constraints =
290
- CS.getConstraintGraph ().gatherConstraints (
291
- typeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
292
- [](Constraint *constraint) -> bool {
293
- return constraint->getKind () == ConstraintKind::LiteralConformsTo &&
294
- constraint->getProtocol ()->isSpecificProtocol (
295
- KnownProtocolKind::ExpressibleByNilLiteral);
296
- });
297
-
298
- for (auto constraint : constraints)
299
- if (CS.simplifyType (constraint->getFirstType ())->isEqual (typeVar))
300
- return true ;
301
-
302
- return false ;
303
- }
304
-
305
321
Optional<ConstraintSystem::PotentialBinding>
306
322
ConstraintSystem::getPotentialBindingForRelationalConstraint (
307
323
PotentialBindings &result, Constraint *constraint,
308
324
bool &hasDependentMemberRelationalConstraints,
309
- bool &hasNonDependentMemberRelationalConstraints,
310
- bool &addOptionalSupertypeBindings) const {
325
+ bool &hasNonDependentMemberRelationalConstraints) const {
311
326
assert (constraint->getClassification () ==
312
327
ConstraintClassification::Relational &&
313
328
" only relational constraints handled here" );
@@ -427,15 +442,6 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
427
442
result.SubtypeOf .insert (bindingTypeVar);
428
443
}
429
444
430
- // If we've already set addOptionalSupertypeBindings, or we aren't
431
- // allowing supertype bindings, we're done.
432
- if (addOptionalSupertypeBindings || kind != AllowedBindingKind::Supertypes)
433
- return None;
434
-
435
- // If the bound is a 'nil' literal type, add optional supertype bindings.
436
- if (hasNilLiteralConstraint (bindingTypeVar, *this ))
437
- addOptionalSupertypeBindings = true ;
438
-
439
445
return None;
440
446
}
441
447
@@ -498,7 +504,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
498
504
llvm::SmallPtrSet<CanType, 4 > exactTypes;
499
505
SmallVector<Constraint *, 2 > defaultableConstraints;
500
506
SmallVector<PotentialBinding, 4 > literalBindings;
501
- bool addOptionalSupertypeBindings = false ;
502
507
bool hasNonDependentMemberRelationalConstraints = false ;
503
508
bool hasDependentMemberRelationalConstraints = false ;
504
509
for (auto constraint : constraints) {
@@ -528,8 +533,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
528
533
529
534
auto binding = getPotentialBindingForRelationalConstraint (
530
535
result, constraint, hasDependentMemberRelationalConstraints,
531
- hasNonDependentMemberRelationalConstraints,
532
- addOptionalSupertypeBindings);
536
+ hasNonDependentMemberRelationalConstraints);
533
537
if (!binding)
534
538
break ;
535
539
@@ -654,13 +658,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
654
658
// this is useful to use for the binding later.
655
659
result.Protocols .push_back (constraint);
656
660
657
- // If there is a 'nil' literal constraint, we might need optional
658
- // supertype bindings.
659
- if (constraint->getProtocol ()->isSpecificProtocol (
660
- KnownProtocolKind::ExpressibleByNilLiteral)) {
661
- addOptionalSupertypeBindings = true ;
662
- }
663
-
664
661
// If there is a default literal type for this protocol, it's a
665
662
// potential binding.
666
663
auto defaultType = TypeChecker::getDefaultType (constraint->getProtocol (), DC);
@@ -886,40 +883,6 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
886
883
binding.Kind == AllowedBindingKind::Subtypes;
887
884
});
888
885
889
- // If we're supposed to add optional supertype bindings, do so now.
890
- if (addOptionalSupertypeBindings) {
891
- for (unsigned i : indices (result.Bindings )) {
892
- auto &binding = result.Bindings [i];
893
- bool wrapInOptional = false ;
894
-
895
- if (binding.Kind == AllowedBindingKind::Supertypes) {
896
- // If the type doesn't conform to ExpressibleByNilLiteral,
897
- // produce an optional of that type as a potential binding. We
898
- // overwrite the binding in place because the non-optional type
899
- // will fail to type-check against the nil-literal conformance.
900
- auto nominalBindingDecl =
901
- binding.BindingType ->getRValueType ()->getAnyNominal ();
902
- bool conformsToExprByNilLiteral = false ;
903
- if (nominalBindingDecl) {
904
- SmallVector<ProtocolConformance *, 2 > conformances;
905
- conformsToExprByNilLiteral = nominalBindingDecl->lookupConformance (
906
- DC->getParentModule (),
907
- getASTContext ().getProtocol (
908
- KnownProtocolKind::ExpressibleByNilLiteral),
909
- conformances);
910
- }
911
- wrapInOptional = !conformsToExprByNilLiteral;
912
- } else if (binding.isDefaultableBinding () &&
913
- binding.BindingType ->isAny ()) {
914
- wrapInOptional = true ;
915
- }
916
-
917
- if (wrapInOptional) {
918
- binding.BindingType = OptionalType::get (binding.BindingType );
919
- }
920
- }
921
- }
922
-
923
886
// If there were both dependent-member and non-dependent-member relational
924
887
// constraints, consider this "fully bound"; we don't want to touch it.
925
888
if (hasDependentMemberRelationalConstraints) {
0 commit comments