Files
swift-mirror/test/Constraints/subscript.swift
Kathy Gray 5e407bce89 Diagnostics change for ambiguous overloads previously specifying 'this'
Updates the message to use the type or ValueDecl instead of this on previous 'Found this candidate' messages
Note: doees not yet change all test cases so more tests are failing

Improve Diagnostic message on overload ambiguitiy

Remove messages that say 'found this candidate' in favour of providing the type for the candidate to aid in selection when the candidates are presented in a dialogue window.

Fix more tests
2025-10-10 17:46:22 +01:00

242 lines
7.0 KiB
Swift

// RUN: %target-typecheck-verify-swift
// Simple subscript of arrays:
func simpleSubscript(_ array: [Float], x: Int) -> Float {
_ = array[x]
return array[x]
}
// Subscript of archetype.
protocol IntToStringSubscript {
subscript (i : Int) -> String { get }
}
class FauxDictionary {
subscript (i : Int) -> String {
get {
return String(i)
}
}
}
func archetypeSubscript<T : IntToStringSubscript, U : FauxDictionary>(_ t: T, u: U)
-> String {
// Subscript an archetype.
if false { return t[17] }
// Subscript an archetype for which the subscript operator is in a base class.
return u[17]
}
// Subscript of existential type.
func existentialSubscript(_ a: IntToStringSubscript) -> String {
return a[17]
}
// Static of above:
// Subscript of archetype.
protocol IntToStringStaticSubscript {
static subscript (i : Int) -> String { get }
}
class FauxStaticDictionary {
static subscript (i : Int) -> String {
get {
return String(i)
}
}
}
func archetypeStaticSubscript<
T : IntToStringStaticSubscript, U : FauxStaticDictionary
>(_ t: T.Type, u: U.Type) -> String {
// Subscript an archetype.
if false { return t[17] }
// Subscript an archetype for which the subscript operator is in a base class.
return u[17]
}
// Subscript of existential type.
func existentialStaticSubscript(
_ a: IntToStringStaticSubscript.Type
) -> String {
return a[17]
}
class MyDictionary<Key, Value> {
subscript (key : Key) -> Value {
get {}
}
}
class MyStringToInt<T> : MyDictionary<String, Int> { }
// Subscript of generic type.
func genericSubscript<T>(_ t: T,
array: Array<Int>,
i2i: MyDictionary<Int, Int>,
t2i: MyDictionary<T, Int>,
s2i: MyStringToInt<()>) -> Int {
if true { return array[5] }
if true { return i2i[5] }
if true { return t2i[t] }
return s2i["hello"]
}
// <rdar://problem/21364448> QoI: Poor error message for ambiguous subscript call
extension String {
func number() -> Int { } // expected-note {{found candidate with type '() -> Int'}}
func number() -> Double { } // expected-note {{found candidate with type '() -> Double'}}
}
let _ = "a".number // expected-error {{ambiguous use of 'number()'}}
extension Int {
subscript(key: String) -> Int { get {} } // expected-note {{found candidate with type '(String) -> Int'}}
subscript(key: String) -> Double { get {} } // expected-note {{found candidate with type '(String) -> Double'}}
}
let _ = 1["1"] // expected-error {{ambiguous use of 'subscript(_:)'}}
let squares = [ 1, 2, 3 ].reduce([:]) { (dict, n) in
var dict = dict
dict[n] = n * n
return dict
}
// <rdar://problem/23670252> QoI: Misleading error message when assigning a value from [String : AnyObject]
func r23670252(_ dictionary: [String : AnyObject], someObject: AnyObject) {
let color : String?
color = dictionary["color"] // expected-error {{cannot assign value of type 'AnyObject?' to type 'String?'}}
// expected-note@-1 {{arguments to generic parameter 'Wrapped' ('AnyObject' and 'String') are expected to be equal}}
_ = color
}
// https://github.com/apple/swift/issues/43333
// Type mismatch reported as extraneous parameter
do {
struct S {
subscript(b : Int) -> Int
{ return 0 }
subscript(a a : UInt) -> Int { return 0 }
}
S()[a: Int()] // expected-error {{cannot convert value of type 'Int' to expected argument type 'UInt'}}
}
// rdar://problem/25601561 - Qol: Bad diagnostic for failed assignment from Any to more specific type
struct S_r25601561 {
func value() -> Any? { return "hi" }
}
class C_r25601561 {
var a: [S_r25601561?] = []
func test(i: Int) -> String {
let s: String = a[i]!.value()! // expected-error {{cannot convert value of type 'Any' to specified type 'String'}}
return s
}
}
// rdar://problem/31977679 - Misleading diagnostics when using subscript with incorrect argument
func r31977679_1(_ properties: [String: String]) -> Any? {
return properties[0] // expected-error {{cannot convert value of type 'Int' to expected argument type 'String'}}
}
func r31977679_2(_ properties: [String: String]) -> Any? {
return properties["foo"] // Ok
}
// rdar://problem/45819956 - inout-to-pointer in a subscript arg could use a better diagnostic
func rdar_45819956() {
struct S {
subscript(takesPtr ptr: UnsafeMutablePointer<Int>) -> Int {
get { return 0 }
}
}
let s = S()
var i = 0
// TODO: It should be possible to suggest `withUnsafe[Mutable]Pointer` as a fix-it
_ = s[takesPtr: &i]
// expected-error@-1 {{cannot pass an inout argument to a subscript; use 'withUnsafeMutablePointer' to explicitly convert argument to a pointer}}
}
// rdar://problem/45825806
// https://github.com/apple/swift/issues/49738
// Array-to-pointer in subscript arg crashes compiler
do {
struct S {
subscript(takesPtr ptr: UnsafePointer<Int>) -> Int {
get { return 0 }
}
}
let s = S()
_ = s[takesPtr: [1, 2, 3]] // Ok
}
func test_generic_subscript_requirements_mismatch_diagnostics() {
struct S {
subscript<T: StringProtocol>(_: T) -> T { // expected-note {{where 'T' = 'Int'}}
fatalError()
}
subscript<T, U: Collection>(v v: [T]) -> U where U.Element == T {
fatalError()
}
subscript<T: Collection>(number num: T) -> Int where T.Element: BinaryInteger {
// expected-note@-1 {{'T.Element' = 'String'}}
return 42
}
}
var s = S()
_ = s[42] // expected-error {{subscript 'subscript(_:)' requires that 'Int' conform to 'StringProtocol'}}
var arr: [Int] = []
let _: [String] = s[v: arr] // expected-error {{cannot convert value of type '[Int]' to expected argument type '[String]'}}
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
s[number: ["hello"]] // expected-error {{subscript 'subscript(number:)' requires that 'String' conform to 'BinaryInteger'}}
}
// rdar://61084565 - infinite recursion in dynamic member lookup
func rdar61084565() {
@dynamicMemberLookup
struct Foo {
subscript(dynamicMember _: KeyPath<Foo, Int>) -> Int {
return 42
}
}
let a = Foo()
a[] // expected-error {{value of type 'Foo' has no subscripts}}
}
// Note: In Swift >= 6 mode this would become an error.
func test_subscript_accepts_type_name_argument() {
struct A {
subscript(a: A.Type) -> Int { get { 42 } }
}
func test(a: A, optA: A?) {
let _ = a[A] // expected-warning {{expected member name or initializer call after type name; this will be an error in Swift 6}}
// expected-note@-1 {{add arguments after the type to construct a value of the type}} {{16-16=()}}
// expected-note@-2 {{use '.self' to reference the type object}} {{16-16=.self}}
let _ = optA?[A] // expected-warning {{expected member name or initializer call after type name; this will be an error in Swift 6}}
// expected-note@-1 {{add arguments after the type to construct a value of the type}} {{20-20=()}}
// expected-note@-2 {{use '.self' to reference the type object}} {{20-20=.self}}
}
}