Skip to content

Commit ff26a2a

Browse files
committed
Revert "[ConstraintSystem] Revert new disjunction favoring algorithm (swiftlang#79128)"
This reverts commit 725bd91.
1 parent 80050bb commit ff26a2a

File tree

56 files changed

+2215
-1730
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
-1730
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
@@ -839,10 +839,6 @@ def solver_scope_threshold_EQ : Joined<["-"], "solver-scope-threshold=">,
839839
def solver_trail_threshold_EQ : Joined<["-"], "solver-trail-threshold=">,
840840
HelpText<"Expression type checking trail change limit">;
841841

842-
def solver_disable_shrink :
843-
Flag<["-"], "solver-disable-shrink">,
844-
HelpText<"Disable the shrink phase of expression type checking">;
845-
846842
def solver_disable_splitter : Flag<["-"], "solver-disable-splitter">,
847843
HelpText<"Disable the component splitter phase of expression type checking">;
848844

include/swift/Sema/Constraint.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -844,11 +844,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
844844
});
845845
}
846846

847-
/// Returns the number of resolved argument types for an applied disjunction
848-
/// constraint. This is always zero for disjunctions that do not represent
849-
/// an applied overload.
850-
unsigned countResolvedArgumentTypes(ConstraintSystem &cs) const;
851-
852847
/// Determine if this constraint represents explicit conversion,
853848
/// e.g. coercion constraint "as X" which forms a disjunction.
854849
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
///
@@ -2260,10 +2268,6 @@ class ConstraintSystem {
22602268

22612269
llvm::SetVector<TypeVariableType *> TypeVariables;
22622270

2263-
/// Maps expressions to types for choosing a favored overload
2264-
/// type in a disjunction constraint.
2265-
llvm::DenseMap<Expr *, TypeBase *> FavoredTypes;
2266-
22672271
/// Maps discovered closures to their types inferred
22682272
/// from declared parameters/result and body.
22692273
///
@@ -2474,74 +2478,6 @@ class ConstraintSystem {
24742478
SynthesizedConformances;
24752479

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

3068-
TypeBase* getFavoredType(Expr *E) {
3069-
assert(E != nullptr);
3070-
return this->FavoredTypes[E];
3071-
}
3072-
void setFavoredType(Expr *E, TypeBase *T) {
3073-
assert(E != nullptr);
3074-
this->FavoredTypes[E] = T;
3075-
}
3076-
30773004
/// Set the type in our type map for the given node, and record the change
30783005
/// in the trail.
30793006
///
@@ -5355,19 +5282,11 @@ class ConstraintSystem {
53555282
/// \returns true if an error occurred, false otherwise.
53565283
bool solveSimplified(SmallVectorImpl<Solution> &solutions);
53575284

5358-
/// Find reduced domains of disjunction constraints for given
5359-
/// expression, this is achieved to solving individual sub-expressions
5360-
/// and combining resolving types. Such algorithm is called directional
5361-
/// path consistency because it goes from children to parents for all
5362-
/// related sub-expressions taking union of their domains.
5363-
///
5364-
/// \param expr The expression to find reductions for.
5365-
void shrink(Expr *expr);
5366-
53675285
/// Pick a disjunction from the InactiveConstraints list.
53685286
///
5369-
/// \returns The selected disjunction.
5370-
Constraint *selectDisjunction();
5287+
/// \returns The selected disjunction and a set of it's favored choices.
5288+
std::optional<std::pair<Constraint *, llvm::TinyPtrVector<Constraint *>>>
5289+
selectDisjunction();
53715290

53725291
/// Pick a conjunction from the InactiveConstraints list.
53735292
///
@@ -5556,11 +5475,6 @@ class ConstraintSystem {
55565475
bool applySolutionToBody(TapExpr *tapExpr,
55575476
SyntacticElementTargetRewriter &rewriter);
55585477

5559-
/// Reorder the disjunctive clauses for a given expression to
5560-
/// increase the likelihood that a favored constraint will be successfully
5561-
/// resolved before any others.
5562-
void optimizeConstraints(Expr *e);
5563-
55645478
void startExpressionTimer(ExpressionTimer::AnchorType anchor);
55655479

55665480
/// Determine if we've already explored too many paths in an
@@ -6301,7 +6215,8 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63016215
public:
63026216
using Element = DisjunctionChoice;
63036217

6304-
DisjunctionChoiceProducer(ConstraintSystem &cs, Constraint *disjunction)
6218+
DisjunctionChoiceProducer(ConstraintSystem &cs, Constraint *disjunction,
6219+
llvm::TinyPtrVector<Constraint *> &favorites)
63056220
: BindingProducer(cs, disjunction->shouldRememberChoice()
63066221
? disjunction->getLocator()
63076222
: nullptr),
@@ -6311,6 +6226,11 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63116226
assert(disjunction->getKind() == ConstraintKind::Disjunction);
63126227
assert(!disjunction->shouldRememberChoice() || disjunction->getLocator());
63136228

6229+
// Mark constraints as favored. This information
6230+
// is going to be used by partitioner.
6231+
for (auto *choice : favorites)
6232+
cs.favorConstraint(choice);
6233+
63146234
// Order and partition the disjunction choices.
63156235
partitionDisjunction(Ordering, PartitionBeginning);
63166236
}
@@ -6355,8 +6275,9 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63556275
// Partition the choices in the disjunction into groups that we will
63566276
// iterate over in an order appropriate to attempt to stop before we
63576277
// have to visit all of the options.
6358-
void partitionDisjunction(SmallVectorImpl<unsigned> &Ordering,
6359-
SmallVectorImpl<unsigned> &PartitionBeginning);
6278+
void
6279+
partitionDisjunction(SmallVectorImpl<unsigned> &Ordering,
6280+
SmallVectorImpl<unsigned> &PartitionBeginning);
63606281

63616282
/// Partition the choices in the range \c first to \c last into groups and
63626283
/// 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
@@ -1859,9 +1859,6 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
18591859
Opts.DebugForbidTypecheckPrefixes.push_back(A);
18601860
}
18611861

1862-
if (Args.getLastArg(OPT_solver_disable_shrink))
1863-
Opts.SolverDisableShrink = true;
1864-
18651862
if (Args.getLastArg(OPT_solver_disable_splitter))
18661863
Opts.SolverDisableSplitter = true;
18671864

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

@@ -1335,7 +1340,31 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
13351340
if (!existingNTD || NTD != existingNTD)
13361341
continue;
13371342

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

13401369
// If new type has a type variable it shouldn't
13411370
// be considered viable.

0 commit comments

Comments
 (0)