Files
swift-mirror/test/decl/protocol/existential_member_access/concrete.swift
Hamish Knight 5c3f6703a0 Remove diag::type_of_expression_is_ambiguous
This is a diagnostic that is only really emitted as a fallback when
the constraint system isn't able to better diagnose the expression.
It's not particulary helpful for the user, and can be often be
misleading since the underlying issue might not actually be an
ambiguity, and the user may well already have a type annotation. Let's
instead just emit the fallback diagnostic that we emit in all other
cases, asking the user to file a bug.
2025-08-19 17:14:23 +01:00

196 lines
6.6 KiB
Swift

// RUN: %target-typecheck-verify-swift -target %target-swift-5.9-abi-triple
/// Used to verify the type of an expression. Use like this:
/// ```
/// var types = SwiftTypePair(typeOf: expr, type2: SwiftType<Int>.self)
/// types.assertTypesAreEqual()
/// ```
struct SwiftType<T> {
init(_: T) {}
}
struct SwiftTypePair<T1, T2> {
init(typeOf: T1, type2: SwiftType<T2>.Type) {}
mutating func assertTypesAreEqual() where T1 == T2 {}
}
struct Struct<T> {
class Nested {}
struct NestedGeneric<U> {}
}
class Class<T> {}
// Test that a reference to a 'Self'-rooted dependent member type does not
// affect the ability to reference a protocol member on an existential when
// it is *fully* concrete.
protocol ConcreteAssocTypes {
associatedtype A1 where A1 == Struct<Self>
associatedtype A2 where A2 == (Bool, Self)
associatedtype A3 where A3 == any Class<A4> & ConcreteAssocTypes
associatedtype A4
func method1(_: A1)
func method2() -> Struct<A2>
func method3(_: A3)
var property1: A1 { get }
var property2: A2 { get }
var property3: A3 { get }
subscript(subscript1 _: A3) -> Bool { get }
subscript(subscript2 _: Bool) -> A1 { get }
subscript(subscript3 _: A2) -> Bool { get }
associatedtype A5 where A5 == Bool
associatedtype A6 where A6 == any ConcreteAssocTypes
associatedtype A7 where A7 == A8.A5
associatedtype A8: ConcreteAssocTypes
func method4(_: Struct<A5>, _: A6.Type, _: () -> A5) -> any Class<Struct<A7>.Nested> & ConcreteAssocTypes
var property4: (Struct<A5>, A6.Type, () -> A5) -> any Class<Struct<A7>.Nested> & ConcreteAssocTypes { get }
subscript(subscript4 _: Struct<A5>, _: A6.Type, _: () -> A5) -> any Class<Struct<A7>.Nested> & ConcreteAssocTypes { get }
}
do {
let exist: any ConcreteAssocTypes
let _ = exist.method1 // expected-error {{member 'method1' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
let _ = exist.method2 // expected-error {{member 'method2' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
let _ = exist.method3 // expected-error {{member 'method3' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
let _ = exist.property1 // expected-error {{member 'property1' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
// Covariant 'Self' erasure works in conjunction with concrete associated types.
do {
var types = SwiftTypePair(
typeOf: exist.property2,
type2: SwiftType<(Bool, any ConcreteAssocTypes)>.self
)
types.assertTypesAreEqual()
}
let _ = exist.property3 // expected-error {{member 'property3' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
let _ = exist[subscript1: false] // expected-error {{member 'subscript' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
let _ = exist[subscript2: false] // expected-error {{member 'subscript' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
let _ = exist[subscript3: false] // expected-error {{member 'subscript' cannot be used on value of type 'any ConcreteAssocTypes'; consider using a generic constraint instead}}
do {
var types = SwiftTypePair(
typeOf: exist.method4,
type2: SwiftType<
(
Struct<Bool>, (any ConcreteAssocTypes).Type, () -> Bool
) -> any Class<Struct<Bool>.Nested> & ConcreteAssocTypes
>.self
)
types.assertTypesAreEqual()
}
do {
var types = SwiftTypePair(
typeOf: exist.property4,
type2: SwiftType<
(
Struct<Bool>, (any ConcreteAssocTypes).Type, () -> Bool
) -> any Class<Struct<Bool>.Nested> & ConcreteAssocTypes
>.self
)
types.assertTypesAreEqual()
}
do {
var types = SwiftTypePair(
typeOf: exist[
subscript4: Struct<Bool>(), (any ConcreteAssocTypes).self, { true }
],
type2: SwiftType<any Class<Struct<Bool>.Nested> & ConcreteAssocTypes>.self
)
types.assertTypesAreEqual()
}
}
protocol ConcreteAssocTypeComposition1 {
associatedtype A
func method(_: A)
}
protocol ConcreteAssocTypeComposition2 where A == Bool {
associatedtype A
}
do {
let exist: any ConcreteAssocTypeComposition1 & ConcreteAssocTypeComposition2
exist.method(true) // ok
}
// Edge case: an associated type can be resolved through a class conformance.
class Class1Simple: ConcreteAssocTypeThroughClass {
typealias A = Bool
}
class Class1Generic<A>: ConcreteAssocTypeThroughClass {
}
protocol ConcreteAssocTypeThroughClass {
associatedtype A
}
protocol ConcreteAssocTypeThroughClassRefined: ConcreteAssocTypeThroughClass {
func method(_: A)
}
extension ConcreteAssocTypeThroughClassRefined {
func test(arg1: any ConcreteAssocTypeThroughClassRefined & Class1Generic<Self>,
arg2: any ConcreteAssocTypeThroughClassRefined & Class1Simple) {
arg1.method(self) // ok
arg2.method(true) // ok
}
}
protocol ConcreteAssocTypeCollision1 where A == Bool {
associatedtype A
func method(_: A)
}
protocol ConcreteAssocTypeCollision2 where A == Never {
associatedtype A
}
do {
let exist: any ConcreteAssocTypeCollision1 & ConcreteAssocTypeCollision2
// FIXME: Should 'A' be ambiguous here?
exist.method(true)
}
class BadConformanceClass: CompositionBrokenClassConformance_a {}
// expected-error@-1 {{type 'BadConformanceClass' does not conform to protocol 'CompositionBrokenClassConformance_a'}}
// expected-note@-2 {{add stubs for conformance}}
protocol CompositionBrokenClassConformance_a {
associatedtype A // expected-note {{protocol requires nested type 'A'}}
}
protocol CompositionBrokenClassConformance_b: CompositionBrokenClassConformance_a {
func method(_: A)
}
do {
// FIXME: Should GenericSignature::getConcreteType return the null type instead
// of the error type here for Self.A, despite the broken conformance?
let exist: any CompositionBrokenClassConformance_b & BadConformanceClass
exist.method(false) // expected-error {{failed to produce diagnostic for expression}}
}
// https://github.com/swiftlang/swift/issues/65533
do {
protocol P<A> {
associatedtype A
func item() -> A
}
class Class {}
func test<GP, ClassGP: Class>(
existGP: any P<GP>,
existClassGP: any P<ClassGP>
) {
do {
let result = SwiftType(existGP.item())
let _: SwiftType<GP> = result
}
do {
let result = SwiftType(existClassGP.item())
let _: SwiftType<ClassGP> = result
}
}
}