Skip to content

Commit 529660d

Browse files
authored
Merge pull request #34315 from hborla/remove-operator-designated-types
[ConstraintSystem] Remove implementation of operator designated types in the solver.
2 parents 01e0d3f + 4c0f49f commit 529660d

22 files changed

+55
-254
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,10 +538,6 @@ namespace swift {
538538
/// Disable constraint system performance hacks.
539539
bool DisableConstraintSolverPerformanceHacks = false;
540540

541-
/// Enable constraint solver support for experimental
542-
/// operator protocol designator feature.
543-
bool SolverEnableOperatorDesignatedTypes = false;
544-
545541
/// Enable experimental support for one-way constraints for the
546542
/// parameters of closures.
547543
bool EnableOneWayClosureParameters = false;

include/swift/Option/FrontendOptions.td

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,6 @@ def enable_operator_designated_types :
480480
Flag<["-"], "enable-operator-designated-types">,
481481
HelpText<"Enable operator designated types">;
482482

483-
def solver_enable_operator_designated_types :
484-
Flag<["-"], "solver-enable-operator-designated-types">,
485-
HelpText<"Enable operator designated types in constraint solver">;
486-
487483
def enable_invalid_ephemeralness_as_error :
488484
Flag<["-"], "enable-invalid-ephemeralness-as-error">,
489485
HelpText<"Diagnose invalid ephemeral to non-ephemeral conversions as errors">;

include/swift/Sema/ConstraintSystem.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5034,8 +5034,6 @@ class ConstraintSystem {
50345034
/// \returns The selected disjunction.
50355035
Constraint *selectDisjunction();
50365036

5037-
Constraint *selectApplyDisjunction();
5038-
50395037
/// Solve the system of constraints generated from provided expression.
50405038
///
50415039
/// \param target The target to generate constraints from.
@@ -5295,19 +5293,6 @@ class ConstraintSystem {
52955293
typedef std::function<void(SmallVectorImpl<unsigned> &options)>
52965294
PartitionAppendCallback;
52975295

5298-
// Attempt to sort nominalTypes based on what we can discover about
5299-
// calls into the overloads in the disjunction that bindOverload is
5300-
// a part of.
5301-
void sortDesignatedTypes(SmallVectorImpl<NominalTypeDecl *> &nominalTypes,
5302-
Constraint *bindOverload);
5303-
5304-
// Partition the choices in a disjunction based on those that match
5305-
// the designated types for the operator that the disjunction was
5306-
// formed for.
5307-
void partitionForDesignatedTypes(ArrayRef<Constraint *> Choices,
5308-
ConstraintMatchLoop forEachChoice,
5309-
PartitionAppendCallback appendPartition);
5310-
53115296
// Partition the choices in the disjunction into groups that we will
53125297
// iterate over in an order appropriate to attempt to stop before we
53135298
// have to visit all of the options.

lib/Frontend/CompilerInvocation.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,6 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
742742
// Always enable operator designated types for the standard library.
743743
Opts.EnableOperatorDesignatedTypes |= FrontendOpts.ParseStdlib;
744744

745-
Opts.SolverEnableOperatorDesignatedTypes |=
746-
Args.hasArg(OPT_solver_enable_operator_designated_types);
747745
Opts.EnableOneWayClosureParameters |=
748746
Args.hasArg(OPT_experimental_one_way_closure_params);
749747

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,30 +1929,6 @@ Constraint *ConstraintSystem::getUnboundBindOverloadDisjunction(
19291929
return result->first;
19301930
}
19311931

1932-
// Find a disjunction associated with an ApplicableFunction constraint
1933-
// where we have some information about all of the types of in the
1934-
// function application (even if we only know something about what the
1935-
// types conform to and not actually a concrete type).
1936-
Constraint *ConstraintSystem::selectApplyDisjunction() {
1937-
for (auto &constraint : InactiveConstraints) {
1938-
if (constraint.getKind() != ConstraintKind::ApplicableFunction)
1939-
continue;
1940-
1941-
auto *applicable = &constraint;
1942-
if (haveTypeInformationForAllArguments(
1943-
applicable->getFirstType()->castTo<FunctionType>())) {
1944-
auto *tyvar = applicable->getSecondType()->castTo<TypeVariableType>();
1945-
1946-
// If we have created the disjunction for this apply, find it.
1947-
auto *disjunction = getUnboundBindOverloadDisjunction(tyvar);
1948-
if (disjunction)
1949-
return disjunction;
1950-
}
1951-
}
1952-
1953-
return nullptr;
1954-
}
1955-
19561932
static bool isOperatorBindOverload(Constraint *bindOverload) {
19571933
if (bindOverload->getKind() != ConstraintKind::BindOverload)
19581934
return false;
@@ -1965,165 +1941,6 @@ static bool isOperatorBindOverload(Constraint *bindOverload) {
19651941
return funcDecl && funcDecl->getOperatorDecl();
19661942
}
19671943

1968-
// Given a bind overload constraint for an operator, return the
1969-
// protocol designated as the first place to look for overloads of the
1970-
// operator.
1971-
static ArrayRef<NominalTypeDecl *>
1972-
getOperatorDesignatedNominalTypes(Constraint *bindOverload) {
1973-
auto choice = bindOverload->getOverloadChoice();
1974-
auto *funcDecl = cast<FuncDecl>(choice.getDecl());
1975-
auto *operatorDecl = funcDecl->getOperatorDecl();
1976-
return operatorDecl->getDesignatedNominalTypes();
1977-
}
1978-
1979-
void ConstraintSystem::sortDesignatedTypes(
1980-
SmallVectorImpl<NominalTypeDecl *> &nominalTypes,
1981-
Constraint *bindOverload) {
1982-
auto *tyvar = bindOverload->getFirstType()->castTo<TypeVariableType>();
1983-
auto applicableFns = getConstraintGraph().gatherConstraints(
1984-
tyvar, ConstraintGraph::GatheringKind::EquivalenceClass,
1985-
[](Constraint *match) {
1986-
return match->getKind() == ConstraintKind::ApplicableFunction;
1987-
});
1988-
1989-
// FIXME: This is not true when we run the constraint optimizer.
1990-
// assert(applicableFns.size() <= 1);
1991-
1992-
// We have a disjunction for an operator but no application of it,
1993-
// so it's being passed as an argument.
1994-
if (applicableFns.size() == 0)
1995-
return;
1996-
1997-
// FIXME: We have more than one applicable per disjunction as a
1998-
// result of merging disjunction type variables. We may want
1999-
// to rip that out at some point.
2000-
Constraint *foundApplicable = nullptr;
2001-
SmallVector<Optional<Type>, 2> argumentTypes;
2002-
for (auto *applicableFn : applicableFns) {
2003-
argumentTypes.clear();
2004-
auto *fnTy = applicableFn->getFirstType()->castTo<FunctionType>();
2005-
ArgumentInfoCollector argInfo(*this, fnTy);
2006-
// Stop if we hit anything with concrete types or conformances to
2007-
// literals.
2008-
if (!argInfo.getTypes().empty() || !argInfo.getLiteralProtocols().empty()) {
2009-
foundApplicable = applicableFn;
2010-
break;
2011-
}
2012-
}
2013-
2014-
if (!foundApplicable)
2015-
return;
2016-
2017-
// FIXME: It would be good to avoid this redundancy.
2018-
auto *fnTy = foundApplicable->getFirstType()->castTo<FunctionType>();
2019-
ArgumentInfoCollector argInfo(*this, fnTy);
2020-
2021-
size_t nextType = 0;
2022-
for (auto argType : argInfo.getTypes()) {
2023-
auto *nominal = argType->getAnyNominal();
2024-
for (size_t i = nextType; i < nominalTypes.size(); ++i) {
2025-
if (nominal == nominalTypes[i]) {
2026-
std::swap(nominalTypes[nextType], nominalTypes[i]);
2027-
++nextType;
2028-
break;
2029-
} else if (auto *protoDecl = dyn_cast<ProtocolDecl>(nominalTypes[i])) {
2030-
if (TypeChecker::conformsToProtocol(argType, protoDecl, DC)) {
2031-
std::swap(nominalTypes[nextType], nominalTypes[i]);
2032-
++nextType;
2033-
break;
2034-
}
2035-
}
2036-
}
2037-
}
2038-
2039-
if (nextType + 1 >= nominalTypes.size())
2040-
return;
2041-
2042-
for (auto *protocol : argInfo.getLiteralProtocols()) {
2043-
auto defaultType = TypeChecker::getDefaultType(protocol, DC);
2044-
// ExpressibleByNilLiteral does not have a default type.
2045-
if (!defaultType)
2046-
continue;
2047-
auto *nominal = defaultType->getAnyNominal();
2048-
for (size_t i = nextType + 1; i < nominalTypes.size(); ++i) {
2049-
if (nominal == nominalTypes[i]) {
2050-
std::swap(nominalTypes[nextType], nominalTypes[i]);
2051-
++nextType;
2052-
break;
2053-
}
2054-
}
2055-
}
2056-
}
2057-
2058-
void ConstraintSystem::partitionForDesignatedTypes(
2059-
ArrayRef<Constraint *> Choices, ConstraintMatchLoop forEachChoice,
2060-
PartitionAppendCallback appendPartition) {
2061-
2062-
auto types = getOperatorDesignatedNominalTypes(Choices[0]);
2063-
if (types.empty())
2064-
return;
2065-
2066-
SmallVector<NominalTypeDecl *, 4> designatedNominalTypes(types.begin(),
2067-
types.end());
2068-
2069-
if (designatedNominalTypes.size() > 1)
2070-
sortDesignatedTypes(designatedNominalTypes, Choices[0]);
2071-
2072-
SmallVector<SmallVector<unsigned, 4>, 4> definedInDesignatedType;
2073-
SmallVector<SmallVector<unsigned, 4>, 4> definedInExtensionOfDesignatedType;
2074-
2075-
auto examineConstraint =
2076-
[&](unsigned constraintIndex, Constraint *constraint) -> bool {
2077-
auto *decl = constraint->getOverloadChoice().getDecl();
2078-
auto *funcDecl = cast<FuncDecl>(decl);
2079-
2080-
auto *parentDC = funcDecl->getParent();
2081-
auto *parentDecl = parentDC->getSelfNominalTypeDecl();
2082-
2083-
// Skip anything not defined in a nominal type.
2084-
if (!parentDecl)
2085-
return false;
2086-
2087-
for (auto designatedTypeIndex : indices(designatedNominalTypes)) {
2088-
auto *designatedNominal =
2089-
designatedNominalTypes[designatedTypeIndex];
2090-
2091-
if (parentDecl != designatedNominal)
2092-
continue;
2093-
2094-
auto &constraints =
2095-
isa<ExtensionDecl>(parentDC)
2096-
? definedInExtensionOfDesignatedType[designatedTypeIndex]
2097-
: definedInDesignatedType[designatedTypeIndex];
2098-
2099-
constraints.push_back(constraintIndex);
2100-
return true;
2101-
}
2102-
2103-
return false;
2104-
};
2105-
2106-
definedInDesignatedType.resize(designatedNominalTypes.size());
2107-
definedInExtensionOfDesignatedType.resize(designatedNominalTypes.size());
2108-
2109-
forEachChoice(Choices, examineConstraint);
2110-
2111-
// Now collect the overload choices that are defined within the type
2112-
// that was designated in the operator declaration.
2113-
// Add partitions for each of the overloads we found in types that
2114-
// were designated as part of the operator declaration.
2115-
for (auto designatedTypeIndex : indices(designatedNominalTypes)) {
2116-
if (designatedTypeIndex < definedInDesignatedType.size()) {
2117-
auto &primary = definedInDesignatedType[designatedTypeIndex];
2118-
appendPartition(primary);
2119-
}
2120-
if (designatedTypeIndex < definedInExtensionOfDesignatedType.size()) {
2121-
auto &secondary = definedInExtensionOfDesignatedType[designatedTypeIndex];
2122-
appendPartition(secondary);
2123-
}
2124-
}
2125-
}
2126-
21271944
// Performance hack: if there are two generic overloads, and one is
21281945
// more specialized than the other, prefer the more-specialized one.
21291946
static Constraint *tryOptimizeGenericDisjunction(
@@ -2266,8 +2083,7 @@ void ConstraintSystem::partitionDisjunction(
22662083
}
22672084

22682085
// Partition SIMD operators.
2269-
if (!getASTContext().TypeCheckerOpts.SolverEnableOperatorDesignatedTypes &&
2270-
isOperatorBindOverload(Choices[0])) {
2086+
if (isOperatorBindOverload(Choices[0])) {
22712087
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
22722088
if (!isOperatorBindOverload(constraint))
22732089
return false;
@@ -2291,11 +2107,6 @@ void ConstraintSystem::partitionDisjunction(
22912107
}
22922108
};
22932109

2294-
if (getASTContext().TypeCheckerOpts.SolverEnableOperatorDesignatedTypes &&
2295-
isOperatorBindOverload(Choices[0])) {
2296-
partitionForDesignatedTypes(Choices, forEachChoice, appendPartition);
2297-
}
2298-
22992110
SmallVector<unsigned, 4> everythingElse;
23002111
// Gather the remaining options.
23012112
forEachChoice(Choices, [&](unsigned index, Constraint *constraint) -> bool {
@@ -2320,17 +2131,6 @@ Constraint *ConstraintSystem::selectDisjunction() {
23202131
if (disjunctions.empty())
23212132
return nullptr;
23222133

2323-
// Attempt apply disjunctions first. When we have operators with
2324-
// designated types, this is important, because it allows us to
2325-
// select all the preferred operator overloads prior to other
2326-
// disjunctions that we may not be able to short-circuit, allowing
2327-
// us to eliminate behavior that is exponential in the number of
2328-
// operators in the expression.
2329-
if (getASTContext().TypeCheckerOpts.SolverEnableOperatorDesignatedTypes) {
2330-
if (auto *disjunction = selectApplyDisjunction())
2331-
return disjunction;
2332-
}
2333-
23342134
if (auto *disjunction = selectBestBindingDisjunction(*this, disjunctions))
23352135
return disjunction;
23362136

lib/Sema/CSStep.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,7 @@ bool DisjunctionStep::shortCircuitDisjunctionAt(
660660
if (currentChoice->getKind() == ConstraintKind::BindOverload &&
661661
isSIMDOperator(currentChoice->getOverloadChoice().getDecl()) &&
662662
lastSuccessfulChoice->getKind() == ConstraintKind::BindOverload &&
663-
!isSIMDOperator(lastSuccessfulChoice->getOverloadChoice().getDecl()) &&
664-
!ctx.TypeCheckerOpts.SolverEnableOperatorDesignatedTypes) {
663+
!isSIMDOperator(lastSuccessfulChoice->getOverloadChoice().getDecl())) {
665664
return true;
666665
}
667666

test/Constraints/add_with_nil.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -swift-version 5 -solver-enable-operator-designated-types -solver-disable-shrink -disable-constraint-solver-performance-hacks
1+
// RUN: %target-typecheck-verify-swift -swift-version 5
22

33
func test(_ x: Int) -> Int {
44
return x + nil

test/attr/attr_implements_fp.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: echo 'main()' >%t/main.swift
3-
// RUN: %target-swiftc_driver -o %t/a.out %s %t/main.swift -Xfrontend -enable-operator-designated-types -Xfrontend -solver-enable-operator-designated-types
3+
// RUN: %target-swiftc_driver -o %t/a.out %s %t/main.swift
44
// RUN: %target-codesign %t/a.out
55
// RUN: %target-run %t/a.out | %FileCheck %s
66
// REQUIRES: executable_test
@@ -13,7 +13,7 @@
1313
public var comparedAsCauxmparablesCount : Int = 0
1414
public var comparedAsFauxtsCount : Int = 0
1515

16-
infix operator .< : ComparisonPrecedence, BinaryFauxtingPoint, Cauxmparable
16+
infix operator .< : ComparisonPrecedence
1717

1818
public protocol Cauxmparable {
1919
static func .< (lhs: Self, rhs: Self) -> Bool

test/attr/attr_implements_serial.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: echo 'client()' >%t/main.swift
3-
// RUN: %target-build-swift-dylib(%t/%target-library-name(AttrImplFP)) -module-name AttrImplFP -emit-module -emit-module-path %t/AttrImplFP.swiftmodule %S/attr_implements_fp.swift -Xfrontend -enable-operator-designated-types -Xfrontend -solver-enable-operator-designated-types
3+
// RUN: %target-build-swift-dylib(%t/%target-library-name(AttrImplFP)) -module-name AttrImplFP -emit-module -emit-module-path %t/AttrImplFP.swiftmodule %S/attr_implements_fp.swift
44
// RUN: %target-build-swift -I %t -o %t/a.out %s %t/main.swift -L %t %target-rpath(%t) -lAttrImplFP
55
// RUN: %target-codesign %t/a.out
66
// RUN: %target-codesign %t/%target-library-name(AttrImplFP)
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// RUN: %target-typecheck-verify-swift -swift-version 4 -solver-expression-time-threshold=1 -solver-disable-shrink -disable-constraint-solver-performance-hacks -solver-enable-operator-designated-types
1+
// RUN: %target-typecheck-verify-swift -swift-version 4 -solver-expression-time-threshold=1
22
// REQUIRES: tools-release,no_asan
33

44
func test(_ i: Int, _ j: Int) -> Int {
55
return 1 + (((i >> 1) + (i >> 2) + (i >> 3) + (i >> 4) << 1) << 1) & 0x40 +
66
1 + (((i >> 1) + (i >> 2) + (i >> 3) + (i >> 4) << 1) << 1) & 0x40 +
77
1 + (((i >> 1) + (i >> 2) + (i >> 3) + (i >> 4) << 1) << 1) & 0x40
8+
// expected-error@-1 {{the compiler is unable to type-check this expression in reasonable time}}
89
}

0 commit comments

Comments
 (0)