Files
swift-mirror/test/Parse/enum.swift
Doug Gregor 126e404fe5 Reimplement inference of type witnesses with a separate non-recursive pass.
Inference of type witnesses for associated types was previously
implemented as part of value witness matching in the constraint
solver. This led to a number of serious problems, including:
  - Recursion problems with the solver hunting for a type witness,
  which triggers more attemts to match value witnesses...
  - Arbitrarily crummy attempts to break the recursion causing
  type-check failures in fun places.
  - Ordering dependencies abound: different results depending on which
  value witnesses were satisfied first, failures because of the order
  in which we attempted to infer type witnesses, etc.

This new implementation of type witness inference uses a separate pass
that occurs whenever we're looking for any type witness, and solves
all of the type witnesses within a given conformance
simultaneously. We still look at potential value witnesses to infer
type witnesses, but we match them structurally, without invoking the
constraint solver.

There are a few caveats to this implementation:
  * We're not currently able to infer type witnesses from value
  witnesses that are global operators, so some tricks involving global
  operators (*cough* ~> *cough*) might require some manually-specified
  type witnesses. Note that the standard library doesn't include any
  such cases.

  * Yes, it's another kind of solver. At simple one, fortunately.

On the other hand, this implementation should be a big step forward:
  * It's far more predictable, order-invariant, and non-recursive.
  * The diagnostics for failures to infer type witnesses have
  improved.

Fixes rdar://problem/20598513.

Swift SVN r27616
2015-04-23 00:20:05 +00:00

338 lines
11 KiB
Swift

// RUN: %target-parse-verify-swift
// FIXME: this test only passes on platforms which have Float80.
// <rdar://problem/19508460> Floating point enum raw values are not portable
// REQUIRES: CPU=i386_or_x86_64
enum Empty {}
enum Boolish {
case falsy
case truthy
init() { self = .falsy }
}
var b = Boolish.falsy
b = .truthy
enum Optionable<T> {
case Nought
case Mere(T)
}
var o = Optionable<Int>.Nought
o = .Mere(0)
enum Color { case Red, Green, Grayscale(Int), Blue }
var c = Color.Red
c = .Green
c = .Grayscale(255)
c = .Blue
let partialApplication = Color.Grayscale // expected-error{{partial application of enum constructor is not allowed}}
// Cases are excluded from non-enums.
case FloatingCase // expected-error{{enum 'case' is not allowed outside of an enum}}
struct SomeStruct {
case StructCase // expected-error{{enum 'case' is not allowed outside of an enum}}
}
class SomeClass {
case ClassCase // expected-error{{enum 'case' is not allowed outside of an enum}}
}
enum EnumWithExtension1 {
case A1
}
extension EnumWithExtension1 {
case A2 // expected-error{{enum 'case' is not allowed outside of an enum}}
}
// Attributes for enum cases.
enum EnumCaseAttributes {
@xyz case EmptyAttributes // expected-error {{unknown attribute 'xyz'}}
}
// Recover when a switch 'case' label is spelled inside an enum (or outside).
enum SwitchEnvy {
case X: // expected-error{{'case' label can only appear inside a 'switch' statement}}
case X(Y): // expected-error{{'case' label can only appear inside a 'switch' statement}}
case X, Y: // expected-error{{'case' label can only appear inside a 'switch' statement}}
case X where true: // expected-error{{'case' label can only appear inside a 'switch' statement}}
case X(Y), Z(W): // expected-error{{'case' label can only appear inside a 'switch' statement}}
case X(Y) where true: // expected-error{{'case' label can only appear inside a 'switch' statement}}
case 0: // expected-error{{'case' label can only appear inside a 'switch' statement}}
case _: // expected-error{{'case' label can only appear inside a 'switch' statement}}
case (_, var x, 0): // expected-error{{'case' label can only appear inside a 'switch' statement}}
}
enum HasMethodsPropertiesAndCtors {
case TweedleDee
case TweedleDum
func method() {}
func staticMethod() {}
init() {}
subscript(x:Int) -> Int {
return 0
}
var property : Int {
return 0
}
}
enum ImproperlyHasIVars {
case Flopsy
case Mopsy
var ivar : Int // expected-error{{enums may not contain stored properties}}
}
// We used to crash on this. rdar://14678675
enum rdar14678675 {
case U1,
case U2 // expected-error{{expected identifier after comma in enum 'case' declaration}}
case U3
}
enum Recovery1 {
case: // expected-error {{'case' label can only appear inside a 'switch' statement}} expected-error {{expected pattern}}
}
enum Recovery2 {
case UE1: // expected-error {{'case' label can only appear inside a 'switch' statement}}
}
enum Recovery3 {
case UE2(): // expected-error {{'case' label can only appear inside a 'switch' statement}}
}
enum Recovery4 {
case Self Self // expected-error {{expected identifier in enum case declaration}} expected-error {{consecutive declarations on a line must be separated by ';'}} expected-error {{expected declaration}}
}
enum RawTypeEmpty : Int {} // expected-error {{an enum with no cases cannot declare a raw type}}
// expected-error@-1{{type 'RawTypeEmpty' does not conform to protocol 'RawRepresentable'}}
enum Raw : Int {
case Ankeny, Burnside
}
enum MultiRawType : Int64, Int32 { // expected-error {{multiple enum raw types 'Int64' and 'Int32'}}
case Couch, Davis
}
protocol RawTypeNotFirstProtocol {}
enum RawTypeNotFirst : RawTypeNotFirstProtocol, Int { // expected-error {{raw type 'Int' must appear first in the enum inheritance clause}}
case E
}
enum RawTypeNotLiteralConvertible : Array<Int> { // expected-error {{raw type 'Array<Int>' is not convertible from any literal}}
// expected-error@-1{{type 'RawTypeNotLiteralConvertible' does not conform to protocol 'RawRepresentable'}}
case Ladd, Elliott, Sixteenth, Harrison
}
enum RawTypeCircularityA : RawTypeCircularityB, IntegerLiteralConvertible { // expected-error {{circular enum raw types 'RawTypeCircularityA' -> 'RawTypeCircularityB' -> 'RawTypeCircularityA'}} FIXME: expected-error{{RawRepresentable}}
case Morrison, Belmont, Madison, Hawthorne
init(integerLiteral value: Int) {
self = .Morrison
}
}
enum RawTypeCircularityB : RawTypeCircularityA, IntegerLiteralConvertible { // expected-note {{enum 'RawTypeCircularityB' declared here}}
case Willamette, Columbia, Sandy, Multnomah
init(integerLiteral value: Int) {
self = .Willamette
}
}
enum RawTypeNotIntegerLiteralConvertible : String {
case Everett // expected-error {{enum cases require explicit raw values when the raw type is not integer literal convertible}}
case Flanders
}
enum RawTypeWithIntValues : Int {
case Glisan = 17, Hoyt = 219, Irving, Johnson = 97209
}
enum RawTypeWithNegativeValues : Int {
case Glisan = -17, Hoyt = -219, Irving, Johnson = -97209
case AutoIncAcrossZero = -1, Zero, One
}
enum RawTypeWithUnicodeScalarValues : UnicodeScalar {
case Kearney = "K"
case Lovejoy // expected-error {{enum case must declare a raw value when the preceding raw value is not an integer}}
case Marshall = "M"
}
enum RawTypeWithCharacterValues : Character {
case First = ""
case Second // expected-error {{enum case must declare a raw value when the preceding raw value is not an integer}}
case Third = ""
}
enum RawTypeWithCharacterValues_Error1 : Character {
case First = "abc" // expected-error {{'String' is not convertible to 'Character'}}
}
enum RawTypeWithFloatValues : Float {
case Northrup = 1.5
case Overton // expected-error {{enum case must declare a raw value when the preceding raw value is not an integer}}
case Pettygrove = 2.25
}
enum RawTypeWithStringValues : String {
case Quimby = "Lucky Lab"
case Raleigh // expected-error {{enum case must declare a raw value when the preceding raw value is not an integer}}
case Savier = "McMenamin's", Thurman = "Kenny and Zuke's"
}
enum RawValuesWithoutRawType {
case Upshur = 22 // expected-error {{enum case cannot have a raw value if the enum does not have a raw type}}
}
enum RawTypeWithRepeatValues : Int {
case Vaughn = 22 // expected-note {{raw value previously used here}}
case Wilson = 22 // expected-error {{raw value for enum case is not unique}}
}
enum RawTypeWithRepeatValues2 : Double {
case Vaughn = 22 // expected-note {{raw value previously used here}}
case Wilson = 22.0 // expected-error {{raw value for enum case is not unique}}
}
enum RawTypeWithRepeatValues3 : Double {
// 2^63-1
case Vaughn = 9223372036854775807 // expected-note {{raw value previously used here}}
case Wilson = 9223372036854775807.0 // expected-error {{raw value for enum case is not unique}}
}
enum RawTypeWithRepeatValues4 : Double {
// 2^64-1
case Vaughn = 18446744073709551615 // expected-note {{raw value previously used here}}
case Wilson = 18446744073709551615.0 // expected-error {{raw value for enum case is not unique}}
}
enum RawTypeWithRepeatValues5 : Double {
// FIXME: should reject.
// 2^65-1
case Vaughn = 36893488147419103231
case Wilson = 36893488147419103231.0
}
enum RawTypeWithRepeatValues6 : Double {
// FIXME: should reject.
// 2^127-1
case Vaughn = 170141183460469231731687303715884105727
case Wilson = 170141183460469231731687303715884105727.0
}
enum RawTypeWithRepeatValues7 : Double {
// FIXME: should reject.
// 2^128-1
case Vaughn = 340282366920938463463374607431768211455
case Wilson = 340282366920938463463374607431768211455.0
}
enum RawTypeWithNonRepeatValues : Double {
case SantaClara = 3.7
case SanFernando = 7.4
case SanAntonio = -3.7
case SanCarlos = -7.4
}
enum RawTypeWithRepeatValuesAutoInc : Double {
case Vaughn = 22 // expected-note {{raw value auto-incremented from here}}
case Wilson // expected-note {{raw value previously used here}}
case Yeon = 23 // expected-error {{raw value for enum case is not unique}}
}
enum RawTypeWithRepeatValuesAutoInc2 : Double {
case Vaughn = 23 // expected-note {{raw value previously used here}}
case Wilson = 22 // expected-note {{raw value auto-incremented from here}}
case Yeon // expected-error {{raw value for enum case is not unique}}
}
enum RawTypeWithRepeatValuesAutoInc3 : Double {
case Vaughn // expected-note {{raw value implicitly auto-incremented from zero}}
case Wilson // expected-note {{raw value previously used here}}
case Yeon = 1 // expected-error {{raw value for enum case is not unique}}
}
enum NonliteralRawValue : Int {
case Yeon = 100 + 20 + 3 // expected-error {{raw value for enum case must be a literal}}
}
enum RawTypeWithPayload : Int { // expected-note {{declared raw type 'Int' here}} expected-note {{declared raw type 'Int' here}}
case Powell(Int) // expected-error {{enum with raw type cannot have cases with arguments}}
case Terwilliger(Int) = 17 // expected-error {{enum with raw type cannot have cases with arguments}}
}
enum RawTypeMismatch : Int {
case Barbur = "foo" // expected-error {{}}
}
enum DuplicateMembers1 {
case Foo // expected-note {{previous definition of 'Foo' is here}}
case Foo // expected-error {{duplicate definition of enum element}}
}
enum DuplicateMembers2 {
case Foo, Bar // expected-note {{previous definition of 'Foo' is here}} expected-note {{previous definition of 'Bar' is here}}
case Foo // expected-error {{duplicate definition of enum element}}
case Bar // expected-error {{duplicate definition of enum element}}
}
enum DuplicateMembers3 {
case Foo // expected-note {{previous definition of 'Foo' is here}}
case Foo(Int) // expected-error {{duplicate definition of enum element}}
}
enum DuplicateMembers4 : Int {
case Foo = 1 // expected-note {{previous definition of 'Foo' is here}}
case Foo = 2 // expected-error {{duplicate definition of enum element}}
}
enum DuplicateMembers5 : Int {
case Foo = 1 // expected-note {{previous definition of 'Foo' is here}}
case Foo = 1 + 1 // expected-error {{duplicate definition of enum element}} expected-error {{raw value for enum case must be a literal}}
}
enum DuplicateMembers6 {
case Foo // expected-note 2{{previous definition of 'Foo' is here}}
case Foo // expected-error {{duplicate definition of enum element}}
case Foo // expected-error {{duplicate definition of enum element}}
}
enum PlaygroundRepresentation : UInt8 {
case Class = 1
case Struct = 2
case Tuple = 3
case Enum = 4
case Aggregate = 5
case Container = 6
case IDERepr = 7
case Gap = 8
case ScopeEntry = 9
case ScopeExit = 10
case Error = 11
case IndexContainer = 12
case KeyContainer = 13
case MembershipContainer = 14
case Unknown = 0xFF
static func fromByte(byte : UInt8) -> PlaygroundRepresentation {
let repr = PlaygroundRepresentation(rawValue: byte)
if repr == .None { return .Unknown } else { return repr! }
}
}