Skip to content

Commit 142e9f6

Browse files
committed
[Diagnostics] Tweak some diagnostics code to allow diagnosing a fix
anchored at a TypeRepr rather than an Expr.
1 parent 2ac8d7e commit 142e9f6

File tree

4 files changed

+30
-14
lines changed

4 files changed

+30
-14
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ void RequirementFailure::emitRequirementNote(const Decl *anchor, Type lhs,
414414
}
415415

416416
bool MissingConformanceFailure::diagnoseAsError() {
417-
auto *anchor = castToExpr(getAnchor());
417+
auto anchor = getAnchor();
418418
auto nonConformingType = getLHS();
419419
auto protocolType = getRHS();
420420

@@ -423,8 +423,9 @@ bool MissingConformanceFailure::diagnoseAsError() {
423423
// with it and if so skip conformance error, otherwise we'd
424424
// produce an unrelated `<type> doesn't conform to Equatable protocol`
425425
// diagnostic.
426-
if (isPatternMatchingOperator(const_cast<Expr *>(anchor))) {
427-
if (auto *binaryOp = dyn_cast_or_null<BinaryExpr>(findParentExpr(anchor))) {
426+
if (isPatternMatchingOperator(anchor)) {
427+
auto *expr = castToExpr(anchor);
428+
if (auto *binaryOp = dyn_cast_or_null<BinaryExpr>(findParentExpr(expr))) {
428429
auto *caseExpr = binaryOp->getArg()->getElement(0);
429430

430431
llvm::SmallPtrSet<Expr *, 4> anchors;
@@ -452,6 +453,7 @@ bool MissingConformanceFailure::diagnoseAsError() {
452453
// says that conformances for enums with associated values can't be
453454
// synthesized.
454455
if (isStandardComparisonOperator(anchor)) {
456+
auto *expr = castToExpr(anchor);
455457
auto isEnumWithAssociatedValues = [](Type type) -> bool {
456458
if (auto *enumType = type->getAs<EnumType>())
457459
return !enumType->getDecl()->hasOnlyCasesWithoutAssociatedValues();
@@ -464,7 +466,7 @@ bool MissingConformanceFailure::diagnoseAsError() {
464466
(protocol->isSpecificProtocol(KnownProtocolKind::Equatable) ||
465467
protocol->isSpecificProtocol(KnownProtocolKind::Comparable))) {
466468
if (RequirementFailure::diagnoseAsError()) {
467-
auto opName = getOperatorName(anchor);
469+
auto opName = getOperatorName(expr);
468470
emitDiagnostic(diag::no_binary_op_overload_for_enum_with_payload,
469471
opName->str());
470472
return true;
@@ -4998,8 +5000,15 @@ bool MissingGenericArgumentsFailure::diagnoseAsError() {
49985000
scopedParameters[base].push_back(GP);
49995001
});
50005002

5001-
if (!isScoped)
5002-
return diagnoseForAnchor(castToExpr(getAnchor()), Parameters);
5003+
// FIXME: this code should be generalized now that we can anchor the
5004+
// fixes on the TypeRepr with the missing generic arg.
5005+
if (!isScoped) {
5006+
assert(getAnchor().is<Expr *>() || getAnchor().is<TypeRepr *>());
5007+
if (auto *expr = getAsExpr(getAnchor()))
5008+
return diagnoseForAnchor(expr, Parameters);
5009+
5010+
return diagnoseForAnchor(getAnchor().get<TypeRepr *>(), Parameters);
5011+
}
50035012

50045013
bool diagnosed = false;
50055014
for (const auto &scope : scopedParameters)

lib/Sema/CSDiagnostics.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,9 @@ class RequirementFailure : public FailureDiagnostic {
265265
assert(getGenericContext() &&
266266
"Affected decl not within a generic context?");
267267

268-
if (auto *parentExpr = findParentExpr(getRawAnchor().get<Expr *>()))
269-
Apply = dyn_cast<ApplyExpr>(parentExpr);
268+
if (auto *expr = getAsExpr(getRawAnchor()))
269+
if (auto *parentExpr = findParentExpr(expr))
270+
Apply = dyn_cast<ApplyExpr>(parentExpr);
270271
}
271272

272273
unsigned getRequirementIndex() const {

lib/Sema/ConstraintSystem.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4249,11 +4249,17 @@ Optional<Identifier> constraints::getOperatorName(Expr *expr) {
42494249
return None;
42504250
}
42514251

4252-
bool constraints::isPatternMatchingOperator(Expr *expr) {
4252+
bool constraints::isPatternMatchingOperator(ASTNode node) {
4253+
auto *expr = getAsExpr(node);
4254+
if (!expr) return false;
4255+
42534256
return isOperator(expr, "~=");
42544257
}
42554258

4256-
bool constraints::isStandardComparisonOperator(Expr *expr) {
4259+
bool constraints::isStandardComparisonOperator(ASTNode node) {
4260+
auto *expr = getAsExpr(node);
4261+
if (!expr) return false;
4262+
42574263
if (auto opName = getOperatorName(expr)) {
42584264
return opName->is("==") || opName->is("!=") || opName->is("===") ||
42594265
opName->is("!==") || opName->is("<") || opName->is(">") ||

lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5224,13 +5224,13 @@ bool isArgumentOfPatternMatchingOperator(ConstraintLocator *locator);
52245224
/// associated with `===` and `!==` operators.
52255225
bool isArgumentOfReferenceEqualityOperator(ConstraintLocator *locator);
52265226

5227-
/// Determine whether given expression is a reference to a
5227+
/// Determine whether the given AST node is a reference to a
52285228
/// pattern-matching operator `~=`
5229-
bool isPatternMatchingOperator(Expr *expr);
5229+
bool isPatternMatchingOperator(ASTNode node);
52305230

5231-
/// Determine whether given expression is a reference to a
5231+
/// Determine whether the given AST node is a reference to a
52325232
/// "standard" comparison operator such as "==", "!=", ">" etc.
5233-
bool isStandardComparisonOperator(Expr *expr);
5233+
bool isStandardComparisonOperator(ASTNode node);
52345234

52355235
/// If given expression references operator overlaod(s)
52365236
/// extract and produce name of the operator.

0 commit comments

Comments
 (0)