@@ -23,9 +23,10 @@ use middle::resolve_lifetime as rl;
23
23
use middle:: weak_lang_items;
24
24
use rustc:: mir:: mono:: Linkage ;
25
25
use rustc:: ty:: query:: Providers ;
26
- use rustc:: ty:: subst:: Substs ;
26
+ use rustc:: ty:: subst:: { Subst , Substs } ;
27
27
use rustc:: ty:: util:: Discr ;
28
28
use rustc:: ty:: util:: IntTypeExt ;
29
+ use rustc:: ty:: subst:: UnpackedKind ;
29
30
use rustc:: ty:: { self , AdtKind , ToPolyTraitRef , Ty , TyCtxt } ;
30
31
use rustc:: ty:: { ReprOptions , ToPredicate } ;
31
32
use rustc:: util:: captures:: Captures ;
@@ -1193,7 +1194,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
1193
1194
tcx. typeck_tables_of ( owner)
1194
1195
. concrete_existential_types
1195
1196
. get ( & def_id)
1196
- . cloned ( )
1197
+ . map ( |opaque| opaque . concrete_type )
1197
1198
. unwrap_or_else ( || {
1198
1199
// This can occur if some error in the
1199
1200
// owner fn prevented us from populating
@@ -1325,7 +1326,13 @@ fn find_existential_constraints<'a, 'tcx>(
1325
1326
struct ConstraintLocator < ' a , ' tcx : ' a > {
1326
1327
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1327
1328
def_id : DefId ,
1328
- found : Option < ( Span , ty:: Ty < ' tcx > ) > ,
1329
+ // First found type span, actual type, mapping from the existential type's generic
1330
+ // parameters to the concrete type's generic parameters
1331
+ //
1332
+ // The mapping is an index for each use site of a generic parameter in the concrete type
1333
+ //
1334
+ // The indices index into the generic parameters on the existential type.
1335
+ found : Option < ( Span , ty:: Ty < ' tcx > , Vec < usize > ) > ,
1329
1336
}
1330
1337
1331
1338
impl < ' a , ' tcx > ConstraintLocator < ' a , ' tcx > {
@@ -1340,13 +1347,50 @@ fn find_existential_constraints<'a, 'tcx>(
1340
1347
. tcx
1341
1348
. typeck_tables_of ( def_id)
1342
1349
. concrete_existential_types
1343
- . get ( & self . def_id )
1344
- . cloned ( ) ;
1345
- if let Some ( ty) = ty {
1350
+ . get ( & self . def_id ) ;
1351
+ if let Some ( ty:: ResolvedOpaqueTy { concrete_type, substs } ) = ty {
1346
1352
// FIXME(oli-obk): trace the actual span from inference to improve errors
1347
1353
let span = self . tcx . def_span ( def_id) ;
1348
- if let Some ( ( prev_span, prev_ty) ) = self . found {
1349
- let mut ty = ty. walk ( ) . fuse ( ) ;
1354
+ // used to quickly look up the position of a generic parameter
1355
+ let mut index_map: FxHashMap < ty:: ParamTy , usize > = FxHashMap :: default ( ) ;
1356
+ // skip binder is ok, since we only use this to find generic parameters and their
1357
+ // positions.
1358
+ for subst in substs. iter ( ) {
1359
+ if let UnpackedKind :: Type ( ty) = subst. unpack ( ) {
1360
+ if let ty:: Param ( p) = ty. sty {
1361
+ let idx = index_map. len ( ) ;
1362
+ if index_map. insert ( p, idx) . is_some ( ) {
1363
+ // there was already an entry for `p`, meaning a generic parameter
1364
+ // was used twice
1365
+ self . tcx . sess . span_err (
1366
+ span,
1367
+ & format ! ( "defining existential type use restricts existential \
1368
+ type by using the generic parameter `{}` twice", p. name) ,
1369
+ ) ;
1370
+ return ;
1371
+ }
1372
+ } else {
1373
+ self . tcx . sess . delay_span_bug (
1374
+ span,
1375
+ & format ! (
1376
+ "non-defining exist ty use in defining scope: {:?}, {:?}" ,
1377
+ concrete_type, substs,
1378
+ ) ,
1379
+ ) ;
1380
+ }
1381
+ }
1382
+ }
1383
+ // compute the index within the existential type for each generic parameter used in
1384
+ // the concrete type
1385
+ let indices = concrete_type
1386
+ . subst ( self . tcx , substs)
1387
+ . walk ( )
1388
+ . filter_map ( |t| match & t. sty {
1389
+ ty:: Param ( p) => Some ( * index_map. get ( p) . unwrap ( ) ) ,
1390
+ _ => None ,
1391
+ } ) . collect ( ) ;
1392
+ if let Some ( ( prev_span, prev_ty, ref prev_indices) ) = self . found {
1393
+ let mut ty = concrete_type. walk ( ) . fuse ( ) ;
1350
1394
let mut prev_ty = prev_ty. walk ( ) . fuse ( ) ;
1351
1395
let iter_eq = ( & mut ty) . zip ( & mut prev_ty) . all ( |( t, p) | match ( & t. sty , & p. sty ) {
1352
1396
// type parameters are equal to any other type parameter for the purpose of
@@ -1359,13 +1403,21 @@ fn find_existential_constraints<'a, 'tcx>(
1359
1403
// found different concrete types for the existential type
1360
1404
let mut err = self . tcx . sess . struct_span_err (
1361
1405
span,
1362
- "defining existential type use differs from previous" ,
1406
+ "concrete type differs from previous defining existential type use" ,
1407
+ ) ;
1408
+ err. span_note ( prev_span, "previous use here" ) ;
1409
+ err. emit ( ) ;
1410
+ } else if indices != * prev_indices {
1411
+ // found "same" concrete types, but the generic parameter order differs
1412
+ let mut err = self . tcx . sess . struct_span_err (
1413
+ span,
1414
+ "concrete type's generic parameters differ from previous defining use" ,
1363
1415
) ;
1364
1416
err. span_note ( prev_span, "previous use here" ) ;
1365
1417
err. emit ( ) ;
1366
1418
}
1367
1419
} else {
1368
- self . found = Some ( ( span, ty ) ) ;
1420
+ self . found = Some ( ( span, concrete_type , indices ) ) ;
1369
1421
}
1370
1422
}
1371
1423
}
@@ -1424,7 +1476,7 @@ fn find_existential_constraints<'a, 'tcx>(
1424
1476
}
1425
1477
1426
1478
match locator. found {
1427
- Some ( ( _, ty) ) => ty,
1479
+ Some ( ( _, ty, _ ) ) => ty,
1428
1480
None => {
1429
1481
let span = tcx. def_span ( def_id) ;
1430
1482
tcx. sess . span_err ( span, "could not find defining uses" ) ;
0 commit comments