Skip to content

Commit 36fff23

Browse files
authored
Merge pull request #29011 from LucianoPAlmeida/coercion-handle-contextual-mismatch
[Diagnostics] Handle CoerceExpr conversion failure in contextual mismatch
2 parents 93d07c6 + 64f8a6b commit 36fff23

File tree

6 files changed

+47
-15
lines changed

6 files changed

+47
-15
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,16 +1887,6 @@ bool FailureDiagnosis::visitCoerceExpr(CoerceExpr *CE) {
18871887
if (!expr)
18881888
return true;
18891889

1890-
auto ref = expr->getReferencedDecl();
1891-
if (auto *decl = ref.getDecl()) {
1892-
// Without explicit coercion we might end up
1893-
// type-checking sub-expression as unavaible
1894-
// declaration, let's try to diagnose that here.
1895-
if (AvailableAttr::isUnavailable(decl))
1896-
return diagnoseExplicitUnavailability(
1897-
decl, expr->getSourceRange(), CS.DC, dyn_cast<ApplyExpr>(expr));
1898-
}
1899-
19001890
return false;
19011891
}
19021892

lib/Sema/CSDiagnostics.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,9 @@ bool ContextualFailure::diagnoseAsError() {
18531853
getFromType(), getToType());
18541854
return true;
18551855
}
1856+
1857+
if (diagnoseCoercionToUnrelatedType())
1858+
return true;
18561859

18571860
return false;
18581861
}
@@ -2220,6 +2223,28 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const {
22202223
return true;
22212224
}
22222225

2226+
bool ContextualFailure::diagnoseCoercionToUnrelatedType() const {
2227+
auto *anchor = getAnchor();
2228+
2229+
if (auto *coerceExpr = dyn_cast<CoerceExpr>(anchor)) {
2230+
auto fromType = getFromType();
2231+
auto toType = getType(coerceExpr->getCastTypeLoc());
2232+
auto diagnostic =
2233+
getDiagnosticFor(CTP_CoerceOperand,
2234+
/*forProtocol=*/toType->isAnyExistentialType());
2235+
2236+
auto diag =
2237+
emitDiagnostic(anchor->getLoc(), *diagnostic, fromType, toType);
2238+
diag.highlight(anchor->getSourceRange());
2239+
2240+
(void)tryFixIts(diag);
2241+
2242+
return true;
2243+
}
2244+
2245+
return false;
2246+
}
2247+
22232248
bool ContextualFailure::diagnoseConversionToBool() const {
22242249
auto toType = getToType();
22252250
if (!toType->isBool())
@@ -2565,6 +2590,10 @@ bool ContextualFailure::trySequenceSubsequenceFixIts(
25652590
if (getFromType()->isEqual(Substring)) {
25662591
if (getToType()->isEqual(String)) {
25672592
auto *anchor = getAnchor()->getSemanticsProvidingExpr();
2593+
if (auto *CE = dyn_cast<CoerceExpr>(anchor)) {
2594+
anchor = CE->getSubExpr();
2595+
}
2596+
25682597
auto range = anchor->getSourceRange();
25692598
diagnostic.fixItInsert(range.Start, "String(");
25702599
diagnostic.fixItInsertAfter(range.End, ")");

lib/Sema/CSDiagnostics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@ class ContextualFailure : public FailureDiagnostic {
554554

555555
/// If we're trying to convert something to `nil`.
556556
bool diagnoseConversionToNil() const;
557+
558+
/// Diagnose failed conversion in a `CoerceExpr`.
559+
bool diagnoseCoercionToUnrelatedType() const;
557560

558561
// If we're trying to convert something of type "() -> T" to T,
559562
// then we probably meant to call the value.

lib/Sema/CSSimplify.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2823,6 +2823,15 @@ bool ConstraintSystem::repairFailures(
28232823
conversionsOrFixes.push_back(coerceToCheckCastFix);
28242824
return true;
28252825
}
2826+
2827+
// If it has a deep equality restriction, defer the diagnostic to
2828+
// GenericMismatch.
2829+
if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality))
2830+
return false;
2831+
2832+
auto *fix = ContextualMismatch::create(*this, lhs, rhs,
2833+
getConstraintLocator(locator));
2834+
conversionsOrFixes.push_back(fix);
28262835
}
28272836

28282837
// This could be:

test/Parse/recovery.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,9 +619,11 @@ class WrongInheritanceClause6(Int {}
619619
class WrongInheritanceClause7<T>(Int where T:AnyObject {}
620620

621621
// <rdar://problem/18502220> [swift-crashes 078] parser crash on invalid cast in sequence expr
622-
Base=1 as Base=1 // expected-error {{cannot convert value of type 'Int' to type 'Base' in coercion}}
623-
624-
622+
Base=1 as Base=1 // expected-error{{cannot convert value of type 'Int' to type 'Base' in coercion}}
623+
// expected-error@-1 {{cannot assign to immutable expression of type 'Base.Type'}}
624+
// expected-error@-2 {{cannot assign to immutable expression of type 'Base'}}
625+
// expected-error@-3 {{cannot assign value of type '()' to type 'Base.Type'}}
626+
// expected-error@-4 {{cannot assign value of type 'Int' to type 'Base'}}
625627

626628
// <rdar://problem/18634543> Parser hangs at swift::Parser::parseType
627629
public enum TestA {

test/type/subclass_composition.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ func basicSubtyping(
105105
let _: Derived = baseAndP2 // expected-error {{cannot convert value of type 'Base<Int> & P2' to specified type 'Derived'}}
106106
let _: Derived & P2 = baseAndP2 // expected-error {{value of type 'Base<Int> & P2' does not conform to specified type 'Derived & P2'}}
107107

108-
// TODO(diagnostics): Diagnostic regression, better message is `value of type 'Unrelated' does not conform to 'Derived & P2' in coercion`
109-
let _ = Unrelated() as Derived & P2 // expected-error {{cannot convert value of type 'Unrelated' to type 'Derived' in coercion}}
108+
let _ = Unrelated() as Derived & P2 // expected-error {{value of type 'Unrelated' does not conform to 'Derived & P2' in coercion}}
110109
let _ = Unrelated() as? Derived & P2 // expected-warning {{always fails}}
111110
let _ = baseAndP2 as Unrelated // expected-error {{cannot convert value of type 'Base<Int> & P2' to type 'Unrelated' in coercion}}
112111
let _ = baseAndP2 as? Unrelated // expected-warning {{always fails}}

0 commit comments

Comments
 (0)