1
- use rustc_data_structures:: fx:: FxHashMap ;
1
+ use rustc_data_structures:: fx:: FxHashSet ;
2
2
use rustc_errors:: { struct_span_err, Applicability , StashKey } ;
3
3
use rustc_hir as hir;
4
4
use rustc_hir:: def:: { DefKind , Res } ;
@@ -7,7 +7,7 @@ use rustc_hir::intravisit;
7
7
use rustc_hir:: intravisit:: Visitor ;
8
8
use rustc_hir:: Node ;
9
9
use rustc_middle:: hir:: map:: Map ;
10
- use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts , Subst } ;
10
+ use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts } ;
11
11
use rustc_middle:: ty:: util:: IntTypeExt ;
12
12
use rustc_middle:: ty:: { self , DefIdTree , Ty , TyCtxt , TypeFoldable } ;
13
13
use rustc_session:: parse:: feature_err;
@@ -369,13 +369,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
369
369
struct ConstraintLocator < ' tcx > {
370
370
tcx : TyCtxt < ' tcx > ,
371
371
def_id : DefId ,
372
- // (first found type span, actual type, mapping from the opaque type's generic
373
- // parameters to the concrete type's generic parameters)
374
- //
375
- // The mapping is an index for each use site of a generic parameter in the concrete type
376
- //
377
- // The indices index into the generic parameters on the opaque type.
378
- found : Option < ( Span , Ty < ' tcx > , Vec < usize > ) > ,
372
+ // (first found type span, actual type)
373
+ found : Option < ( Span , Ty < ' tcx > ) > ,
379
374
}
380
375
381
376
impl ConstraintLocator < ' _ > {
@@ -407,14 +402,15 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
407
402
408
403
// FIXME(oli-obk): trace the actual span from inference to improve errors.
409
404
let span = self . tcx . def_span ( def_id) ;
410
- // used to quickly look up the position of a generic parameter
411
- let mut index_map: FxHashMap < ty:: ParamTy , usize > = FxHashMap :: default ( ) ;
412
- // Skipping binder is ok, since we only use this to find generic parameters and
413
- // their positions.
414
- for ( idx, subst) in substs. iter ( ) . enumerate ( ) {
415
- if let GenericArgKind :: Type ( ty) = subst. unpack ( ) {
405
+
406
+ let opaque_generics = self . tcx . generics_of ( self . def_id ) ;
407
+ let mut used_params: FxHashSet < ty:: ParamTy > = FxHashSet :: default ( ) ;
408
+ let mut has_errors = false ;
409
+ for ( i, arg) in substs. iter ( ) . enumerate ( ) {
410
+ // FIXME(eddyb) enforce lifetime and const param 1:1 mapping.
411
+ if let GenericArgKind :: Type ( ty) = arg. unpack ( ) {
416
412
if let ty:: Param ( p) = ty. kind {
417
- if index_map . insert ( p, idx ) . is_some ( ) {
413
+ if !used_params . insert ( p) {
418
414
// There was already an entry for `p`, meaning a generic parameter
419
415
// was used twice.
420
416
self . tcx . sess . span_err (
@@ -428,62 +424,28 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
428
424
return ;
429
425
}
430
426
} else {
431
- self . tcx . sess . delay_span_bug (
427
+ let param = opaque_generics. param_at ( i, self . tcx ) ;
428
+ self . tcx . sess . span_err (
432
429
span,
433
430
& format ! (
434
- "non-defining opaque ty use in defining scope: {:?}, {:?}" ,
435
- concrete_type, substs,
431
+ "defining opaque type use does not fully define opaque type: \
432
+ generic parameter `{}` is specified as concrete {} `{}`",
433
+ param. name,
434
+ param. kind. descr( ) ,
435
+ arg,
436
436
) ,
437
437
) ;
438
+ has_errors = true ;
438
439
}
439
440
}
440
441
}
441
- // Compute the index within the opaque type for each generic parameter used in
442
- // the concrete type.
443
- let indices = concrete_type
444
- . subst ( self . tcx , substs)
445
- . walk ( )
446
- . filter_map ( |t| match & t. kind {
447
- ty:: Param ( p) => Some ( * index_map. get ( p) . unwrap ( ) ) ,
448
- _ => None ,
449
- } )
450
- . collect ( ) ;
451
- let is_param = |ty : Ty < ' _ > | match ty. kind {
452
- ty:: Param ( _) => true ,
453
- _ => false ,
454
- } ;
455
- let bad_substs: Vec < _ > = substs
456
- . iter ( )
457
- . enumerate ( )
458
- . filter_map ( |( i, k) | {
459
- if let GenericArgKind :: Type ( ty) = k. unpack ( ) { Some ( ( i, ty) ) } else { None }
460
- } )
461
- . filter ( |( _, ty) | !is_param ( ty) )
462
- . collect ( ) ;
463
- if !bad_substs. is_empty ( ) {
464
- let identity_substs = InternalSubsts :: identity_for_item ( self . tcx , self . def_id ) ;
465
- for ( i, bad_subst) in bad_substs {
466
- self . tcx . sess . span_err (
467
- span,
468
- & format ! (
469
- "defining opaque type use does not fully define opaque type: \
470
- generic parameter `{}` is specified as concrete type `{}`",
471
- identity_substs. type_at( i) ,
472
- bad_subst
473
- ) ,
474
- ) ;
475
- }
476
- } else if let Some ( ( prev_span, prev_ty, ref prev_indices) ) = self . found {
477
- let mut ty = concrete_type. walk ( ) . fuse ( ) ;
478
- let mut p_ty = prev_ty. walk ( ) . fuse ( ) ;
479
- let iter_eq = ( & mut ty) . zip ( & mut p_ty) . all ( |( t, p) | match ( & t. kind , & p. kind ) {
480
- // Type parameters are equal to any other type parameter for the purpose of
481
- // concrete type equality, as it is possible to obtain the same type just
482
- // by passing matching parameters to a function.
483
- ( ty:: Param ( _) , ty:: Param ( _) ) => true ,
484
- _ => t == p,
485
- } ) ;
486
- if !iter_eq || ty. next ( ) . is_some ( ) || p_ty. next ( ) . is_some ( ) {
442
+
443
+ if has_errors {
444
+ return ;
445
+ }
446
+
447
+ if let Some ( ( prev_span, prev_ty) ) = self . found {
448
+ if * concrete_type != prev_ty {
487
449
debug ! ( "find_opaque_ty_constraints: span={:?}" , span) ;
488
450
// Found different concrete types for the opaque type.
489
451
let mut err = self . tcx . sess . struct_span_err (
@@ -496,34 +458,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
496
458
) ;
497
459
err. span_note ( prev_span, "previous use here" ) ;
498
460
err. emit ( ) ;
499
- } else if indices != * prev_indices {
500
- // Found "same" concrete types, but the generic parameter order differs.
501
- let mut err = self . tcx . sess . struct_span_err (
502
- span,
503
- "concrete type's generic parameters differ from previous defining use" ,
504
- ) ;
505
- use std:: fmt:: Write ;
506
- let mut s = String :: new ( ) ;
507
- write ! ( s, "expected [" ) . unwrap ( ) ;
508
- let list = |s : & mut String , indices : & Vec < usize > | {
509
- let mut indices = indices. iter ( ) . cloned ( ) ;
510
- if let Some ( first) = indices. next ( ) {
511
- write ! ( s, "`{}`" , substs[ first] ) . unwrap ( ) ;
512
- for i in indices {
513
- write ! ( s, ", `{}`" , substs[ i] ) . unwrap ( ) ;
514
- }
515
- }
516
- } ;
517
- list ( & mut s, prev_indices) ;
518
- write ! ( s, "], got [" ) . unwrap ( ) ;
519
- list ( & mut s, & indices) ;
520
- write ! ( s, "]" ) . unwrap ( ) ;
521
- err. span_label ( span, s) ;
522
- err. span_note ( prev_span, "previous use here" ) ;
523
- err. emit ( ) ;
524
461
}
525
462
} else {
526
- self . found = Some ( ( span, concrete_type, indices ) ) ;
463
+ self . found = Some ( ( span, concrete_type) ) ;
527
464
}
528
465
} else {
529
466
debug ! (
@@ -606,7 +543,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
606
543
}
607
544
608
545
match locator. found {
609
- Some ( ( _, ty, _ ) ) => ty,
546
+ Some ( ( _, ty) ) => ty,
610
547
None => {
611
548
let span = tcx. def_span ( def_id) ;
612
549
tcx. sess . span_err ( span, "could not find defining uses" ) ;
0 commit comments