@@ -47,7 +47,8 @@ STATISTIC(LargestSolutionAttemptNumber, "# of the largest solution attempt");
4747// /
4848// / \returns the type to bind to, if the binding is okay.
4949static Optional<Type> checkTypeOfBinding (ConstraintSystem &cs,
50- TypeVariableType *typeVar, Type type) {
50+ TypeVariableType *typeVar, Type type,
51+ bool *isNilLiteral = nullptr ) {
5152 if (!type)
5253 return None;
5354
@@ -63,8 +64,15 @@ static Optional<Type> checkTypeOfBinding(ConstraintSystem &cs,
6364 // If the type is a type variable itself, don't permit the binding.
6465 // FIXME: This is a hack. We need to be smarter about whether there's enough
6566 // 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+
6774 return None;
75+ }
6876
6977 // Okay, allow the binding (with the simplified type).
7078 return type;
@@ -709,20 +717,22 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
709717
710718 // Local function to add a potential binding to the list of bindings,
711719 // 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 ) {
713722 // 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
715724 // types.
716725 if (binding.Kind == AllowedBindingKind::Supertypes &&
717726 !binding.BindingType ->hasTypeVariable () &&
718727 !binding.DefaultedProtocol &&
719- !binding.IsDefaultableBinding ) {
728+ !binding.IsDefaultableBinding &&
729+ allowJoinMeet) {
720730 if (lastSupertypeIndex) {
721- // Can we compute a meet ?
731+ // Can we compute a join ?
722732 auto &lastBinding = result.Bindings [*lastSupertypeIndex];
723733 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.
726736 lastBinding.BindingType = meet;
727737 return ;
728738 }
@@ -739,6 +749,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
739749 llvm::SmallPtrSet<CanType, 4 > exactTypes;
740750 llvm::SmallPtrSet<ProtocolDecl *, 4 > literalProtocols;
741751 SmallVector<Constraint *, 2 > defaultableConstraints;
752+ bool addOptionalSupertypeBindings = false ;
742753 auto &tc = cs.getTypeChecker ();
743754 for (auto constraint : constraints) {
744755 // Only visit each constraint once.
@@ -917,11 +928,18 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
917928
918929 // Check whether we can perform this binding.
919930 // 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)) {
921933 type = *boundType;
922934 if (type->hasTypeVariable ())
923935 result.InvolvesTypeVariables = true ;
924936 } 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+
925943 result.InvolvesTypeVariables = true ;
926944 continue ;
927945 }
@@ -980,7 +998,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
980998 addPotentialBinding ({type, kind, None});
981999 if (alternateType &&
9821000 exactTypes.insert (alternateType->getCanonicalType ()).second )
983- addPotentialBinding ({alternateType, kind, None});
1001+ addPotentialBinding ({alternateType, kind, None}, /* allowJoinMeet= */ false );
9841002 }
9851003
9861004 // If we have any literal constraints, check whether there is already a
@@ -1071,6 +1089,30 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
10711089 binding.Kind == AllowedBindingKind::Subtypes;
10721090 });
10731091
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+
10741116 return result;
10751117}
10761118
0 commit comments