Skip to content

Commit b3f05e1

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

File tree

56 files changed

+2216
-1739
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

+2216
-1739
lines changed

include/swift/Basic/LangOptions.h

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

978-
/// Disable the shrink phase of the expression type checker.
979-
bool SolverDisableShrink = false;
980-
981978
/// Enable experimental operator designated types feature.
982979
bool EnableOperatorDesignatedTypes = false;
983980

include/swift/Option/FrontendOptions.td

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

855-
def solver_disable_shrink :
856-
Flag<["-"], "solver-disable-shrink">,
857-
HelpText<"Disable the shrink phase of expression type checking">;
858-
859855
def solver_disable_splitter : Flag<["-"], "solver-disable-splitter">,
860856
HelpText<"Disable the component splitter phase of expression type checking">;
861857

include/swift/Sema/Constraint.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -852,11 +852,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,
852852
});
853853
}
854854

855-
/// Returns the number of resolved argument types for an applied disjunction
856-
/// constraint. This is always zero for disjunctions that do not represent
857-
/// an applied overload.
858-
unsigned countResolvedArgumentTypes(ConstraintSystem &cs) const;
859-
860855
/// Determine if this constraint represents explicit conversion,
861856
/// e.g. coercion constraint "as X" which forms a disjunction.
862857
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
///
@@ -5376,19 +5303,11 @@ class ConstraintSystem {
53765303
/// \returns true if an error occurred, false otherwise.
53775304
bool solveSimplified(SmallVectorImpl<Solution> &solutions);
53785305

5379-
/// Find reduced domains of disjunction constraints for given
5380-
/// expression, this is achieved to solving individual sub-expressions
5381-
/// and combining resolving types. Such algorithm is called directional
5382-
/// path consistency because it goes from children to parents for all
5383-
/// related sub-expressions taking union of their domains.
5384-
///
5385-
/// \param expr The expression to find reductions for.
5386-
void shrink(Expr *expr);
5387-
53885306
/// Pick a disjunction from the InactiveConstraints list.
53895307
///
5390-
/// \returns The selected disjunction.
5391-
Constraint *selectDisjunction();
5308+
/// \returns The selected disjunction and a set of it's favored choices.
5309+
std::optional<std::pair<Constraint *, llvm::TinyPtrVector<Constraint *>>>
5310+
selectDisjunction();
53925311

53935312
/// Pick a conjunction from the InactiveConstraints list.
53945313
///
@@ -5577,11 +5496,6 @@ class ConstraintSystem {
55775496
bool applySolutionToBody(TapExpr *tapExpr,
55785497
SyntacticElementTargetRewriter &rewriter);
55795498

5580-
/// Reorder the disjunctive clauses for a given expression to
5581-
/// increase the likelihood that a favored constraint will be successfully
5582-
/// resolved before any others.
5583-
void optimizeConstraints(Expr *e);
5584-
55855499
void startExpressionTimer(ExpressionTimer::AnchorType anchor);
55865500

55875501
/// Determine if we've already explored too many paths in an
@@ -6322,7 +6236,8 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63226236
public:
63236237
using Element = DisjunctionChoice;
63246238

6325-
DisjunctionChoiceProducer(ConstraintSystem &cs, Constraint *disjunction)
6239+
DisjunctionChoiceProducer(ConstraintSystem &cs, Constraint *disjunction,
6240+
llvm::TinyPtrVector<Constraint *> &favorites)
63266241
: BindingProducer(cs, disjunction->shouldRememberChoice()
63276242
? disjunction->getLocator()
63286243
: nullptr),
@@ -6332,6 +6247,11 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63326247
assert(disjunction->getKind() == ConstraintKind::Disjunction);
63336248
assert(!disjunction->shouldRememberChoice() || disjunction->getLocator());
63346249

6250+
// Mark constraints as favored. This information
6251+
// is going to be used by partitioner.
6252+
for (auto *choice : favorites)
6253+
cs.favorConstraint(choice);
6254+
63356255
// Order and partition the disjunction choices.
63366256
partitionDisjunction(Ordering, PartitionBeginning);
63376257
}
@@ -6376,8 +6296,9 @@ class DisjunctionChoiceProducer : public BindingProducer<DisjunctionChoice> {
63766296
// Partition the choices in the disjunction into groups that we will
63776297
// iterate over in an order appropriate to attempt to stop before we
63786298
// have to visit all of the options.
6379-
void partitionDisjunction(SmallVectorImpl<unsigned> &Ordering,
6380-
SmallVectorImpl<unsigned> &PartitionBeginning);
6299+
void
6300+
partitionDisjunction(SmallVectorImpl<unsigned> &Ordering,
6301+
SmallVectorImpl<unsigned> &PartitionBeginning);
63816302

63826303
/// Partition the choices in the range \c first to \c last into groups and
63836304
/// 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
@@ -2015,9 +2015,6 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
20152015
Opts.DebugForbidTypecheckPrefixes.push_back(A);
20162016
}
20172017

2018-
if (Args.getLastArg(OPT_solver_disable_shrink))
2019-
Opts.SolverDisableShrink = true;
2020-
20212018
if (Args.getLastArg(OPT_solver_disable_splitter))
20222019
Opts.SolverDisableSplitter = true;
20232020

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_swift_host_library(swiftSema STATIC
1414
CSStep.cpp
1515
CSTrail.cpp
1616
CSFix.cpp
17+
CSOptimizer.cpp
1718
CSDiagnostics.cpp
1819
CodeSynthesis.cpp
1920
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

@@ -1348,7 +1353,31 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) {
13481353
if (!existingNTD || NTD != existingNTD)
13491354
continue;
13501355

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

13531382
// If new type has a type variable it shouldn't
13541383
// be considered viable.

0 commit comments

Comments
 (0)