Skip to content

Commit 3ab722e

Browse files
authored
Merge pull request #59962 from DougGregor/constraint-solver-recoverable-error-5.7
[5.7] [Constraint solver] Improve fix behaviors for better concurrency-related recovery and overloading
2 parents 1cc3be8 + f08097e commit 3ab722e

File tree

10 files changed

+242
-113
lines changed

10 files changed

+242
-113
lines changed

include/swift/Sema/CSFix.h

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/Types.h"
2626
#include "swift/Basic/Debug.h"
2727
#include "swift/Sema/ConstraintLocator.h"
28+
#include "swift/Sema/FixBehavior.h"
2829
#include "llvm/ADT/ArrayRef.h"
2930
#include "llvm/ADT/SmallVector.h"
3031
#include "llvm/Support/TrailingObjects.h"
@@ -45,6 +46,7 @@ class ConstraintSystem;
4546
class ConstraintLocator;
4647
class ConstraintLocatorBuilder;
4748
enum class ConversionRestrictionKind;
49+
enum ScoreKind: unsigned int;
4850
class Solution;
4951
struct MemberLookupResult;
5052

@@ -402,13 +404,12 @@ class ConstraintFix {
402404
ConstraintLocator *Locator;
403405

404406
/// The behavior limit to apply to the diagnostics emitted.
405-
DiagnosticBehavior behaviorLimit;
407+
FixBehavior fixBehavior;
406408

407409
public:
408410
ConstraintFix(ConstraintSystem &cs, FixKind kind, ConstraintLocator *locator,
409-
DiagnosticBehavior behaviorLimit =
410-
DiagnosticBehavior::Unspecified)
411-
: CS(cs), Kind(kind), Locator(locator), behaviorLimit(behaviorLimit) {}
411+
FixBehavior fixBehavior = FixBehavior::Error)
412+
: CS(cs), Kind(kind), Locator(locator), fixBehavior(fixBehavior) {}
412413

413414
virtual ~ConstraintFix();
414415

@@ -419,14 +420,27 @@ class ConstraintFix {
419420

420421
FixKind getKind() const { return Kind; }
421422

422-
bool isWarning() const {
423-
return behaviorLimit == DiagnosticBehavior::Warning ||
424-
behaviorLimit == DiagnosticBehavior::Ignore;
423+
/// Whether it is still possible to "apply" a solution containing this kind
424+
/// of fix to get a usable AST.
425+
bool canApplySolution() const {
426+
switch (fixBehavior) {
427+
case FixBehavior::AlwaysWarning:
428+
case FixBehavior::DowngradeToWarning:
429+
case FixBehavior::Suppress:
430+
return true;
431+
432+
case FixBehavior::Error:
433+
return false;
434+
}
425435
}
426436

437+
/// Whether this kind of fix affects the solution score, and which score
438+
/// it affects.
439+
Optional<ScoreKind> affectsSolutionScore() const;
440+
427441
/// The diagnostic behavior limit that will be applied to any emitted
428442
/// diagnostics.
429-
DiagnosticBehavior diagBehaviorLimit() const { return behaviorLimit; }
443+
FixBehavior diagfixBehavior() const { return fixBehavior; }
430444

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

@@ -672,16 +686,15 @@ class ContextualMismatch : public ConstraintFix {
672686

673687
ContextualMismatch(ConstraintSystem &cs, Type lhs, Type rhs,
674688
ConstraintLocator *locator,
675-
DiagnosticBehavior behaviorLimit)
676-
: ConstraintFix(cs, FixKind::ContextualMismatch, locator, behaviorLimit),
689+
FixBehavior fixBehavior)
690+
: ConstraintFix(cs, FixKind::ContextualMismatch, locator, fixBehavior),
677691
LHS(lhs), RHS(rhs) {}
678692

679693
protected:
680694
ContextualMismatch(ConstraintSystem &cs, FixKind kind, Type lhs, Type rhs,
681695
ConstraintLocator *locator,
682-
DiagnosticBehavior behaviorLimit =
683-
DiagnosticBehavior::Unspecified)
684-
: ConstraintFix(cs, kind, locator, behaviorLimit), LHS(lhs), RHS(rhs) {}
696+
FixBehavior fixBehavior = FixBehavior::Error)
697+
: ConstraintFix(cs, kind, locator, fixBehavior), LHS(lhs), RHS(rhs) {}
685698

686699
public:
687700
std::string getName() const override { return "fix contextual mismatch"; }
@@ -766,9 +779,9 @@ class MarkExplicitlyEscaping final : public ContextualMismatch {
766779
class MarkGlobalActorFunction final : public ContextualMismatch {
767780
MarkGlobalActorFunction(ConstraintSystem &cs, Type lhs, Type rhs,
768781
ConstraintLocator *locator,
769-
DiagnosticBehavior behaviorLimit)
782+
FixBehavior fixBehavior)
770783
: ContextualMismatch(cs, FixKind::MarkGlobalActorFunction, lhs, rhs,
771-
locator, behaviorLimit) {
784+
locator, fixBehavior) {
772785
}
773786

774787
public:
@@ -778,7 +791,7 @@ class MarkGlobalActorFunction final : public ContextualMismatch {
778791

779792
static MarkGlobalActorFunction *create(ConstraintSystem &cs, Type lhs,
780793
Type rhs, ConstraintLocator *locator,
781-
DiagnosticBehavior behaviorLimit);
794+
FixBehavior fixBehavior);
782795

783796
static bool classof(ConstraintFix *fix) {
784797
return fix->getKind() == FixKind::MarkGlobalActorFunction;
@@ -814,9 +827,9 @@ class ForceOptional final : public ContextualMismatch {
814827
class AddSendableAttribute final : public ContextualMismatch {
815828
AddSendableAttribute(ConstraintSystem &cs, FunctionType *fromType,
816829
FunctionType *toType, ConstraintLocator *locator,
817-
DiagnosticBehavior behaviorLimit)
830+
FixBehavior fixBehavior)
818831
: ContextualMismatch(cs, FixKind::AddSendableAttribute, fromType, toType,
819-
locator, behaviorLimit) {
832+
locator, fixBehavior) {
820833
assert(fromType->isSendable() != toType->isSendable());
821834
}
822835

@@ -829,7 +842,7 @@ class AddSendableAttribute final : public ContextualMismatch {
829842
FunctionType *fromType,
830843
FunctionType *toType,
831844
ConstraintLocator *locator,
832-
DiagnosticBehavior behaviorLimit);
845+
FixBehavior fixBehavior);
833846

834847
static bool classof(ConstraintFix *fix) {
835848
return fix->getKind() == FixKind::AddSendableAttribute;
@@ -1392,11 +1405,14 @@ class AllowTypeOrInstanceMember final : public AllowInvalidMemberRef {
13921405
};
13931406

13941407
class AllowInvalidPartialApplication final : public ConstraintFix {
1408+
bool isWarning;
1409+
13951410
AllowInvalidPartialApplication(bool isWarning, ConstraintSystem &cs,
13961411
ConstraintLocator *locator)
13971412
: ConstraintFix(cs, FixKind::AllowInvalidPartialApplication, locator,
1398-
isWarning ? DiagnosticBehavior::Warning
1399-
: DiagnosticBehavior::Unspecified) {}
1413+
isWarning ? FixBehavior::AlwaysWarning
1414+
: FixBehavior::Error),
1415+
isWarning(isWarning) {}
14001416

14011417
public:
14021418
std::string getName() const override {
@@ -2130,10 +2146,9 @@ class AllowArgumentMismatch : public ContextualMismatch {
21302146

21312147
AllowArgumentMismatch(ConstraintSystem &cs, FixKind kind, Type argType,
21322148
Type paramType, ConstraintLocator *locator,
2133-
DiagnosticBehavior behaviorLimit =
2134-
DiagnosticBehavior::Unspecified)
2149+
FixBehavior fixBehavior = FixBehavior::Error)
21352150
: ContextualMismatch(
2136-
cs, kind, argType, paramType, locator, behaviorLimit) {}
2151+
cs, kind, argType, paramType, locator, fixBehavior) {}
21372152

21382153
public:
21392154
std::string getName() const override {
@@ -2281,9 +2296,9 @@ class TreatEphemeralAsNonEphemeral final : public AllowArgumentMismatch {
22812296
TreatEphemeralAsNonEphemeral(ConstraintSystem &cs, ConstraintLocator *locator,
22822297
Type srcType, Type dstType,
22832298
ConversionRestrictionKind conversionKind,
2284-
DiagnosticBehavior behaviorLimit)
2299+
FixBehavior fixBehavior)
22852300
: AllowArgumentMismatch(cs, FixKind::TreatEphemeralAsNonEphemeral,
2286-
srcType, dstType, locator, behaviorLimit),
2301+
srcType, dstType, locator, fixBehavior),
22872302
ConversionKind(conversionKind) {}
22882303

22892304
public:
@@ -2447,7 +2462,7 @@ class AllowCoercionToForceCast final : public ContextualMismatch {
24472462
AllowCoercionToForceCast(ConstraintSystem &cs, Type fromType, Type toType,
24482463
ConstraintLocator *locator)
24492464
: ContextualMismatch(cs, FixKind::AllowCoercionToForceCast, fromType,
2450-
toType, locator, DiagnosticBehavior::Warning) {}
2465+
toType, locator, FixBehavior::AlwaysWarning) {}
24512466

24522467
public:
24532468
std::string getName() const override {
@@ -2561,7 +2576,7 @@ class SpecifyLabelToAssociateTrailingClosure final : public ConstraintFix {
25612576
SpecifyLabelToAssociateTrailingClosure(ConstraintSystem &cs,
25622577
ConstraintLocator *locator)
25632578
: ConstraintFix(cs, FixKind::SpecifyLabelToAssociateTrailingClosure,
2564-
locator, DiagnosticBehavior::Warning) {}
2579+
locator, FixBehavior::AlwaysWarning) {}
25652580

25662581
public:
25672582
std::string getName() const override {
@@ -2731,7 +2746,7 @@ class SpecifyBaseTypeForOptionalUnresolvedMember final : public ConstraintFix {
27312746
DeclNameRef memberName,
27322747
ConstraintLocator *locator)
27332748
: ConstraintFix(cs, FixKind::SpecifyBaseTypeForOptionalUnresolvedMember,
2734-
locator, DiagnosticBehavior::Warning),
2749+
locator, FixBehavior::AlwaysWarning),
27352750
MemberName(memberName) {}
27362751
DeclNameRef MemberName;
27372752

@@ -2762,7 +2777,7 @@ class CheckedCastContextualMismatchWarning : public ContextualMismatch {
27622777
CheckedCastKind kind,
27632778
ConstraintLocator *locator)
27642779
: ContextualMismatch(cs, fixKind, fromType, toType, locator,
2765-
DiagnosticBehavior::Warning),
2780+
FixBehavior::AlwaysWarning),
27662781
CastKind(kind) {}
27672782
CheckedCastKind CastKind;
27682783
};
@@ -2873,7 +2888,7 @@ class AllowTupleLabelMismatch final : public ContextualMismatch {
28732888
AllowTupleLabelMismatch(ConstraintSystem &cs, Type fromType, Type toType,
28742889
ConstraintLocator *locator)
28752890
: ContextualMismatch(cs, FixKind::AllowTupleLabelMismatch, fromType,
2876-
toType, locator, DiagnosticBehavior::Warning) {}
2891+
toType, locator, FixBehavior::AlwaysWarning) {}
28772892

28782893
public:
28792894
std::string getName() const override { return "allow tuple label mismatch"; }

include/swift/Sema/ConstraintSystem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ class FunctionArgApplyInfo {
775775

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

781781
/// A fix needs to be applied to the source.

include/swift/Sema/FixBehavior.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- FixBehavior.h - Constraint Fix Behavior --------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file provides information about how a constraint fix should behavior.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_SEMA_FIXBEHAVIOR_H
18+
#define SWIFT_SEMA_FIXBEHAVIOR_H
19+
20+
namespace swift {
21+
namespace constraints {
22+
23+
/// Describes the behavior of the diagnostic corresponding to a given fix.
24+
enum class FixBehavior {
25+
/// The diagnostic is an error, and should prevent constraint application.
26+
Error,
27+
/// The diagnostic is always a warning, which should not prevent constraint
28+
/// application.
29+
AlwaysWarning,
30+
/// The diagnostic should be downgraded to a warning, and not prevent
31+
/// constraint application.
32+
DowngradeToWarning,
33+
/// The diagnostic should be suppressed, and not prevent constraint
34+
/// application.
35+
Suppress
36+
};
37+
38+
}
39+
}
40+
41+
#endif // SWIFT_SEMA_FIXBEHAVIOR_H

lib/Sema/CSApply.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8480,7 +8480,7 @@ bool ConstraintSystem::applySolutionFixes(const Solution &solution) {
84808480

84818481
auto diagnosed =
84828482
primaryFix->coalesceAndDiagnose(solution, secondaryFixes);
8483-
if (primaryFix->isWarning()) {
8483+
if (primaryFix->canApplySolution()) {
84848484
assert(diagnosed && "warnings should always be diagnosed");
84858485
(void)diagnosed;
84868486
} else {
@@ -9105,16 +9105,23 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
91059105
Solution &solution, SolutionApplicationTarget target) {
91069106
// If any fixes needed to be applied to arrive at this solution, resolve
91079107
// them to specific expressions.
9108+
unsigned numResolvableFixes = 0;
91089109
if (!solution.Fixes.empty()) {
91099110
if (shouldSuppressDiagnostics())
91109111
return None;
91119112

91129113
bool diagnosedErrorsViaFixes = applySolutionFixes(solution);
9114+
bool canApplySolution = true;
9115+
for (const auto fix : solution.Fixes) {
9116+
if (!fix->canApplySolution())
9117+
canApplySolution = false;
9118+
if (fix->affectsSolutionScore() == SK_Fix && fix->canApplySolution())
9119+
++numResolvableFixes;
9120+
}
9121+
91139122
// If all of the available fixes would result in a warning,
91149123
// we can go ahead and apply this solution to AST.
9115-
if (!llvm::all_of(solution.Fixes, [](const ConstraintFix *fix) {
9116-
return fix->isWarning();
9117-
})) {
9124+
if (!canApplySolution) {
91189125
// If we already diagnosed any errors via fixes, that's it.
91199126
if (diagnosedErrorsViaFixes)
91209127
return None;
@@ -9131,7 +9138,7 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
91319138
// produce a fallback diagnostic to highlight the problem.
91329139
{
91339140
const auto &score = solution.getFixedScore();
9134-
if (score.Data[SK_Fix] > 0 || score.Data[SK_Hole] > 0) {
9141+
if (score.Data[SK_Fix] > numResolvableFixes || score.Data[SK_Hole] > 0) {
91359142
maybeProduceFallbackDiagnostic(target);
91369143
return None;
91379144
}

lib/Sema/CSDiagnostics.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,22 @@ template <typename... ArgTypes>
103103
InFlightDiagnostic
104104
FailureDiagnostic::emitDiagnosticAt(ArgTypes &&... Args) const {
105105
auto &DE = getASTContext().Diags;
106+
DiagnosticBehavior behaviorLimit;
107+
switch (fixBehavior) {
108+
case FixBehavior::Error:
109+
case FixBehavior::AlwaysWarning:
110+
behaviorLimit = DiagnosticBehavior::Unspecified;
111+
break;
112+
113+
case FixBehavior::DowngradeToWarning:
114+
behaviorLimit = DiagnosticBehavior::Warning;
115+
break;
116+
117+
case FixBehavior::Suppress:
118+
behaviorLimit = DiagnosticBehavior::Ignore;
119+
break;
120+
}
121+
106122
return std::move(DE.diagnose(std::forward<ArgTypes>(Args)...)
107123
.limitBehavior(behaviorLimit));
108124
}

0 commit comments

Comments
 (0)