Skip to content

Commit d1d2411

Browse files
authored
Merge pull request #78267 from slavapestov/incremental-bindings-part-0
Sema: Some small cleanups in CSBindings.cpp and related code
2 parents a5cc53f + 9a48fed commit d1d2411

15 files changed

+327
-222
lines changed

include/swift/Basic/LangOptions.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -913,13 +913,6 @@ namespace swift {
913913
/// is for testing purposes.
914914
std::vector<std::string> DebugForbidTypecheckPrefixes;
915915

916-
/// The upper bound to number of sub-expressions unsolved
917-
/// before termination of the shrink phrase of the constraint solver.
918-
unsigned SolverShrinkUnsolvedThreshold = 10;
919-
920-
/// Disable the shrink phase of the expression type checker.
921-
bool SolverDisableShrink = false;
922-
923916
/// Enable experimental operator designated types feature.
924917
bool EnableOperatorDesignatedTypes = false;
925918

@@ -935,6 +928,9 @@ namespace swift {
935928
/// Allow request evalutation to perform type checking lazily, instead of
936929
/// eagerly typechecking source files after parsing.
937930
bool EnableLazyTypecheck = false;
931+
932+
/// Disable the component splitter phase of the expression type checker.
933+
bool SolverDisableSplitter = false;
938934
};
939935

940936
/// Options for controlling the behavior of the Clang importer.

include/swift/Option/FrontendOptions.td

+8-6
Original file line numberDiff line numberDiff line change
@@ -825,15 +825,17 @@ def downgrade_typecheck_interface_error : Flag<["-"], "downgrade-typecheck-inter
825825
def enable_volatile_modules : Flag<["-"], "enable-volatile-modules">,
826826
HelpText<"Load Swift modules in memory">;
827827

828-
def solver_expression_time_threshold_EQ : Joined<["-"], "solver-expression-time-threshold=">;
828+
def solver_expression_time_threshold_EQ : Joined<["-"], "solver-expression-time-threshold=">,
829+
HelpText<"Expression type checking timeout, in seconds">;
829830

830-
def solver_scope_threshold_EQ : Joined<["-"], "solver-scope-threshold=">;
831+
def solver_scope_threshold_EQ : Joined<["-"], "solver-scope-threshold=">,
832+
HelpText<"Expression type checking scope limit">;
831833

832-
def solver_trail_threshold_EQ : Joined<["-"], "solver-trail-threshold=">;
834+
def solver_trail_threshold_EQ : Joined<["-"], "solver-trail-threshold=">,
835+
HelpText<"Expression type checking trail change limit">;
833836

834-
def solver_disable_shrink :
835-
Flag<["-"], "solver-disable-shrink">,
836-
HelpText<"Disable the shrink phase of expression type checking">;
837+
def solver_disable_splitter : Flag<["-"], "solver-disable-splitter">,
838+
HelpText<"Disable the component splitter phase of expression type checking">;
837839

838840
def disable_constraint_solver_performance_hacks : Flag<["-"], "disable-constraint-solver-performance-hacks">,
839841
HelpText<"Disable all the hacks in the constraint solver">;

include/swift/Sema/CSBindings.h

+12-44
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,11 @@ struct PotentialBindings {
301301
Constraint *constraint);
302302

303303
void reset();
304+
305+
void dump(ConstraintSystem &CS,
306+
TypeVariableType *TypeVar,
307+
llvm::raw_ostream &out,
308+
unsigned indent) const;
304309
};
305310

306311

@@ -567,64 +572,27 @@ class BindingSet {
567572
///
568573
/// \param inferredBindings The set of all bindings inferred for type
569574
/// variables in the workset.
570-
void inferTransitiveBindings(
571-
const llvm::SmallDenseMap<TypeVariableType *, BindingSet>
572-
&inferredBindings);
575+
void inferTransitiveBindings();
573576

574577
/// Detect subtype, conversion or equivalence relationship
575578
/// between two type variables and attempt to propagate protocol
576579
/// requirements down the subtype or equivalence chain.
577-
void inferTransitiveProtocolRequirements(
578-
llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings);
580+
void inferTransitiveProtocolRequirements();
579581

580582
/// Finalize binding computation for this type variable by
581583
/// inferring bindings from context e.g. transitive bindings.
582584
///
583585
/// \returns true if finalization successful (which makes binding set viable),
584586
/// and false otherwise.
585-
bool finalize(
586-
llvm::SmallDenseMap<TypeVariableType *, BindingSet> &inferredBindings);
587+
bool finalize(bool transitive);
587588

588589
static BindingScore formBindingScore(const BindingSet &b);
589590

590-
/// Compare two sets of bindings, where \c x < y indicates that
591-
/// \c x is a better set of bindings that \c y.
592-
friend bool operator<(const BindingSet &x, const BindingSet &y) {
593-
auto xScore = formBindingScore(x);
594-
auto yScore = formBindingScore(y);
595-
596-
if (xScore < yScore)
597-
return true;
598-
599-
if (yScore < xScore)
600-
return false;
601-
602-
auto xDefaults = x.getNumViableDefaultableBindings();
603-
auto yDefaults = y.getNumViableDefaultableBindings();
604-
605-
// If there is a difference in number of default types,
606-
// prioritize bindings with fewer of them.
607-
if (xDefaults != yDefaults)
608-
return xDefaults < yDefaults;
609-
610-
// If neither type variable is a "hole" let's check whether
611-
// there is a subtype relationship between them and prefer
612-
// type variable which represents superclass first in order
613-
// for "subtype" type variable to attempt more bindings later.
614-
// This is required because algorithm can't currently infer
615-
// bindings for subtype transitively through superclass ones.
616-
if (!(std::get<0>(xScore) && std::get<0>(yScore))) {
617-
if (x.Info.isSubtypeOf(y.getTypeVariable()))
618-
return false;
619-
620-
if (y.Info.isSubtypeOf(x.getTypeVariable()))
621-
return true;
622-
}
591+
bool operator==(const BindingSet &other);
623592

624-
// As a last resort, let's check if the bindings are
625-
// potentially incomplete, and if so, let's de-prioritize them.
626-
return x.isPotentiallyIncomplete() < y.isPotentiallyIncomplete();
627-
}
593+
/// Compare two sets of bindings, where \c this < other indicates that
594+
/// \c this is a better set of bindings that \c other.
595+
bool operator<(const BindingSet &other);
628596

629597
void dump(llvm::raw_ostream &out, unsigned indent) const;
630598

include/swift/Sema/ConstraintGraph.h

+25-14
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,24 @@ class ConstraintGraphNode {
8484
/// as this type variable.
8585
ArrayRef<TypeVariableType *> getEquivalenceClass() const;
8686

87-
inference::PotentialBindings &getCurrentBindings() {
88-
assert(forRepresentativeVar());
89-
return Bindings;
87+
inference::PotentialBindings &getPotentialBindings() {
88+
DEBUG_ASSERT(forRepresentativeVar());
89+
return Potential;
90+
}
91+
92+
void initBindingSet();
93+
94+
inference::BindingSet &getBindingSet() {
95+
ASSERT(hasBindingSet());
96+
return *Set;
97+
}
98+
99+
bool hasBindingSet() const {
100+
return Set.has_value();
101+
}
102+
103+
void resetBindingSet() {
104+
Set.reset();
90105
}
91106

92107
private:
@@ -131,15 +146,6 @@ class ConstraintGraphNode {
131146

132147
/// Binding Inference {
133148

134-
/// Infer bindings from the given constraint and notify referenced variables
135-
/// about its arrival (if requested). This happens every time a new constraint
136-
/// gets added to a constraint graph node.
137-
void introduceToInference(Constraint *constraint);
138-
139-
/// Forget about the given constraint. This happens every time a constraint
140-
/// gets removed for a constraint graph.
141-
void retractFromInference(Constraint *constraint);
142-
143149
/// Perform graph updates that must be undone after we bind a fixed type
144150
/// to a type variable.
145151
void retractFromInference(Type fixedType);
@@ -182,8 +188,13 @@ class ConstraintGraphNode {
182188
/// The type variable this node represents.
183189
TypeVariableType *TypeVar;
184190

185-
/// The set of bindings associated with this type variable.
186-
inference::PotentialBindings Bindings;
191+
/// The potential bindings for this type variable, updated incrementally by
192+
/// the constraint graph.
193+
inference::PotentialBindings Potential;
194+
195+
/// The binding set for this type variable, computed by
196+
/// determineBestBindings().
197+
std::optional<inference::BindingSet> Set;
187198

188199
/// The vector of constraints that mention this type variable, in a stable
189200
/// order for iteration.

include/swift/Sema/ConstraintSystem.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -5170,7 +5170,9 @@ class ConstraintSystem {
51705170

51715171
/// Get bindings for the given type variable based on current
51725172
/// state of the constraint system.
5173-
BindingSet getBindingsFor(TypeVariableType *typeVar, bool finalize = true);
5173+
///
5174+
/// FIXME: Remove this.
5175+
BindingSet getBindingsFor(TypeVariableType *typeVar);
51745176

51755177
private:
51765178
/// Add a constraint to the constraint system.

lib/Frontend/CompilerInvocation.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1772,8 +1772,6 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
17721772
Opts.SolverScopeThreshold);
17731773
setUnsignedIntegerArgument(OPT_solver_trail_threshold_EQ,
17741774
Opts.SolverTrailThreshold);
1775-
setUnsignedIntegerArgument(OPT_solver_shrink_unsolved_threshold,
1776-
Opts.SolverShrinkUnsolvedThreshold);
17771775

17781776
Opts.DebugTimeFunctionBodies |= Args.hasArg(OPT_debug_time_function_bodies);
17791777
Opts.DebugTimeExpressions |=
@@ -1862,8 +1860,8 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
18621860
Opts.DebugForbidTypecheckPrefixes.push_back(A);
18631861
}
18641862

1865-
if (Args.getLastArg(OPT_solver_disable_shrink))
1866-
Opts.SolverDisableShrink = true;
1863+
if (Args.getLastArg(OPT_solver_disable_splitter))
1864+
Opts.SolverDisableSplitter = true;
18671865

18681866
if (FrontendOpts.RequestedAction == FrontendOptions::ActionType::Immediate)
18691867
Opts.DeferToRuntime = true;

0 commit comments

Comments
 (0)