@@ -47,7 +47,8 @@ STATISTIC(LargestSolutionAttemptNumber, "# of the largest solution attempt");
47
47
// /
48
48
// / \returns the type to bind to, if the binding is okay.
49
49
static Optional<Type> checkTypeOfBinding (ConstraintSystem &cs,
50
- TypeVariableType *typeVar, Type type) {
50
+ TypeVariableType *typeVar, Type type,
51
+ bool *isNilLiteral = nullptr ) {
51
52
if (!type)
52
53
return None;
53
54
@@ -63,8 +64,15 @@ static Optional<Type> checkTypeOfBinding(ConstraintSystem &cs,
63
64
// If the type is a type variable itself, don't permit the binding.
64
65
// FIXME: This is a hack. We need to be smarter about whether there's enough
65
66
// structure in the type to produce an interesting binding, or not.
66
- if (type->getRValueType ()->is <TypeVariableType>())
67
+ if (auto bindingTypeVar = type->getRValueType ()->getAs <TypeVariableType>()) {
68
+ if (isNilLiteral &&
69
+ bindingTypeVar->getImpl ().literalConformanceProto &&
70
+ bindingTypeVar->getImpl ().literalConformanceProto ->isSpecificProtocol (
71
+ KnownProtocolKind::ExpressibleByNilLiteral))
72
+ *isNilLiteral = true ;
73
+
67
74
return None;
75
+ }
68
76
69
77
// Okay, allow the binding (with the simplified type).
70
78
return type;
@@ -709,20 +717,22 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
709
717
710
718
// Local function to add a potential binding to the list of bindings,
711
719
// coalescing supertype bounds when we are able to compute the meet.
712
- auto addPotentialBinding = [&](PotentialBinding binding) {
720
+ auto addPotentialBinding = [&](PotentialBinding binding,
721
+ bool allowJoinMeet = true ) {
713
722
// If this is a non-defaulted supertype binding, check whether we can
714
- // combine it with another supertype binding by computing the 'meet ' of the
723
+ // combine it with another supertype binding by computing the 'join ' of the
715
724
// types.
716
725
if (binding.Kind == AllowedBindingKind::Supertypes &&
717
726
!binding.BindingType ->hasTypeVariable () &&
718
727
!binding.DefaultedProtocol &&
719
- !binding.IsDefaultableBinding ) {
728
+ !binding.IsDefaultableBinding &&
729
+ allowJoinMeet) {
720
730
if (lastSupertypeIndex) {
721
- // Can we compute a meet ?
731
+ // Can we compute a join ?
722
732
auto &lastBinding = result.Bindings [*lastSupertypeIndex];
723
733
if (auto meet =
724
- Type::meet (lastBinding.BindingType , binding.BindingType )) {
725
- // Replace the last supertype binding with the meet . We're done.
734
+ Type::join (lastBinding.BindingType , binding.BindingType )) {
735
+ // Replace the last supertype binding with the join . We're done.
726
736
lastBinding.BindingType = meet;
727
737
return ;
728
738
}
@@ -739,6 +749,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
739
749
llvm::SmallPtrSet<CanType, 4 > exactTypes;
740
750
llvm::SmallPtrSet<ProtocolDecl *, 4 > literalProtocols;
741
751
SmallVector<Constraint *, 2 > defaultableConstraints;
752
+ bool addOptionalSupertypeBindings = false ;
742
753
auto &tc = cs.getTypeChecker ();
743
754
for (auto constraint : constraints) {
744
755
// Only visit each constraint once.
@@ -917,11 +928,18 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
917
928
918
929
// Check whether we can perform this binding.
919
930
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
920
- if (auto boundType = checkTypeOfBinding (cs, typeVar, type)) {
931
+ bool isNilLiteral = false ;
932
+ if (auto boundType = checkTypeOfBinding (cs, typeVar, type, &isNilLiteral)) {
921
933
type = *boundType;
922
934
if (type->hasTypeVariable ())
923
935
result.InvolvesTypeVariables = true ;
924
936
} else {
937
+ // If the bound is a 'nil' literal type, add optional supertype bindings.
938
+ if (isNilLiteral && kind == AllowedBindingKind::Supertypes) {
939
+ addOptionalSupertypeBindings = true ;
940
+ continue ;
941
+ }
942
+
925
943
result.InvolvesTypeVariables = true ;
926
944
continue ;
927
945
}
@@ -980,7 +998,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
980
998
addPotentialBinding ({type, kind, None});
981
999
if (alternateType &&
982
1000
exactTypes.insert (alternateType->getCanonicalType ()).second )
983
- addPotentialBinding ({alternateType, kind, None});
1001
+ addPotentialBinding ({alternateType, kind, None}, /* allowJoinMeet= */ false );
984
1002
}
985
1003
986
1004
// If we have any literal constraints, check whether there is already a
@@ -1071,6 +1089,30 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
1071
1089
binding.Kind == AllowedBindingKind::Subtypes;
1072
1090
});
1073
1091
1092
+ // If we're supposed to add optional supertype bindings, do so now.
1093
+ if (addOptionalSupertypeBindings) {
1094
+ for (unsigned i : indices (result.Bindings )) {
1095
+ // Only interested in supertype bindings.
1096
+ auto &binding = result.Bindings [i];
1097
+ if (binding.Kind != AllowedBindingKind::Supertypes) continue ;
1098
+
1099
+ // If the type doesn't conform to ExpressibleByNilLiteral,
1100
+ // produce an optional of that type as a potential binding. We
1101
+ // overwrite the binding in place because the non-optional type
1102
+ // will fail to type-check against the nil-literal conformance.
1103
+ auto nominalBindingDecl = binding.BindingType ->getAnyNominal ();
1104
+ if (!nominalBindingDecl) continue ;
1105
+ SmallVector<ProtocolConformance *, 2 > conformances;
1106
+ if (!nominalBindingDecl->lookupConformance (
1107
+ cs.DC ->getParentModule (),
1108
+ cs.getASTContext ().getProtocol (
1109
+ KnownProtocolKind::ExpressibleByNilLiteral),
1110
+ conformances)) {
1111
+ binding.BindingType = OptionalType::get (binding.BindingType );
1112
+ }
1113
+ }
1114
+ }
1115
+
1074
1116
return result;
1075
1117
}
1076
1118
0 commit comments