Skip to content

Sema: Do better at diagnosing missing each #78434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,16 +794,13 @@ namespace {
// value packs cannot be referenced without `each` immediately
// preceding them.
if (auto *expansionType = knownType->getAs<PackExpansionType>()) {
if (auto *parentExpansionExpr = getParentPackExpansionExpr(E);
parentExpansionExpr &&
!isExpr<PackElementExpr>(CS.getParentExpr(E))) {
if (!isExpr<PackElementExpr>(CS.getParentExpr(E))) {
auto packType = expansionType->getPatternType();
(void)CS.recordFix(
IgnoreMissingEachKeyword::create(CS, packType, locator));
auto eltType =
openPackElement(packType, locator, parentExpansionExpr);
CS.setType(E, eltType);
return eltType;

return openPackElement(packType, locator,
getParentPackExpansionExpr(E));
}
}
}
Expand Down
135 changes: 77 additions & 58 deletions test/Constraints/pack-expansion-expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -263,27 +263,6 @@ func forwardFunctionPack<each T>(functions: repeat (each T) -> Bool) {
takesFunctionPack(functions: repeat each functions)
}

func packOutsideExpansion<each T>(_ t: repeat each T) {
_ = t
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

forward(t)
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

_ = each t
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

forward(each t)
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

let tuple = (repeat each t)

_ = tuple

_ = each tuple
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}
}

func identity<T>(_ t: T) -> T { t }
func concrete(_: Int) {}

Expand Down Expand Up @@ -474,18 +453,6 @@ do {
}
}

// rdar://107675464 - misplaced `each` results in `type of expression is ambiguous without a type annotation`
do {
func test_correct_each<each T: P>(_ value: repeat each T) -> (repeat (each T).A) {
return (repeat (each value).makeA()) // Ok
}

func test_misplaced_each<each T: P>(_ value: repeat each T) -> (repeat (each T).A) {
return (repeat each value.makeA())
// expected-error@-1 {{value pack 'each T' must be referenced with 'each'}} {{25-25=(each }} {{30-30=)}}
}
}

// rdar://107835215 - failed to produce a diagnostic for invalid pack expansion expression
do {
func test1(x: Int) {
Expand All @@ -509,19 +476,6 @@ do {
}
}

// missing 'each' keyword before value pack references
do {
func overloaded<each U>(_: String, _: repeat each U) -> Int { 42 }
func overloaded<each T>(_: Int, _ b: repeat each T) -> (repeat each T) {
fatalError()
}

func test<each T>(v: repeat each T) {
_ = (repeat overloaded(42, v)) // expected-error {{value pack 'each T' must be referenced with 'each'}} {{32-32=each }}
_ = (repeat overloaded(42, each v)) // Ok
}
}

// rdar://108904190 - top-level 'repeat' not allowed in single-expression closures
func test_pack_expansion_to_void_conv_for_closure_result<each T>(x: repeat each T) {
let _: () -> Void = { repeat print(each x) } // Ok
Expand Down Expand Up @@ -715,18 +669,6 @@ do {
}
}

// rdar://110847476 - unrelated assignment and raw representable diagnostics
do {
struct Test<each Base: AsyncSequence> {
let base: (repeat each Base)

init(base: repeat each Base) {
self.base = base
// expected-error@-1 {{pack reference 'each Base' can only appear in pack expansion}}
}
}
}

// Pack Iteration
do {
func test<each T>(_ t: repeat each T) {
Expand Down Expand Up @@ -765,3 +707,80 @@ func butt<T>(x: T) {}
func rump<each T>(x: repeat each T) {
let x = (repeat { butt(each x) }()) // expected-error {{missing argument label 'x:' in call}}
}

// Placement of `each` in expressions.
do {
do {
func overload<each U>(_: String, _: repeat each U) -> Int {}
func overload<each T>(_: Int, _ b: repeat each T) -> (repeat each T) {}

func test<each T>(
t: repeat each T,
t2: repeat (each T)?,
t3: repeat () -> each T
) {
_ = t
// expected-error@-1{{value pack 'each T' must be referenced with 'each'}}

forward(t)
// expected-error@-1{{value pack 'each T' must be referenced with 'each'}}

_ = each t
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

forward(each t)
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

let tuple = (repeat each t)
_ = tuple
_ = each tuple
// expected-error@-1{{pack reference 'each T' can only appear in pack expansion}}

// https://github.com/swiftlang/swift/issues/78393
let _ = (t2)
// expected-error@-1{{value pack '(each T)?' must be referenced with 'each'}}
let _ = t3
// expected-error@-1{{value pack '() -> each T' must be referenced with 'each'}}

let _ = (repeat overload(42, t)) // expected-error {{value pack 'each T' must be referenced with 'each'}} {{36-36=each }}
let _ = (repeat overload(42, each t)) // Ok
}
}

// FIXME: https://github.com/swiftlang/swift/issues/78426
do {
func f<each T>(_: (repeat each T) -> (repeat each T)) {}
// expected-error@+2 {{cannot infer type of closure parameter 'x' without a type annotation}}
// expected-error@+1 {{cannot convert value of type '(Int, Int)' to closure result type '(_: _)'}}
f { x in
// Once this issue is fixed, verify that 'x' below is diagnosed correctly.
// If it is not, please reopen https://github.com/swiftlang/swift/issues/78393.
let _ = x
return (1, 2)
}
}

// rdar://107675464 - misplaced `each` results in `type of expression is ambiguous without a type annotation`
do {
func test_correct_each<each T: P>(_ value: repeat each T) -> (repeat (each T).A) {
return (repeat (each value).makeA()) // Ok
}

func test_misplaced_each<each T: P>(_ value: repeat each T) -> (repeat (each T).A) {
return (repeat each value.makeA())
// expected-error@-1 {{value pack 'each T' must be referenced with 'each'}} {{27-27=(each }} {{32-32=)}}
}
}

// rdar://110847476 - unrelated assignment and raw representable diagnostics
do {
struct Test<each Base: AsyncSequence> {
let base: (repeat each Base)

init(base: repeat each Base) {
self.base = base
// expected-error@-1 {{value pack 'each Base' must be referenced with 'each'}}
}
}
}
}