Skip to content

Commit 0926808

Browse files
authored
Merge pull request swiftlang#18664 from xedin/cs-improve-fix-interface
[ConstraintSystem] Replace `Fix` with richer `ConstraintFix` interface
2 parents a69a806 + dd9c28b commit 0926808

File tree

11 files changed

+573
-431
lines changed

11 files changed

+573
-431
lines changed

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_swift_library(swiftSema STATIC
1111
CSRanking.cpp
1212
CSSimplify.cpp
1313
CSSolver.cpp
14+
CSFix.cpp
1415
CSDiagnostics.cpp
1516
CalleeCandidateInfo.cpp
1617
CodeSynthesis.cpp

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -7762,21 +7762,20 @@ Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
77627762
/// Emit the fixes computed as part of the solution, returning true if we were
77637763
/// able to emit an error message, or false if none of the fixits worked out.
77647764
bool ConstraintSystem::applySolutionFixes(Expr *E, const Solution &solution) {
7765-
llvm::SmallDenseMap<Expr *,
7766-
SmallVector<std::pair<Fix, ConstraintLocator *>, 4>>
7765+
llvm::SmallDenseMap<Expr *, SmallVector<const ConstraintFix *, 4>>
77677766
fixesPerExpr;
77687767

7769-
for (const auto &fix : solution.Fixes)
7770-
fixesPerExpr[fix.second->getAnchor()].push_back(fix);
7768+
for (auto *fix : solution.Fixes)
7769+
fixesPerExpr[fix->getAnchor()].push_back(fix);
77717770

77727771
auto diagnoseExprFailures = [&](Expr *expr) -> bool {
77737772
auto fixes = fixesPerExpr.find(expr);
77747773
if (fixes == fixesPerExpr.end())
77757774
return false;
77767775

77777776
bool diagnosed = false;
7778-
for (auto &fix : fixes->second)
7779-
diagnosed |= applySolutionFix(E, solution, fix);
7777+
for (const auto *fix : fixes->second)
7778+
diagnosed |= fix->diagnose(E, solution);
77807779
return diagnosed;
77817780
};
77827781

@@ -7793,86 +7792,6 @@ bool ConstraintSystem::applySolutionFixes(Expr *E, const Solution &solution) {
77937792
return diagnosed;
77947793
}
77957794

7796-
/// \brief Apply the specified Fix to this solution, producing a fix-it hint
7797-
/// diagnostic for it and returning true. If the fix-it hint turned out to be
7798-
/// bogus, this returns false and doesn't emit anything.
7799-
bool ConstraintSystem::applySolutionFix(
7800-
Expr *expr, const Solution &solution,
7801-
std::pair<Fix, ConstraintLocator *> &fix) {
7802-
// Some fixes need more information from the locator.
7803-
ConstraintLocator *locator = fix.second;
7804-
7805-
// In the case of us having applied a type member constraint against a
7806-
// synthesized type variable during diagnostic generation, we may not have
7807-
// a valid locator.
7808-
if (!locator)
7809-
return false;
7810-
7811-
switch (fix.first.getKind()) {
7812-
case FixKind::ForceOptional: {
7813-
MissingOptionalUnwrapFailure failure(expr, solution, locator);
7814-
return failure.diagnose();
7815-
}
7816-
7817-
case FixKind::UnwrapOptionalBase: {
7818-
auto memberName = fix.first.getDeclNameArgument(*this);
7819-
bool resultIsOptional =
7820-
fix.first.isUnwrapOptionalBaseByOptionalChaining(*this);
7821-
MemberAccessOnOptionalBaseFailure failure(expr, solution, locator,
7822-
memberName, resultIsOptional);
7823-
return failure.diagnose();
7824-
}
7825-
7826-
case FixKind::ForceDowncast: {
7827-
MissingExplicitConversionFailure failure(expr, solution, locator,
7828-
fix.first.getTypeArgument(*this));
7829-
return failure.diagnose();
7830-
}
7831-
7832-
case FixKind::AddressOf: {
7833-
MissingAddressOfFailure failure(expr, solution, locator);
7834-
return failure.diagnose();
7835-
}
7836-
7837-
case FixKind::CoerceToCheckedCast: {
7838-
MissingForcedDowncastFailure failure(expr, solution, locator);
7839-
return failure.diagnose();
7840-
}
7841-
7842-
case FixKind::ExplicitlyEscaping: {
7843-
NoEscapeFuncToTypeConversionFailure failure(expr, solution, locator);
7844-
return failure.diagnose();
7845-
}
7846-
7847-
case FixKind::ExplicitlyEscapingToAny: {
7848-
NoEscapeFuncToTypeConversionFailure failure(expr, solution, locator,
7849-
getASTContext().TheAnyType);
7850-
return failure.diagnose();
7851-
}
7852-
7853-
case FixKind::RelabelArguments: {
7854-
LabelingFailure failure(solution, fix.second,
7855-
fix.first.getArgumentLabels(*this));
7856-
return failure.diagnose();
7857-
}
7858-
7859-
case FixKind::AddConformance: {
7860-
auto *anchor = locator->getAnchor();
7861-
auto &reqLoc = locator->getPath().back();
7862-
MissingConformanceFailure failure(
7863-
expr, solution, fix.second,
7864-
MissingConformances[{anchor, reqLoc.getValue()}]);
7865-
return failure.diagnose();
7866-
}
7867-
}
7868-
7869-
// FIXME: It would be really nice to emit a follow-up note showing where
7870-
// we got the other type information from, e.g., the parameter we're
7871-
// initializing.
7872-
return false;
7873-
}
7874-
7875-
78767795
/// \brief Apply a given solution to the expression, producing a fully
78777796
/// type-checked expression.
78787797
Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class MissingConformanceFailure final : public RequirementFailure {
155155
public:
156156
MissingConformanceFailure(Expr *expr, const Solution &solution,
157157
ConstraintLocator *locator,
158-
std::pair<TypeBase *, ProtocolDecl *> conformance)
158+
std::pair<Type, ProtocolDecl *> conformance)
159159
: RequirementFailure(expr, solution, locator),
160160
NonConformingType(conformance.first), Protocol(conformance.second) {}
161161

lib/Sema/CSFix.cpp

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//===--- CSFix.cpp - Constraint Fixes -------------------------------------===//
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 implements the \c ConstraintFix class and its related types,
14+
// which is used by constraint solver to attempt to fix constraints to be
15+
// able to produce a solution which is easily diagnosable.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#include "CSFix.h"
20+
#include "CSDiagnostics.h"
21+
#include "ConstraintLocator.h"
22+
#include "ConstraintSystem.h"
23+
#include "swift/AST/Expr.h"
24+
#include "swift/AST/Type.h"
25+
#include "swift/Basic/SourceManager.h"
26+
#include "llvm/ADT/SmallString.h"
27+
#include "llvm/Support/raw_ostream.h"
28+
#include <string>
29+
30+
using namespace swift;
31+
using namespace constraints;
32+
33+
ConstraintFix::~ConstraintFix() {}
34+
35+
Expr *ConstraintFix::getAnchor() const { return getLocator()->getAnchor(); }
36+
37+
void ConstraintFix::print(llvm::raw_ostream &Out, SourceManager *sm) const {
38+
Out << "[fix: ";
39+
Out << getName();
40+
Out << ']';
41+
Out << " @ ";
42+
getLocator()->dump(sm, Out);
43+
}
44+
45+
void ConstraintFix::dump(SourceManager *sm) const { print(llvm::errs(), sm); }
46+
47+
std::string ForceDowncast::getName() const {
48+
llvm::SmallString<16> name;
49+
name += "force downcast (as! ";
50+
name += DowncastTo->getString();
51+
name += ")";
52+
return name.c_str();
53+
}
54+
55+
bool ForceDowncast::diagnose(Expr *expr, const Solution &solution) const {
56+
MissingExplicitConversionFailure failure(expr, solution, getLocator(),
57+
DowncastTo);
58+
return failure.diagnose();
59+
}
60+
61+
ForceDowncast *ForceDowncast::create(ConstraintSystem &cs, Type toType,
62+
ConstraintLocator *locator) {
63+
return new (cs.getAllocator()) ForceDowncast(toType, locator);
64+
}
65+
66+
bool ForceOptional::diagnose(Expr *root, const Solution &solution) const {
67+
MissingOptionalUnwrapFailure failure(root, solution, getLocator());
68+
return failure.diagnose();
69+
}
70+
71+
ForceOptional *ForceOptional::create(ConstraintSystem &cs,
72+
ConstraintLocator *locator) {
73+
return new (cs.getAllocator()) ForceOptional(locator);
74+
}
75+
76+
bool UnwrapOptionalBase::diagnose(Expr *root, const Solution &solution) const {
77+
bool resultIsOptional =
78+
getKind() == FixKind::UnwrapOptionalBaseWithOptionalResult;
79+
MemberAccessOnOptionalBaseFailure failure(root, solution, getLocator(),
80+
MemberName, resultIsOptional);
81+
return failure.diagnose();
82+
}
83+
84+
UnwrapOptionalBase *UnwrapOptionalBase::create(ConstraintSystem &cs,
85+
DeclName member,
86+
ConstraintLocator *locator) {
87+
return new (cs.getAllocator())
88+
UnwrapOptionalBase(FixKind::UnwrapOptionalBase, member, locator);
89+
}
90+
91+
UnwrapOptionalBase *UnwrapOptionalBase::createWithOptionalResult(
92+
ConstraintSystem &cs, DeclName member, ConstraintLocator *locator) {
93+
return new (cs.getAllocator()) UnwrapOptionalBase(
94+
FixKind::UnwrapOptionalBaseWithOptionalResult, member, locator);
95+
}
96+
97+
bool AddAddressOf::diagnose(Expr *root, const Solution &solution) const {
98+
MissingAddressOfFailure failure(root, solution, getLocator());
99+
return failure.diagnose();
100+
}
101+
102+
AddAddressOf *AddAddressOf::create(ConstraintSystem &cs,
103+
ConstraintLocator *locator) {
104+
return new (cs.getAllocator()) AddAddressOf(locator);
105+
}
106+
107+
bool CoerceToCheckedCast::diagnose(Expr *root, const Solution &solution) const {
108+
MissingForcedDowncastFailure failure(root, solution, getLocator());
109+
return failure.diagnose();
110+
}
111+
112+
CoerceToCheckedCast *CoerceToCheckedCast::create(ConstraintSystem &cs,
113+
ConstraintLocator *locator) {
114+
return new (cs.getAllocator()) CoerceToCheckedCast(locator);
115+
}
116+
117+
bool MarkExplicitlyEscaping::diagnose(Expr *root,
118+
const Solution &solution) const {
119+
NoEscapeFuncToTypeConversionFailure failure(root, solution, getLocator(),
120+
ConvertTo);
121+
return failure.diagnose();
122+
}
123+
124+
MarkExplicitlyEscaping *
125+
MarkExplicitlyEscaping::create(ConstraintSystem &cs, ConstraintLocator *locator,
126+
Type convertingTo) {
127+
return new (cs.getAllocator()) MarkExplicitlyEscaping(locator, convertingTo);
128+
}
129+
130+
bool RelabelArguments::diagnose(Expr *root, const Solution &solution) const {
131+
LabelingFailure failure(solution, getLocator(), getLabels());
132+
return failure.diagnose();
133+
}
134+
135+
RelabelArguments *
136+
RelabelArguments::create(ConstraintSystem &cs,
137+
llvm::ArrayRef<Identifier> correctLabels,
138+
ConstraintLocator *locator) {
139+
unsigned size = totalSizeToAlloc<Identifier>(correctLabels.size());
140+
void *mem = cs.getAllocator().Allocate(size, alignof(RelabelArguments));
141+
return new (mem) RelabelArguments(correctLabels, locator);
142+
}
143+
144+
bool MissingConformance::diagnose(Expr *root, const Solution &solution) const {
145+
MissingConformanceFailure failure(root, solution, getLocator(),
146+
{NonConformingType, Protocol});
147+
return failure.diagnose();
148+
}
149+
150+
MissingConformance *MissingConformance::create(ConstraintSystem &cs, Type type,
151+
ProtocolDecl *protocol,
152+
ConstraintLocator *locator) {
153+
return new (cs.getAllocator()) MissingConformance(type, protocol, locator);
154+
}

0 commit comments

Comments
 (0)