Skip to content

Commit 08904ff

Browse files
[SR-12242] Apply to Arg involving ConstraintLocator::GenericArgument diagnostics improvement (#30814)
* [CSDiagnostics] Handle arg to param generic when locator points to ConstraintLocator::GenericArgument * [test] Add SR-12242 test case * [CSDiagnostics] Handle arg to param on Generic mismatch as a fallback diagnostic * [CSDiagnostics] Make assign diagnostics in GenericMismatchFailure handle more cases * [test] Adding test cases for assign expr in GenericMismatch diagnostics * [CSDiagnostics] Improving inout to pointer argument conversions with optionals diagnostics
1 parent f2dda13 commit 08904ff

File tree

3 files changed

+79
-9
lines changed

3 files changed

+79
-9
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -667,20 +667,17 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
667667
}
668668

669669
case ConstraintLocator::GenericArgument: {
670-
// In cases like `[[Int]]` vs. `[[String]]`
671-
if (auto *assignExpr = dyn_cast<AssignExpr>(anchor)) {
672-
diagnostic = getDiagnosticFor(CTP_AssignSource);
673-
fromType = getType(assignExpr->getSrc());
674-
toType = getType(assignExpr->getDest());
675-
}
676670
break;
677671
}
678-
672+
679673
case ConstraintLocator::OptionalPayload: {
680674
// If we have an inout expression, this comes from an
681675
// InoutToPointer argument mismatch failure.
682676
if (isa<InOutExpr>(anchor)) {
683677
diagnostic = diag::cannot_convert_argument_value;
678+
auto applyInfo = getFunctionArgApplyInfo(getLocator());
679+
if (applyInfo)
680+
toType = applyInfo->getParamType();
684681
}
685682
break;
686683
}
@@ -703,6 +700,24 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
703700
}
704701
}
705702

703+
if (!diagnostic) {
704+
// Handle all mismatches involving an `AssignExpr`
705+
if (auto *assignExpr = dyn_cast<AssignExpr>(anchor)) {
706+
diagnostic = getDiagnosticFor(CTP_AssignSource);
707+
fromType = getType(assignExpr->getSrc());
708+
toType = getType(assignExpr->getDest());
709+
} else {
710+
// If we couldn't find a specific diagnostic let's fallback to
711+
// attempt to handle cases where we have an apply arg to param.
712+
auto applyInfo = getFunctionArgApplyInfo(getLocator());
713+
if (applyInfo) {
714+
diagnostic = diag::cannot_convert_argument_value;
715+
fromType = applyInfo->getArgType();
716+
toType = applyInfo->getParamType();
717+
}
718+
}
719+
}
720+
706721
if (!diagnostic)
707722
return false;
708723

test/Constraints/diagnostics.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,3 +1415,58 @@ f11(3, f4) // expected-error {{global function 'f11' requires that 'Int' conform
14151415
let f12: (Int) -> Void = { _ in }
14161416
func f12<T : P2>(_ n: T, _ f: @escaping (T) -> T) {}
14171417
f12(3, f4)// expected-error {{extra argument in call}}
1418+
1419+
// SR-12242
1420+
struct SR_12242_R<Value> {}
1421+
struct SR_12242_T {}
1422+
1423+
protocol SR_12242_P {}
1424+
1425+
func fSR_12242() -> SR_12242_R<[SR_12242_T]> {}
1426+
1427+
func genericFunc<SR_12242_T: SR_12242_P>(_ completion: @escaping (SR_12242_R<[SR_12242_T]>) -> Void) {
1428+
let t = fSR_12242()
1429+
completion(t) // expected-error {{cannot convert value of type 'diagnostics.SR_12242_R<[diagnostics.SR_12242_T]>' to expected argument type 'diagnostics.SR_12242_R<[SR_12242_T]>'}}
1430+
// expected-note@-1 {{arguments to generic parameter 'Element' ('diagnostics.SR_12242_T' and 'SR_12242_T') are expected to be equal}}
1431+
}
1432+
1433+
func assignGenericMismatch() {
1434+
var a: [Int]?
1435+
var b: [String]
1436+
1437+
a = b // expected-error {{cannot assign value of type '[String]' to type '[Int]?'}}
1438+
// expected-note@-1 {{arguments to generic parameter 'Element' ('String' and 'Int') are expected to be equal}}
1439+
1440+
b = a // expected-error {{cannot assign value of type '[Int]' to type '[String]'}}
1441+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
1442+
// expected-error@-2 {{value of optional type '[Int]?' must be unwrapped to a value of type '[Int]'}}
1443+
// expected-note@-3 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
1444+
// expected-note@-4 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
1445+
}
1446+
1447+
// [Int] to [String]? argument to param conversion
1448+
let value: [Int] = []
1449+
func gericArgToParamOptional(_ param: [String]?) {}
1450+
1451+
gericArgToParamOptional(value) // expected-error {{convert value of type '[Int]' to expected argument type '[String]?'}}
1452+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
1453+
1454+
// Inout Expr conversions
1455+
func gericArgToParamInout1(_ x: inout [[Int]]) {}
1456+
func gericArgToParamInout2(_ x: inout [[String]]) {
1457+
gericArgToParamInout1(&x) // expected-error {{cannot convert value of type '[[String]]' to expected argument type '[[Int]]'}}
1458+
// expected-note@-1 {{arguments to generic parameter 'Element' ('String' and 'Int') are expected to be equal}}
1459+
}
1460+
1461+
func gericArgToParamInoutOptional(_ x: inout [[String]]?) {
1462+
gericArgToParamInout1(&x) // expected-error {{cannot convert value of type '[[String]]?' to expected argument type '[[Int]]'}}
1463+
// expected-note@-1 {{arguments to generic parameter 'Element' ('String' and 'Int') are expected to be equal}}
1464+
// expected-error@-2 {{value of optional type '[[String]]?' must be unwrapped to a value of type '[[String]]'}}
1465+
// expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
1466+
}
1467+
1468+
func gericArgToParamInout(_ x: inout [[Int]]) { // expected-note {{change variable type to '[[String]]?' if it doesn't need to be declared as '[[Int]]'}}
1469+
gericArgToParamInoutOptional(&x) // expected-error {{cannot convert value of type '[[Int]]' to expected argument type '[[String]]?'}}
1470+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
1471+
// expected-error@-2 {{inout argument could be set to a value with a type other than '[[Int]]'; use a value declared as type '[[String]]?' instead}}
1472+
}

test/Constraints/valid_pointer_conversions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ func givesPtr(_ str: String) {
3131
takesDoubleOptionalPtr(i) // expected-error {{cannot convert value of type 'Int' to expected argument type 'UnsafeRawPointer??'}}
3232
takesMutableDoubleOptionalPtr(arr) // expected-error {{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutableRawPointer??'}}
3333

34-
takesMutableDoubleOptionalTypedPtr(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<Int>' to expected argument type 'UnsafeMutablePointer<Double>'}}
34+
takesMutableDoubleOptionalTypedPtr(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<Int>' to expected argument type 'UnsafeMutablePointer<Double>??'}}
3535
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'Double') are expected to be equal}}
3636
}
3737

3838
// SR12382
3939
func SR12382(_ x: UnsafeMutablePointer<Double>??) {}
4040

4141
var i = 0
42-
SR12382(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<Int>' to expected argument type 'UnsafeMutablePointer<Double>'}}
42+
SR12382(&i) // expected-error {{cannot convert value of type 'UnsafeMutablePointer<Int>' to expected argument type 'UnsafeMutablePointer<Double>??'}}
4343
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'Double') are expected to be equal}}

0 commit comments

Comments
 (0)