Skip to content

Commit f468fd1

Browse files
authored
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?
2 parents 94ab407 + 3e7ea40 commit f468fd1

File tree

8 files changed

+104
-17
lines changed

8 files changed

+104
-17
lines changed

compiler/rustc_hir/src/hir.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-filelength
12
use crate::def::{DefKind, Namespace, Res};
23
use crate::def_id::DefId;
34
crate use crate::hir_id::HirId;
@@ -1280,7 +1281,7 @@ impl Body<'hir> {
12801281
}
12811282

12821283
/// The type of source expression that caused this generator to be created.
1283-
#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
1284+
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
12841285
pub enum GeneratorKind {
12851286
/// An explicit `async` block or the body of an async function.
12861287
Async(AsyncGeneratorKind),
@@ -1298,12 +1299,21 @@ impl fmt::Display for GeneratorKind {
12981299
}
12991300
}
13001301

1302+
impl GeneratorKind {
1303+
pub fn descr(&self) -> &'static str {
1304+
match self {
1305+
GeneratorKind::Async(ask) => ask.descr(),
1306+
GeneratorKind::Gen => "generator",
1307+
}
1308+
}
1309+
}
1310+
13011311
/// In the case of a generator created as part of an async construct,
13021312
/// which kind of async construct caused it to be created?
13031313
///
13041314
/// This helps error messages but is also used to drive coercions in
13051315
/// type-checking (see #60424).
1306-
#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
1316+
#[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
13071317
pub enum AsyncGeneratorKind {
13081318
/// An explicit `async` block written by the user.
13091319
Block,
@@ -1325,6 +1335,16 @@ impl fmt::Display for AsyncGeneratorKind {
13251335
}
13261336
}
13271337

1338+
impl AsyncGeneratorKind {
1339+
pub fn descr(&self) -> &'static str {
1340+
match self {
1341+
AsyncGeneratorKind::Block => "`async` block",
1342+
AsyncGeneratorKind::Closure => "`async` closure body",
1343+
AsyncGeneratorKind::Fn => "`async fn` body",
1344+
}
1345+
}
1346+
}
1347+
13281348
#[derive(Copy, Clone, Debug)]
13291349
pub enum BodyOwnerKind {
13301350
/// Functions and methods.

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15091509

15101510
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
15111511
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1512-
if let Some((kind, def_id)) = TyCategory::from_ty(t) {
1512+
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
15131513
let span = self.tcx.def_span(def_id);
15141514
// Avoid cluttering the output when the "found" and error span overlap:
15151515
//
@@ -1582,11 +1582,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15821582
};
15831583
if let Some((expected, found)) = expected_found {
15841584
let expected_label = match exp_found {
1585-
Mismatch::Variable(ef) => ef.expected.prefix_string(),
1585+
Mismatch::Variable(ef) => ef.expected.prefix_string(self.tcx),
15861586
Mismatch::Fixed(s) => s.into(),
15871587
};
15881588
let found_label = match exp_found {
1589-
Mismatch::Variable(ef) => ef.found.prefix_string(),
1589+
Mismatch::Variable(ef) => ef.found.prefix_string(self.tcx),
15901590
Mismatch::Fixed(s) => s.into(),
15911591
};
15921592
let exp_found = match exp_found {
@@ -2489,7 +2489,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
24892489
pub enum TyCategory {
24902490
Closure,
24912491
Opaque,
2492-
Generator,
2492+
Generator(hir::GeneratorKind),
24932493
Foreign,
24942494
}
24952495

@@ -2498,16 +2498,18 @@ impl TyCategory {
24982498
match self {
24992499
Self::Closure => "closure",
25002500
Self::Opaque => "opaque type",
2501-
Self::Generator => "generator",
2501+
Self::Generator(gk) => gk.descr(),
25022502
Self::Foreign => "foreign type",
25032503
}
25042504
}
25052505

2506-
pub fn from_ty(ty: Ty<'_>) -> Option<(Self, DefId)> {
2506+
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
25072507
match *ty.kind() {
25082508
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
25092509
ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
2510-
ty::Generator(def_id, ..) => Some((Self::Generator, def_id)),
2510+
ty::Generator(def_id, ..) => {
2511+
Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
2512+
}
25112513
ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
25122514
_ => None,
25132515
}

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
383383
InferenceDiagnosticsData {
384384
name: s,
385385
span: None,
386-
kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string() },
386+
kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
387387
parent: None,
388388
}
389389
}

compiler/rustc_middle/src/ty/error.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ impl<'tcx> ty::TyS<'tcx> {
270270
}
271271
}
272272
ty::Closure(..) => "closure".into(),
273-
ty::Generator(..) => "generator".into(),
273+
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
274274
ty::GeneratorWitness(..) => "generator witness".into(),
275275
ty::Tuple(..) => "tuple".into(),
276276
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
@@ -288,7 +288,7 @@ impl<'tcx> ty::TyS<'tcx> {
288288
}
289289
}
290290

291-
pub fn prefix_string(&self) -> Cow<'static, str> {
291+
pub fn prefix_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
292292
match *self.kind() {
293293
ty::Infer(_)
294294
| ty::Error(_)
@@ -314,7 +314,7 @@ impl<'tcx> ty::TyS<'tcx> {
314314
ty::FnPtr(_) => "fn pointer".into(),
315315
ty::Dynamic(..) => "trait object".into(),
316316
ty::Closure(..) => "closure".into(),
317-
ty::Generator(..) => "generator".into(),
317+
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
318318
ty::GeneratorWitness(..) => "generator witness".into(),
319319
ty::Tuple(..) => "tuple".into(),
320320
ty::Placeholder(..) => "higher-ranked type".into(),

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1368,8 +1368,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
13681368
Some(t) => Some(t),
13691369
None => {
13701370
let ty = parent_trait_ref.skip_binder().self_ty();
1371-
let span =
1372-
TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
1371+
let span = TyCategory::from_ty(self.tcx, ty)
1372+
.map(|(_, def_id)| self.tcx.def_span(def_id));
13731373
Some((ty.to_string(), span))
13741374
}
13751375
}

compiler/rustc_typeck/src/check/method/suggest.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
390390
"no {} named `{}` found for {} `{}` in the current scope",
391391
item_kind,
392392
item_name,
393-
actual.prefix_string(),
393+
actual.prefix_string(self.tcx),
394394
ty_str,
395395
);
396396
if let Mode::MethodCall = mode {
@@ -732,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
732732
.map(|(_, path)| path)
733733
.collect::<Vec<_>>()
734734
.join("\n");
735-
let actual_prefix = actual.prefix_string();
735+
let actual_prefix = actual.prefix_string(self.tcx);
736736
err.set_primary_message(&format!(
737737
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
738738
));
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// edition:2018
2+
#![feature(async_closure)]
3+
use std::future::Future;
4+
5+
async fn one() {}
6+
async fn two() {}
7+
8+
fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
9+
fn main() {
10+
fun(async {}, async {});
11+
//~^ ERROR mismatched types
12+
fun(one(), two());
13+
//~^ ERROR mismatched types
14+
fun((async || {})(), (async || {})());
15+
//~^ ERROR mismatched types
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/generator-desc.rs:10:25
3+
|
4+
LL | fun(async {}, async {});
5+
| -- ^^ expected `async` block, found a different `async` block
6+
| |
7+
| the expected `async` block
8+
|
9+
= note: expected `async` block `[static generator@$DIR/generator-desc.rs:10:15: 10:17]`
10+
found `async` block `[static generator@$DIR/generator-desc.rs:10:25: 10:27]`
11+
12+
error[E0308]: mismatched types
13+
--> $DIR/generator-desc.rs:12:16
14+
|
15+
LL | async fn one() {}
16+
| - the `Output` of this `async fn`'s expected opaque type
17+
LL | async fn two() {}
18+
| - the `Output` of this `async fn`'s found opaque type
19+
...
20+
LL | fun(one(), two());
21+
| ^^^^^ expected opaque type, found a different opaque type
22+
|
23+
= note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>)
24+
found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>)
25+
= help: consider `await`ing on both `Future`s
26+
= note: distinct uses of `impl Trait` result in different opaque types
27+
28+
error[E0308]: mismatched types
29+
--> $DIR/generator-desc.rs:14:26
30+
|
31+
LL | fun((async || {})(), (async || {})());
32+
| -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
33+
| |
34+
| the expected `async` closure body
35+
|
36+
::: $SRC_DIR/core/src/future/mod.rs:LL:COL
37+
|
38+
LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
39+
| -------------------------------
40+
| |
41+
| the expected opaque type
42+
| the found opaque type
43+
|
44+
= note: expected opaque type `impl Future` (`async` closure body)
45+
found opaque type `impl Future` (`async` closure body)
46+
47+
error: aborting due to 3 previous errors
48+
49+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)