// RUN: %target-typecheck-verify-swift /* block comments */ /* /* nested too */ */ func markUsed(_ t: T) {} func f1(_ a: Int, _ y: Int) {} func f2() {} func f3() -> Int {} func invalid_semi() { ; // expected-error {{';' statements are not allowed}} {{3-5=}} } func nested1(_ x: Int) { var y : Int func nested2(_ z: Int) -> Int { return x+y+z } _ = nested2(1) } func funcdecl5(_ a: Int, y: Int) { var x : Int // a few statements if (x != 0) { if (x != 0 || f3() != 0) { // while with and without a space after it. while(true) { 4; 2; 1 } // expected-warning 3 {{integer literal is unused}} while (true) { 4; 2; 1 } // expected-warning 3 {{integer literal is unused}} } } // Assignment statement. x = y (x) = y 1 = x // expected-error {{cannot assign to a literal value}} (1) = x // expected-error {{cannot assign to a literal value}} (x:1).x = 1 // expected-error {{cannot assign to immutable expression of type 'Int'}} var tup : (x:Int, y:Int) tup.x = 1 _ = tup let B : Bool // if/then/else. if (B) { } else if (y == 2) { } // This diagnostic is terrible - rdar://12939553 if x {} // expected-error {{'Int' is not convertible to 'Bool'}} if true { if (B) { } else { } } if (B) { f1(1,2) } else { f2() } if (B) { if (B) { f1(1,2) } else { f2() } } else { f2() } // while statement. while (B) { } // It's okay to leave out the spaces in these. while(B) {} if(B) {} } struct infloopbool { var boolValue: infloopbool { return self } } func infloopbooltest() { if (infloopbool()) {} // expected-error {{'infloopbool' is not convertible to 'Bool'}} } // test "builder" API style extension Int { static func builder() -> Int { } var builderProp: Int { return 0 } func builder2() {} } Int .builder() .builderProp .builder2() struct SomeGeneric { static func builder() -> SomeGeneric { } var builderProp: SomeGeneric { return .builder() } func builder2() {} } SomeGeneric .builder() .builderProp .builder2() break // expected-error {{'break' is only allowed inside a loop, if, do, or switch}} continue // expected-error {{'continue' is only allowed inside a loop}} while true { func f() { break // expected-error {{'break' is only allowed inside a loop}} continue // expected-error {{'continue' is only allowed inside a loop}} } // Labeled if MyIf: if 1 != 2 { break MyIf continue MyIf // expected-error {{'continue' cannot be used with if statements}} break // break the while continue // continue the while. } } // Labeled if MyOtherIf: if 1 != 2 { break MyOtherIf continue MyOtherIf // expected-error {{'continue' cannot be used with if statements}} break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if}} continue // expected-error {{'continue' is only allowed inside a loop}} } do { break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do}} } func tuple_assign() { var a,b,c,d : Int (a,b) = (1,2) func f() -> (Int,Int) { return (1,2) } ((a,b), (c,d)) = (f(), f()) } func missing_semicolons() { var w = 321 func g() {} g() w += 1 // expected-error{{consecutive statements}} {{6-6=;}} var z = w"hello" // expected-error{{consecutive statements}} {{12-12=;}} expected-warning {{string literal is unused}} class C {}class C2 {} // expected-error{{consecutive statements}} {{14-14=;}} struct S {}struct S2 {} // expected-error{{consecutive statements}} {{14-14=;}} func j() {}func k() {} // expected-error{{consecutive statements}} {{14-14=;}} } //===--- Return statement. return 42 // expected-error {{return invalid outside of a func}} return // expected-error {{return invalid outside of a func}} func NonVoidReturn1() -> Int { return // expected-error {{non-void function should return a value}} } func NonVoidReturn2() -> Int { return + // expected-error {{unary operator cannot be separated from its operand}} {{11-1=}} expected-error {{expected expression in 'return' statement}} } func VoidReturn1() { if true { return } // Semicolon should be accepted -- rdar://11344875 return; // no-error } func VoidReturn2() { return () // no-error } func VoidReturn3() { return VoidReturn2() // no-error } //===--- If statement. func IfStmt1() { if 1 > 0 // expected-error {{expected '{' after 'if' condition}} _ = 42 } func IfStmt2() { if 1 > 0 { } else // expected-error {{expected '{' after 'else'}} _ = 42 } //===--- While statement. func WhileStmt1() { while 1 > 0 // expected-error {{expected '{' after 'while' condition}} _ = 42 } //===-- Do statement. func DoStmt() { // This is just a 'do' statement now. do { } } func DoWhileStmt() { do { // expected-error {{'do-while' statement is not allowed; use 'repeat-while' instead}} {{3-5=repeat}} } while true } //===--- Repeat-while statement. func RepeatWhileStmt1() { repeat {} while true repeat {} while false repeat { break } while true repeat { continue } while true } func RepeatWhileStmt2() { repeat // expected-error {{expected '{' after 'repeat'}} expected-error {{expected 'while' after body of 'repeat' statement}} } func RepeatWhileStmt4() { repeat { } while + // expected-error {{unary operator cannot be separated from its operand}} {{12-1=}} expected-error {{expected expression in 'repeat-while' condition}} } func brokenSwitch(_ x: Int) -> Int { switch x { case .Blah(var rep): // expected-error{{pattern cannot match values of type 'Int'}} return rep } } func switchWithVarsNotMatchingTypes(_ x: Int, y: Int, z: String) -> Int { switch (x,y,z) { case (let a, 0, _), (0, let a, _): // OK return a case (let a, _, _), (_, _, let a): // expected-error {{pattern variable bound to type 'String', expected type 'Int'}} // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} return a } } func breakContinue(_ x : Int) -> Int { Outer: for _ in 0...1000 { Switch: // expected-error {{switch must be exhaustive}} expected-note{{do you want to add a default clause?}} switch x { case 42: break Outer case 97: continue Outer case 102: break Switch case 13: continue case 139: break // 'break' should be able to break out of switch statements } } // shadowing loop labels should be an error Loop: // expected-note {{previously declared here}} for _ in 0...2 { Loop: // expected-error {{label 'Loop' cannot be reused on an inner statement}} for _ in 0...2 { } } // Following a 'break' statement by another statement on a new line result in an error/fit-it switch 5 { case 5: markUsed("before the break") break markUsed("after the break") // 'markUsed' is not a label for the break. default: markUsed("") } let x : Int? = 42 // Should be able to pattern match 'nil' against optionals switch x { // expected-error {{switch must be exhaustive}} // expected-note@-1 {{missing case: '.some(_)'}} case .some(42): break case nil: break } } enum MyEnumWithCaseLabels { case Case(one: String, two: Int) } func testMyEnumWithCaseLabels(_ a : MyEnumWithCaseLabels) { // Enum case labels are ignored in "case let" statements switch a { case let .Case(one: _, two: x): break // ok case let .Case(xxx: _, two: x): break // expected-error {{tuple pattern element label 'xxx' must be 'one'}} // TODO: In principle, reordering like this could be supported. case let .Case(two: _, one: x): break // expected-error {{tuple pattern element label}} } } // "defer" func test_defer(_ a : Int) { defer { VoidReturn1() } defer { breakContinue(1)+42 } // expected-warning {{result of operator '+' is unused}} // Ok: defer { while false { break } } // Not ok. while false { defer { break } } // expected-error {{'break' cannot transfer control out of a defer statement}} defer { return } // expected-error {{'return' cannot transfer control out of a defer statement}} } class SomeTestClass { var x = 42 func method() { defer { x = 97 } // self. not required here! } } class SomeDerivedClass: SomeTestClass { override init() { defer { super.init() // expected-error {{initializer chaining ('super.init') cannot be nested in another expression}} } } } func test_guard(_ x : Int, y : Int??, cond : Bool) { // These are all ok. guard let a = y else {} markUsed(a) guard let b = y, cond else {} guard case let c = x, cond else {} guard case let Optional.some(d) = y else {} guard x != 4, case _ = x else { } guard let e, cond else {} // expected-error {{variable binding in a condition requires an initializer}} guard case let f? : Int?, cond else {} // expected-error {{variable binding in a condition requires an initializer}} guard let g = y else { markUsed(g) // expected-error {{variable declared in 'guard' condition is not usable in its body}} } guard let h = y, cond {} // expected-error {{expected 'else' after 'guard' condition}} {{25-25=else }} guard case _ = x else {} // expected-warning {{'guard' condition is always true, body is unreachable}} } func test_is_as_patterns() { switch 4 { case is Int: break // expected-warning {{'is' test is always true}} case _ as Int: break // expected-warning {{'as' test is always true}} // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} case _: break // expected-warning {{case is already handled by previous patterns; consider removing it}} } } // Fuzzing SourceKit: crash in Parser::parseStmtForEach(...) func matching_pattern_recursion() { switch 42 { case { // expected-error {{expression pattern of type '() -> ()' cannot match values of type 'Int'}} for i in zs { } }: break } } // Swift's break operator in switch should be indicated in errors func r18776073(_ a : Int?) { switch a { case nil: // expected-error {{'case' label in a 'switch' should have at least one executable statement}} {{14-14= break}} case _?: break } } // unhelpful error message from "throw nil" func testThrowNil() throws { throw nil // expected-error {{cannot infer concrete Error for thrown 'nil' value}} } // rdar://problem/23684220 // Even if the condition fails to typecheck, save it in the AST anyway; the old // condition may have contained a SequenceExpr. func r23684220(_ b: Any) { if let _ = b ?? b {} // expected-error {{initializer for conditional binding must have Optional type, not 'Any'}} // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type 'Any', so the right side is never used}} } // QoI: try/catch (instead of do/catch) creates silly diagnostics func f21080671() { try { // expected-error {{the 'do' keyword is used to specify a 'catch' region}} {{3-6=do}} } catch { } try { // expected-error {{the 'do' keyword is used to specify a 'catch' region}} {{3-6=do}} f21080671() } catch let x as Int { } catch { } } // QoI: Using "&& #available" should fixit to comma // https://twitter.com/radexp/status/694561060230184960 func f(_ x : Int, y : Int) { if x == y && #available(iOS 52, *) {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{12-15=,}} if #available(iOS 52, *) && x == y {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{27-30=,}} // https://twitter.com/radexp/status/694790631881883648 if x == y && let _ = Optional(y) {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{12-15=,}} if x == y&&let _ = Optional(y) {} // expected-error {{expected ',' joining parts of a multi-clause condition}} {{12-14=,}} } // QoI: Warn about cases where switch statement "ignores" where clause enum Type { case Foo case Bar } func r25178926(_ a : Type) { switch a { // expected-error {{switch must be exhaustive}} // expected-note@-1 {{missing case: '.Bar'}} case .Foo, .Bar where 1 != 100: // expected-warning @-1 {{'where' only applies to the second pattern match in this case}} // expected-note @-2 {{disambiguate by adding a line break between them if this is desired}} {{14-14=\n }} // expected-note @-3 {{duplicate the 'where' on both patterns to check both patterns}} {{12-12= where 1 != 100}} break } switch a { // expected-error {{switch must be exhaustive}} // expected-note@-1 {{missing case: '.Bar'}} case .Foo: break case .Bar where 1 != 100: break } switch a { // expected-error {{switch must be exhaustive}} // expected-note@-1 {{missing case: '.Bar'}} case .Foo, // no warn .Bar where 1 != 100: break } switch a { // expected-error {{switch must be exhaustive}} // expected-note@-1 {{missing case: '.Foo'}} // expected-note@-2 {{missing case: '.Bar'}} case .Foo where 1 != 100, .Bar where 1 != 100: break } } do { guard 1 == 2 else { break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do}} } } func fn(a: Int) { guard a < 1 else { break // expected-error {{'break' is only allowed inside a loop, if, do, or switch}} } } func fn(x: Int) { if x >= 0 { guard x < 1 else { guard x < 2 else { break // expected-error {{unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do}} } return } } } func bad_if() { if 1 {} // expected-error {{'Int' is not convertible to 'Bool'}} if (x: false) {} // expected-error {{'(x: Bool)' is not convertible to 'Bool'}} if (x: 1) {} // expected-error {{'(x: Int)' is not convertible to 'Bool'}} } // Errors in case syntax class case, // expected-error {{expected identifier in enum 'case' declaration}} expected-error {{expected pattern}} case // expected-error {{expected identifier after comma in enum 'case' declaration}} expected-error {{expected identifier in enum 'case' declaration}} expected-error {{enum 'case' is not allowed outside of an enum}} expected-error {{expected pattern}} // NOTE: EOF is important here to properly test a code path that used to crash the parser