Skip to content

Commit 9c0000c

Browse files
committed
Point at opaque and closure type definitions in type errors
1 parent ed6468d commit 9c0000c

14 files changed

+137
-8
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,11 @@ use rustc_hir as hir;
6868
use rustc_hir::def_id::DefId;
6969
use rustc_hir::Node;
7070

71-
use errors::{struct_span_err, Applicability, DiagnosticBuilder, DiagnosticStyledString};
71+
use errors::{
72+
pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticStyledString,
73+
};
7274
use rustc_error_codes::*;
73-
use rustc_span::{Pos, Span};
75+
use rustc_span::{DesugaringKind, Pos, Span};
7476
use rustc_target::spec::abi;
7577
use std::{cmp, fmt};
7678

@@ -1289,6 +1291,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12891291
mut values: Option<ValuePairs<'tcx>>,
12901292
terr: &TypeError<'tcx>,
12911293
) {
1294+
let span = cause.span(self.tcx);
1295+
12921296
// For some types of errors, expected-found does not make
12931297
// sense, so just ignore the values we were given.
12941298
match terr {
@@ -1298,6 +1302,85 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12981302
_ => {}
12991303
}
13001304

1305+
struct OpaqueTypesVisitor<'tcx> {
1306+
types: FxHashMap<&'static str, FxHashSet<Span>>,
1307+
expected: FxHashMap<&'static str, FxHashSet<Span>>,
1308+
found: FxHashMap<&'static str, FxHashSet<Span>>,
1309+
ignore_span: Span,
1310+
tcx: TyCtxt<'tcx>,
1311+
}
1312+
1313+
impl<'tcx> OpaqueTypesVisitor<'tcx> {
1314+
fn visit_expected_found(
1315+
tcx: TyCtxt<'tcx>,
1316+
expected: Ty<'tcx>,
1317+
found: Ty<'tcx>,
1318+
ignore_span: Span,
1319+
) -> Self {
1320+
let mut types_visitor = OpaqueTypesVisitor {
1321+
types: Default::default(),
1322+
expected: Default::default(),
1323+
found: Default::default(),
1324+
ignore_span,
1325+
tcx,
1326+
};
1327+
expected.visit_with(&mut types_visitor);
1328+
std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
1329+
found.visit_with(&mut types_visitor);
1330+
std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
1331+
types_visitor
1332+
}
1333+
1334+
fn report(&self, err: &mut DiagnosticBuilder<'_>) {
1335+
for (target, types) in &[("expected", &self.expected), ("found", &self.found)] {
1336+
for (key, values) in types.iter() {
1337+
let count = values.len();
1338+
for sp in values {
1339+
err.span_label(
1340+
*sp,
1341+
format!(
1342+
"{}this is {}the {} {}{}",
1343+
if sp.is_desugaring(DesugaringKind::Async) {
1344+
"in the desugared `async fn`, "
1345+
} else {
1346+
""
1347+
},
1348+
if count > 1 { "one of" } else { "" },
1349+
target,
1350+
key,
1351+
pluralize!(count),
1352+
),
1353+
);
1354+
}
1355+
}
1356+
}
1357+
}
1358+
}
1359+
1360+
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
1361+
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
1362+
let kind = match t.kind {
1363+
ty::Closure(..) => "closure",
1364+
ty::Opaque(..) => "opaque type",
1365+
_ => "",
1366+
};
1367+
match t.kind {
1368+
ty::Closure(def_id, _) | ty::Opaque(def_id, _) => {
1369+
let span = self.tcx.def_span(def_id);
1370+
debug!("note_type_err visit_ty {:?}", span.macro_backtrace());
1371+
if !self.ignore_span.overlaps(span)
1372+
&& !self.expected.values().any(|exp| exp.iter().any(|sp| *sp == span))
1373+
{
1374+
let entry = self.types.entry(kind).or_default();
1375+
entry.insert(span);
1376+
}
1377+
}
1378+
_ => {}
1379+
}
1380+
t.super_visit_with(self)
1381+
}
1382+
}
1383+
13011384
debug!("note_type_err(diag={:?})", diag);
13021385
let (expected_found, exp_found, is_simple_error) = match values {
13031386
None => (None, None, false),
@@ -1306,6 +1389,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13061389
ValuePairs::Types(exp_found) => {
13071390
let is_simple_err =
13081391
exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
1392+
OpaqueTypesVisitor::visit_expected_found(
1393+
self.tcx,
1394+
exp_found.expected,
1395+
exp_found.found,
1396+
span,
1397+
)
1398+
.report(diag);
13091399

13101400
(is_simple_err, Some(exp_found))
13111401
}
@@ -1323,8 +1413,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13231413
}
13241414
};
13251415

1326-
let span = cause.span(self.tcx);
1327-
13281416
// Ignore msg for object safe coercion
13291417
// since E0038 message will be printed
13301418
match terr {
@@ -1336,7 +1424,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13361424
}
13371425
}
13381426
};
1339-
13401427
if let Some((expected, found)) = expected_found {
13411428
let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string());
13421429
let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string());

src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4743,14 +4743,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
47434743
.join(", ");
47444744
}
47454745
Some(Node::Expr(hir::Expr {
4746-
kind: ExprKind::Closure(_, _, body_id, closure_span, _),
4746+
kind: ExprKind::Closure(_, _, body_id, _, _),
47474747
span: full_closure_span,
47484748
..
47494749
})) => {
47504750
if *full_closure_span == expr.span {
47514751
return false;
47524752
}
4753-
err.span_label(*closure_span, "closure defined here");
47544753
msg = "call this closure";
47554754
let body = hir.body(*body_id);
47564755
sugg_call = body

src/test/ui/async-await/dont-suggest-missing-await.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/dont-suggest-missing-await.rs:14:18
33
|
4+
LL | async fn make_u32() -> u32 {
5+
| --- in the desugared `async fn`, this is the found opaque type
6+
...
47
LL | take_u32(x)
58
| ^ expected `u32`, found opaque type
69
|

src/test/ui/async-await/suggest-missing-await-closure.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/suggest-missing-await-closure.rs:16:18
33
|
4+
LL | async fn make_u32() -> u32 {
5+
| --- in the desugared `async fn`, this is the found opaque type
6+
...
47
LL | take_u32(x)
58
| ^
69
| |

src/test/ui/async-await/suggest-missing-await.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/suggest-missing-await.rs:13:14
33
|
4+
LL | async fn make_u32() -> u32 {
5+
| --- in the desugared `async fn`, this is the found opaque type
6+
...
47
LL | take_u32(x)
58
| ^
69
| |

src/test/ui/closures/closure-reform-bad.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0308]: mismatched types
22
--> $DIR/closure-reform-bad.rs:11:15
33
|
4+
LL | let f = |s: &str| println!("{}{}", s, string);
5+
| ------------------------------------- this is the found closure
46
LL | call_bare(f)
57
| ^ expected fn pointer, found closure
68
|

src/test/ui/impl-trait/equality2.stderr

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/equality2.rs:25:18
33
|
4+
LL | fn hide<T: Foo>(x: T) -> impl Foo {
5+
| -------- this is the found opaque type
6+
...
47
LL | let _: u32 = hide(0_u32);
58
| --- ^^^^^^^^^^^ expected `u32`, found opaque type
69
| |
@@ -12,6 +15,9 @@ LL | let _: u32 = hide(0_u32);
1215
error[E0308]: mismatched types
1316
--> $DIR/equality2.rs:31:18
1417
|
18+
LL | fn hide<T: Foo>(x: T) -> impl Foo {
19+
| -------- this is the found opaque type
20+
...
1521
LL | let _: i32 = Leak::leak(hide(0_i32));
1622
| --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
1723
| |
@@ -25,6 +31,9 @@ LL | let _: i32 = Leak::leak(hide(0_i32));
2531
error[E0308]: mismatched types
2632
--> $DIR/equality2.rs:38:10
2733
|
34+
LL | fn hide<T: Foo>(x: T) -> impl Foo {
35+
| -------- this is the expected opaque type
36+
...
2837
LL | x = (x.1,
2938
| ^^^ expected `u32`, found `i32`
3039
|
@@ -34,6 +43,9 @@ LL | x = (x.1,
3443
error[E0308]: mismatched types
3544
--> $DIR/equality2.rs:41:10
3645
|
46+
LL | fn hide<T: Foo>(x: T) -> impl Foo {
47+
| -------- this is the expected opaque type
48+
...
3749
LL | x.0);
3850
| ^^^ expected `i32`, found `u32`
3951
|

src/test/ui/issues/issue-24036.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0308]: mismatched types
22
--> $DIR/issue-24036.rs:3:9
33
|
4+
LL | let mut x = |c| c + 1;
5+
| --------- this is the expected closure
46
LL | x = |c| c + 1;
57
| ^^^^^^^^^ expected closure, found a different closure
68
|

src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ error[E0308]: mismatched types
236236
--> $DIR/fn-or-tuple-struct-without-args.rs:46:20
237237
|
238238
LL | let closure = || 42;
239-
| -- closure defined here
239+
| ----- this is the found closure
240240
LL | let _: usize = closure;
241241
| ----- ^^^^^^^
242242
| | |

src/test/ui/suggestions/opaque-type-error.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: `if` and `else` have incompatible types
22
--> $DIR/opaque-type-error.rs:20:9
33
|
4+
LL | fn thing_two() -> impl Future<Output = Result<(), ()>> {
5+
| ------------------------------------ this is the found opaque type
6+
...
47
LL | / if true {
58
LL | | thing_one()
69
| | ----------- expected because of this

src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ LL | let z: i32 = x;
1111
| --- ^ expected `i32`, found opaque type
1212
| |
1313
| expected due to this
14+
...
15+
LL | type WrongGeneric<T> = impl 'static;
16+
| ------------------------------------ this is the found opaque type
1417
|
1518
= note: expected type `i32`
1619
found opaque type `WrongGeneric::<&{integer}>`

src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ LL | let z: i32 = x;
1111
| --- ^ expected `i32`, found opaque type
1212
| |
1313
| expected due to this
14+
...
15+
LL | type WrongGeneric<T> = impl 'static;
16+
| ------------------------------------ this is the found opaque type
1417
|
1518
= note: expected type `i32`
1619
found opaque type `WrongGeneric::<&{integer}>`

src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/never_reveal_concrete_type.rs:13:27
33
|
4+
LL | type NoReveal = impl std::fmt::Debug;
5+
| ------------------------------------- this is the found opaque type
6+
...
47
LL | let _: &'static str = x;
58
| ------------ ^ expected `&str`, found opaque type
69
| |

src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/no_revealing_outside_defining_module.rs:15:19
33
|
4+
LL | pub type Boo = impl ::std::fmt::Debug;
5+
| -------------------------------------- this is the found opaque type
6+
...
47
LL | let _: &str = bomp();
58
| ---- ^^^^^^ expected `&str`, found opaque type
69
| |
@@ -12,6 +15,9 @@ LL | let _: &str = bomp();
1215
error[E0308]: mismatched types
1316
--> $DIR/no_revealing_outside_defining_module.rs:19:5
1417
|
18+
LL | pub type Boo = impl ::std::fmt::Debug;
19+
| -------------------------------------- this is the expected opaque type
20+
...
1521
LL | fn bomp() -> boo::Boo {
1622
| -------- expected `Boo` because of return type
1723
LL | ""

0 commit comments

Comments
 (0)