Skip to content

[Constraint solver] Track "isolated by preconcurrency" in the solver. #59963

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
77 changes: 46 additions & 31 deletions include/swift/Sema/CSFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "swift/AST/Types.h"
#include "swift/Basic/Debug.h"
#include "swift/Sema/ConstraintLocator.h"
#include "swift/Sema/FixBehavior.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/TrailingObjects.h"
Expand All @@ -45,6 +46,7 @@ class ConstraintSystem;
class ConstraintLocator;
class ConstraintLocatorBuilder;
enum class ConversionRestrictionKind;
enum ScoreKind: unsigned int;
class Solution;
struct MemberLookupResult;

Expand Down Expand Up @@ -410,13 +412,12 @@ class ConstraintFix {
ConstraintLocator *Locator;

/// The behavior limit to apply to the diagnostics emitted.
DiagnosticBehavior behaviorLimit;
FixBehavior fixBehavior;

public:
ConstraintFix(ConstraintSystem &cs, FixKind kind, ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
: CS(cs), Kind(kind), Locator(locator), behaviorLimit(behaviorLimit) {}
FixBehavior fixBehavior = FixBehavior::Error)
: CS(cs), Kind(kind), Locator(locator), fixBehavior(fixBehavior) {}

virtual ~ConstraintFix();

Expand All @@ -427,14 +428,27 @@ class ConstraintFix {

FixKind getKind() const { return Kind; }

bool isWarning() const {
return behaviorLimit == DiagnosticBehavior::Warning ||
behaviorLimit == DiagnosticBehavior::Ignore;
/// Whether it is still possible to "apply" a solution containing this kind
/// of fix to get a usable AST.
bool canApplySolution() const {
switch (fixBehavior) {
case FixBehavior::AlwaysWarning:
case FixBehavior::DowngradeToWarning:
case FixBehavior::Suppress:
return true;

case FixBehavior::Error:
return false;
}
}

/// Whether this kind of fix affects the solution score, and which score
/// it affects.
Optional<ScoreKind> affectsSolutionScore() const;

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

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

Expand Down Expand Up @@ -680,16 +694,15 @@ class ContextualMismatch : public ConstraintFix {

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

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

public:
std::string getName() const override { return "fix contextual mismatch"; }
Expand Down Expand Up @@ -777,9 +790,9 @@ class MarkExplicitlyEscaping final : public ContextualMismatch {
class MarkGlobalActorFunction final : public ContextualMismatch {
MarkGlobalActorFunction(ConstraintSystem &cs, Type lhs, Type rhs,
ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit)
FixBehavior fixBehavior)
: ContextualMismatch(cs, FixKind::MarkGlobalActorFunction, lhs, rhs,
locator, behaviorLimit) {
locator, fixBehavior) {
}

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

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

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

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

static bool classof(ConstraintFix *fix) {
return fix->getKind() == FixKind::AddSendableAttribute;
Expand Down Expand Up @@ -1403,11 +1416,14 @@ class AllowTypeOrInstanceMember final : public AllowInvalidMemberRef {
};

class AllowInvalidPartialApplication final : public ConstraintFix {
bool isWarning;

AllowInvalidPartialApplication(bool isWarning, ConstraintSystem &cs,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::AllowInvalidPartialApplication, locator,
isWarning ? DiagnosticBehavior::Warning
: DiagnosticBehavior::Unspecified) {}
isWarning ? FixBehavior::AlwaysWarning
: FixBehavior::Error),
isWarning(isWarning) {}

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

AllowArgumentMismatch(ConstraintSystem &cs, FixKind kind, Type argType,
Type paramType, ConstraintLocator *locator,
DiagnosticBehavior behaviorLimit =
DiagnosticBehavior::Unspecified)
FixBehavior fixBehavior = FixBehavior::Error)
: ContextualMismatch(
cs, kind, argType, paramType, locator, behaviorLimit) {}
cs, kind, argType, paramType, locator, fixBehavior) {}

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

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

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

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

Expand Down Expand Up @@ -2773,7 +2788,7 @@ class CheckedCastContextualMismatchWarning : public ContextualMismatch {
CheckedCastKind kind,
ConstraintLocator *locator)
: ContextualMismatch(cs, fixKind, fromType, toType, locator,
DiagnosticBehavior::Warning),
FixBehavior::AlwaysWarning),
CastKind(kind) {}
CheckedCastKind CastKind;
};
Expand Down Expand Up @@ -2932,7 +2947,7 @@ class AllowTupleLabelMismatch final : public ContextualMismatch {
AllowTupleLabelMismatch(ConstraintSystem &cs, Type fromType, Type toType,
ConstraintLocator *locator)
: ContextualMismatch(cs, FixKind::AllowTupleLabelMismatch, fromType,
toType, locator, DiagnosticBehavior::Warning) {}
toType, locator, FixBehavior::AlwaysWarning) {}

public:
std::string getName() const override { return "allow tuple label mismatch"; }
Expand Down
25 changes: 24 additions & 1 deletion include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ class FunctionArgApplyInfo {

/// Describes an aspect of a solution that affects its overall score, i.e., a
/// user-defined conversions.
enum ScoreKind {
enum ScoreKind: unsigned int {
// These values are used as indices into a Score value.

/// A fix needs to be applied to the source.
Expand Down Expand Up @@ -1320,6 +1320,10 @@ class Solution {
/// The set of parameters that have been inferred to be 'isolated'.
llvm::SmallVector<ParamDecl *, 2> isolatedParams;

/// The set of closures that have been inferred to be "isolated by
/// preconcurrency".
llvm::SmallVector<const ClosureExpr *, 2> preconcurrencyClosures;

/// The set of functions that have been transformed by a result builder.
llvm::MapVector<AnyFunctionRef, AppliedBuilderTransform>
resultBuilderTransformed;
Expand Down Expand Up @@ -2519,6 +2523,13 @@ struct GetClosureType {
Type operator()(const AbstractClosureExpr *expr) const;
};

/// Retrieve the closure type from the constraint system.
struct ClosureIsolatedByPreconcurrency {
ConstraintSystem &cs;

bool operator()(const ClosureExpr *expr) const;
};

/// Describes the type produced when referencing a declaration.
struct DeclReferenceType {
/// The "opened" type, which is the type of the declaration where any
Expand Down Expand Up @@ -2573,6 +2584,7 @@ class ConstraintSystem {
friend class ConjunctionElement;
friend class RequirementFailure;
friend class MissingMemberFailure;
friend struct ClosureIsolatedByPreconcurrency;

class SolverScope;

Expand Down Expand Up @@ -2703,6 +2715,10 @@ class ConstraintSystem {
/// The set of parameters that have been inferred to be 'isolated'.
llvm::SmallSetVector<ParamDecl *, 2> isolatedParams;

/// The set of closures that have been inferred to be "isolated by
/// preconcurrency".
llvm::SmallSetVector<const ClosureExpr *, 2> preconcurrencyClosures;

/// Maps closure parameters to type variables.
llvm::DenseMap<const ParamDecl *, TypeVariableType *>
OpenedParameterTypes;
Expand Down Expand Up @@ -3273,6 +3289,9 @@ class ConstraintSystem {
/// The length of \c isolatedParams.
unsigned numIsolatedParams;

/// The length of \c PreconcurrencyClosures.
unsigned numPreconcurrencyClosures;

/// The length of \c ImplicitValueConversions.
unsigned numImplicitValueConversions;

Expand Down Expand Up @@ -4553,6 +4572,10 @@ class ConstraintSystem {
llvm::function_ref<Type(const AbstractClosureExpr *)> getClosureType =
[](const AbstractClosureExpr *) {
return Type();
},
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency =
[](const ClosureExpr *closure) {
return closure->isIsolatedByPreconcurrency();
});

/// Given the opened type and a pile of information about a member reference,
Expand Down
41 changes: 41 additions & 0 deletions include/swift/Sema/FixBehavior.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===--- FixBehavior.h - Constraint Fix Behavior --------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides information about how a constraint fix should behavior.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SEMA_FIXBEHAVIOR_H
#define SWIFT_SEMA_FIXBEHAVIOR_H

namespace swift {
namespace constraints {

/// Describes the behavior of the diagnostic corresponding to a given fix.
enum class FixBehavior {
/// The diagnostic is an error, and should prevent constraint application.
Error,
/// The diagnostic is always a warning, which should not prevent constraint
/// application.
AlwaysWarning,
/// The diagnostic should be downgraded to a warning, and not prevent
/// constraint application.
DowngradeToWarning,
/// The diagnostic should be suppressed, and not prevent constraint
/// application.
Suppress
};

}
}

#endif // SWIFT_SEMA_FIXBEHAVIOR_H
Loading