Skip to content

Sema: Don't attempt deep equality if we're also attempting optional-to-optional #78958

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,9 @@ namespace swift {

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

/// Disable some experimental optimizations.
bool DisableOptimizedRestrictions = false;
};

/// Options for controlling the behavior of the Clang importer.
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,9 @@ def solver_disable_splitter : Flag<["-"], "solver-disable-splitter">,
def disable_constraint_solver_performance_hacks : Flag<["-"], "disable-constraint-solver-performance-hacks">,
HelpText<"Disable all the hacks in the constraint solver">;

def disable_optimized_restrictions : Flag<["-"], "disable-optimized-restrictions">,
HelpText<"Disable an experimental constraint solver optimization">;

def enable_operator_designated_types :
Flag<["-"], "enable-operator-designated-types">,
HelpText<"Enable operator designated types">;
Expand Down
87 changes: 25 additions & 62 deletions include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -4700,31 +4700,6 @@ class ConstraintSystem {
Error
};

class TypeMatchResult {
SolutionKind Kind;

public:
inline bool isSuccess() const { return Kind == SolutionKind::Solved; }
inline bool isFailure() const { return Kind == SolutionKind::Error; }
inline bool isAmbiguous() const { return Kind == SolutionKind::Unsolved; }

static TypeMatchResult success() {
return {SolutionKind::Solved};
}

static TypeMatchResult failure() {
return {SolutionKind::Error};
}

static TypeMatchResult ambiguous() {
return {SolutionKind::Unsolved};
}

operator SolutionKind() { return Kind; }
private:
TypeMatchResult(SolutionKind result) : Kind(result) {}
};

/// Attempt to repair typing failures and record fixes if needed.
/// \return true if at least some of the failures has been repaired
/// successfully, which allows type matcher to continue.
Expand All @@ -4733,12 +4708,12 @@ class ConstraintSystem {
SmallVectorImpl<RestrictionOrFix> &conversionsOrFixes,
ConstraintLocatorBuilder locator);

TypeMatchResult
SolutionKind
matchPackTypes(PackType *pack1, PackType *pack2,
ConstraintKind kind, TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

TypeMatchResult
SolutionKind
matchPackExpansionTypes(PackExpansionType *expansion1,
PackExpansionType *expansion2,
ConstraintKind kind, TypeMatchOptions flags,
Expand All @@ -4747,13 +4722,13 @@ class ConstraintSystem {
/// Subroutine of \c matchTypes(), which matches up two tuple types.
///
/// \returns the result of performing the tuple-to-tuple conversion.
TypeMatchResult matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
ConstraintKind kind, TypeMatchOptions flags,
ConstraintLocatorBuilder locator);
SolutionKind matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
ConstraintKind kind, TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

/// Subroutine of \c matchTypes(), which matches up two function
/// types.
TypeMatchResult matchFunctionTypes(FunctionType *func1, FunctionType *func2,
SolutionKind matchFunctionTypes(FunctionType *func1, FunctionType *func2,
ConstraintKind kind, TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

Expand All @@ -4764,14 +4739,14 @@ class ConstraintSystem {

/// Subroutine of \c matchTypes(), which matches up a value to a
/// superclass.
TypeMatchResult matchSuperclassTypes(Type type1, Type type2,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);
SolutionKind matchSuperclassTypes(Type type1, Type type2,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

/// Subroutine of \c matchTypes(), which matches up two types that
/// refer to the same declaration via their generic arguments.
TypeMatchResult matchDeepEqualityTypes(Type type1, Type type2,
ConstraintLocatorBuilder locator);
SolutionKind matchDeepEqualityTypes(Type type1, Type type2,
ConstraintLocatorBuilder locator);

/// Subroutine of \c matchTypes(), which matches up a value to an
/// existential type.
Expand All @@ -4780,23 +4755,23 @@ class ConstraintSystem {
/// Usually this uses Subtype, but when matching the instance type of a
/// metatype with the instance type of an existential metatype, since we
/// want an actual conformance check.
TypeMatchResult matchExistentialTypes(Type type1, Type type2,
ConstraintKind kind,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);
SolutionKind matchExistentialTypes(Type type1, Type type2,
ConstraintKind kind,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

/// Subroutine of \c matchTypes(), used to bind a type to a
/// type variable.
TypeMatchResult matchTypesBindTypeVar(
SolutionKind matchTypesBindTypeVar(
TypeVariableType *typeVar, Type type, ConstraintKind kind,
TypeMatchOptions flags, ConstraintLocatorBuilder locator,
llvm::function_ref<TypeMatchResult()> formUnsolvedResult);
llvm::function_ref<SolutionKind()> formUnsolvedResult);

/// Matches two function result types for a function application. This is
/// usually a bind, but also handles e.g IUO unwraps.
TypeMatchResult matchFunctionResultTypes(Type expectedResult, Type fnResult,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);
SolutionKind matchFunctionResultTypes(Type expectedResult, Type fnResult,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

public: // FIXME: public due to statics in CSSimplify.cpp
/// Attempt to match up types \c type1 and \c type2, which in effect
Expand All @@ -4816,21 +4791,9 @@ class ConstraintSystem {
/// the specific types being matched.
///
/// \returns the result of attempting to solve this constraint.
TypeMatchResult matchTypes(Type type1, Type type2, ConstraintKind kind,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

TypeMatchResult getTypeMatchSuccess() {
return TypeMatchResult::success();
}

TypeMatchResult getTypeMatchFailure(ConstraintLocatorBuilder locator) {
return TypeMatchResult::failure();
}

TypeMatchResult getTypeMatchAmbiguous() {
return TypeMatchResult::ambiguous();
}
SolutionKind matchTypes(Type type1, Type type2, ConstraintKind kind,
TypeMatchOptions flags,
ConstraintLocatorBuilder locator);

public:
// Build a disjunction that attempts both T? and T for a particular
Expand Down Expand Up @@ -5244,7 +5207,7 @@ class ConstraintSystem {
///
/// \returns \c None when the result builder cannot be applied at all,
/// otherwise the result of applying the result builder.
std::optional<TypeMatchResult>
std::optional<SolutionKind>
matchResultBuilder(AnyFunctionRef fn, Type builderType, Type bodyResultType,
ConstraintKind bodyResultConstraintKind,
Type contextualType, ConstraintLocatorBuilder locator);
Expand All @@ -5259,7 +5222,7 @@ class ConstraintSystem {

/// Matches a wrapped or projected value parameter type to its backing
/// property wrapper type by applying the property wrapper.
TypeMatchResult applyPropertyWrapperToParameter(
SolutionKind applyPropertyWrapperToParameter(
Type wrapperType, Type paramType, ParamDecl *param, Identifier argLabel,
ConstraintKind matchKind, ConstraintLocator *locator,
ConstraintLocator *calleeLocator);
Expand Down
3 changes: 3 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1865,6 +1865,9 @@ static bool ParseTypeCheckerArgs(TypeCheckerOptions &Opts, ArgList &Args,
if (Args.getLastArg(OPT_solver_disable_splitter))
Opts.SolverDisableSplitter = true;

if (Args.getLastArg(OPT_disable_optimized_restrictions))
Opts.DisableOptimizedRestrictions = true;

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

Expand Down
22 changes: 11 additions & 11 deletions lib/Sema/BuilderTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ TypeChecker::applyResultBuilderBodyTransform(FuncDecl *func, Type builderType) {
func, builderType, resultContextType, resultConstraintKind,
/*contextualType=*/Type(),
cs.getConstraintLocator(func->getBody()))) {
if (result->isFailure())
if (*result == ConstraintSystem::SolutionKind::Error)
return nullptr;
}

Expand Down Expand Up @@ -1106,7 +1106,7 @@ TypeChecker::applyResultBuilderBodyTransform(FuncDecl *func, Type builderType) {
return nullptr;
}

std::optional<ConstraintSystem::TypeMatchResult>
std::optional<ConstraintSystem::SolutionKind>
ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
Type bodyResultType,
ConstraintKind bodyResultConstraintKind,
Expand All @@ -1121,7 +1121,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
if (InvalidResultBuilderBodies.count(fn)) {
(void)recordFix(IgnoreInvalidResultBuilderBody::create(
*this, getConstraintLocator(fn.getAbstractClosureExpr())));
return getTypeMatchSuccess();
return SolutionKind::Solved;
}

// We have already pre-checked the result builder body. Technically, we
Expand All @@ -1137,9 +1137,9 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
if (recordFix(IgnoreResultBuilderWithReturnStmts::create(
*this, builderType,
getConstraintLocator(fn.getAbstractClosureExpr()))))
return getTypeMatchFailure(locator);
return SolutionKind::Error;

return getTypeMatchSuccess();
return SolutionKind::Solved;
}

// If the body has a return statement, suppress the transform but
Expand All @@ -1161,31 +1161,31 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,

// If we aren't supposed to attempt fixes, fail.
if (!shouldAttemptFixes()) {
return getTypeMatchFailure(locator);
return SolutionKind::Error;
}

// If we're solving for code completion and the body contains the code
// completion location, skipping it won't get us to a useful solution so
// just bail.
if (isForCodeCompletion() &&
containsIDEInspectionTarget(fn.getBody())) {
return getTypeMatchFailure(locator);
return SolutionKind::Error;
}

// Record the first unhandled construct as a fix.
if (recordFix(
SkipUnhandledConstructInResultBuilder::create(
*this, unsupported, builder, getConstraintLocator(locator)),
/*impact=*/100)) {
return getTypeMatchFailure(locator);
return SolutionKind::Error;
}

if (auto *closure =
getAsExpr<ClosureExpr>(fn.getAbstractClosureExpr())) {
recordTypeVariablesAsHoles(getClosureType(closure));
}

return getTypeMatchSuccess();
return SolutionKind::Solved;
}

transformedBody = std::make_pair(transform.getBuilderSelf(), body);
Expand Down Expand Up @@ -1216,9 +1216,9 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
recordResultBuilderTransform(fn, std::move(transformInfo));

if (generateConstraints(fn, transformInfo.transformedBody))
return getTypeMatchFailure(locator);
return SolutionKind::Error;

return getTypeMatchSuccess();
return SolutionKind::Solved;
}

void ConstraintSystem::recordResultBuilderTransform(AnyFunctionRef fn,
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2941,7 +2941,7 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
auto result =
cs.matchTypes(TypeVar, type, ConstraintKind::Bind, options, srcLocator);

if (result.isFailure()) {
if (result == ConstraintSystem::SolutionKind::Error) {
if (cs.isDebugMode()) {
PrintOptions PO;
PO.PrintTypesForDebugging = true;
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/CSFix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1793,7 +1793,7 @@ ExpandArrayIntoVarargs::attempt(ConstraintSystem &cs, Type argType,
auto result = cs.matchTypes(elementType, paramType, ConstraintKind::Subtype,
options, builder);

if (result.isFailure())
if (result == ConstraintSystem::SolutionKind::Error)
return nullptr;

return new (cs.getAllocator())
Expand Down Expand Up @@ -2089,7 +2089,7 @@ UnwrapOptionalBaseKeyPathApplication::attempt(ConstraintSystem &cs, Type baseTy,
auto result =
cs.matchTypes(nonOptionalTy, rootTy, ConstraintKind::Subtype,
ConstraintSystem::TypeMatchFlags::TMF_ApplyingFix, locator);
if (result.isFailure())
if (result == ConstraintSystem::SolutionKind::Error)
return nullptr;

return new (cs.getAllocator())
Expand Down
17 changes: 9 additions & 8 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2696,7 +2696,8 @@ namespace {
// type variable and a one-way constraint to assign it to either the
// deduced type or the externally-imposed type.
Type oneWayVarType;
if (bindPatternVarsOneWay) {
if (CS.getASTContext().TypeCheckerOpts.DisableOptimizedRestrictions &&
bindPatternVarsOneWay) {
oneWayVarType = CS.createTypeVariable(
CS.getConstraintLocator(locator), TVO_CanBindToNoEscape);

Expand Down Expand Up @@ -5046,23 +5047,23 @@ void ConstraintSystem::removePropertyWrapper(Expr *anchor) {
}
}

ConstraintSystem::TypeMatchResult
ConstraintSystem::SolutionKind
ConstraintSystem::applyPropertyWrapperToParameter(
Type wrapperType, Type paramType, ParamDecl *param, Identifier argLabel,
ConstraintKind matchKind, ConstraintLocator *locator,
ConstraintLocator *calleeLocator) {
Expr *anchor = getAsExpr(calleeLocator->getAnchor());

auto recordPropertyWrapperFix = [&](ConstraintFix *fix) -> TypeMatchResult {
auto recordPropertyWrapperFix = [&](ConstraintFix *fix) -> SolutionKind {
if (!shouldAttemptFixes())
return getTypeMatchFailure(locator);
return SolutionKind::Error;

recordAnyTypeVarAsPotentialHole(paramType);

if (recordFix(fix))
return getTypeMatchFailure(locator);
return SolutionKind::Error;

return getTypeMatchSuccess();
return SolutionKind::Solved;
};

// Incorrect use of projected value argument
Expand Down Expand Up @@ -5102,10 +5103,10 @@ ConstraintSystem::applyPropertyWrapperToParameter(

applyPropertyWrapper(anchor, { wrapperType, PropertyWrapperInitKind::WrappedValue });
} else {
return getTypeMatchFailure(locator);
return SolutionKind::Error;
}

return getTypeMatchSuccess();
return SolutionKind::Solved;
}

void ConstraintSystem::optimizeConstraints(Expr *e) {
Expand Down
Loading