Description
I tried this code:
pub fn foo() -> impl Iterator<Item = u32> {
loop {}
// or panic!(), etc.
}
// Equivalent code modulo cut elimination
pub fn bar() -> impl Iterator<Item = u32> {
bar_helper()
}
fn bar_helper() -> std::iter::Empty<u32> {
loop {}
}
I expected to see this happen:
Module should compile without error. If foo
or bar
are invoked, they
should diverge. In particular, foo
and bar
should be equivalent in
terms of both static and dynamic semantics.
In general, fn foo() -> T { loop {} }
should compile for any type T
,
because loop {}
should be at type !
and !
should be a subtype of
every type. This seems to be the case for all proper types that I've
tried, including uninhabited ones like std::convert::Infallible
, but
not when T
is actually a return-position impl Trait
.
Instead, this happened:
error[E0277]: `()` is not an iterator
--> src/lib.rs:1:17
|
1 | pub fn foo() -> impl Iterator<Item = u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator
|
= help: the trait `Iterator` is not implemented for `()`
This is surprising, because I'm not sure where the unit type is coming
from. If I replace impl Iterator<Item = u32>
with impl Default
, or
another trait that ()
does implement, then it compiles without error.
But if I use impl Trait
for a trait that ()
does not implement, then
it raises this compile-time error.
The fact that bar
compiles makes it feel especially weird that foo
does not compile, because they should be equivalent. Yes, there's more
type information (I've used std::iter::Empty<u32>
as a specific type
implementing Iterator<Item = u32>
), but I don't see why that should
matter. The error given by rustc wasn't a "ambiguous type; specify type
annotations" kind of error.
Playground with these examples and a few more:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=e8061b7ffb50afef8b230892d458d26b
Meta
rustc --version --verbose
:
rustc 1.70.0 (90c541806 2023-05-31)
binary: rustc
commit-hash: 90c541806f23a127002de5b4038be731ba1458ca
commit-date: 2023-05-31
host: x86_64-unknown-linux-gnu
release: 1.70.0
LLVM version: 16.0.2
Also exists in nightly 2023-07-18.