Skip to content

Commit 9128da4

Browse files
committed
Revert "[ConstraintSystem] Revert new disjunction favoring algorithm (swiftlang#79128)"
This reverts commit 725bd91.
1 parent 71f994d commit 9128da4

File tree

56 files changed

+2215
-1729
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2215
-1729
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -905,9 +905,6 @@ namespace swift {
905905
/// is for testing purposes.
906906
std::vector<std::string> DebugForbidTypecheckPrefixes;
907907

908-
/// Disable the shrink phase of the expression type checker.
909-
bool SolverDisableShrink = false;
910-
911908
/// Enable experimental operator designated types feature.
912909
bool EnableOperatorDesignatedTypes = false;
913910

include/swift/Option/FrontendOptions.td

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -836,10 +836,6 @@ def solver_scope_threshold_EQ : Joined<["-"], "solver-scope-threshold=">,
836836
def solver_trail_threshold_EQ : Joined<["-"], "solver-trail-threshold=">,
837837
HelpText<"Expression type checking trail change limit">;
838838

839-
def solver_disable_shrink :
840-
Flag<["-"], "solver-disable-shrink">,
841-
HelpText<"Disable the shrink phase of expression type checking">;
842-
843839
def solver_disable_splitter : Flag<["-"], "solver-disable-splitter">,
844840
HelpText<"Disable the component splitter phase of expression type checking">;
845841

include/swift/Sema/Constraint.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -840,11 +840,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
840840
});
841841
}
842842

843-
/// Returns the number of resolved argument types for an applied disjunction
844-
/// constraint. This is always zero for disjunctions that do not represent
845-
/// an applied overload.
846-
unsigned countResolvedArgumentTypes(ConstraintSystem &cs) const;
847-
848843
/// Determine if this constraint represents explicit conversion,
849844
/// e.g. coercion constraint "as X" which forms a disjunction.
850845
bool isExplicitConversion() const;

include/swift/Sema/ConstraintSystem.h

Lines changed: 21 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,14 @@ class TypeVariableType::Implementation {
488488
/// literal (represented by `ArrayExpr` and `DictionaryExpr` in AST).
489489
bool isCollectionLiteralType() const;
490490

491+
/// Determine whether this type variable represents a literal such
492+
/// as an integer value, a floating-point value with and without a sign.
493+
bool isNumberLiteralType() const;
494+
495+
/// Determine whether this type variable represents a result type of a
496+
/// function call.
497+
bool isFunctionResult() const;
498+
491499
/// Retrieve the representative of the equivalence class to which this
492500
/// type variable belongs.
493501
///
@@ -2242,10 +2250,6 @@ class ConstraintSystem {
22422250

22432251
llvm::SetVector<TypeVariableType *> TypeVariables;
22442252

2245-
/// Maps expressions to types for choosing a favored overload
2246-
/// type in a disjunction constraint.
2247-
llvm::DenseMap<Expr *, TypeBase *> FavoredTypes;
2248-
22492253
/// Maps discovered closures to their types inferred
22502254
/// from declared parameters/result and body.
22512255
///
@@ -2458,74 +2462,6 @@ class ConstraintSystem {
24582462
SynthesizedConformances;
24592463

24602464
private:
2461-
/// Describe the candidate expression for partial solving.
2462-
/// This class used by shrink & solve methods which apply
2463-
/// variation of directional path consistency algorithm in attempt
2464-
/// to reduce scopes of the overload sets (disjunctions) in the system.
2465-
class Candidate {
2466-
Expr *E;
2467-
DeclContext *DC;
2468-
llvm::BumpPtrAllocator &Allocator;
2469-
2470-
// Contextual Information.
2471-
Type CT;
2472-
ContextualTypePurpose CTP;
2473-
2474-
public:
2475-
Candidate(ConstraintSystem &cs, Expr *expr, Type ct = Type(),
2476-
ContextualTypePurpose ctp = ContextualTypePurpose::CTP_Unused)
2477-
: E(expr), DC(cs.DC), Allocator(cs.Allocator), CT(ct), CTP(ctp) {}
2478-
2479-
/// Return underlying expression.
2480-
Expr *getExpr() const { return E; }
2481-
2482-
/// Try to solve this candidate sub-expression
2483-
/// and re-write it's OSR domains afterwards.
2484-
///
2485-
/// \param shrunkExprs The set of expressions which
2486-
/// domains have been successfully shrunk so far.
2487-
///
2488-
/// \returns true on solver failure, false otherwise.
2489-
bool solve(llvm::SmallSetVector<OverloadSetRefExpr *, 4> &shrunkExprs);
2490-
2491-
/// Apply solutions found by solver as reduced OSR sets for
2492-
/// for current and all of it's sub-expressions.
2493-
///
2494-
/// \param solutions The solutions found by running solver on the
2495-
/// this candidate expression.
2496-
///
2497-
/// \param shrunkExprs The set of expressions which
2498-
/// domains have been successfully shrunk so far.
2499-
void applySolutions(
2500-
llvm::SmallVectorImpl<Solution> &solutions,
2501-
llvm::SmallSetVector<OverloadSetRefExpr *, 4> &shrunkExprs) const;
2502-
2503-
/// Check if attempt at solving of the candidate makes sense given
2504-
/// the current conditions - number of shrunk domains which is related
2505-
/// to the given candidate over the total number of disjunctions present.
2506-
static bool
2507-
isTooComplexGiven(ConstraintSystem *const cs,
2508-
llvm::SmallSetVector<OverloadSetRefExpr *, 4> &shrunkExprs) {
2509-
SmallVector<Constraint *, 8> disjunctions;
2510-
cs->collectDisjunctions(disjunctions);
2511-
2512-
unsigned unsolvedDisjunctions = disjunctions.size();
2513-
for (auto *disjunction : disjunctions) {
2514-
auto *locator = disjunction->getLocator();
2515-
if (!locator)
2516-
continue;
2517-
2518-
if (auto *OSR = getAsExpr<OverloadSetRefExpr>(locator->getAnchor())) {
2519-
if (shrunkExprs.count(OSR) > 0)
2520-
--unsolvedDisjunctions;
2521-
}
2522-
}
2523-
2524-
// The threshold used to be `TypeCheckerOpts.SolverShrinkUnsolvedThreshold`
2525-
return unsolvedDisjunctions >= 10;
2526-
}
2527-
};
2528-
25292465
/// Describes the current solver state.
25302466
struct SolverState {
25312467
SolverState(ConstraintSystem &cs,
@@ -3049,15 +2985,6 @@ class ConstraintSystem {
30492985
return nullptr;
30502986
}
30512987

3052-
TypeBase* getFavoredType(Expr *E) {
3053-
assert(E != nullptr);
3054-
return this->FavoredTypes[E];
3055-
}
3056-
void setFavoredType(Expr *E, TypeBase *T) {
3057-
assert(E != nullptr);
3058-
this->FavoredTypes[E] = T;
3059-
}
3060-
30612988
/// Set the type in our type map for the given node, and record the change
30622989
/// in the trail.
30632990
///
@@ -5318,19 +5245,11 @@ class ConstraintSystem {
53185245
/// \returns true if an error occurred, false otherwise.
53195246
bool solveSimplified(SmallVectorImpl<Solution> &solutions);
53205247

5321-
/// Find reduced domains of disjunction constraints for given
5322-
/// expression, this is achieved to solving individual sub-expressions
5323-
/// and combining resolving types. Such algorithm is called directional
5324-
/// path consistency because it goes from children to parents for all
5325-
/// related sub-expressions taking union of their domains.
5326-
///
5327-
/// \param expr The expression to find reductions for.
5328-
void shrink(Expr *expr);
5329-
53305248
/// Pick a disjunction from the InactiveConstraints list.
53315249
///
5332-
/// \returns The selected disjunction.
5333-
Constraint *selectDisjunction();
5250+
/// \returns The selected disjunction and a set of it's favored choices.
5251+
std::optional<std::pair<Constraint *, llvm::TinyPtrVector<Constraint *>>>
5252+
selectDisjunction();
53345253

53355254
/// Pick a conjunction from the InactiveConstraints list.
53365255
///
@@ -5519,11 +5438,6 @@ class ConstraintSystem {
55195438
bool applySolutionToBody(TapExpr *tapExpr,
55205439
SyntacticElementTargetRewriter &rewriter);
55215440

5522-
/// Reorder the disjunctive clauses for a given expression to
5523-
/// increase the likelihood that a favored constraint will be successfully
5524-
/// resolved before any others.
5525-
void optimizeConstraints(Expr *e);
5526-
55275441
void startExpressionTimer(ExpressionTimer::AnchorType anchor);
55285442

55295443
/// Determine if we've already explored too many paths in an
@@ -6264,7 +6178,8 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
62646178
public:
62656179
using Element = DisjunctionChoice;
62666180

6267-
DisjunctionChoiceProducer(ConstraintSystem &cs, Constraint *disjunction)
6181+
DisjunctionChoiceProducer(ConstraintSystem &cs, Constraint *disjunction,
6182+
llvm::TinyPtrVector<Constraint *> &favorites)
62686183
: BindingProducer(cs, disjunction->shouldRememberChoice()
62696184
? disjunction->getLocator()
62706185
: nullptr),
@@ -6274,6 +6189,11 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
62746189
assert(disjunction->getKind() == ConstraintKind::Disjunction);
62756190
assert(!disjunction->shouldRememberChoice() || disjunction->getLocator());
62766191

6192+
// Mark constraints as favored. This information
6193+
// is going to be used by partitioner.
6194+
for (auto *choice : favorites)
6195+
cs.favorConstraint(choice);
6196+
62776197
// Order and partition the disjunction choices.
62786198
partitionDisjunction(Ordering, PartitionBeginning);
62796199
}
@@ -6318,8 +6238,9 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63186238
// Partition the choices in the disjunction into groups that we will
63196239
// iterate over in an order appropriate to attempt to stop before we
63206240
// have to visit all of the options.
6321-
void partitionDisjunction(SmallVectorImpl<unsigned> &Ordering,
6322-
SmallVectorImpl<unsigned> &PartitionBeginning);
6241+
void
6242+
partitionDisjunction(SmallVectorImpl<unsigned> &Ordering,
6243+
SmallVectorImpl<unsigned> &PartitionBeginning);
63236244

63246245
/// Partition the choices in the range \c first to \c last into groups and
63256246
/// order the groups in the best order to attempt based on the argument

lib/Frontend/CompilerInvocation.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,9 +1856,6 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
18561856
Opts.DebugForbidTypecheckPrefixes.push_back(A);
18571857
}
18581858

1859-
if (Args.getLastArg(OPT_solver_disable_shrink))
1860-
Opts.SolverDisableShrink = true;
1861-
18621859
if (Args.getLastArg(OPT_solver_disable_splitter))
18631860
Opts.SolverDisableSplitter = true;
18641861

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ add_swift_host_library(swiftSema STATIC
1313
CSStep.cpp
1414
CSTrail.cpp
1515
CSFix.cpp
16+
CSOptimizer.cpp
1617
CSDiagnostics.cpp
1718
CodeSynthesis.cpp
1819
CodeSynthesisDistributedActor.cpp

lib/Sema/CSBindings.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ using namespace swift;
3131
using namespace constraints;
3232
using namespace inference;
3333

34-
3534
void ConstraintGraphNode::initBindingSet() {
3635
ASSERT(!hasBindingSet());
3736
ASSERT(forRepresentativeVar());
3837

3938
Set.emplace(CG.getConstraintSystem(), TypeVar, Potential);
4039
}
4140

41+
/// Check whether there exists a type that could be implicitly converted
42+
/// to a given type i.e. is the given type is Double or Optional<..> this
43+
/// function is going to return true because CGFloat could be converted
44+
/// to a Double and non-optional value could be injected into an optional.
45+
static bool hasConversions(Type);
46+
4247
static std::optional<Type> checkTypeOfBinding(TypeVariableType *typeVar,
4348
Type type);
4449

@@ -1333,7 +1338,31 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
13331338
if (!existingNTD || NTD != existingNTD)
13341339
continue;
13351340

1336-
// FIXME: What is going on here needs to be thoroughly re-evaluated.
1341+
// What is going on in this method needs to be thoroughly re-evaluated!
1342+
//
1343+
// This logic aims to skip dropping bindings if
1344+
// collection type has conversions i.e. in situations like:
1345+
//
1346+
// [$T1] conv $T2
1347+
// $T2 conv [(Int, String)]
1348+
// $T2.Element equal $T5.Element
1349+
//
1350+
// `$T1` could be bound to `(i: Int, v: String)` after
1351+
// `$T2` is bound to `[(Int, String)]` which is is a problem
1352+
// because it means that `$T2` was attempted to early
1353+
// before the solver had a chance to discover all viable
1354+
// bindings.
1355+
//
1356+
// Let's say existing binding is `[(Int, String)]` and
1357+
// relation is "exact", in this case there is no point
1358+
// tracking `[$T1]` because upcasts are only allowed for
1359+
// subtype and other conversions.
1360+
if (existing->Kind != AllowedBindingKind::Exact) {
1361+
if (existingType->isKnownStdlibCollectionType() &&
1362+
hasConversions(existingType)) {
1363+
continue;
1364+
}
1365+
}
13371366

13381367
// If new type has a type variable it shouldn't
13391368
// be considered viable.

0 commit comments

Comments
 (0)