-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Code
pub struct Bar;
trait BarBar {}
impl BarBar for Bar {}
pub struct Foo<T> {
t: T,
bar: Bar,
}
pub type Foo1 = Foo<i32>;
pub type Foo2 = Foo<String>;
pub trait FooFoo {
fn bar(self) -> impl BarBar;
}
impl<T> FooFoo for Foo<T> {
fn bar(self) -> impl BarBar {
self.bar
}
}
enum Oh {
FooInt(Foo1),
FooStr(Foo2),
}
impl FooFoo for Oh {
fn bar(self) -> impl BarBar {
use Oh::*;
match self {
FooInt(fi) => fi.bar(),
FooStr(fs) => fs.bar(),
}
}
}
Current output
error[E0308]: `match` arms have incompatible types
--> src\lib.rs:45:27
|
30 | fn bar(self) -> impl BarBar {
| -----------
| |
| the expected opaque type
| the found opaque type
...
43 | / match self {
44 | | FooInt(fi) => fi.bar(),
| | -------- this is found to be of type `impl BarBar`
45 | | FooStr(fs) => fs.bar(),
| | ^^^^^^^^ expected `i32`, found `String`
46 | | }
| |_________- `match` arms have incompatible types
|
= note: expected opaque type `impl BarBar` (`i32`)
found opaque type `impl BarBar` (`String`)
= note: distinct uses of `impl Trait` result in different opaque types
help: you could change the return type to be a boxed trait object
|
41 - fn bar(self) -> impl BarBar {
41 + fn bar(self) -> Box<dyn BarBar> {
|
help: if you change the return type to expect trait objects, box the returned expressions
|
44 ~ FooInt(fi) => Box::new(fi.bar()),
45 ~ FooStr(fs) => Box::new(fs.bar()),
|
For more information about this error, try `rustc --explain E0308`.
Desired output
// I don't know. I expected the code to compile at first,
// but maybe I am missing something so that's arguable.
// However, anyway, neither fi.bar() is i32 nor fs.bar() is String, so the diagnose parts:
fs.bar(),
^^^^^^^^ expected `i32`, found `String`
// ...and:
= note: expected opaque type `impl BarBar` (`i32`)
found opaque type `impl BarBar` (`String`)
// seem confusing to me.
Rationale and extra context
Why I expected the code to compile:
In my understanding, RPITIT is a sugar for associated types. So I tried the "desugared" code and that compiles:
pub struct Bar;
trait BarBar {}
impl BarBar for Bar {}
pub struct Foo<T> {
t: T,
bar: Bar,
}
pub type Foo1 = Foo<i32>;
pub type Foo2 = Foo<String>;
pub trait FooFoo {
type BarBarT: BarBar;
fn bar(self) -> Self::BarBarT;
}
impl<T> FooFoo for Foo<T> {
type BarBarT = Bar;
fn bar(self) -> Bar {
self.bar
}
}
enum Oh {
FooInt(Foo1),
FooStr(Foo2),
}
impl FooFoo for Oh {
type BarBarT = Bar;
fn bar(self) -> Bar {
use Oh::*;
match self {
FooInt(fi) => fi.bar(),
FooStr(fs) => fs.bar(),
}
}
}
But the code using RPITIT doesn't. I don't know what is going on there.
Other cases
I also tried this code:
pub struct Bar;
trait BarBar {}
impl BarBar for Bar {}
pub struct Foo<T> {
t: T,
bar: Bar,
}
pub type Foo1 = Foo<i32>;
pub type Foo2 = Foo<String>;
pub trait FooFoo {
fn bar(self) -> impl BarBar;
}
impl FooFoo for Foo1 {
fn bar(self) -> impl BarBar {
self.bar
}
}
impl FooFoo for Foo2 {
fn bar(self) -> impl BarBar {
self.bar
}
}
enum Oh {
FooInt(Foo1),
FooStr(Foo2),
}
impl FooFoo for Oh {
fn bar(self) -> impl BarBar {
use Oh::*;
match self {
FooInt(fi) => fi.bar(),
FooStr(fs) => fs.bar(),
}
}
}
And the code above cannot compile either:
error[E0308]: `match` arms have incompatible types
--> src\lib.rs:39:27
|
19 | fn bar(self) -> impl BarBar {
| ----------- the expected opaque type
...
24 | fn bar(self) -> impl BarBar {
| ----------- the found opaque type
...
37 | / match self {
38 | | FooInt(fi) => fi.bar(),
| | -------- this is found to be of type `impl BarBar`
39 | | FooStr(fs) => fs.bar(),
| | ^^^^^^^^ expected opaque type, found a different opaque type
40 | | }
| |_________- `match` arms have incompatible types
|
= note: expected opaque type `impl BarBar`
found opaque type `impl BarBar`
= note: distinct uses of `impl Trait` result in different opaque types
help: you could change the return type to be a boxed trait object
|
35 - fn bar(self) -> impl BarBar {
35 + fn bar(self) -> Box<dyn BarBar> {
|
help: if you change the return type to expect trait objects, box the returned expressions
|
38 ~ FooInt(fi) => Box::new(fi.bar()),
39 ~ FooStr(fs) => Box::new(fs.bar()),
|
For more information about this error, try `rustc --explain E0308`.
However this case above makes sense for me since there are separate trait implementations. The diagnose message is also clear.
Edit:
I also came up with a case which does not require RPITIT, just RPIT. The case below gives a similar error message to the "Current output" section.
pub struct Bar;
trait BarBar {}
impl BarBar for Bar {}
pub struct Foo<T> {
t: T,
bar: Bar,
}
pub type Foo1 = Foo<i32>;
pub type Foo2 = Foo<String>;
pub trait FooFoo {
fn bar(self) -> impl BarBar;
}
fn bar<T>(f: Foo<T>) -> impl BarBar {
f.bar
}
enum Oh {
FooInt(Foo1),
FooStr(Foo2),
}
fn oh_bar(oh: Oh) -> impl BarBar {
use Oh::*;
match oh {
FooInt(fi) => bar(fi),
FooStr(fs) => bar(fs),
}
}
Rust Version
rustc 1.88.0 (6b00bc388 2025-06-23)
binary: rustc
commit-hash: 6b00bc3880198600130e1cf62b8f8a93494488cc
commit-date: 2025-06-23
host: x86_64-pc-windows-gnu
release: 1.88.0
LLVM version: 20.1.5
Anything else?
No response
Metadata
Metadata
Assignees
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.