mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
378 lines
7.3 KiB
Swift
378 lines
7.3 KiB
Swift
// RUN: %batch-code-completion -debug-forbid-typecheck-prefix FORBIDDEN
|
|
|
|
enum E {
|
|
case e
|
|
case f(Int)
|
|
}
|
|
|
|
struct SomeError: Error {}
|
|
|
|
func ifExprDotReturn() -> E {
|
|
if .random() {
|
|
.#^DOT1?check=DOT^#
|
|
} else {
|
|
.e
|
|
}
|
|
}
|
|
|
|
func switchExprDotReturn() -> E {
|
|
switch Bool.random() {
|
|
case true:
|
|
.e
|
|
case false:
|
|
.#^DOT2?check=DOT^#
|
|
}
|
|
}
|
|
|
|
func ifExprDotClosureReturn() -> E {
|
|
let x: E = {
|
|
if .random() {
|
|
.e
|
|
} else {
|
|
.#^DOT3?check=DOT^#
|
|
}
|
|
}()
|
|
return x
|
|
}
|
|
|
|
func switchExprDotClosureReturn() -> E {
|
|
let x: E = {
|
|
switch Bool.random() {
|
|
case true:
|
|
.#^DOT4?check=DOT^#
|
|
case false:
|
|
.e
|
|
}
|
|
}()
|
|
return x
|
|
}
|
|
|
|
func ifExprBranchInferenceReturn1() -> E {
|
|
let fn = {
|
|
if .random() {
|
|
E.e
|
|
} else {
|
|
.#^DOT5?check=DOT^#
|
|
}
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
func switchExprBranchInferenceReturn1() -> E {
|
|
let fn = {
|
|
switch Bool.random() {
|
|
case true:
|
|
E.e
|
|
case false:
|
|
.#^DOT6?check=DOT^#
|
|
}
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
func ifExprBranchInferenceReturn2() -> E {
|
|
let fn = {
|
|
if .random() {
|
|
.#^DOT7?check=DOT^#
|
|
} else {
|
|
E.e
|
|
}
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
func switchExprBranchInferenceReturn2() -> E {
|
|
let fn = {
|
|
switch Bool.random() {
|
|
case true:
|
|
.#^DOT8?check=DOT^#
|
|
case false:
|
|
E.e
|
|
}
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
func ifExprBinding() -> E {
|
|
let x: E =
|
|
if .random() {
|
|
.e
|
|
} else {
|
|
.#^DOT9?check=DOT^#
|
|
}
|
|
return x
|
|
}
|
|
|
|
func switchExprBinding() -> E {
|
|
let x: E =
|
|
switch Bool.random() {
|
|
case true:
|
|
.e
|
|
case false:
|
|
.#^DOT10?check=DOT^#
|
|
}
|
|
return x
|
|
}
|
|
|
|
struct NO {
|
|
// Triggering interface type computation of this will cause an assert to fire,
|
|
// ensuring we don't attempt to type-check any references to it.
|
|
static var TYPECHECK = FORBIDDEN
|
|
}
|
|
|
|
func testSkipTypechecking1() -> E {
|
|
// Make sure we don't try to type-check the first branch, as it doesn't
|
|
// contribute to the type.
|
|
if .random() {
|
|
_ = NO.TYPECHECK
|
|
throw SomeError()
|
|
} else {
|
|
.#^DOT11?check=DOT^#
|
|
}
|
|
}
|
|
|
|
func testSkipTypechecking2() -> E {
|
|
// Make sure we don't try to type-check the second branch, as it doesn't
|
|
// contribute to the type.
|
|
if .random() {
|
|
.#^DOT12?check=DOT^#
|
|
} else {
|
|
_ = NO.TYPECHECK
|
|
throw SomeError()
|
|
}
|
|
}
|
|
|
|
func testSkipTypechecking3() -> E {
|
|
// Make sure we don't try to type-check the first branch, as it doesn't
|
|
// contribute to the type.
|
|
switch Bool.random() {
|
|
case true:
|
|
_ = NO.TYPECHECK
|
|
throw SomeError()
|
|
case false:
|
|
.#^DOT13?check=DOT^#
|
|
}
|
|
}
|
|
|
|
func testSkipTypechecking4() -> E {
|
|
// Make sure we don't try to type-check the second branch, as it doesn't
|
|
// contribute to the type.
|
|
switch Bool.random() {
|
|
case true:
|
|
.#^DOT14?check=DOT^#
|
|
case false:
|
|
_ = NO.TYPECHECK
|
|
throw SomeError()
|
|
}
|
|
}
|
|
|
|
func takesE(_ e: E) {}
|
|
|
|
func testSkipTypechecking5() throws -> E {
|
|
// Make sure we only type-check the first branch.
|
|
if .random() {
|
|
// We can still skip type-checking this tho.
|
|
x = NO.TYPECHECK
|
|
|
|
takesE(.#^DOT15?check=DOT^#)
|
|
throw SomeError()
|
|
} else {
|
|
NO.TYPECHECK
|
|
}
|
|
}
|
|
|
|
func testSkipTypechecking6() throws -> E {
|
|
// Make sure we only type-check the first branch.
|
|
switch Bool.random() {
|
|
case true:
|
|
// We can still skip type-checking this tho.
|
|
x = NO.TYPECHECK
|
|
|
|
takesE(.#^DOT16?check=DOT^#)
|
|
throw SomeError()
|
|
case false:
|
|
NO.TYPECHECK
|
|
}
|
|
}
|
|
|
|
enum F {
|
|
case x
|
|
}
|
|
|
|
func takesIntOrDouble(_ i: Int) -> E { E.e }
|
|
func takesIntOrDouble(_ i: Double) -> F { F.x }
|
|
|
|
func testSkipTypechecking7() throws -> E {
|
|
let fn = {
|
|
switch Bool.random() {
|
|
case true:
|
|
.#^DOT17?check=DOT^#
|
|
case false:
|
|
// Make sure we don't end up with an ambiguity here.
|
|
takesIntOrDouble(0)
|
|
}
|
|
}
|
|
return fn()
|
|
}
|
|
|
|
func testSkipTypeChecking8() throws -> E {
|
|
let e: E = if Bool.random() {
|
|
takesE(.#^DOT18?check=DOT^#)
|
|
throw NO.TYPECHECK
|
|
} else {
|
|
NO.TYPECHECK
|
|
}
|
|
return e
|
|
}
|
|
|
|
func testSkipTypeChecking8a() throws -> E {
|
|
// Only need to type-check the inner function in this case.
|
|
let e: E = if Bool.random() {
|
|
func localFunc() {
|
|
takesE(.#^DOT19?check=DOT^#)
|
|
}
|
|
throw NO.TYPECHECK
|
|
} else {
|
|
NO.TYPECHECK
|
|
}
|
|
return e
|
|
}
|
|
|
|
func takesArgAndClosure<T>(_ x: Int, fn: () -> T) -> T { fatalError() }
|
|
|
|
func testSkipTypeChecking9() -> E {
|
|
// We need to type-check everything for this.
|
|
if Bool.random() {
|
|
.e
|
|
} else {
|
|
takesArgAndClosure(0) {
|
|
.#^DOT20?check=DOT^#
|
|
}
|
|
}
|
|
}
|
|
|
|
func testSkipTypeChecking10() -> E {
|
|
// Similar to the above case, we need to type-check everything for this since
|
|
// the type-checking of 'takesArgAndClosure' is required to correctly handle
|
|
// any potential captures in 'foo'.
|
|
if Bool.random() {
|
|
.e
|
|
} else {
|
|
takesArgAndClosure(0) {
|
|
func foo() {
|
|
// We can however skip unrelated elements in the local function.
|
|
let x = NO.TYPECHECK
|
|
if NO.TYPECHECK {
|
|
takesE(NO.TYPECHECK)
|
|
}
|
|
takesE(.#^DOT21?check=DOT^#)
|
|
}
|
|
return .e
|
|
}
|
|
}
|
|
}
|
|
|
|
func testSkipTypeChecking11() -> E {
|
|
// We only need to type-check the inner-most function for this.
|
|
if Bool.random() {
|
|
NO.TYPECHECK
|
|
} else {
|
|
if NO.TYPECHECK {
|
|
func foo() {
|
|
takesE(.#^DOT22?check=DOT^#)
|
|
}
|
|
throw NO.TYPECHECK
|
|
} else {
|
|
NO.TYPECHECK
|
|
}
|
|
}
|
|
}
|
|
|
|
func testSkipTypeChecking12() -> E {
|
|
// Only need to type-check the condition here.
|
|
if .#^DOT23?check=BOOL^# {
|
|
NO.TYPECHECK
|
|
} else {
|
|
NO.TYPECHECK
|
|
}
|
|
}
|
|
|
|
// BOOL: Begin completions
|
|
// BOOL-DAG: Decl[Constructor]/CurrNominal/IsSystem/TypeRelation[Convertible]: init()[#Bool#]; name=init()
|
|
// BOOL-DAG: Decl[StaticMethod]/CurrNominal/Flair[ExprSpecific]/IsSystem/TypeRelation[Convertible]: random()[#Bool#]; name=random()
|
|
|
|
func testSkipTypeChecking13(_ e: E) -> E {
|
|
// TODO: Currently this requires type-checking the bodies, but we ought to
|
|
// be able to skip them. This is also an issue in closures.
|
|
switch e {
|
|
case .#^DOT24?check=DOT^#:
|
|
.e
|
|
default:
|
|
.e
|
|
}
|
|
}
|
|
|
|
func testSkipTypeChecking14() -> E {
|
|
if Bool.random() {
|
|
.#^DOT25?check=DOT^#
|
|
} else if .random() {
|
|
let x = NO.TYPECHECK
|
|
throw x
|
|
} else if .random() {
|
|
let x = NO.TYPECHECK
|
|
throw x
|
|
} else {
|
|
let x = NO.TYPECHECK
|
|
throw x
|
|
}
|
|
}
|
|
|
|
func testSkipTypeChecking15() -> E {
|
|
switch Bool.random() {
|
|
case true:
|
|
.#^DOT26?check=DOT^#
|
|
case _ where Bool.random():
|
|
let x = NO.TYPECHECK
|
|
throw x
|
|
case _ where Bool.random():
|
|
let x = NO.TYPECHECK
|
|
throw x
|
|
default:
|
|
let x = NO.TYPECHECK
|
|
throw x
|
|
}
|
|
}
|
|
|
|
func testSkipTypechecking16(_ x: inout Int) -> E {
|
|
switch Bool.random() {
|
|
case true:
|
|
.#^DOT27?check=DOT^#
|
|
case false:
|
|
x = 0
|
|
}
|
|
}
|
|
|
|
// DOT: Begin completions, 2 items
|
|
// DOT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: e[#E#]; name=e
|
|
// DOT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: f({#Int#})[#E#]; name=f()
|
|
|
|
// https://github.com/apple/swift/issues/71384
|
|
func testCompleteBinding1(_ e: E) -> Int {
|
|
switch e {
|
|
case .f(let foobar):
|
|
#^BINDING1?check=BINDING^#
|
|
case .e:
|
|
0
|
|
}
|
|
}
|
|
|
|
func testCompleteBinding2(_ x: Int?) -> Int {
|
|
if let foobar = x {
|
|
#^BINDING2?check=BINDING^#
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
// BINDING-DAG: Decl[LocalVar]/Local/TypeRelation[Convertible]: foobar[#Int#]; name=foobar
|