Skip to content

Commit c9ef005

Browse files
authored
Merge pull request swiftlang#35072 from xedin/rdar-72166791
[Diagnostics] Special case assignment between nominal types with optional promotion
2 parents 5f4fd6d + ec31d77 commit c9ef005

File tree

5 files changed

+59
-11
lines changed

5 files changed

+59
-11
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,9 @@ bool ContextualFailure::diagnoseAsError() {
21202120
}
21212121

21222122
if (isExpr<AssignExpr>(anchor)) {
2123-
emitDiagnostic(diag::cannot_convert_assign, getFromType(), getToType());
2123+
auto diagnostic = emitDiagnostic(diag::cannot_convert_assign,
2124+
getFromType(), getToType());
2125+
tryIntegerCastFixIts(diagnostic);
21242126
return true;
21252127
}
21262128

@@ -2729,6 +2731,15 @@ bool ContextualFailure::tryIntegerCastFixIts(
27292731
auto fromType = getFromType();
27302732
auto toType = getToType();
27312733

2734+
auto anchor = getAnchor();
2735+
auto exprRange = getSourceRange();
2736+
2737+
if (auto *assignment = getAsExpr<AssignExpr>(anchor)) {
2738+
toType = toType->lookThroughAllOptionalTypes();
2739+
anchor = assignment->getSrc();
2740+
exprRange = assignment->getSrc()->getSourceRange();
2741+
}
2742+
27322743
if (!isIntegerType(fromType) || !isIntegerType(toType))
27332744
return false;
27342745

@@ -2747,8 +2758,8 @@ bool ContextualFailure::tryIntegerCastFixIts(
27472758
return parenE->getSubExpr();
27482759
};
27492760

2750-
if (auto *anchor = getAsExpr(getAnchor())) {
2751-
if (Expr *innerE = getInnerCastedExpr(anchor)) {
2761+
if (auto *expr = getAsExpr(anchor)) {
2762+
if (Expr *innerE = getInnerCastedExpr(expr)) {
27522763
Type innerTy = getType(innerE);
27532764
if (TypeChecker::isConvertibleTo(innerTy, toType, getDC())) {
27542765
// Remove the unnecessary cast.
@@ -2763,7 +2774,6 @@ bool ContextualFailure::tryIntegerCastFixIts(
27632774
std::string convWrapBefore = toType.getString();
27642775
convWrapBefore += "(";
27652776
std::string convWrapAfter = ")";
2766-
SourceRange exprRange = getSourceRange();
27672777
diagnostic.fixItInsert(exprRange.Start, convWrapBefore);
27682778
diagnostic.fixItInsertAfter(exprRange.End, convWrapAfter);
27692779
return true;

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3722,14 +3722,15 @@ bool ConstraintSystem::repairFailures(
37223722
if (lhs->is<FunctionType>() && rhs->is<FunctionType>())
37233723
return false;
37243724

3725-
// If either object type is a bound generic or existential it means
3726-
// that follow-up to value-to-optional is going to be:
3725+
// If either object type is a generic, nominal or existential type
3726+
// it means that follow-up to value-to-optional is going to be:
37273727
//
37283728
// 1. "deep equality" check, which is handled by generic argument(s)
3729-
// mismatch fix, or
3729+
// or contextual mismatch fix, or
37303730
// 2. "existential" check, which is handled by a missing conformance
37313731
// fix.
37323732
if ((lhs->is<BoundGenericType>() && rhs->is<BoundGenericType>()) ||
3733+
(lhs->is<NominalType>() && rhs->is<NominalType>()) ||
37333734
rhs->isAnyExistentialType())
37343735
return false;
37353736
}

test/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ var afterMessageCount : Int?
345345
func uintFunc() -> UInt {}
346346
func takeVoidVoidFn(_ a : () -> ()) {}
347347
takeVoidVoidFn { () -> Void in
348-
afterMessageCount = uintFunc() // expected-error {{cannot assign value of type 'UInt' to type 'Int'}}
348+
afterMessageCount = uintFunc() // expected-error {{cannot assign value of type 'UInt' to type 'Int?'}} {{23-23=Int(}} {{33-33=)}}
349349
}
350350

351351
// <rdar://problem/19997471> Swift: Incorrect compile error when calling a function inside a closure

test/Constraints/sr13951.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol TheProtocol {}
4+
struct TheType1: TheProtocol {}
5+
6+
enum TheEnum: RawRepresentable {
7+
typealias RawValue = TheProtocol
8+
9+
case case1
10+
case case2
11+
12+
init?(rawValue: TheProtocol) {
13+
self = .case1
14+
}
15+
16+
var rawValue: TheProtocol {
17+
return TheType1()
18+
}
19+
}
20+
21+
func aTransformer(input: Int) -> TheEnum {
22+
if input % 2 == 0 {
23+
return .case1
24+
} else {
25+
return .case2
26+
}
27+
}
28+
29+
func theProblem(input: Int?) {
30+
var enumValue: TheEnum?
31+
32+
if let input = input {
33+
enumValue = aTransformer(input: input) // Ok
34+
}
35+
36+
_ = enumValue // To silence the warning
37+
}

test/decl/var/property_wrappers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,12 +1100,12 @@ struct TestComposition {
11001100
// expected-error@-2 {{composed wrapper type 'WrapperE<Int>' does not match former 'wrappedValue' type 'WrapperC<Value>'}}
11011101

11021102
func triggerErrors(d: Double) { // expected-note 6 {{mark method 'mutating' to make 'self' mutable}} {{2-2=mutating }}
1103-
p1 = d // expected-error{{cannot assign value of type 'Double' to type 'Int'}} {{8-8=Int(}} {{9-9=)}}
1103+
p1 = d // expected-error{{cannot assign value of type 'Double' to type 'Int?'}} {{8-8=Int(}} {{9-9=)}}
11041104
// expected-error@-1 {{cannot assign to property: 'self' is immutable}}
1105-
p2 = d // expected-error{{cannot assign value of type 'Double' to type 'String'}}
1105+
p2 = d // expected-error{{cannot assign value of type 'Double' to type 'String?'}}
11061106
// expected-error@-1 {{cannot assign to property: 'self' is immutable}}
11071107
// TODO(diagnostics): Looks like source range for 'd' here is reported as starting at 10, but it should be 8
1108-
p3 = d // expected-error{{cannot assign value of type 'Double' to type 'Int'}} {{10-10=Int(}} {{11-11=)}}
1108+
p3 = d // expected-error{{cannot assign value of type 'Double' to type 'Int?'}} {{10-10=Int(}} {{11-11=)}}
11091109
// expected-error@-1 {{cannot assign to property: 'self' is immutable}}
11101110

11111111
_p1 = d // expected-error{{cannot assign value of type 'Double' to type 'WrapperA<WrapperB<WrapperC<Int>>>'}}

0 commit comments

Comments
 (0)