mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CS] Handle conditional requirements in existential conversions of literals.
This likely affects other things too, but literals are where it appears most. Previously, the mid-solving literal types like Array<$T0> were just checked for whether they conformed to the protocol, without acknowledging that this might introduce requirements on $T0, instead the conditional requirements were checked against $T0, and so failed (there's no reason that $T0 should satisfy the requirements at all, it's a recently-constructed transient type variable). Instead, capture the requirements and add them as constraints to the type variable. Fixes https://bugs.swift.org/browse/SR-7192 and rdar://problem/38461036 and improves https://bugs.swift.org/browse/SR-6941.
This commit is contained in:
@@ -2580,7 +2580,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
|
||||
case ConstraintKind::SelfObjectOfProtocol:
|
||||
if (auto conformance =
|
||||
TC.containsProtocol(type, protocol, DC,
|
||||
ConformanceCheckFlags::InExpression)) {
|
||||
(ConformanceCheckFlags::InExpression|
|
||||
ConformanceCheckFlags::SkipConditionalRequirements))) {
|
||||
return recordConformance(*conformance);
|
||||
}
|
||||
break;
|
||||
|
||||
130
test/Generics/conditional_conformances_literals.swift
Normal file
130
test/Generics/conditional_conformances_literals.swift
Normal file
@@ -0,0 +1,130 @@
|
||||
// RUN: %target-typecheck-verify-swift -typecheck -verify
|
||||
|
||||
// rdar://problem/38461036 , https://bugs.swift.org/browse/SR-7192 and highlights the real problem in https://bugs.swift.org/browse/SR-6941
|
||||
|
||||
protocol SameType {}
|
||||
protocol Conforms {}
|
||||
|
||||
struct Works: Hashable, Conforms {}
|
||||
struct Fails: Hashable {}
|
||||
|
||||
extension Array: SameType where Element == Works {}
|
||||
extension Dictionary: SameType where Value == Works {}
|
||||
extension Array: Conforms where Element: Conforms {}
|
||||
extension Dictionary: Conforms where Value: Conforms {}
|
||||
|
||||
let works = Works()
|
||||
let fails = Fails()
|
||||
|
||||
func arraySameType() {
|
||||
let arrayWorks = [works]
|
||||
let arrayFails = [fails]
|
||||
|
||||
let _: SameType = [works]
|
||||
let _: SameType = [fails]
|
||||
// expected-error@-1 {{value of type '[Fails]' does not conform to specified type 'SameType'}}
|
||||
|
||||
let _: SameType = arrayWorks
|
||||
let _: SameType = arrayFails
|
||||
// expected-error@-1 {{value of type '[Fails]' does not conform to specified type 'SameType'}}
|
||||
|
||||
let _: SameType = [works] as [Works]
|
||||
let _: SameType = [fails] as [Fails]
|
||||
// expected-error@-1 {{value of type '[Fails]' does not conform to specified type 'SameType'}}
|
||||
|
||||
let _: SameType = [works] as SameType
|
||||
let _: SameType = [fails] as SameType
|
||||
// expected-error@-1 {{'[Fails]' is not convertible to 'SameType'}}
|
||||
|
||||
let _: SameType = arrayWorks as SameType
|
||||
let _: SameType = arrayFails as SameType
|
||||
// expected-error@-1 {{'[Fails]' is not convertible to 'SameType'}}
|
||||
}
|
||||
|
||||
func dictionarySameType() {
|
||||
let dictWorks: [Int : Works] = [0 : works]
|
||||
let dictFails: [Int : Fails] = [0 : fails]
|
||||
|
||||
let _: SameType = [0 : works]
|
||||
let _: SameType = [0 : fails]
|
||||
// expected-error@-1 {{contextual type 'SameType' cannot be used with dictionary literal}}
|
||||
|
||||
let _: SameType = dictWorks
|
||||
let _: SameType = dictFails
|
||||
// expected-error@-1 {{value of type '[Int : Fails]' does not conform to specified type 'SameType'}}
|
||||
|
||||
let _: SameType = [0 : works] as [Int : Works]
|
||||
let _: SameType = [0 : fails] as [Int : Fails]
|
||||
// expected-error@-1 {{value of type '[Int : Fails]' does not conform to specified type 'SameType'}}
|
||||
|
||||
let _: SameType = [0 : works] as SameType
|
||||
let _: SameType = [0 : fails] as SameType
|
||||
// expected-error@-1 {{'[Int : Fails]' is not convertible to 'SameType'}}
|
||||
|
||||
let _: SameType = dictWorks as SameType
|
||||
let _: SameType = dictFails as SameType
|
||||
// expected-error@-1 {{'[Int : Fails]' is not convertible to 'SameType'}}
|
||||
}
|
||||
|
||||
func arrayConforms() {
|
||||
let arrayWorks = [works]
|
||||
let arrayFails = [fails]
|
||||
|
||||
let _: Conforms = [works]
|
||||
let _: Conforms = [fails]
|
||||
// expected-error@-1 {{value of type '[Fails]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
let _: Conforms = arrayWorks
|
||||
let _: Conforms = arrayFails
|
||||
// expected-error@-1 {{value of type '[Fails]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
let _: Conforms = [works] as [Works]
|
||||
let _: Conforms = [fails] as [Fails]
|
||||
// expected-error@-1 {{value of type '[Fails]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
let _: Conforms = [works] as Conforms
|
||||
let _: Conforms = [fails] as Conforms
|
||||
// expected-error@-1 {{'[Fails]' is not convertible to 'Conforms'}}
|
||||
|
||||
let _: Conforms = arrayWorks as Conforms
|
||||
let _: Conforms = arrayFails as Conforms
|
||||
// expected-error@-1 {{'[Fails]' is not convertible to 'Conforms'}}
|
||||
}
|
||||
|
||||
func dictionaryConforms() {
|
||||
let dictWorks: [Int : Works] = [0 : works]
|
||||
let dictFails: [Int : Fails] = [0 : fails]
|
||||
|
||||
let _: Conforms = [0 : works]
|
||||
let _: Conforms = [0 : fails]
|
||||
// expected-error@-1 {{contextual type 'Conforms' cannot be used with dictionary literal}}
|
||||
|
||||
let _: Conforms = dictWorks
|
||||
let _: Conforms = dictFails
|
||||
// expected-error@-1 {{value of type '[Int : Fails]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
let _: Conforms = [0 : works] as [Int : Works]
|
||||
let _: Conforms = [0 : fails] as [Int : Fails]
|
||||
// expected-error@-1 {{value of type '[Int : Fails]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
let _: Conforms = [0 : works] as Conforms
|
||||
let _: Conforms = [0 : fails] as Conforms
|
||||
// expected-error@-1 {{'[Int : Fails]' is not convertible to 'Conforms'}}
|
||||
|
||||
let _: Conforms = dictWorks as Conforms
|
||||
let _: Conforms = dictFails as Conforms
|
||||
// expected-error@-1 {{'[Int : Fails]' is not convertible to 'Conforms'}}
|
||||
}
|
||||
|
||||
func combined() {
|
||||
let _: Conforms = [[0: [1 : [works]]]]
|
||||
let _: Conforms = [[0: [1 : [fails]]]]
|
||||
// expected-error@-1 {{value of type '[[Int : [Int : [Fails]]]]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
// Needs self conforming protocols:
|
||||
let _: Conforms = [[0: [1 : [works]] as Conforms]]
|
||||
// expected-error@-1 {{value of type '[[Int : Conforms]]' does not conform to specified type 'Conforms'}}
|
||||
|
||||
let _: Conforms = [[0: [1 : [fails]] as Conforms]]
|
||||
// expected-error@-1 {{'[Int : [Fails]]' is not convertible to 'Conforms'}}
|
||||
}
|
||||
Reference in New Issue
Block a user