Skip to content

Commit 7cfd3cb

Browse files
authored
Merge pull request #29064 from LucianoPAlmeida/handle-csdiag-coerce-diagnostics
[Diagnostics] Removing FailureDiagnosis::visitCoerceExpr from CSDiag
2 parents d919bfa + 4443966 commit 7cfd3cb

File tree

6 files changed

+54
-25
lines changed

6 files changed

+54
-25
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
247247

248248
bool visitSubscriptExpr(SubscriptExpr *SE);
249249
bool visitApplyExpr(ApplyExpr *AE);
250-
bool visitCoerceExpr(CoerceExpr *CE);
251250
bool visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E);
252251
};
253252
} // end anonymous namespace
@@ -1878,17 +1877,6 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
18781877
return true;
18791878
}
18801879

1881-
bool FailureDiagnosis::visitCoerceExpr(CoerceExpr *CE) {
1882-
// Coerce the input to whatever type is specified by the CoerceExpr.
1883-
auto expr = typeCheckChildIndependently(CE->getSubExpr(),
1884-
CS.getType(CE->getCastTypeLoc()),
1885-
CTP_CoerceOperand);
1886-
if (!expr)
1887-
return true;
1888-
1889-
return false;
1890-
}
1891-
18921880
bool FailureDiagnosis::
18931881
visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E) {
18941882
// Don't walk the children for this node, it leads to multiple diagnostics

lib/Sema/CSDiagnostics.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,6 +1905,12 @@ bool ContextualFailure::diagnoseAsError() {
19051905
diagnostic = diag::cannot_convert_condition_value;
19061906
break;
19071907
}
1908+
1909+
case ConstraintLocator::InstanceType: {
1910+
if (diagnoseCoercionToUnrelatedType())
1911+
return true;
1912+
break;
1913+
}
19081914

19091915
case ConstraintLocator::TernaryBranch: {
19101916
auto *ifExpr = cast<IfExpr>(getRawAnchor());
@@ -2235,11 +2241,12 @@ bool ContextualFailure::diagnoseCoercionToUnrelatedType() const {
22352241
auto *anchor = getAnchor();
22362242

22372243
if (auto *coerceExpr = dyn_cast<CoerceExpr>(anchor)) {
2238-
auto fromType = getFromType();
2244+
auto fromType = getType(coerceExpr->getSubExpr());
22392245
auto toType = getType(coerceExpr->getCastTypeLoc());
2246+
22402247
auto diagnostic =
22412248
getDiagnosticFor(CTP_CoerceOperand,
2242-
/*forProtocol=*/toType->isAnyExistentialType());
2249+
/*forProtocol=*/toType->isExistentialType());
22432250

22442251
auto diag =
22452252
emitDiagnostic(anchor->getLoc(), *diagnostic, fromType, toType);

lib/Sema/CSSimplify.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,9 +2200,19 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
22002200
}
22012201
} else { // There are no elements in the path
22022202
auto *anchor = locator.getAnchor();
2203-
if (!(anchor && isa<AssignExpr>(anchor)))
2203+
if (!(anchor &&
2204+
(isa<AssignExpr>(anchor) || isa<CoerceExpr>(anchor))))
22042205
return getTypeMatchFailure(locator);
22052206
}
2207+
2208+
auto *anchor = locator.getAnchor();
2209+
if (isa<CoerceExpr>(anchor)) {
2210+
auto *fix = ContextualMismatch::create(
2211+
*this, type1, type2, getConstraintLocator(locator));
2212+
if (recordFix(fix))
2213+
return getTypeMatchFailure(locator);
2214+
break;
2215+
}
22062216

22072217
auto *fix = MissingConformance::forContextual(
22082218
*this, type1, proto, getConstraintLocator(locator));
@@ -2830,10 +2840,16 @@ bool ConstraintSystem::repairFailures(
28302840
conversionsOrFixes.push_back(coerceToCheckCastFix);
28312841
return true;
28322842
}
2833-
2843+
28342844
// If it has a deep equality restriction, defer the diagnostic to
28352845
// GenericMismatch.
2836-
if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality))
2846+
if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality) &&
2847+
!hasConversionOrRestriction(
2848+
ConversionRestrictionKind::OptionalToOptional)) {
2849+
return false;
2850+
}
2851+
2852+
if (hasConversionOrRestriction(ConversionRestrictionKind::Existential))
28372853
return false;
28382854

28392855
auto *fix = ContextualMismatch::create(*this, lhs, rhs,
@@ -3492,6 +3508,13 @@ bool ConstraintSystem::repairFailures(
34923508
break;
34933509
}
34943510
}
3511+
// Handle function result coerce expression wrong type conversion.
3512+
if (isa<CoerceExpr>(anchor)) {
3513+
auto *fix =
3514+
ContextualMismatch::create(*this, lhs, rhs, loc);
3515+
conversionsOrFixes.push_back(fix);
3516+
break;
3517+
}
34953518
LLVM_FALLTHROUGH;
34963519
}
34973520

@@ -4059,9 +4082,20 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
40594082
subKind = ConstraintKind::Bind;
40604083
}
40614084

4062-
return matchTypes(
4063-
instanceType1, instanceType2, subKind, subflags,
4064-
locator.withPathElement(ConstraintLocator::InstanceType));
4085+
auto result =
4086+
matchTypes(instanceType1, instanceType2, subKind, subflags,
4087+
locator.withPathElement(ConstraintLocator::InstanceType));
4088+
if (shouldAttemptFixes() && result.isFailure()) {
4089+
auto *anchor = locator.getAnchor();
4090+
if (anchor && isa<CoerceExpr>(anchor)) {
4091+
auto *fix =
4092+
ContextualMismatch::create(*this, instanceType1, instanceType2,
4093+
getConstraintLocator(locator));
4094+
conversionsOrFixes.push_back(fix);
4095+
break;
4096+
}
4097+
}
4098+
return result;
40654099
}
40664100

40674101
case TypeKind::Function: {

test/ClangImporter/objc_parse.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,8 @@ func testProtocolQualified(_ obj: CopyableNSObject, cell: CopyableSomeCell,
550550
_ = cell as NSCopying
551551
_ = cell as SomeCell
552552

553-
_ = plainObj as CopyableNSObject // expected-error {{'NSObject' is not convertible to 'CopyableNSObject' (aka 'NSCopying & NSObjectProtocol'); did you mean to use 'as!' to force downcast?}} {{16-18=as!}}
554-
_ = plainCell as CopyableSomeCell // expected-error {{'SomeCell' is not convertible to 'CopyableSomeCell' (aka 'SomeCell & NSCopying'); did you mean to use 'as!' to force downcast?}}
553+
_ = plainObj as CopyableNSObject // expected-error {{value of type 'NSObject' does not conform to 'CopyableNSObject' (aka 'NSCopying & NSObjectProtocol') in coercion}}
554+
_ = plainCell as CopyableSomeCell // expected-error {{value of type 'SomeCell' does not conform to 'CopyableSomeCell' (aka 'SomeCell & NSCopying') in coercion}}
555555
}
556556

557557
extension Printing {

test/Generics/function_defs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func otherExistential<T : EqualComparable>(_ t1: T) {
5353
otherEqComp2 = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}}
5454
_ = otherEqComp2
5555

56-
_ = t1 as EqualComparable & OtherEqualComparable // expected-error{{'T' is not convertible to 'EqualComparable & OtherEqualComparable'; did you mean to use 'as!' to force downcast?}} {{10-12=as!}} expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}}
56+
_ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}} expected-error{{protocol 'OtherEqualComparable' can only be used as a generic constraint}} expected-error{{protocol 'EqualComparable' can only be used as a generic constraint}}
5757
}
5858

5959
protocol Runcible {

test/decl/protocol/protocols.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ struct Circle {
118118
func testCircular(_ circle: Circle) {
119119
// FIXME: It would be nice if this failure were suppressed because the protocols
120120
// have circular definitions.
121-
_ = circle as CircleStart // expected-error{{'Circle' is not convertible to 'CircleStart'; did you mean to use 'as!' to force downcast?}} {{14-16=as!}}
121+
_ = circle as CircleStart // expected-error{{value of type 'Circle' does not conform to 'CircleStart' in coercion}}
122122
}
123123

124124
// <rdar://problem/14750346>
@@ -482,7 +482,7 @@ func f<T : C1>(_ x : T) {
482482

483483
class C2 {}
484484
func g<T : C2>(_ x : T) {
485-
x as P2 // expected-error{{'T' is not convertible to 'P2'; did you mean to use 'as!' to force downcast?}} {{5-7=as!}}
485+
x as P2 // expected-error{{value of type 'T' does not conform to 'P2' in coercion}}
486486
}
487487

488488
class C3 : P1 {} // expected-error{{type 'C3' does not conform to protocol 'P1'}}

0 commit comments

Comments
 (0)