Repository navigation
Closed
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsAsyncAwait-PolishAsync-await issues that are part of the "polish" areaAsync-await issues that are part of the "polish" areaAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.D-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.T-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
use std::future::Future;
pub trait Bound {}
pub struct Error;
impl Bound for Error {}
pub struct Wrap;
impl<T: Bound> From<T> for Wrap {
fn from(input: T) -> Self {
Wrap
}
}
impl<T: Into<Wrap>> From<T> for Error {
fn from(input: T) -> Self {
Error
}
}
fn fail() -> impl Future<Output = Result<(), Error>> {
async move {
let a: Result<(), Error> = Ok(());
let a: () = a?;
Ok(())
}
}This fails with type annotations required: cannot resolve Error: std::convert::From<Error> (E0283) instead of the expected conflicting implementations of trait std::convert::From<Error> for type Error (E0119). Changing fail to
fn fail() -> Result<(), Error> {
let a: Result<(), Error> = Ok(());
let a: () = a?;
Ok(())
}i.e. eliminating the async block leads to the expected error message being produced.
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsAsyncAwait-PolishAsync-await issues that are part of the "polish" areaAsync-await issues that are part of the "polish" areaAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.D-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.T-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.
Type
Projects
- StatusShow more project fieldsDone
Activity
tmandry commentedon Jan 7, 2020
@Centril said they'd look into minimizing this further.
tmandry commentedon Jan 7, 2020
Also assigning @nikomatsakis to look into this along with #66312.
Centril commentedon Jan 7, 2020
Reduced:
nikomatsakis commentedon Jan 8, 2020
I've been investigating this. I'm not sure I understand yet what is going on, but I'm going to leave a few breadcrumbs as I go. To start, I think part of the problem lies on this line:
rust/src/librustc_typeck/collect.rs
Line 1395 in ed6468d
Specifically what is happening here is that we are executing the
type_ofquery on a generator, and this is triggering us to do a full typeck. There is probably a good reason for this, but it's not generally how things are meant to work. This query is meant to be "modular", in that we can create the type for all items without type checking their bodies (this is possible because, for example, Rust requires us to fully specify the type signature for functions). I'm not quite sure why generators behave differently -- closures, for example, do not, as you can see if I give a bit more context:rust/src/librustc_typeck/collect.rs
Lines 1393 to 1400 in ed6468d
Here, on lines 1398-1399, you can see that for a closure we create a type with "identity substitutions", which means a closure type like
Closure<P0...Pn>wherePiis a reference to a type parameter.(I see that opaque types also behave differently; it seems like
tcx.type_of(opaque)is used to fetch the concrete type of an opaque type. I actually think we should make that a distinct query, but I think it's neither here nor there.)(I'm going to look a bit more at why generators behave this way now, not obvious to me that they must -- @Zoxc may have some details here?)
UPDATE: Based on some exploration of git history, this line goes way back to the original gen branch at least.
nikomatsakis commentedon Jan 8, 2020
OK, I can confirm that the "naive fix" causes downstream errors, I haven't investigated those much yet:
I suspect they can be fixed though
Zoxc commentedon Jan 8, 2020
@nikomatsakis Generator types contain the types of the values inside which are live across a yield statement, that is why
typeck_tables_ofis required there. We could move getting the interior type of the generator into a separate query, but that would only help if the problematic caller oftype_ofdoes not actually look at these.nikomatsakis commentedon Jan 13, 2020
@Zoxc I don't think that's sufficient reason by itself. Closure types also contain details that result from inference (e.g., the types that their upvars use), but
type_ofapplied to a closure just gives you a fully generic type.tmandry commentedon Feb 4, 2020
We hit an instance of this in Fuchsia. Minimal example: (playground)
Gives
instead of the expected error, which is what you get if you remove the async block:
cc @JakeEhrlich
Rollup merge of rust-lang#68884 - Zoxc:gen-type, r=nikomatsakis
Rollup merge of rust-lang#68884 - Zoxc:gen-type, r=nikomatsakis
Rollup merge of rust-lang#68884 - Zoxc:gen-type, r=nikomatsakis
Rollup merge of rust-lang#68884 - Zoxc:gen-type, r=nikomatsakis