Skip to content

Commit 2ae8e8d

Browse files
committed
[CSBindings] Cleanup tryTypeVariableBindings
* Move logic to ensure that r-value type var would get r-value type to `PotentialBindings`; * Strip uncessary parens directly when creating `PotentialBinding`; * Check if the binding is viable before inclusion in the set, instead of filtering it later; * Assert that bindings don't have types with errors included in the set.
1 parent 6e16e29 commit 2ae8e8d

File tree

4 files changed

+47
-37
lines changed

4 files changed

+47
-37
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,45 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
209209
if (auto *literalProtocol = binding.DefaultedProtocol)
210210
foundLiteralBinding(literalProtocol);
211211

212+
// If the type variable can't bind to an lvalue, make sure the
213+
// type we pick isn't an lvalue.
214+
if (!TypeVar->getImpl().canBindToLValue() &&
215+
binding.BindingType->hasLValueType()) {
216+
binding = binding.withType(binding.BindingType->getRValueType());
217+
}
218+
219+
if (!isViable(binding))
220+
return;
221+
212222
Bindings.push_back(std::move(binding));
213223
}
214224

225+
bool ConstraintSystem::PotentialBindings::isViable(
226+
PotentialBinding &binding) const {
227+
// Prevent against checking against the same bound generic type
228+
// over and over again. Doing so means redundant work in the best
229+
// case. In the worst case, we'll produce lots of duplicate solutions
230+
// for this constraint system, which is problematic for overload
231+
// resolution.
232+
auto type = binding.BindingType;
233+
if (type->hasTypeVariable()) {
234+
auto *BGT = type->getAs<BoundGenericType>();
235+
if (!BGT)
236+
return true;
237+
238+
for (auto &existing : Bindings) {
239+
auto existingBGT = existing.BindingType->getAs<BoundGenericType>();
240+
if (!existingBGT)
241+
continue;
242+
243+
if (BGT != existingBGT && BGT->getDecl() == existingBGT->getDecl())
244+
return false;
245+
}
246+
}
247+
248+
return true;
249+
}
250+
215251
Optional<ConstraintSystem::PotentialBinding>
216252
ConstraintSystem::getPotentialBindingForRelationalConstraint(
217253
PotentialBindings &result, Constraint *constraint,

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -580,42 +580,10 @@ bool ConstraintSystem::tryTypeVariableBindings(
580580
continue;
581581

582582
auto type = binding.BindingType;
583-
584-
// If the type variable can't bind to an lvalue, make sure the
585-
// type we pick isn't an lvalue.
586-
if (!typeVar->getImpl().canBindToLValue())
587-
type = type->getRValueType();
588-
589-
// Remove parentheses. They're insignificant here.
590-
type = type->getWithoutParens();
591-
592583
// If we've already tried this binding, move on.
593584
if (!boundTypes.insert(type.getPointer()).second)
594585
continue;
595586

596-
// Prevent against checking against the same bound generic type
597-
// over and over again. Doing so means redundant work in the best
598-
// case. In the worst case, we'll produce lots of duplicate solutions
599-
// for this constraint system, which is problematic for overload
600-
// resolution.
601-
if (type->hasTypeVariable()) {
602-
auto triedBinding = false;
603-
if (auto BGT = type->getAs<BoundGenericType>()) {
604-
for (auto bt : boundTypes) {
605-
if (auto BBGT = bt->getAs<BoundGenericType>()) {
606-
if (BGT != BBGT &&
607-
BGT->getDecl() == BBGT->getDecl()) {
608-
triedBinding = true;
609-
break;
610-
}
611-
}
612-
}
613-
}
614-
615-
if (triedBinding)
616-
continue;
617-
}
618-
619587
if (tc.getLangOpts().DebugConstraintSolver) {
620588
auto &log = getASTContext().TypeCheckerDebug->getStream();
621589
log.indent(depth * 2)
@@ -680,8 +648,7 @@ bool ConstraintSystem::tryTypeVariableBindings(
680648
// Enumerate the supertypes of each of the types we tried.
681649
for (auto binding : bindings) {
682650
const auto type = binding.BindingType;
683-
if (type->hasError())
684-
continue;
651+
assert(!type->hasError());
685652

686653
// After our first pass, note that we've explored these
687654
// types.

lib/Sema/ConstraintSystem.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,11 +2774,15 @@ class ConstraintSystem {
27742774
ConstraintKind bindingSource,
27752775
ProtocolDecl *defaultedProtocol = nullptr,
27762776
ConstraintLocator *defaultableBinding = nullptr)
2777-
: BindingType(type), Kind(kind), BindingSource(bindingSource),
2778-
DefaultedProtocol(defaultedProtocol),
2777+
: BindingType(type->getWithoutParens()), Kind(kind),
2778+
BindingSource(bindingSource), DefaultedProtocol(defaultedProtocol),
27792779
DefaultableBinding(defaultableBinding) {}
27802780

27812781
bool isDefaultableBinding() const { return DefaultableBinding != nullptr; }
2782+
2783+
PotentialBinding withType(Type type) const {
2784+
return {type, Kind, BindingSource, DefaultedProtocol, DefaultableBinding};
2785+
}
27822786
};
27832787

27842788
struct PotentialBindings {
@@ -2869,6 +2873,9 @@ class ConstraintSystem {
28692873
void addPotentialBinding(PotentialBinding binding,
28702874
bool allowJoinMeet = true);
28712875

2876+
/// Check if this binding is viable for inclusion in the set.
2877+
bool isViable(PotentialBinding &binding) const;
2878+
28722879
void dump(llvm::raw_ostream &out,
28732880
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
28742881
out.indent(indent);

validation-test/Sema/type_checker_perf/slow/rdar19181998.swift.gyb renamed to validation-test/Sema/type_checker_perf/fast/rdar19181998.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %scale-test --invert-result --begin 1 --end 4 --step 1 --select incrementScopeCounter %s
1+
// RUN: %scale-test --begin 1 --end 30 --step 1 --select incrementScopeCounter %s
22
// REQUIRES: OS=macosx
33
// REQUIRES: asserts
44

0 commit comments

Comments
 (0)