Skip to content

Commit d073375

Browse files
committed
[Constraint solver] Try ‘defaultable’ bindings even if there are other possibilities.
Fixes rdar://problem/17444930.
1 parent 82ba4df commit d073375

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ namespace {
523523
enum class LiteralBindingKind : unsigned char {
524524
None,
525525
Collection,
526+
Float,
526527
Atom,
527528
};
528529

@@ -537,7 +538,16 @@ namespace {
537538
AllowedBindingKind Kind;
538539

539540
/// The defaulted protocol associated with this binding.
540-
Optional<ProtocolDecl *> DefaultedProtocol;
541+
Optional<ProtocolDecl *> DefaultedProtocol;
542+
543+
/// Whether this is a binding that comes from a 'Defaultable' constraint.
544+
bool IsDefaultableBinding = false;
545+
546+
PotentialBinding(Type type, AllowedBindingKind kind,
547+
Optional<ProtocolDecl *> defaultedProtocol = None,
548+
bool isDefaultableBinding = false)
549+
: BindingType(type), Kind(kind), DefaultedProtocol(defaultedProtocol),
550+
IsDefaultableBinding(isDefaultableBinding) { }
541551
};
542552

543553
struct PotentialBindings {
@@ -556,25 +566,35 @@ namespace {
556566
/// Whether this type variable is only bound above by existential types.
557567
bool SubtypeOfExistentialType = false;
558568

569+
/// The number of defaultable bindings.
570+
unsigned NumDefaultableBindings = 0;
571+
559572
/// Determine whether the set of bindings is non-empty.
560573
explicit operator bool() const {
561574
return !Bindings.empty();
562575
}
563576

577+
/// Whether there are any non-defaultable bindings.
578+
bool hasNonDefaultableBindings() const {
579+
return Bindings.size() > NumDefaultableBindings;
580+
}
581+
564582
/// Compare two sets of bindings, where \c x < y indicates that
565583
/// \c x is a better set of bindings that \c y.
566584
friend bool operator<(const PotentialBindings &x,
567585
const PotentialBindings &y) {
568-
return std::make_tuple(x.FullyBound,
586+
return std::make_tuple(!x.hasNonDefaultableBindings(),
587+
x.FullyBound,
569588
x.SubtypeOfExistentialType,
570589
static_cast<unsigned char>(x.LiteralBinding),
571590
x.InvolvesTypeVariables,
572-
-x.Bindings.size())
573-
< std::make_tuple(y.FullyBound,
591+
-(x.Bindings.size() - x.NumDefaultableBindings))
592+
< std::make_tuple(!y.hasNonDefaultableBindings(),
593+
y.FullyBound,
574594
y.SubtypeOfExistentialType,
575595
static_cast<unsigned char>(y.LiteralBinding),
576596
y.InvolvesTypeVariables,
577-
-y.Bindings.size());
597+
-(y.Bindings.size() - y.NumDefaultableBindings));
578598
}
579599

580600
void foundLiteralBinding(ProtocolDecl *proto) {
@@ -585,6 +605,10 @@ namespace {
585605
LiteralBinding = LiteralBindingKind::Collection;
586606
break;
587607

608+
case KnownProtocolKind::ExpressibleByFloatLiteral:
609+
LiteralBinding = LiteralBindingKind::Float;
610+
break;
611+
588612
default:
589613
if (LiteralBinding != LiteralBindingKind::Collection)
590614
LiteralBinding = LiteralBindingKind::Atom;
@@ -672,7 +696,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
672696
PotentialBindings result;
673697
llvm::SmallPtrSet<CanType, 4> exactTypes;
674698
llvm::SmallPtrSet<ProtocolDecl *, 4> literalProtocols;
675-
bool hasDefaultableConstraint = false;
699+
SmallVector<Constraint *, 2> defaultableConstraints;
676700
auto &tc = cs.getTypeChecker();
677701
for (auto constraint : constraints) {
678702
// Only visit each constraint once.
@@ -709,7 +733,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
709733

710734
case ConstraintKind::Defaultable:
711735
// Do these in a separate pass.
712-
hasDefaultableConstraint = true;
736+
defaultableConstraints.push_back(constraint);
713737
continue;
714738

715739
case ConstraintKind::Disjunction:
@@ -985,17 +1009,14 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
9851009
}
9861010
}
9871011

988-
// If we haven't found any other bindings yet, go ahead and consider
989-
// the defaulting constraints.
990-
if (result.Bindings.empty() && hasDefaultableConstraint) {
991-
for (Constraint *constraint : constraints) {
992-
if (constraint->getKind() != ConstraintKind::Defaultable)
993-
continue;
1012+
/// Add defaultable constraints last.
1013+
for (auto constraint : defaultableConstraints) {
1014+
Type type = constraint->getSecondType();
1015+
if (!exactTypes.insert(type->getCanonicalType()).second)
1016+
continue;
9941017

995-
result.Bindings.push_back({constraint->getSecondType(),
996-
AllowedBindingKind::Exact,
997-
None});
998-
}
1018+
++result.NumDefaultableBindings;
1019+
result.Bindings.push_back({type, AllowedBindingKind::Exact, None, true});
9991020
}
10001021

10011022
// Determine if the bindings only constrain the type variable from above with
@@ -1062,7 +1083,12 @@ static bool tryTypeVariableBindings(
10621083
log <<"\n";
10631084
}
10641085

1065-
for (auto binding : bindings) {
1086+
for (const auto &binding : bindings) {
1087+
// If this is a defaultable binding and we have found any solutions,
1088+
// don't explore the default binding.
1089+
if (binding.IsDefaultableBinding && anySolved)
1090+
continue;
1091+
10661092
auto type = binding.BindingType;
10671093

10681094
// If the type variable can't bind to an lvalue, make sure the

test/Parse/pointer_conversion.swift.gyb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,8 @@ func constVoidPointerArguments(_ p: UnsafeMutablePointer<Int>,
187187
takesConstVoidPointer(ii)
188188
takesConstVoidPointer(ff)
189189

190-
// TODO: These two should be accepted, tracked by rdar://17444930.
191-
takesConstVoidPointer([0, 1, 2]) // expected-error {{contextual type 'UnsafeRawPointer' cannot be used with array literal}}
192-
takesConstVoidPointer([0.0, 1.0, 2.0]) // expected-error {{contextual type 'UnsafeRawPointer' cannot be used with array literal}}
190+
takesConstVoidPointer([0, 1, 2])
191+
takesConstVoidPointer([0.0, 1.0, 2.0])
193192

194193
// We don't allow these conversions outside of function arguments.
195194
var x: UnsafeRawPointer = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafeRawPointer'}}
@@ -228,9 +227,8 @@ func constRawPointerArguments(_ p: UnsafeMutablePointer<Int>,
228227
takesConstRawPointer(ii)
229228
takesConstRawPointer(ff)
230229

231-
// TODO: These two should be accepted, tracked by rdar://17444930.
232-
takesConstRawPointer([0, 1, 2]) // expected-error {{contextual type 'UnsafeRawPointer' cannot be used with array literal}}
233-
takesConstRawPointer([0.0, 1.0, 2.0]) // expected-error {{contextual type 'UnsafeRawPointer' cannot be used with array literal}}
230+
takesConstRawPointer([0, 1, 2])
231+
takesConstRawPointer([0.0, 1.0, 2.0])
234232

235233
// We don't allow these conversions outside of function arguments.
236234
var x: UnsafeRawPointer = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafeRawPointer'}}

0 commit comments

Comments
 (0)