@@ -1303,15 +1303,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1303
1303
_ => { }
1304
1304
}
1305
1305
1306
+ /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
1307
+ /// extra information about each type, but we only care about the category.
1306
1308
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
1307
- enum TyKind {
1309
+ enum TyCategory {
1308
1310
Closure ,
1309
1311
Opaque ,
1310
1312
Generator ,
1311
1313
Foreign ,
1312
1314
}
1313
1315
1314
- impl TyKind {
1316
+ impl TyCategory {
1315
1317
fn descr ( & self ) -> & ' static str {
1316
1318
match self {
1317
1319
Self :: Closure => "closure" ,
@@ -1334,8 +1336,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1334
1336
1335
1337
struct OpaqueTypesVisitor < ' tcx > {
1336
1338
types : FxHashMap < TyKind , FxHashSet < Span > > ,
1337
- expected : FxHashMap < TyKind , FxHashSet < Span > > ,
1338
- found : FxHashMap < TyKind , FxHashSet < Span > > ,
1339
+ expected : FxHashMap < TyCategory , FxHashSet < Span > > ,
1340
+ found : FxHashMap < TyCategory , FxHashSet < Span > > ,
1339
1341
ignore_span : Span ,
1340
1342
tcx : TyCtxt < ' tcx > ,
1341
1343
}
@@ -1354,6 +1356,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1354
1356
ignore_span,
1355
1357
tcx,
1356
1358
} ;
1359
+ // The visitor puts all the relevant encountered types in `self.types`, but in
1360
+ // here we want to visit two separate types with no relation to each other, so we
1361
+ // move the results from `types` to `expected` or `found` as appropriate.
1357
1362
expected. visit_with ( & mut types_visitor) ;
1358
1363
std:: mem:: swap ( & mut types_visitor. expected , & mut types_visitor. types ) ;
1359
1364
found. visit_with ( & mut types_visitor) ;
@@ -1362,28 +1367,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1362
1367
}
1363
1368
1364
1369
fn report ( & self , err : & mut DiagnosticBuilder < ' _ > ) {
1365
- for ( target, types) in & [ ( "expected" , & self . expected ) , ( "found" , & self . found ) ] {
1366
- for ( key, values) in types. iter ( ) {
1367
- let count = values. len ( ) ;
1368
- for sp in values {
1369
- err. span_label (
1370
- * sp,
1371
- format ! (
1372
- "{}{}{} {}{}" ,
1373
- if sp. is_desugaring( DesugaringKind :: Async ) {
1374
- "the `Output` of this `async fn`'s "
1375
- } else if count == 1 {
1376
- "the "
1377
- } else {
1378
- ""
1379
- } ,
1380
- if count > 1 { "one of the " } else { "" } ,
1381
- target,
1382
- key. descr( ) ,
1383
- pluralize!( count) ,
1384
- ) ,
1385
- ) ;
1386
- }
1370
+ self . add_labels_for_types ( err, "expected" , & self . expected ) ;
1371
+ self . add_labels_for_types ( err, "found" , & self . found ) ;
1372
+ }
1373
+
1374
+ fn add_labels_for_types (
1375
+ & self ,
1376
+ err : & mut DiagnosticBuilder < ' _ > ,
1377
+ target : & str ,
1378
+ types : & FxHashMap < TyKind , FxHashSet < Span > > ,
1379
+ ) {
1380
+ for ( key, values) in types. iter ( ) {
1381
+ let count = values. len ( ) ;
1382
+ let kind = key. descr ( ) ;
1383
+ for sp in values {
1384
+ err. span_label (
1385
+ * sp,
1386
+ format ! (
1387
+ "{}{}{} {}{}" ,
1388
+ if sp. is_desugaring( DesugaringKind :: Async ) {
1389
+ "the `Output` of this `async fn`'s "
1390
+ } else if count == 1 {
1391
+ "the "
1392
+ } else {
1393
+ ""
1394
+ } ,
1395
+ if count > 1 { "one of the " } else { "" } ,
1396
+ target,
1397
+ key,
1398
+ pluralize!( count) ,
1399
+ ) ,
1400
+ ) ;
1387
1401
}
1388
1402
}
1389
1403
}
0 commit comments