-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
impl_trait_in_bindings
fails with Option<impl Trait>
#54600
Comments
Another relevant example: #![feature(nll)]
#![feature(impl_trait_in_bindings)]
use std::fmt::Debug;
fn foo() -> String {
let x: impl Debug = 22;
format!("{}", x)
}
fn main() { } This fails to compile, which seems correct, though I'm not sure precisely what semantics we want. Alternatively, we may want to encode the |
@nikomatsakis I think the second example works exactly as intended (and as the RFC specifies). It's intuitive to me, at least. You're right about the first example; that's the wrong way to go about it. I didn't see a better approach at the time though, and I forgot about it while solving other issues. The lowering and type checking is basically okay, that said... it's the NLL borrow checking that's the problem. Which I think is something that requires your expertise, to be honest. |
Tagging T-lang due to Niko's notes in #54600 (comment). |
Shouldn't |
@mikeyhew Nope, I think he meant that... since he follows it by saying "This fails to compile, which seems correct". With |
So @alexreg has been asking me to leave some notes on how to do this properly. The high-level strategy that I think we should be pursuing is changing let x: impl Foo = y would sort of compile "as if" the user had written In fact, it might be illustrative to see what happens there. Given this example program (playground): fn main() {
let x: &dyn std::fmt::Debug = &3;
} we get the following MIR (excerpted and simplified):
The key bit is that
I'm not sure yet if this should be an "ordinary" cast -- it seems potentially different, since the "opaque type" is treated in rather a particular way. But maybe it's ok to frame it as a cast. OK, I'll stop there for this comment. I'm not yet sure the best way to implement so I'll probably leave a few comments exploring a few options. |
Hmm before going any further I also want to raise up a few interesting questions. The possibility of Right now, the initializers can kind of act in two ways. e.g., here, let y = 22;
let ref x: u32 = y; // equivalent to `let x = &y;` In principle you could have: let ref x: impl Debug = y; and wind up with |
So what happens when you have a rust/src/librustc_typeck/check/coercion.rs Line 166 in 365b900
Here rust/src/librustc_typeck/check/coercion.rs Line 200 in 365b900
This routine is pretty complex and I'll skip over the details (reminds me though that #50753 would be really nice to fix). It will however ultimately produce an This adjustment is stored alongside the source expression (here, rust/src/librustc_mir/hair/cx/expr.rs Lines 81 to 85 in 365b900
|
Triage: the first example still gives an ICE.
|
For people following at home, |
…sts, r=oli-obk Add regression tests for the impl_trait_in_bindings ICEs Closes rust-lang#54600, closes rust-lang#54840, closes rust-lang#58504, closes rust-lang#58956, closes rust-lang#70971, closes rust-lang#79099, closes rust-lang#84919, closes rust-lang#86201, closes rust-lang#86642, closes rust-lang#87295 r? `@oli-obk`
This example ICEs:
The reason is that the code which chooses when to "reveal" opaque types looks only for opaque types at the top level (and, oddly, it does so only if ordinary unification fails; having code that branches based on whether unification succeeded is in general a bad idea, so we should fix that too):
rust/src/librustc_mir/borrow_check/nll/type_check/mod.rs
Lines 893 to 899 in c7df1f5
More deeply, though, this code is taking a somewhat flawed approach. In particular, it is looking at the results of inference, but -- at least presently -- opaque types can end up in the inferred type in one of two ways. (As shown by #54593.)
For example, one might have a mixture of opaque types that came from a recursive call (and which ought not to be revealed) and opaque types that the user wrote:
The correct way to do this, I suspect, is to leverage the user-type annotations that we are tracking for NLL.
cc @alexreg @cramertj @eddyb
The text was updated successfully, but these errors were encountered: