You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Drop tracking ICE involving await in left hand side of assignment (-Zdrop-tracking) #102383
BrokenMIR: generator contains typeCurrentUser in MIR, but typeck only knows about {ResumeTy,&Handler, serenity::prelude::Context, serenity::model::channel::Message,impl std::future::Future<Output = CurrentUser>,(),bool,String,Arc<serenity::http::Http>,impl std::future::Future<Output = Result<serenity::model::channel::Message,SerenityError>>,Handler,Option<regex::Captures>, regex::Captures,u64,Token,impl std::future::Future<Output = Result<Response<egg_mode::tweet::Tweet>, egg_mode::error::Error>>,impl std::future::Future<Output = Result<Reaction,SerenityError>>,&DraftTweet,DraftTweet,impl std::future::Future<Output = Result<Response<egg_mode::tweet::Tweet>, egg_mode::error::Error>>,Response<egg_mode::tweet::Tweet>,impl std::future::Future<Output = Result<serenity::model::channel::Message,SerenityError>>} and [&Handler, serenity::prelude::Context, serenity::model::channel::Message]
Where the MIR known type does not know the type CurrentUser but knows the type impl std::future::Future<Output = CurrentUser>, I think this was a regression right? the MIR should know also CurrentUser or vice versa the future need to be unwrapped to CurrentUser!
Yeah, so for some more background, this bug is with a new generator capture analysis called Drop Tracking. Drop tracking is more precise than the current analysis, which means that it finds fewer types in the generator type than before (basically, the current analysis has a lot of false positives and drop tracking has less of them). This analysis happens during type checking, and then the code is lowered to MIR. In MIR a similar analysis is done to find the values that need to be captured as part of the generator state. The MIR analysis is also more conservative than in strictly needs to be (it also has false positives), so sometimes we have to make drop tracking less aggressive than it could be to match the MIR analysis. We've had a lot of bugs like that so far, so I would expect that's what's going on here. That said, it could also be that the drop tracking analysis is bad and is missing something that it actually should be finding.
changed the title [-]Drop tracking ICE involving await in left hand side of assignment[/-][+]Drop tracking ICE involving await in left hand side of assignment (`-Zdrop-tracking`)[/+]on Dec 19, 2022
use std::collections::HashMap;fnmain(){let _ = real_main();}asyncfnnop(){}asyncfnreal_main(){nop().await;nop().await;nop().await;nop().await;letmut map:HashMap<(),()> = HashMap::new();
map.insert((),nop().await);}
Once again we have the four load-bearing nops. I'm guessing this issue is more generally about having four or more awaits followed by some mutable borrow being held across another await.
Okay, I made some progress this afternoon so I wanted to update here.
The problem is that we refer to yields by where they come up in a post-order traversal of the HIR tree, but we have some disagreement in how they are counted. For a loop that gets desugared from a .await, cfg_build.rs counts one less expression than the similar calculation in region.rs. This is why the bug only shows up after having four useless awaits, since that's how far we need the counts to drift so we'll have different liveness information.
I looked for places in region.rs where we change expr_and_pat_count to find cases that we might not be matching in cfg_build.rs. I noticed we have some save and restore logic when handling bodies that we don't have cfg_build.rs. Tomorrow I plan to look into this some more to figure out what it's doing and how we should match that logic.
Activity
Rageking8 commentedon Oct 3, 2022
@rustbot label +T-compiler +C-bug
eholk commentedon Oct 10, 2022
@rustbot label +AsyncAwait-Triaged
vincenzopalazzo commentedon Oct 10, 2022
As discussed on Zulip I will try to make some report tomorrow regarding this issue!
@rustbot claim
vincenzopalazzo commentedon Oct 11, 2022
After playing a little bit with this today, as posted also on Zulip I can have a thesis that can make sense, I take a look to the following crates report https://crater-reports.s3.amazonaws.com/pr-97334-1/try%23b755f8b9936d084e0363ce6b393c7e444a37080e/gh/88IO.blogpost-rs/log.txt
where the message crash is the following one
Where the MIR known type does not know the type CurrentUser but knows the type
impl std::future::Future<Output = CurrentUser>, I think this was a regression right? the MIR should know also CurrentUser or vice versa the future need to be unwrapped to CurrentUser!eholk commentedon Oct 11, 2022
Yeah, so for some more background, this bug is with a new generator capture analysis called Drop Tracking. Drop tracking is more precise than the current analysis, which means that it finds fewer types in the generator type than before (basically, the current analysis has a lot of false positives and drop tracking has less of them). This analysis happens during type checking, and then the code is lowered to MIR. In MIR a similar analysis is done to find the values that need to be captured as part of the generator state. The MIR analysis is also more conservative than in strictly needs to be (it also has false positives), so sometimes we have to make drop tracking less aggressive than it could be to match the MIR analysis. We've had a lot of bugs like that so far, so I would expect that's what's going on here. That said, it could also be that the drop tracking analysis is bad and is missing something that it actually should be finding.
vincenzopalazzo commentedon Oct 14, 2022
Minimal Exaple to reproduce it
bryangarza commentedon Nov 10, 2022
@rustbot claim
4 remaining items
matthiaskrgr commentedon Dec 19, 2022
@eholk has this been fixed? Can you still reproduce this ice?
compiler-errors commentedon Dec 19, 2022
This issue still reproduces with
-Zdrop-tracking.[-]Drop tracking ICE involving await in left hand side of assignment[/-][+]Drop tracking ICE involving await in left hand side of assignment (`-Zdrop-tracking`)[/+]eholk commentedon Jan 9, 2023
I found another instance of this:
Once again we have the four load-bearing
nops. I'm guessing this issue is more generally about having four or more awaits followed by some mutable borrow being held across another await.eholk commentedon Jan 9, 2023
@rustbot claim
I'm going to take a look at fixing this.
eholk commentedon Jan 10, 2023
Okay, I made some progress this afternoon so I wanted to update here.
The problem is that we refer to yields by where they come up in a post-order traversal of the HIR tree, but we have some disagreement in how they are counted. For a loop that gets desugared from a
.await,cfg_build.rscounts one less expression than the similar calculation inregion.rs. This is why the bug only shows up after having four useless awaits, since that's how far we need the counts to drift so we'll have different liveness information.I've started a branch that will eventually have a fix, but for now I've just added some more debug logging and assertions to detect this drift better.
I looked for places in
region.rswhere we changeexpr_and_pat_countto find cases that we might not be matching incfg_build.rs. I noticed we have some save and restore logic when handling bodies that we don't havecfg_build.rs. Tomorrow I plan to look into this some more to figure out what it's doing and how we should match that logic.Rollup merge of rust-lang#106699 - eholk:await-chains-drop-tracking, …
Rollup merge of rust-lang#106699 - eholk:await-chains-drop-tracking, …