Skip to content

Commit d4e8d58

Browse files
authored
Revert "[ConstraintSystem] Use missing conformance fix to diagnose contextual failures"
1 parent cbf4185 commit d4e8d58

File tree

13 files changed

+49
-210
lines changed

13 files changed

+49
-210
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
20522052
// system had a contextual type specified, we use it - it will have a purpose
20532053
// indicator which allows us to give a very "to the point" diagnostic.
20542054
Diag<Type, Type> diagID;
2055+
Diag<Type, Type> diagIDProtocol;
20552056
Diag<Type> nilDiag;
20562057
std::function<void(void)> nilFollowup;
20572058

@@ -2068,6 +2069,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
20682069
"contextual type");
20692070
case CTP_Initialization:
20702071
diagID = diag::cannot_convert_initializer_value;
2072+
diagIDProtocol = diag::cannot_convert_initializer_value_protocol;
20712073
nilDiag = diag::cannot_convert_initializer_value_nil;
20722074
nilFollowup = [this] {
20732075
TypeRepr *patternTR = CS.getContextualTypeLoc().getTypeRepr();
@@ -2093,6 +2095,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
20932095
}
20942096

20952097
diagID = diag::cannot_convert_to_return_type;
2098+
diagIDProtocol = diag::cannot_convert_to_return_type_protocol;
20962099
nilDiag = diag::cannot_convert_to_return_type_nil;
20972100
break;
20982101
case CTP_ThrowStmt: {
@@ -2140,10 +2143,12 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
21402143

21412144
case CTP_EnumCaseRawValue:
21422145
diagID = diag::cannot_convert_raw_initializer_value;
2146+
diagIDProtocol = diag::cannot_convert_raw_initializer_value;
21432147
nilDiag = diag::cannot_convert_raw_initializer_value_nil;
21442148
break;
21452149
case CTP_DefaultParameter:
21462150
diagID = diag::cannot_convert_default_arg_value;
2151+
diagIDProtocol = diag::cannot_convert_default_arg_value_protocol;
21472152
nilDiag = diag::cannot_convert_default_arg_value_nil;
21482153
break;
21492154

@@ -2163,34 +2168,42 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
21632168
return true;
21642169
case CTP_YieldByValue:
21652170
diagID = diag::cannot_convert_yield_value;
2171+
diagIDProtocol = diag::cannot_convert_yield_value_protocol;
21662172
nilDiag = diag::cannot_convert_yield_value_nil;
21672173
break;
21682174
case CTP_CallArgument:
21692175
diagID = diag::cannot_convert_argument_value;
2176+
diagIDProtocol = diag::cannot_convert_argument_value_protocol;
21702177
nilDiag = diag::cannot_convert_argument_value_nil;
21712178
break;
21722179
case CTP_ClosureResult:
21732180
diagID = diag::cannot_convert_closure_result;
2181+
diagIDProtocol = diag::cannot_convert_closure_result_protocol;
21742182
nilDiag = diag::cannot_convert_closure_result_nil;
21752183
break;
21762184
case CTP_ArrayElement:
21772185
diagID = diag::cannot_convert_array_element;
2186+
diagIDProtocol = diag::cannot_convert_array_element_protocol;
21782187
nilDiag = diag::cannot_convert_array_element_nil;
21792188
break;
21802189
case CTP_DictionaryKey:
21812190
diagID = diag::cannot_convert_dict_key;
2191+
diagIDProtocol = diag::cannot_convert_dict_key_protocol;
21822192
nilDiag = diag::cannot_convert_dict_key_nil;
21832193
break;
21842194
case CTP_DictionaryValue:
21852195
diagID = diag::cannot_convert_dict_value;
2196+
diagIDProtocol = diag::cannot_convert_dict_value_protocol;
21862197
nilDiag = diag::cannot_convert_dict_value_nil;
21872198
break;
21882199
case CTP_CoerceOperand:
21892200
diagID = diag::cannot_convert_coerce;
2201+
diagIDProtocol = diag::cannot_convert_coerce_protocol;
21902202
nilDiag = diag::cannot_convert_coerce_nil;
21912203
break;
21922204
case CTP_AssignSource:
21932205
diagID = diag::cannot_convert_assign;
2206+
diagIDProtocol = diag::cannot_convert_assign_protocol;
21942207
nilDiag = diag::cannot_convert_assign_nil;
21952208
break;
21962209
}
@@ -2302,13 +2315,10 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
23022315

23032316
// When complaining about conversion to a protocol type, complain about
23042317
// conformance instead of "conversion".
2305-
if (contextualType->isExistentialType()) {
2306-
MissingContextualConformanceFailure failure(
2307-
expr, CS, CTP, exprType, contextualType,
2308-
CS.getConstraintLocator(expr, ConstraintLocator::ContextualType));
2309-
return failure.diagnoseAsError();
2310-
}
2311-
2318+
if (contextualType->is<ProtocolType>() ||
2319+
contextualType->is<ProtocolCompositionType>())
2320+
diagID = diagIDProtocol;
2321+
23122322
// Try to simplify irrelevant details of function types. For example, if
23132323
// someone passes a "() -> Float" function to a "() throws -> Int"
23142324
// parameter, then uttering the "throws" may confuse them into thinking that

lib/Sema/CSDiagnostics.cpp

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2812,83 +2812,3 @@ bool CollectionElementContextualFailure::diagnoseAsError() {
28122812
eltType, contextualType, anchor);
28132813
return true;
28142814
}
2815-
2816-
bool MissingContextualConformanceFailure::diagnoseAsError() {
2817-
auto *anchor = getAnchor();
2818-
auto path = getLocator()->getPath();
2819-
2820-
Optional<Diag<Type, Type>> diagnostic;
2821-
if (path.empty()) {
2822-
assert(isa<AssignExpr>(anchor));
2823-
diagnostic = getDiagnosticFor(CTP_AssignSource);
2824-
} else {
2825-
const auto &last = path.back();
2826-
switch (last.getKind()) {
2827-
case ConstraintLocator::ContextualType:
2828-
assert(Context != CTP_Unused);
2829-
diagnostic = getDiagnosticFor(Context);
2830-
break;
2831-
2832-
default:
2833-
break;
2834-
}
2835-
}
2836-
2837-
if (!diagnostic)
2838-
return false;
2839-
2840-
auto srcType = getFromType();
2841-
auto dstType = getToType();
2842-
2843-
emitDiagnostic(anchor->getLoc(), *diagnostic, srcType, dstType);
2844-
2845-
if (isa<InOutExpr>(anchor))
2846-
return true;
2847-
2848-
if (srcType->isAny() && dstType->isAnyObject()) {
2849-
emitDiagnostic(anchor->getLoc(), diag::any_as_anyobject_fixit)
2850-
.fixItInsertAfter(anchor->getEndLoc(), " as AnyObject");
2851-
}
2852-
2853-
return true;
2854-
}
2855-
2856-
Optional<Diag<Type, Type>>
2857-
MissingContextualConformanceFailure::getDiagnosticFor(
2858-
ContextualTypePurpose context) {
2859-
switch (context) {
2860-
case CTP_Initialization:
2861-
return diag::cannot_convert_initializer_value_protocol;
2862-
case CTP_ReturnStmt:
2863-
case CTP_ReturnSingleExpr:
2864-
return diag::cannot_convert_to_return_type_protocol;
2865-
case CTP_EnumCaseRawValue:
2866-
return diag::cannot_convert_raw_initializer_value;
2867-
case CTP_DefaultParameter:
2868-
return diag::cannot_convert_default_arg_value_protocol;
2869-
case CTP_YieldByValue:
2870-
return diag::cannot_convert_yield_value_protocol;
2871-
case CTP_CallArgument:
2872-
return diag::cannot_convert_argument_value_protocol;
2873-
case CTP_ClosureResult:
2874-
return diag::cannot_convert_closure_result_protocol;
2875-
case CTP_ArrayElement:
2876-
return diag::cannot_convert_array_element_protocol;
2877-
case CTP_DictionaryKey:
2878-
return diag::cannot_convert_dict_key_protocol;
2879-
case CTP_DictionaryValue:
2880-
return diag::cannot_convert_dict_value_protocol;
2881-
case CTP_CoerceOperand:
2882-
return diag::cannot_convert_coerce_protocol;
2883-
case CTP_AssignSource:
2884-
return diag::cannot_convert_assign_protocol;
2885-
2886-
case CTP_ThrowStmt:
2887-
case CTP_Unused:
2888-
case CTP_CannotFail:
2889-
case CTP_YieldByReference:
2890-
case CTP_CalleeResult:
2891-
break;
2892-
}
2893-
return None;
2894-
}

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -324,15 +324,14 @@ class RequirementFailure : public FailureDiagnostic {
324324
/// ```
325325
class MissingConformanceFailure final : public RequirementFailure {
326326
Type NonConformingType;
327-
Type ProtocolType;
327+
ProtocolDecl *Protocol;
328328

329329
public:
330330
MissingConformanceFailure(Expr *expr, ConstraintSystem &cs,
331331
ConstraintLocator *locator,
332-
std::pair<Type, Type> conformance)
332+
std::pair<Type, ProtocolDecl *> conformance)
333333
: RequirementFailure(cs, expr, RequirementKind::Conformance, locator),
334-
NonConformingType(conformance.first), ProtocolType(conformance.second) {
335-
}
334+
NonConformingType(conformance.first), Protocol(conformance.second) {}
336335

337336
bool diagnoseAsError() override;
338337

@@ -342,7 +341,7 @@ class MissingConformanceFailure final : public RequirementFailure {
342341
Type getLHS() const override { return NonConformingType; }
343342

344343
/// The protocol generic requirement expected associated type to conform to.
345-
Type getRHS() const override { return ProtocolType; }
344+
Type getRHS() const override { return Protocol->getDeclaredType(); }
346345

347346
protected:
348347
DiagOnDecl getDiagnosticOnDecl() const override {
@@ -1203,27 +1202,6 @@ class CollectionElementContextualFailure final : public ContextualFailure {
12031202
bool diagnoseAsError() override;
12041203
};
12051204

1206-
class MissingContextualConformanceFailure final : public ContextualFailure {
1207-
ContextualTypePurpose Context;
1208-
1209-
public:
1210-
MissingContextualConformanceFailure(Expr *root, ConstraintSystem &cs,
1211-
ContextualTypePurpose context, Type type,
1212-
Type protocolType,
1213-
ConstraintLocator *locator)
1214-
: ContextualFailure(root, cs, type, protocolType, locator),
1215-
Context(context) {
1216-
assert(protocolType->is<ProtocolType>() ||
1217-
protocolType->is<ProtocolCompositionType>());
1218-
}
1219-
1220-
bool diagnoseAsError() override;
1221-
1222-
private:
1223-
static Optional<Diag<Type, Type>>
1224-
getDiagnosticFor(ContextualTypePurpose purpose);
1225-
};
1226-
12271205
} // end namespace constraints
12281206
} // end namespace swift
12291207

lib/Sema/CSFix.cpp

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -160,35 +160,16 @@ RelabelArguments::create(ConstraintSystem &cs,
160160
}
161161

162162
bool MissingConformance::diagnose(Expr *root, bool asNote) const {
163-
auto &cs = getConstraintSystem();
164-
auto *locator = getLocator();
165-
166-
if (IsContextual) {
167-
auto context = cs.getContextualTypePurpose();
168-
MissingContextualConformanceFailure failure(
169-
root, cs, context, NonConformingType, ProtocolType, locator);
170-
return failure.diagnose(asNote);
171-
}
172-
173-
MissingConformanceFailure failure(
174-
root, cs, locator, std::make_pair(NonConformingType, ProtocolType));
163+
MissingConformanceFailure failure(root, getConstraintSystem(), getLocator(),
164+
{NonConformingType, Protocol});
175165
return failure.diagnose(asNote);
176166
}
177167

178-
MissingConformance *
179-
MissingConformance::forContextual(ConstraintSystem &cs, Type type,
180-
Type protocolType,
181-
ConstraintLocator *locator) {
182-
return new (cs.getAllocator()) MissingConformance(
183-
cs, /*isContextual=*/true, type, protocolType, locator);
184-
}
185-
186-
MissingConformance *
187-
MissingConformance::forRequirement(ConstraintSystem &cs, Type type,
188-
Type protocolType,
189-
ConstraintLocator *locator) {
190-
return new (cs.getAllocator()) MissingConformance(
191-
cs, /*isContextual=*/false, type, protocolType, locator);
168+
MissingConformance *MissingConformance::create(ConstraintSystem &cs, Type type,
169+
ProtocolDecl *protocol,
170+
ConstraintLocator *locator) {
171+
return new (cs.getAllocator())
172+
MissingConformance(cs, type, protocol, locator);
192173
}
193174

194175
bool SkipSameTypeRequirement::diagnose(Expr *root, bool asNote) const {

lib/Sema/CSFix.h

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -363,19 +363,13 @@ class RelabelArguments final
363363

364364
/// Add a new conformance to the type to satisfy a requirement.
365365
class MissingConformance final : public ConstraintFix {
366-
// Determines whether given protocol type comes from the context e.g.
367-
// assignment destination or argument comparison.
368-
bool IsContextual;
369-
370366
Type NonConformingType;
371-
// This could either be a protocol or protocol composition.
372-
Type ProtocolType;
367+
ProtocolDecl *Protocol;
373368

374-
MissingConformance(ConstraintSystem &cs, bool isContextual, Type type,
375-
Type protocolType, ConstraintLocator *locator)
369+
MissingConformance(ConstraintSystem &cs, Type type, ProtocolDecl *protocol,
370+
ConstraintLocator *locator)
376371
: ConstraintFix(cs, FixKind::AddConformance, locator),
377-
IsContextual(isContextual), NonConformingType(type),
378-
ProtocolType(protocolType) {}
372+
NonConformingType(type), Protocol(protocol) {}
379373

380374
public:
381375
std::string getName() const override {
@@ -384,17 +378,13 @@ class MissingConformance final : public ConstraintFix {
384378

385379
bool diagnose(Expr *root, bool asNote = false) const override;
386380

387-
static MissingConformance *forRequirement(ConstraintSystem &cs, Type type,
388-
Type protocolType,
389-
ConstraintLocator *locator);
390-
391-
static MissingConformance *forContextual(ConstraintSystem &cs, Type type,
392-
Type protocolType,
393-
ConstraintLocator *locator);
381+
static MissingConformance *create(ConstraintSystem &cs, Type type,
382+
ProtocolDecl *protocol,
383+
ConstraintLocator *locator);
394384

395385
Type getNonConformingType() { return NonConformingType; }
396386

397-
Type getProtocolType() { return ProtocolType; }
387+
ProtocolDecl *getProtocol() { return Protocol; }
398388
};
399389

400390
/// Skip same-type generic requirement constraint,

0 commit comments

Comments
 (0)