Skip to content

Partial revert of https://github.com/swiftlang/swift/pull/78301 #79105

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 7 commits into from
Feb 2, 2025
11 changes: 11 additions & 0 deletions include/swift/Sema/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ enum class ConstraintKind : char {
/// The key path type is chosen based on the selection of overloads for the
/// member references along the path.
KeyPath,
/// The first type will be equal to the second type, but only when the
/// second type has been fully determined (and mapped down to a concrete
/// type). At that point, this constraint will be treated like an `Equal`
/// constraint.
OneWayEqual,
/// If there is no contextual info e.g. `_ = { 42 }` default first type
/// to a second type. This is effectively a `Defaultable` constraint
/// which one significant difference:
Expand Down Expand Up @@ -675,6 +680,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
case ConstraintKind::DynamicCallableApplicableFunction:
case ConstraintKind::BindOverload:
case ConstraintKind::OptionalObject:
case ConstraintKind::OneWayEqual:
case ConstraintKind::FallbackType:
case ConstraintKind::UnresolvedMemberChainBase:
case ConstraintKind::PackElementOf:
Expand Down Expand Up @@ -820,6 +826,11 @@ class Constraint final : public llvm::ilist_node<Constraint>,
/// from the rest of the constraint system.
bool isIsolated() const { return IsIsolated; }

/// Whether this is a one-way constraint.
bool isOneWayConstraint() const {
return Kind == ConstraintKind::OneWayEqual;
}

/// Retrieve the overload choice for an overload-binding constraint.
OverloadChoice getOverloadChoice() const {
assert(Kind == ConstraintKind::BindOverload);
Expand Down
38 changes: 28 additions & 10 deletions include/swift/Sema/ConstraintGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,18 +300,25 @@ class ConstraintGraph {
/// to a type variable.
void introduceToInference(TypeVariableType *typeVar, Type fixedType);

/// Gather constraints associated with all of the variables within the
/// same equivalence class as the given type variable, as well as its
/// immediate fixed bindings.
llvm::TinyPtrVector<Constraint *>
gatherAllConstraints(TypeVariableType *typeVar);
/// Describes which constraints \c gatherConstraints should gather.
enum class GatheringKind {
/// Gather constraints associated with all of the variables within the
/// same equivalence class as the given type variable, as well as its
/// immediate fixed bindings.
EquivalenceClass,
/// Gather all constraints that mention this type variable or type variables
/// that it is a fixed binding of. Unlike EquivalenceClass, this looks
/// through transitive fixed bindings. This can be used to find all the
/// constraints that may be affected when binding a type variable.
AllMentions,
};

/// Gather all constraints that mention this type variable or type variables
/// that it is a fixed binding of. Unlike EquivalenceClass, this looks
/// through transitive fixed bindings. This can be used to find all the
/// constraints that may be affected when binding a type variable.
/// Gather the set of constraints that involve the given type variable,
/// i.e., those constraints that will be affected when the type variable
/// gets merged or bound to a fixed type.
llvm::TinyPtrVector<Constraint *>
gatherNearbyConstraints(TypeVariableType *typeVar,
gatherConstraints(TypeVariableType *typeVar,
GatheringKind kind,
llvm::function_ref<bool(Constraint *)> acceptConstraint =
[](Constraint *constraint) { return true; });

Expand All @@ -336,6 +343,12 @@ class ConstraintGraph {
/// The constraints in this component.
TinyPtrVector<Constraint *> constraints;

/// The set of components that this component depends on, such that
/// the partial solutions of the those components need to be available
/// before this component can be solved.
///
SmallVector<unsigned, 2> dependencies;

public:
Component(unsigned solutionIndex) : solutionIndex(solutionIndex) { }

Expand All @@ -351,6 +364,11 @@ class ConstraintGraph {
return constraints;
}

/// Records a component which this component depends on.
void recordDependency(const Component &component);

ArrayRef<unsigned> getDependencies() const { return dependencies; }

unsigned getNumDisjunctions() const { return numDisjunctions; }
};

Expand Down
7 changes: 7 additions & 0 deletions include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -4516,6 +4516,7 @@ class ConstraintSystem {
/// \returns a possibly-sanitized initializer, or null if an error occurred.
[[nodiscard]]
Type generateConstraints(Pattern *P, ConstraintLocatorBuilder locator,
bool bindPatternVarsOneWay,
PatternBindingDecl *patternBinding,
unsigned patternIndex);

Expand Down Expand Up @@ -5022,6 +5023,12 @@ class ConstraintSystem {
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

/// Attempt to simplify a one-way constraint.
SolutionKind simplifyOneWayConstraint(ConstraintKind kind,
Type first, Type second,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

/// Simplify an equality constraint between result and base types of
/// an unresolved member chain.
SolutionKind simplifyUnresolvedMemberChainBaseConstraint(
Expand Down
16 changes: 14 additions & 2 deletions include/swift/Sema/SyntacticElementTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ class SyntacticElementTarget {
/// Whether the expression result will be discarded at the end.
bool isDiscarded;

/// Whether to bind the variables encountered within the pattern to
/// fresh type variables via one-way constraints.
bool bindPatternVarsOneWay;

union {
struct {
/// The pattern binding declaration for an initialization, if any.
Expand Down Expand Up @@ -251,14 +255,14 @@ class SyntacticElementTarget {
/// Form a target for the initialization of a pattern from an expression.
static SyntacticElementTarget
forInitialization(Expr *initializer, DeclContext *dc, Type patternType,
Pattern *pattern);
Pattern *pattern, bool bindPatternVarsOneWay);

/// Form a target for the initialization of a pattern binding entry from
/// an expression.
static SyntacticElementTarget
forInitialization(Expr *initializer, Type patternType,
PatternBindingDecl *patternBinding,
unsigned patternBindingIndex);
unsigned patternBindingIndex, bool bindPatternVarsOneWay);

/// Form an expression target for a ReturnStmt.
static SyntacticElementTarget
Expand Down Expand Up @@ -493,6 +497,14 @@ class SyntacticElementTarget {
return false;
}

/// Whether to bind the types of any variables within the pattern via
/// one-way constraints.
bool shouldBindPatternVarsOneWay() const {
if (kind == Kind::expression)
return expression.bindPatternVarsOneWay;
return false;
}

/// Whether or not an opaque value placeholder should be injected into the
/// first \c wrappedValue argument of an apply expression so the initializer
/// expression can be turned into a property wrapper generator function.
Expand Down
14 changes: 14 additions & 0 deletions lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,20 @@ void PotentialBindings::infer(ConstraintSystem &CS,

break;
}

case ConstraintKind::OneWayEqual:{
// Don't produce any bindings if this type variable is on the left-hand
// side of a one-way binding.
auto firstType = constraint->getFirstType();
if (auto *tv = firstType->getAs<TypeVariableType>()) {
if (tv->getImpl().getRepresentative(nullptr) == TypeVar) {
DelayedBy.push_back(constraint);
break;
}
}

break;
}
}
}

Expand Down
Loading