i have a generic method that takes a closure which looks like:
func highlight<Link>(_ fragments:[Fragment<Link>],
_ anchor:(Link) throws -> Anchor)
rethrows
however, if i call it with Link == Never, i get the “warning: will never be executed” warning:
warning: will never be executed
return .code(Self.highlight(signature) { _ in fatalError("unreachable") })
^
note: '_' is of type 'Never' which cannot be constructed because it is an
enum with no cases
return .code(Self.highlight(signature) { _ in fatalError("unreachable") })
how do i get rid of this warning?
I think replacing this:
with this:
return .code(Self.highlight(signature) { _ in /*no code here*/})
would work.
that causes
error: cannot convert value of type '()' to closure result type 'Anchor'
I suppose is a bug then. At least one of those should not warn, I think.
xwu
(Xiaodi Wu)
5
I'm not able to reproduce this with the simple example below. Is there something else going on perhaps?
func f<T>(_ argument: T?, _ closure: (T) throws -> Int) rethrows {
if let argument = argument {
try closure(argument)
}
}
f(nil as Never?) { _ in fatalError() }
I ran across a similar issue a few weeks ago when I tried to switch over a multi-thousand case enum. The switch was technically exhaustive, but the compiler told me it didn't want to do the checking and recommended I short-circuit by adding a default. It compiled once I added the default, however with a warning similar to will never be executed
.
1 Like
mayoff
(Rob Mayoff)
7
Try this:
func absurd<A>(_: Never) -> A { }
...
return .code(Self.highlight(signature, absurd))
1 Like
here’s a minimal example:
func foo<T>(first:[Int], second:[T], _ function:(T) throws -> Int)
rethrows -> [Int]
{
try first + second.map(function)
}
func bar()
{
let _ = foo(first: [0], second: [] as [Never])
{
_ in fatalError("unreachable")
}
}
mayoff
(Rob Mayoff)
10
While I agree that the compiler should treat them the same, it does not:
BTW, I didn't invent this workaround. I first saw it in swift-composable-architecture.
2 Likes
xwu
(Xiaodi Wu)
11
Ugh, I am able to reproduce it with both my minimal example and yours; the warning is just suppressed in Swift Playgrounds (which I find handy for these little snippets).
It's not exactly a diagnostics bug, as the fatalError call is indeed unreachable. Rather, there seems to be some sort of type inference bug, as a sufficient workaround is actually to annotate the closure argument type, leaving the body empty:
foo(first: [0], second: [] as [Never]) { (_: Never) -> Int in }
Put another way, it's the error you encounter with an empty closure that's the bug and not the warning, and that is indeed worthy of a report.
2 Likes
mayoff
(Rob Mayoff)
12
Giving an explicit return type seems to suffice:
let _ = foo(first: [0], second: [] as [Never]) { _ -> Int in }
2 Likes
xwu
(Xiaodi Wu)
13
Cool, this nicely implicates closure return type inference as the problem :)
1 Like