mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Try to fix constraint system in a way where member reference is going to be defined in terms of its use, which makes it seem like parameters match arguments exactly. Such helps to produce solutions and diagnose failures related to missing members precisely. These changes would be further extended to diagnose use of unavailable members and other structural member failures. Resolves: rdar://problem/34583132 Resolves: rdar://problem/36989788 Resolved: rdar://problem/39586166 Resolves: rdar://problem/40537782 Resolves: rdar://problem/46211109
222 lines
3.6 KiB
Swift
222 lines
3.6 KiB
Swift
// RUN: %target-typecheck-verify-swift -D ENABLE_C
|
|
|
|
enum E {
|
|
case A,B
|
|
#if ENABLE_C
|
|
case C
|
|
#endif
|
|
#if ENABLE_D
|
|
case D
|
|
#endif
|
|
}
|
|
|
|
func foo(x: E, intVal: Int) {
|
|
// Active guarded case first.
|
|
switch x {
|
|
#if ENABLE_C
|
|
case .C:
|
|
break
|
|
#endif
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
}
|
|
|
|
// Active guarded case last.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if ENABLE_C
|
|
case .C:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// Active guarded case middle.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
#if ENABLE_C
|
|
case .C:
|
|
break
|
|
#endif
|
|
default:
|
|
break
|
|
}
|
|
|
|
// Active guarded case after default.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
default:
|
|
break
|
|
#if ENABLE_C
|
|
case .C: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}}
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// Inactive guarded case after default.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
default:
|
|
break
|
|
#if ENABLE_D
|
|
case .D:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// #elseif.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if NEVER
|
|
#elseif ENABLE_C
|
|
case .C:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// #else.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if !ENABLE_C
|
|
#else
|
|
case .C:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// Nested #if.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if ENABLE_C
|
|
#if NEVER
|
|
#else
|
|
case .C:
|
|
break
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
// Exhaustive check.
|
|
switch x { // expected-error {{switch must be exhaustive}} expected-note {{add missing case: '.C'}}
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if NEVER
|
|
case .C:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// Exhaustive check 2.
|
|
switch x {
|
|
#if ENABLE_C
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
case .C:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// Empty check.
|
|
switch intVal { // expected-error {{'switch' statement body must have at least one 'case' or 'default' block; do you want to add a default case?}}
|
|
#if NEVER
|
|
case 1:
|
|
break
|
|
case 2:
|
|
break
|
|
case 3:
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// Non-'case' statement in '#else' block.
|
|
switch x {
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if ENABLE_C
|
|
case .C:
|
|
break
|
|
#else
|
|
break // expected-error {{all statements inside a switch must be covered by a 'case' or 'default'}}
|
|
#endif
|
|
}
|
|
|
|
// Non-'case' statement in '#if' block.
|
|
switch x { // expected-error {{switch must be exhaustive}} expected-note {{add missing case: '.C'}}
|
|
case .A:
|
|
break
|
|
case .B:
|
|
break
|
|
#if !ENABLE_C
|
|
break
|
|
#else
|
|
case .C: // expected-error {{'case' label can only appear inside a 'switch' statement}}
|
|
break
|
|
#endif
|
|
}
|
|
|
|
// '#if ... case' after non-covered statements.
|
|
switch x {
|
|
print() // expected-error {{all statements inside a switch must be covered by a 'case' or 'default'}}
|
|
#if ENABLE_C
|
|
case .NOT_EXIST: // expected-error {{type 'E' has no member 'NOT_EXIST'}}
|
|
break
|
|
case .C:
|
|
break
|
|
#endif
|
|
case .A, .B:
|
|
break
|
|
}
|
|
|
|
// '#if ... stmt' after non-covered statements.
|
|
switch x {
|
|
print() // expected-error {{all statements inside a switch must be covered by a 'case' or 'default'}}
|
|
#if true
|
|
print()
|
|
#endif
|
|
#if ENABLE_C
|
|
case .C:
|
|
break
|
|
#endif
|
|
case .A, .B:
|
|
break
|
|
}
|
|
|
|
// 'fallthrough' target.
|
|
switch intVal {
|
|
case 1:
|
|
fallthrough // expected-error {{'fallthrough' from a case which doesn't bind variable 'val'}}
|
|
#if ENABLE_C
|
|
case let val:
|
|
break
|
|
#endif
|
|
case 2:
|
|
fallthrough // expected-error {{'fallthrough' without a following 'case' or 'default' block}}
|
|
#if NEVER
|
|
case 3:
|
|
break
|
|
#endif
|
|
}
|
|
}
|