mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #81496 - guswynn:expected_async_block, r=oli-obk
name async generators something more human friendly in type error diagnostic fixes #81457 Some details: 1. I opted to load the generator kind from the hir in TyCategory. I also use 1 impl in the hir for the descr 2. I named both the source of the future, in addition to the general type (`future`), not sure what is preferred 3. I am not sure what is required to make sure "generator" is not referred to anywhere. A brief `rg "\"generator\"" showed me that most diagnostics correctly distinguish from generators and async generator, but the `descr` of `DefKind` is pretty general (not sure how thats used) 4. should the descr impl of AsyncGeneratorKind use its display impl instead of copying the string?
This commit is contained in:
commit
f468fd1d23
@ -1,3 +1,4 @@
|
|||||||
|
// ignore-tidy-filelength
|
||||||
use crate::def::{DefKind, Namespace, Res};
|
use crate::def::{DefKind, Namespace, Res};
|
||||||
use crate::def_id::DefId;
|
use crate::def_id::DefId;
|
||||||
crate use crate::hir_id::HirId;
|
crate use crate::hir_id::HirId;
|
||||||
@ -1280,7 +1281,7 @@ impl Body<'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The type of source expression that caused this generator to be created.
|
/// The type of source expression that caused this generator to be created.
|
||||||
#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
|
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
|
||||||
pub enum GeneratorKind {
|
pub enum GeneratorKind {
|
||||||
/// An explicit `async` block or the body of an async function.
|
/// An explicit `async` block or the body of an async function.
|
||||||
Async(AsyncGeneratorKind),
|
Async(AsyncGeneratorKind),
|
||||||
@ -1298,12 +1299,21 @@ impl fmt::Display for GeneratorKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GeneratorKind {
|
||||||
|
pub fn descr(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
GeneratorKind::Async(ask) => ask.descr(),
|
||||||
|
GeneratorKind::Gen => "generator",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// In the case of a generator created as part of an async construct,
|
/// In the case of a generator created as part of an async construct,
|
||||||
/// which kind of async construct caused it to be created?
|
/// which kind of async construct caused it to be created?
|
||||||
///
|
///
|
||||||
/// This helps error messages but is also used to drive coercions in
|
/// This helps error messages but is also used to drive coercions in
|
||||||
/// type-checking (see #60424).
|
/// type-checking (see #60424).
|
||||||
#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
|
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
|
||||||
pub enum AsyncGeneratorKind {
|
pub enum AsyncGeneratorKind {
|
||||||
/// An explicit `async` block written by the user.
|
/// An explicit `async` block written by the user.
|
||||||
Block,
|
Block,
|
||||||
@ -1325,6 +1335,16 @@ impl fmt::Display for AsyncGeneratorKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsyncGeneratorKind {
|
||||||
|
pub fn descr(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
AsyncGeneratorKind::Block => "`async` block",
|
||||||
|
AsyncGeneratorKind::Closure => "`async` closure body",
|
||||||
|
AsyncGeneratorKind::Fn => "`async fn` body",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum BodyOwnerKind {
|
pub enum BodyOwnerKind {
|
||||||
/// Functions and methods.
|
/// Functions and methods.
|
||||||
|
@ -1509,7 +1509,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
if let Some((kind, def_id)) = TyCategory::from_ty(t) {
|
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
|
||||||
let span = self.tcx.def_span(def_id);
|
let span = self.tcx.def_span(def_id);
|
||||||
// Avoid cluttering the output when the "found" and error span overlap:
|
// Avoid cluttering the output when the "found" and error span overlap:
|
||||||
//
|
//
|
||||||
@ -1582,11 +1582,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
if let Some((expected, found)) = expected_found {
|
if let Some((expected, found)) = expected_found {
|
||||||
let expected_label = match exp_found {
|
let expected_label = match exp_found {
|
||||||
Mismatch::Variable(ef) => ef.expected.prefix_string(),
|
Mismatch::Variable(ef) => ef.expected.prefix_string(self.tcx),
|
||||||
Mismatch::Fixed(s) => s.into(),
|
Mismatch::Fixed(s) => s.into(),
|
||||||
};
|
};
|
||||||
let found_label = match exp_found {
|
let found_label = match exp_found {
|
||||||
Mismatch::Variable(ef) => ef.found.prefix_string(),
|
Mismatch::Variable(ef) => ef.found.prefix_string(self.tcx),
|
||||||
Mismatch::Fixed(s) => s.into(),
|
Mismatch::Fixed(s) => s.into(),
|
||||||
};
|
};
|
||||||
let exp_found = match exp_found {
|
let exp_found = match exp_found {
|
||||||
@ -2489,7 +2489,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
|||||||
pub enum TyCategory {
|
pub enum TyCategory {
|
||||||
Closure,
|
Closure,
|
||||||
Opaque,
|
Opaque,
|
||||||
Generator,
|
Generator(hir::GeneratorKind),
|
||||||
Foreign,
|
Foreign,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2498,16 +2498,18 @@ impl TyCategory {
|
|||||||
match self {
|
match self {
|
||||||
Self::Closure => "closure",
|
Self::Closure => "closure",
|
||||||
Self::Opaque => "opaque type",
|
Self::Opaque => "opaque type",
|
||||||
Self::Generator => "generator",
|
Self::Generator(gk) => gk.descr(),
|
||||||
Self::Foreign => "foreign type",
|
Self::Foreign => "foreign type",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_ty(ty: Ty<'_>) -> Option<(Self, DefId)> {
|
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
|
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
|
||||||
ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
|
ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
|
||||||
ty::Generator(def_id, ..) => Some((Self::Generator, def_id)),
|
ty::Generator(def_id, ..) => {
|
||||||
|
Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
|
||||||
|
}
|
||||||
ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
|
ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -383,7 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
InferenceDiagnosticsData {
|
InferenceDiagnosticsData {
|
||||||
name: s,
|
name: s,
|
||||||
span: None,
|
span: None,
|
||||||
kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string() },
|
kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
|
||||||
parent: None,
|
parent: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Closure(..) => "closure".into(),
|
ty::Closure(..) => "closure".into(),
|
||||||
ty::Generator(..) => "generator".into(),
|
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
|
||||||
ty::GeneratorWitness(..) => "generator witness".into(),
|
ty::GeneratorWitness(..) => "generator witness".into(),
|
||||||
ty::Tuple(..) => "tuple".into(),
|
ty::Tuple(..) => "tuple".into(),
|
||||||
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
|
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
|
||||||
@ -288,7 +288,7 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prefix_string(&self) -> Cow<'static, str> {
|
pub fn prefix_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
|
||||||
match *self.kind() {
|
match *self.kind() {
|
||||||
ty::Infer(_)
|
ty::Infer(_)
|
||||||
| ty::Error(_)
|
| ty::Error(_)
|
||||||
@ -314,7 +314,7 @@ impl<'tcx> ty::TyS<'tcx> {
|
|||||||
ty::FnPtr(_) => "fn pointer".into(),
|
ty::FnPtr(_) => "fn pointer".into(),
|
||||||
ty::Dynamic(..) => "trait object".into(),
|
ty::Dynamic(..) => "trait object".into(),
|
||||||
ty::Closure(..) => "closure".into(),
|
ty::Closure(..) => "closure".into(),
|
||||||
ty::Generator(..) => "generator".into(),
|
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
|
||||||
ty::GeneratorWitness(..) => "generator witness".into(),
|
ty::GeneratorWitness(..) => "generator witness".into(),
|
||||||
ty::Tuple(..) => "tuple".into(),
|
ty::Tuple(..) => "tuple".into(),
|
||||||
ty::Placeholder(..) => "higher-ranked type".into(),
|
ty::Placeholder(..) => "higher-ranked type".into(),
|
||||||
|
@ -1368,8 +1368,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
Some(t) => Some(t),
|
Some(t) => Some(t),
|
||||||
None => {
|
None => {
|
||||||
let ty = parent_trait_ref.skip_binder().self_ty();
|
let ty = parent_trait_ref.skip_binder().self_ty();
|
||||||
let span =
|
let span = TyCategory::from_ty(self.tcx, ty)
|
||||||
TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
|
.map(|(_, def_id)| self.tcx.def_span(def_id));
|
||||||
Some((ty.to_string(), span))
|
Some((ty.to_string(), span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
"no {} named `{}` found for {} `{}` in the current scope",
|
"no {} named `{}` found for {} `{}` in the current scope",
|
||||||
item_kind,
|
item_kind,
|
||||||
item_name,
|
item_name,
|
||||||
actual.prefix_string(),
|
actual.prefix_string(self.tcx),
|
||||||
ty_str,
|
ty_str,
|
||||||
);
|
);
|
||||||
if let Mode::MethodCall = mode {
|
if let Mode::MethodCall = mode {
|
||||||
@ -732,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.map(|(_, path)| path)
|
.map(|(_, path)| path)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
let actual_prefix = actual.prefix_string();
|
let actual_prefix = actual.prefix_string(self.tcx);
|
||||||
err.set_primary_message(&format!(
|
err.set_primary_message(&format!(
|
||||||
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
|
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
|
||||||
));
|
));
|
||||||
|
16
src/test/ui/async-await/generator-desc.rs
Normal file
16
src/test/ui/async-await/generator-desc.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// edition:2018
|
||||||
|
#![feature(async_closure)]
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
async fn one() {}
|
||||||
|
async fn two() {}
|
||||||
|
|
||||||
|
fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
|
||||||
|
fn main() {
|
||||||
|
fun(async {}, async {});
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
fun(one(), two());
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
fun((async || {})(), (async || {})());
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
49
src/test/ui/async-await/generator-desc.stderr
Normal file
49
src/test/ui/async-await/generator-desc.stderr
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/generator-desc.rs:10:25
|
||||||
|
|
|
||||||
|
LL | fun(async {}, async {});
|
||||||
|
| -- ^^ expected `async` block, found a different `async` block
|
||||||
|
| |
|
||||||
|
| the expected `async` block
|
||||||
|
|
|
||||||
|
= note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]`
|
||||||
|
found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/generator-desc.rs:12:16
|
||||||
|
|
|
||||||
|
LL | async fn one() {}
|
||||||
|
| - the `Output` of this `async fn`'s expected opaque type
|
||||||
|
LL | async fn two() {}
|
||||||
|
| - the `Output` of this `async fn`'s found opaque type
|
||||||
|
...
|
||||||
|
LL | fun(one(), two());
|
||||||
|
| ^^^^^ expected opaque type, found a different opaque type
|
||||||
|
|
|
||||||
|
= note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>)
|
||||||
|
found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>)
|
||||||
|
= help: consider `await`ing on both `Future`s
|
||||||
|
= note: distinct uses of `impl Trait` result in different opaque types
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/generator-desc.rs:14:26
|
||||||
|
|
|
||||||
|
LL | fun((async || {})(), (async || {})());
|
||||||
|
| -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
|
||||||
|
| |
|
||||||
|
| the expected `async` closure body
|
||||||
|
|
|
||||||
|
::: $SRC_DIR/core/src/future/mod.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
|
||||||
|
| -------------------------------
|
||||||
|
| |
|
||||||
|
| the expected opaque type
|
||||||
|
| the found opaque type
|
||||||
|
|
|
||||||
|
= note: expected opaque type `impl Future` (`async` closure body)
|
||||||
|
found opaque type `impl Future` (`async` closure body)
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user