Skip to content

Sema: Some small cleanups in CSBindings.cpp and related code #78267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,13 +913,6 @@ namespace swift {
/// is for testing purposes.
std::vector<std::string> DebugForbidTypecheckPrefixes;

/// The upper bound to number of sub-expressions unsolved
/// before termination of the shrink phrase of the constraint solver.
unsigned SolverShrinkUnsolvedThreshold = 10;

/// Disable the shrink phase of the expression type checker.
bool SolverDisableShrink = false;

/// Enable experimental operator designated types feature.
bool EnableOperatorDesignatedTypes = false;

Expand All @@ -935,6 +928,9 @@ namespace swift {
/// Allow request evalutation to perform type checking lazily, instead of
/// eagerly typechecking source files after parsing.
bool EnableLazyTypecheck = false;

/// Disable the component splitter phase of the expression type checker.
bool SolverDisableSplitter = false;
};

/// Options for controlling the behavior of the Clang importer.
Expand Down
14 changes: 8 additions & 6 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -825,15 +825,17 @@ def downgrade_typecheck_interface_error : Flag<["-"], "downgrade-typecheck-inter
def enable_volatile_modules : Flag<["-"], "enable-volatile-modules">,
HelpText<"Load Swift modules in memory">;

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

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

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

def solver_disable_shrink :
Flag<["-"], "solver-disable-shrink">,
HelpText<"Disable the shrink phase of expression type checking">;
def solver_disable_splitter : Flag<["-"], "solver-disable-splitter">,
HelpText<"Disable the component splitter phase of expression type checking">;

def disable_constraint_solver_performance_hacks : Flag<["-"], "disable-constraint-solver-performance-hacks">,
HelpText<"Disable all the hacks in the constraint solver">;
Expand Down
56 changes: 12 additions & 44 deletions include/swift/Sema/CSBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ struct PotentialBindings {
Constraint *constraint);

void reset();

void dump(ConstraintSystem &CS,
TypeVariableType *TypeVar,
llvm::raw_ostream &out,
unsigned indent) const;
};


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

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

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

static BindingScore formBindingScore(const BindingSet &b);

/// Compare two sets of bindings, where \c x < y indicates that
/// \c x is a better set of bindings that \c y.
friend bool operator<(const BindingSet &x, const BindingSet &y) {
auto xScore = formBindingScore(x);
auto yScore = formBindingScore(y);

if (xScore < yScore)
return true;

if (yScore < xScore)
return false;

auto xDefaults = x.getNumViableDefaultableBindings();
auto yDefaults = y.getNumViableDefaultableBindings();

// If there is a difference in number of default types,
// prioritize bindings with fewer of them.
if (xDefaults != yDefaults)
return xDefaults < yDefaults;

// If neither type variable is a "hole" let's check whether
// there is a subtype relationship between them and prefer
// type variable which represents superclass first in order
// for "subtype" type variable to attempt more bindings later.
// This is required because algorithm can't currently infer
// bindings for subtype transitively through superclass ones.
if (!(std::get<0>(xScore) && std::get<0>(yScore))) {
if (x.Info.isSubtypeOf(y.getTypeVariable()))
return false;

if (y.Info.isSubtypeOf(x.getTypeVariable()))
return true;
}
bool operator==(const BindingSet &other);

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

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

Expand Down
39 changes: 25 additions & 14 deletions include/swift/Sema/ConstraintGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,24 @@ class ConstraintGraphNode {
/// as this type variable.
ArrayRef<TypeVariableType *> getEquivalenceClass() const;

inference::PotentialBindings &getCurrentBindings() {
assert(forRepresentativeVar());
return Bindings;
inference::PotentialBindings &getPotentialBindings() {
DEBUG_ASSERT(forRepresentativeVar());
return Potential;
}

void initBindingSet();

inference::BindingSet &getBindingSet() {
ASSERT(hasBindingSet());
return *Set;
}

bool hasBindingSet() const {
return Set.has_value();
}

void resetBindingSet() {
Set.reset();
}

private:
Expand Down Expand Up @@ -131,15 +146,6 @@ class ConstraintGraphNode {

/// Binding Inference {

/// Infer bindings from the given constraint and notify referenced variables
/// about its arrival (if requested). This happens every time a new constraint
/// gets added to a constraint graph node.
void introduceToInference(Constraint *constraint);

/// Forget about the given constraint. This happens every time a constraint
/// gets removed for a constraint graph.
void retractFromInference(Constraint *constraint);

/// Perform graph updates that must be undone after we bind a fixed type
/// to a type variable.
void retractFromInference(Type fixedType);
Expand Down Expand Up @@ -182,8 +188,13 @@ class ConstraintGraphNode {
/// The type variable this node represents.
TypeVariableType *TypeVar;

/// The set of bindings associated with this type variable.
inference::PotentialBindings Bindings;
/// The potential bindings for this type variable, updated incrementally by
/// the constraint graph.
inference::PotentialBindings Potential;

/// The binding set for this type variable, computed by
/// determineBestBindings().
std::optional<inference::BindingSet> Set;

/// The vector of constraints that mention this type variable, in a stable
/// order for iteration.
Expand Down
4 changes: 3 additions & 1 deletion include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -5161,7 +5161,9 @@ class ConstraintSystem {

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

private:
/// Add a constraint to the constraint system.
Expand Down
6 changes: 2 additions & 4 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1775,8 +1775,6 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
Opts.SolverScopeThreshold);
setUnsignedIntegerArgument(OPT_solver_trail_threshold_EQ,
Opts.SolverTrailThreshold);
setUnsignedIntegerArgument(OPT_solver_shrink_unsolved_threshold,
Opts.SolverShrinkUnsolvedThreshold);

Opts.DebugTimeFunctionBodies |= Args.hasArg(OPT_debug_time_function_bodies);
Opts.DebugTimeExpressions |=
Expand Down Expand Up @@ -1865,8 +1863,8 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
Opts.DebugForbidTypecheckPrefixes.push_back(A);
}

if (Args.getLastArg(OPT_solver_disable_shrink))
Opts.SolverDisableShrink = true;
if (Args.getLastArg(OPT_solver_disable_splitter))
Opts.SolverDisableSplitter = true;

if (FrontendOpts.RequestedAction == FrontendOptions::ActionType::Immediate)
Opts.DeferToRuntime = true;
Expand Down
Loading