diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 35170fa7c1d02..e5829b1c4f713 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1274,7 +1274,7 @@ impl Body<'hir> { } /// 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 { /// An explicit `async` block or the body of an async function. Async(AsyncGeneratorKind), @@ -1292,12 +1292,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, /// which kind of async construct caused it to be created? /// /// This helps error messages but is also used to drive coercions in /// 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 { /// An explicit `async` block written by the user. Block, @@ -1319,6 +1328,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)] pub enum BodyOwnerKind { /// Functions and methods. diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index c39daea0811e0..893fe343fdd19 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1509,7 +1509,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - 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); // 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 { 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(), }; 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(), }; let exp_found = match exp_found { @@ -2436,7 +2436,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { pub enum TyCategory { Closure, Opaque, - Generator, + Generator(hir::GeneratorKind), Foreign, } @@ -2445,16 +2445,18 @@ impl TyCategory { match self { Self::Closure => "closure", Self::Opaque => "opaque type", - Self::Generator => "generator", + Self::Generator(gk) => gk.descr(), 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() { ty::Closure(def_id, _) => Some((Self::Closure, 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)), _ => None, } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index bd43d3c01e218..e7de11fffdea0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -383,7 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { InferenceDiagnosticsData { name: s, span: None, - kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string() }, + kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) }, parent: None, } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index c211f07bed8c2..5625264911aac 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -264,7 +264,7 @@ impl<'tcx> ty::TyS<'tcx> { } } 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::Tuple(..) => "tuple".into(), ty::Infer(ty::TyVar(_)) => "inferred type".into(), @@ -282,7 +282,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() { ty::Infer(_) | ty::Error(_) @@ -308,7 +308,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(..) => "trait object".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::Tuple(..) => "tuple".into(), ty::Placeholder(..) => "higher-ranked type".into(), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index a42a05c5f0284..7b00a828a974f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1366,8 +1366,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { Some(t) => Some(t), None => { let ty = parent_trait_ref.skip_binder().self_ty(); - let span = - TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id)); + let span = TyCategory::from_ty(self.tcx, ty) + .map(|(_, def_id)| self.tcx.def_span(def_id)); Some((ty.to_string(), span)) } } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index d49c7cae8222b..09a15df97a2d1 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "no {} named `{}` found for {} `{}` in the current scope", item_kind, item_name, - actual.prefix_string(), + actual.prefix_string(self.tcx), ty_str, ); if let Mode::MethodCall = mode { @@ -728,7 +728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|(_, path)| path) .collect::>() .join("\n"); - let actual_prefix = actual.prefix_string(); + let actual_prefix = actual.prefix_string(self.tcx); err.set_primary_message(&format!( "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" )); diff --git a/src/test/ui/async-await/generator-desc.rs b/src/test/ui/async-await/generator-desc.rs new file mode 100644 index 0000000000000..5008120166711 --- /dev/null +++ b/src/test/ui/async-await/generator-desc.rs @@ -0,0 +1,16 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +async fn one() {} +async fn two() {} + +fn fun>(f1: F, f2: F) {} +fn main() { + fun(async {}, async {}); + //~^ ERROR mismatched types + fun(one(), two()); + //~^ ERROR mismatched types + fun((async || {})(), (async || {})()); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr new file mode 100644 index 0000000000000..b85926c7a03c0 --- /dev/null +++ b/src/test/ui/async-await/generator-desc.stderr @@ -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(gen: T) -> impl Future + | ------------------------------- + | | + | 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`.