Skip to content

Commit aae22ad

Browse files
committed
[CSSimplify] Detect when generic argument mismatch applies to argument and produce a tailed fix
The problem detection logic currently expects `generic argument #<N>` location to always be associated with two generic types, but that is not always the case, this locator element is sometimes used for i.e. optional object types and pointer `Pointee` type when types appear in argument positions. This needs to be handled specifically. Resolves: rdar://82971941
1 parent 4f1d0d0 commit aae22ad

File tree

7 files changed

+43
-16
lines changed

7 files changed

+43
-16
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6884,9 +6884,28 @@ bool ConstraintSystem::repairFailures(
68846884
if (!path.empty() && path.back().is<LocatorPathElt::PackElement>())
68856885
path.pop_back();
68866886

6887-
if (!path.empty() && path.back().is<LocatorPathElt::AnyRequirement>()) {
6888-
return repairFailures(lhs, rhs, matchKind, flags, conversionsOrFixes,
6889-
getConstraintLocator(anchor, path));
6887+
if (!path.empty()) {
6888+
if (path.back().is<LocatorPathElt::AnyRequirement>()) {
6889+
return repairFailures(lhs, rhs, matchKind, flags, conversionsOrFixes,
6890+
getConstraintLocator(anchor, path));
6891+
}
6892+
6893+
if (auto argConv = path.back().getAs<LocatorPathElt::ApplyArgToParam>()) {
6894+
auto argIdx = argConv->getArgIdx();
6895+
auto paramIdx = argConv->getParamIdx();
6896+
6897+
auto *argLoc = getConstraintLocator(anchor, path);
6898+
if (auto overload = findSelectedOverloadFor(getCalleeLocator(argLoc))) {
6899+
auto *overloadTy =
6900+
simplifyType(overload->boundType)->castTo<FunctionType>();
6901+
auto *argList = getAsExpr(anchor)->getArgs();
6902+
ASSERT(argList);
6903+
conversionsOrFixes.push_back(AllowArgumentMismatch::create(
6904+
*this, getType(argList->getExpr(argIdx)),
6905+
overloadTy->getParams()[paramIdx].getPlainType(), argLoc));
6906+
return true;
6907+
}
6908+
}
68906909
}
68916910

68926911
// When the solver sets `TMF_MatchingGenericArguments` it means

test/Constraints/bridging.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,9 @@ func rdar19836341(_ ns: NSString?, vns: NSString?) {
296296

297297
// <rdar://problem/20029786> Swift compiler sometimes suggests changing "as!" to "as?!"
298298
func rdar20029786(_ ns: NSString?) {
299-
var s: String = ns ?? "str" as String as String // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{19-19=(}} {{50-50=) as String}}
300-
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'NSString'}} {{50-50= as NSString}}
301-
var s2 = ns ?? "str" as String as String // expected-error {{cannot convert value of type 'String' to expected argument type 'NSString'}}{{43-43= as NSString}}
299+
var s: String = ns ?? "str" as String as String
300+
// expected-error@-1 {{cannot convert value of type 'NSString?' to expected argument type 'String?'}} {{21-21= as String?}}
301+
var s2 = ns ?? "str" as String as String // expected-error {{binary operator '??' cannot be applied to operands of type 'NSString?' and 'String'}}
302302

303303
let s3: NSString? = "str" as String? // expected-error {{cannot convert value of type 'String?' to specified type 'NSString?'}}{{39-39= as NSString?}}
304304

test/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ struct R_76250381<Result, Failure: Error> {
11561156
func rdar77022842(argA: Bool? = nil, argB: Bool? = nil) {
11571157
if let a = argA ?? false, if let b = argB ?? {
11581158
// expected-error@-1 {{initializer for conditional binding must have Optional type, not 'Bool'}}
1159-
// expected-error@-2 {{closure passed to parameter of type 'Bool?' that does not accept a closure}}
1159+
// expected-error@-2 {{cannot convert value of type 'Bool?' to expected argument type '(() -> ())?'}}
11601160
// expected-error@-3 {{cannot convert value of type 'Void' to expected condition type 'Bool'}}
11611161
// expected-error@-4 {{'if' may only be used as expression in return, throw, or as the source of an assignment}}
11621162
// expected-error@-5 {{'if' must have an unconditional 'else' to be used as expression}}

test/Constraints/optional.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,3 +607,14 @@ func testExtraQuestionMark(action: () -> Void, v: Int) {
607607
// expected-error@-1 {{cannot convert value of type 'Int' to expected argument type '() -> Void'}}
608608
// expected-error@-2 {{cannot use optional chaining on non-optional value of type 'Int'}}
609609
}
610+
611+
func testPassingOptionalChainAsWrongArgument() {
612+
class Test {
613+
func fn(_ asdType: String?) {
614+
}
615+
}
616+
617+
func test(test: Test, arr: [Int]?) {
618+
test.fn(arr?.first) // expected-error {{cannot convert value of type 'Int?' to expected argument type 'String?'}}
619+
}
620+
}

test/decl/func/typed_throws.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ enum G_E<T> {
192192

193193
func testArrMap(arr: [String]) {
194194
_ = mapArray(arr, body: G_E<Int>.tuple)
195-
// expected-error@-1{{cannot convert value of type '((x: Int, y: Int)) -> G_E<Int>' to expected argument type '(String) -> G_E<Int>'}}
195+
// expected-error@-1{{conflicting arguments to generic parameter 'T' ('String' vs. '(x: Int, y: Int)')}}
196196
}
197197

198198
// Shadowing of typed-throws Result.get() addresses a source compatibility

test/expr/expressions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ func testNilCoalescePrecedence(cond: Bool, a: Int?, r: ClosedRange<Int>?) {
794794

795795
// ?? should have lower precedence than range and arithmetic operators.
796796
let r1 = r ?? (0...42) // ok
797-
let r2 = (r ?? 0)...42 // not ok: expected-error {{binary operator '??' cannot be applied to operands of type 'ClosedRange<Int>?' and 'Int'}}
797+
let r2 = (r ?? 0)...42 // not ok: expected-error {{cannot convert value of type 'ClosedRange<Int>?' to expected argument type 'Int?'}}
798798
let r3 = r ?? 0...42 // parses as the first one, not the second.
799799

800800

test/stdlib/UnsafePointerDiagnostics.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,14 @@ func unsafePointerConversionAvailability(
7878

7979
_ = UnsafeMutablePointer<Int>(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafeMutablePointer<Int>'}}
8080
_ = UnsafeMutablePointer<Int>(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer<Int>'}}
81-
// Two candidates here: OpaquePointer? and UnsafeMutablePointer<Int>?
81+
// This is ambiguous because we have failable and non-failable initializers that accept the same argument type.
8282
_ = UnsafeMutablePointer<Int>(orp) // expected-error {{no exact matches in call to initializer}}
83-
// Two candidates here: OpaquePointer? and UnsafeMutablePointer<Int>?
84-
_ = UnsafeMutablePointer<Int>(omrp) // expected-error {{no exact matches in call to initializer}}
83+
_ = UnsafeMutablePointer<Int>(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafeMutablePointer<Int>'}}
8584

8685
_ = UnsafePointer<Int>(rp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer<Int>'}}
8786
_ = UnsafePointer<Int>(mrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer<Int>'}}
88-
// Two candidates here: OpaquePointer? and UnsafeMutablePointer<Int>?
89-
_ = UnsafePointer<Int>(orp) // expected-error {{no exact matches in call to initializer}}
90-
// Two candidates here: OpaquePointer? and UnsafeMutablePointer<Int>?
91-
_ = UnsafePointer<Int>(omrp) // expected-error {{no exact matches in call to initializer}}
87+
_ = UnsafePointer<Int>(orp) // expected-error {{cannot convert value of type 'UnsafeRawPointer' to expected argument type 'UnsafePointer<Int>'}}
88+
_ = UnsafePointer<Int>(omrp) // expected-error {{cannot convert value of type 'UnsafeMutableRawPointer' to expected argument type 'UnsafePointer<Int>'}}
9289

9390
_ = UnsafePointer<Int>(ups) // expected-error {{cannot convert value of type 'UnsafePointer<String>' to expected argument type 'UnsafePointer<Int>'}}
9491
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('String' and 'Int') are expected to be equal}}

0 commit comments

Comments
 (0)