Skip to content

[Constraint solver] Don't adjust types in calls to @preconcurrency functions #59849

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
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
66 changes: 40 additions & 26 deletions include/swift/Sema/CSFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,14 +409,14 @@ class ConstraintFix {
FixKind Kind;
ConstraintLocator *Locator;

/// Determines whether this fix is simplify a warning which doesn't
/// require immediate source changes.
bool IsWarning;
/// The behavior limit to apply to the diagnostics emitted.
DiagnosticBehavior behaviorLimit;

public:
ConstraintFix(ConstraintSystem &cs, FixKind kind, ConstraintLocator *locator,
bool warning = false)
: CS(cs), Kind(kind), Locator(locator), IsWarning(warning) {}
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: CS(cs), Kind(kind), Locator(locator), behaviorLimit(behaviorLimit) {}

virtual ~ConstraintFix();

Expand All @@ -427,7 +427,14 @@ class ConstraintFix {

FixKind getKind() const { return Kind; }

bool isWarning() const { return IsWarning; }
bool isWarning() const {
return behaviorLimit == DiagnosticBehavior::Warning ||
behaviorLimit == DiagnosticBehavior::Ignore;
}

/// The diagnostic behavior limit that will be applied to any emitted
/// diagnostics.
DiagnosticBehavior diagBehaviorLimit() const { return behaviorLimit; }

virtual std::string getName() const = 0;

Expand Down Expand Up @@ -672,14 +679,17 @@ class ContextualMismatch : public ConstraintFix {
Type LHS, RHS;

ContextualMismatch(ConstraintSystem &cs, Type lhs, Type rhs,
ConstraintLocator *locator, bool warning)
: ConstraintFix(cs, FixKind::ContextualMismatch, locator, warning),
ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit)
: ConstraintFix(cs, FixKind::ContextualMismatch, locator, behaviorLimit),
LHS(lhs), RHS(rhs) {}

protected:
ContextualMismatch(ConstraintSystem &cs, FixKind kind, Type lhs, Type rhs,
ConstraintLocator *locator, bool warning = false)
: ConstraintFix(cs, kind, locator, warning), LHS(lhs), RHS(rhs) {}
ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: ConstraintFix(cs, kind, locator, behaviorLimit), LHS(lhs), RHS(rhs) {}

public:
std::string getName() const override { return "fix contextual mismatch"; }
Expand Down Expand Up @@ -766,9 +776,10 @@ class MarkExplicitlyEscaping final : public ContextualMismatch {
/// Mark function type as being part of a global actor.
class MarkGlobalActorFunction final : public ContextualMismatch {
MarkGlobalActorFunction(ConstraintSystem &cs, Type lhs, Type rhs,
ConstraintLocator *locator, bool warning)
ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit)
: ContextualMismatch(cs, FixKind::MarkGlobalActorFunction, lhs, rhs,
locator, warning) {
locator, behaviorLimit) {
}

public:
Expand All @@ -778,7 +789,7 @@ class MarkGlobalActorFunction final : public ContextualMismatch {

static MarkGlobalActorFunction *create(ConstraintSystem &cs, Type lhs,
Type rhs, ConstraintLocator *locator,
bool warning);
DiagnosticBehavior behaviorLimit);

static bool classof(ConstraintFix *fix) {
return fix->getKind() == FixKind::MarkGlobalActorFunction;
Expand Down Expand Up @@ -814,9 +825,9 @@ class ForceOptional final : public ContextualMismatch {
class AddSendableAttribute final : public ContextualMismatch {
AddSendableAttribute(ConstraintSystem &cs, FunctionType *fromType,
FunctionType *toType, ConstraintLocator *locator,
bool warning)
DiagnosticBehavior behaviorLimit)
: ContextualMismatch(cs, FixKind::AddSendableAttribute, fromType, toType,
locator, warning) {
locator, behaviorLimit) {
assert(fromType->isSendable() != toType->isSendable());
}

Expand All @@ -829,7 +840,7 @@ class AddSendableAttribute final : public ContextualMismatch {
FunctionType *fromType,
FunctionType *toType,
ConstraintLocator *locator,
bool warning);
DiagnosticBehavior behaviorLimit);

static bool classof(ConstraintFix *fix) {
return fix->getKind() == FixKind::AddSendableAttribute;
Expand Down Expand Up @@ -1395,7 +1406,8 @@ class AllowInvalidPartialApplication final : public ConstraintFix {
AllowInvalidPartialApplication(bool isWarning, ConstraintSystem &cs,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::AllowInvalidPartialApplication, locator,
isWarning) {}
isWarning ? DiagnosticBehavior::Warning
: DiagnosticBehavior::Unspecified) {}

public:
std::string getName() const override {
Expand Down Expand Up @@ -2129,8 +2141,10 @@ class AllowArgumentMismatch : public ContextualMismatch {

AllowArgumentMismatch(ConstraintSystem &cs, FixKind kind, Type argType,
Type paramType, ConstraintLocator *locator,
bool warning = false)
: ContextualMismatch(cs, kind, argType, paramType, locator, warning) {}
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: ContextualMismatch(
cs, kind, argType, paramType, locator, behaviorLimit) {}

public:
std::string getName() const override {
Expand Down Expand Up @@ -2278,9 +2292,9 @@ class TreatEphemeralAsNonEphemeral final : public AllowArgumentMismatch {
TreatEphemeralAsNonEphemeral(ConstraintSystem &cs, ConstraintLocator *locator,
Type srcType, Type dstType,
ConversionRestrictionKind conversionKind,
bool downgradeToWarning)
DiagnosticBehavior behaviorLimit)
: AllowArgumentMismatch(cs, FixKind::TreatEphemeralAsNonEphemeral,
srcType, dstType, locator, downgradeToWarning),
srcType, dstType, locator, behaviorLimit),
ConversionKind(conversionKind) {}

public:
Expand Down Expand Up @@ -2444,7 +2458,7 @@ class AllowCoercionToForceCast final : public ContextualMismatch {
AllowCoercionToForceCast(ConstraintSystem &cs, Type fromType, Type toType,
ConstraintLocator *locator)
: ContextualMismatch(cs, FixKind::AllowCoercionToForceCast, fromType,
toType, locator, /*warning*/ true) {}
toType, locator, DiagnosticBehavior::Warning) {}

public:
std::string getName() const override {
Expand Down Expand Up @@ -2558,7 +2572,7 @@ class SpecifyLabelToAssociateTrailingClosure final : public ConstraintFix {
SpecifyLabelToAssociateTrailingClosure(ConstraintSystem &cs,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::SpecifyLabelToAssociateTrailingClosure,
locator, /*isWarning=*/true) {}
locator, DiagnosticBehavior::Warning) {}

public:
std::string getName() const override {
Expand Down Expand Up @@ -2728,7 +2742,7 @@ class SpecifyBaseTypeForOptionalUnresolvedMember final : public ConstraintFix {
DeclNameRef memberName,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::SpecifyBaseTypeForOptionalUnresolvedMember,
locator, /*isWarning=*/true),
locator, DiagnosticBehavior::Warning),
MemberName(memberName) {}
DeclNameRef MemberName;

Expand Down Expand Up @@ -2759,7 +2773,7 @@ class CheckedCastContextualMismatchWarning : public ContextualMismatch {
CheckedCastKind kind,
ConstraintLocator *locator)
: ContextualMismatch(cs, fixKind, fromType, toType, locator,
/*isWarning*/ true),
DiagnosticBehavior::Warning),
CastKind(kind) {}
CheckedCastKind CastKind;
};
Expand Down Expand Up @@ -2918,7 +2932,7 @@ class AllowTupleLabelMismatch final : public ContextualMismatch {
AllowTupleLabelMismatch(ConstraintSystem &cs, Type fromType, Type toType,
ConstraintLocator *locator)
: ContextualMismatch(cs, FixKind::AllowTupleLabelMismatch, fromType,
toType, locator, /*warning*/ true) {}
toType, locator, DiagnosticBehavior::Warning) {}

public:
std::string getName() const override { return "allow tuple label mismatch"; }
Expand Down
11 changes: 0 additions & 11 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1846,24 +1846,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILFunctionConventions substConv(substTy, F.getModule());
unsigned appliedArgStartIdx =
substConv.getNumSILArguments() - PAI->getNumArguments();
bool isSendableAndStageIsCanonical =
PAI->getFunctionType()->isSendable() &&
F.getModule().getStage() >= SILStage::Canonical;
for (auto p : llvm::enumerate(PAI->getArguments())) {
requireSameType(
p.value()->getType(),
substConv.getSILArgumentType(appliedArgStartIdx + p.index(),
F.getTypeExpansionContext()),
"applied argument types do not match suffix of function type's "
"inputs");

// TODO: Expand this to also be true for address only types.
if (isSendableAndStageIsCanonical)
require(
!p.value()->getType().getASTType()->is<SILBoxType>() ||
p.value()->getType().getSILBoxFieldType(&F).isAddressOnly(F),
"Concurrent partial apply in canonical SIL with a loadable box "
"type argument?!");
}

// The arguments to the result function type must match the prefix of the
Expand Down
11 changes: 10 additions & 1 deletion lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5706,8 +5706,17 @@ ArgumentList *ExprRewriter::coerceCallArguments(
// Quickly test if any further fix-ups for the argument types are necessary.
auto matches = args->matches(params, [&](Expr *E) { return cs.getType(E); });
if (matches && !shouldInjectWrappedValuePlaceholder &&
!paramInfo.anyContextualInfo())
!paramInfo.anyContextualInfo()) {
// Propagate preconcurrency to any closure arguments.
if (preconcurrency) {
for (const auto &arg : *args) {
Expr *argExpr = arg.getExpr();
applyContextualClosureFlags(argExpr, false, false, preconcurrency);
}
}

return args;
}

// Determine the parameter bindings that were applied.
auto *locatorPtr = cs.getConstraintLocator(locator);
Expand Down
4 changes: 1 addition & 3 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,8 @@ template <typename... ArgTypes>
InFlightDiagnostic
FailureDiagnostic::emitDiagnosticAt(ArgTypes &&... Args) const {
auto &DE = getASTContext().Diags;
auto behavior = isWarning ? DiagnosticBehavior::Warning
: DiagnosticBehavior::Unspecified;
return std::move(DE.diagnose(std::forward<ArgTypes>(Args)...)
.limitBehavior(behavior));
.limitBehavior(behaviorLimit));
}

Expr *FailureDiagnostic::findParentExpr(const Expr *subExpr) const {
Expand Down
42 changes: 25 additions & 17 deletions lib/Sema/CSDiagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,19 @@ class FunctionArgApplyInfo;
class FailureDiagnostic {
const Solution &S;
ConstraintLocator *Locator;
bool isWarning;
DiagnosticBehavior behaviorLimit;

public:
FailureDiagnostic(const Solution &solution, ConstraintLocator *locator,
bool isWarning = false)
: S(solution), Locator(locator), isWarning(isWarning) {}
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: S(solution), Locator(locator), behaviorLimit(behaviorLimit) {}

FailureDiagnostic(const Solution &solution, ASTNode anchor,
bool isWarning = false)
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: FailureDiagnostic(solution, solution.getConstraintLocator(anchor),
isWarning) { }
behaviorLimit) { }

virtual ~FailureDiagnostic();

Expand Down Expand Up @@ -605,20 +607,23 @@ class ContextualFailure : public FailureDiagnostic {

public:
ContextualFailure(const Solution &solution, Type lhs, Type rhs,
ConstraintLocator *locator, bool isWarning = false)
ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: ContextualFailure(
solution,
locator->isForContextualType()
? locator->castLastElementTo<LocatorPathElt::ContextualType>()
.getPurpose()
: solution.getConstraintSystem().getContextualTypePurpose(
locator->getAnchor()),
lhs, rhs, locator, isWarning) {}
lhs, rhs, locator, behaviorLimit) {}

ContextualFailure(const Solution &solution, ContextualTypePurpose purpose,
Type lhs, Type rhs, ConstraintLocator *locator,
bool isWarning = false)
: FailureDiagnostic(solution, locator, isWarning), CTP(purpose),
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: FailureDiagnostic(solution, locator, behaviorLimit), CTP(purpose),
RawFromType(lhs), RawToType(rhs) {
assert(lhs && "Expected a valid 'from' type");
assert(rhs && "Expected a valid 'to' type");
Expand Down Expand Up @@ -759,8 +764,9 @@ class AttributedFuncToTypeConversionFailure final : public ContextualFailure {
AttributedFuncToTypeConversionFailure(const Solution &solution, Type fromType,
Type toType, ConstraintLocator *locator,
AttributeKind attributeKind,
bool isWarning = false)
: ContextualFailure(solution, fromType, toType, locator, isWarning),
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: ContextualFailure(solution, fromType, toType, locator, behaviorLimit),
attributeKind(attributeKind) {}

bool diagnoseAsError() override;
Expand All @@ -784,8 +790,8 @@ class DroppedGlobalActorFunctionAttr final : public ContextualFailure {
public:
DroppedGlobalActorFunctionAttr(const Solution &solution, Type fromType,
Type toType, ConstraintLocator *locator,
bool isWarning)
: ContextualFailure(solution, fromType, toType, locator, isWarning) { }
DiagnosticBehavior behaviorLimit)
: ContextualFailure(solution, fromType, toType, locator, behaviorLimit) { }

bool diagnoseAsError() override;
};
Expand Down Expand Up @@ -1955,8 +1961,9 @@ class ArgumentMismatchFailure : public ContextualFailure {
public:
ArgumentMismatchFailure(const Solution &solution, Type argType,
Type paramType, ConstraintLocator *locator,
bool warning = false)
: ContextualFailure(solution, argType, paramType, locator, warning),
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: ContextualFailure(solution, argType, paramType, locator, behaviorLimit),
Info(*getFunctionArgApplyInfo(getLocator())) {}

bool diagnoseAsError() override;
Expand Down Expand Up @@ -2135,8 +2142,9 @@ class NonEphemeralConversionFailure final : public ArgumentMismatchFailure {
ConstraintLocator *locator, Type fromType,
Type toType,
ConversionRestrictionKind conversionKind,
bool warning)
: ArgumentMismatchFailure(solution, fromType, toType, locator, warning),
DiagnosticBehavior behaviorLimit)
: ArgumentMismatchFailure(
solution, fromType, toType, locator, behaviorLimit),
ConversionKind(conversionKind) {
}

Expand Down
Loading