mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CSBindings] Open collection before binding parameter only if original argument type failed
Instead of always opening argument type represented by a collection without type variables (to support subtyping when element is a labeled tuple), let's try original type first and if that fails use a slower path with indirection which attempts `array upcast`. Doing it this way helps to propagate contextual information faster which fixes a performance regression. Resolves: rdar://problem/54580247
This commit is contained in:
@@ -1043,6 +1043,25 @@ bool TypeVarBindingProducer::computeNext() {
|
|||||||
if (auto simplifiedSuper = CS.checkTypeOfBinding(TypeVar, supertype))
|
if (auto simplifiedSuper = CS.checkTypeOfBinding(TypeVar, supertype))
|
||||||
addNewBinding(binding.withType(*simplifiedSuper));
|
addNewBinding(binding.withType(*simplifiedSuper));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto srcLocator = binding.getLocator();
|
||||||
|
if (srcLocator &&
|
||||||
|
srcLocator->isLastElement<LocatorPathElt::ApplyArgToParam>() &&
|
||||||
|
!type->hasTypeVariable() && CS.isCollectionType(type)) {
|
||||||
|
// If the type binding comes from the argument conversion, let's
|
||||||
|
// instead of binding collection types directly, try to bind
|
||||||
|
// using temporary type variables substituted for element
|
||||||
|
// types, that's going to ensure that subtype relationship is
|
||||||
|
// always preserved.
|
||||||
|
auto *BGT = type->castTo<BoundGenericType>();
|
||||||
|
auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(),
|
||||||
|
BGT->getASTContext());
|
||||||
|
|
||||||
|
auto dstLocator = TypeVar->getImpl().getLocator();
|
||||||
|
auto newType = CS.openUnboundGenericType(UGT, dstLocator)
|
||||||
|
->reconstituteSugar(/*recursive=*/false);
|
||||||
|
addNewBinding(binding.withType(newType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newBindings.empty())
|
if (newBindings.empty())
|
||||||
@@ -1062,20 +1081,6 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
|
|||||||
if (Binding.hasDefaultedLiteralProtocol()) {
|
if (Binding.hasDefaultedLiteralProtocol()) {
|
||||||
type = cs.openUnboundGenericType(type, dstLocator);
|
type = cs.openUnboundGenericType(type, dstLocator);
|
||||||
type = type->reconstituteSugar(/*recursive=*/false);
|
type = type->reconstituteSugar(/*recursive=*/false);
|
||||||
} else if (srcLocator &&
|
|
||||||
srcLocator->isLastElement<LocatorPathElt::ApplyArgToParam>() &&
|
|
||||||
!type->hasTypeVariable() && cs.isCollectionType(type)) {
|
|
||||||
// If the type binding comes from the argument conversion, let's
|
|
||||||
// instead of binding collection types directly, try to bind
|
|
||||||
// using temporary type variables substituted for element
|
|
||||||
// types, that's going to ensure that subtype relationship is
|
|
||||||
// always preserved.
|
|
||||||
auto *BGT = type->castTo<BoundGenericType>();
|
|
||||||
auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(),
|
|
||||||
BGT->getASTContext());
|
|
||||||
|
|
||||||
type = cs.openUnboundGenericType(UGT, dstLocator);
|
|
||||||
type = type->reconstituteSugar(/*recursive=*/false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.addConstraint(ConstraintKind::Bind, TypeVar, type, srcLocator);
|
cs.addConstraint(ConstraintKind::Bind, TypeVar, type, srcLocator);
|
||||||
|
|||||||
@@ -3799,9 +3799,11 @@ bool ConstraintSystem::repairFailures(
|
|||||||
if (tupleLocator->isLastElement<LocatorPathElt::SequenceElementType>())
|
if (tupleLocator->isLastElement<LocatorPathElt::SequenceElementType>())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Generic argument failures have a more general fix which is attached to a
|
// Generic argument/requirement failures have a more general fix which
|
||||||
// parent type and aggregates all argument failures into a single fix.
|
// is attached to a parent type and aggregates all argument failures
|
||||||
if (tupleLocator->isLastElement<LocatorPathElt::GenericArgument>())
|
// into a single fix.
|
||||||
|
if (tupleLocator->isLastElement<LocatorPathElt::AnyRequirement>() ||
|
||||||
|
tupleLocator->isLastElement<LocatorPathElt::GenericArgument>())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ConstraintFix *fix;
|
ConstraintFix *fix;
|
||||||
|
|||||||
@@ -216,7 +216,6 @@ func rdar_50668864() {
|
|||||||
struct Foo {
|
struct Foo {
|
||||||
init(anchors: [Int]) { // expected-note {{'init(anchors:)' declared here}}
|
init(anchors: [Int]) { // expected-note {{'init(anchors:)' declared here}}
|
||||||
self = .init { _ in [] } // expected-error {{trailing closure passed to parameter of type '[Int]' that does not accept a closure}}
|
self = .init { _ in [] } // expected-error {{trailing closure passed to parameter of type '[Int]' that does not accept a closure}}
|
||||||
// expected-error@-1 {{generic parameter 'Element' could not be inferred}}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
// FIXME: This should be linear instead of exponential.
|
// RUN: %scale-test --begin 1 --end 20 --step 1 --select NumLeafScopes %s -Xfrontend=-solver-expression-time-threshold=1
|
||||||
// RUN: %scale-test --begin 1 --end 10 --step 1 --select NumLeafScopes --invert-result %s -Xfrontend=-solver-expression-time-threshold=1
|
|
||||||
// REQUIRES: asserts,no_asan
|
// REQUIRES: asserts,no_asan
|
||||||
// REQUIRES: rdar57138194,SR11770
|
|
||||||
|
|
||||||
enum Val {
|
enum Val {
|
||||||
case d([String: Val])
|
case d([String: Val])
|
||||||
Reference in New Issue
Block a user