1- use rustc_data_structures:: fx:: FxHashMap ;
1+ use rustc_data_structures:: fx:: FxHashSet ;
22use rustc_errors:: { struct_span_err, Applicability , StashKey } ;
33use rustc_hir as hir;
44use rustc_hir:: def:: { DefKind , Res } ;
@@ -7,7 +7,7 @@ use rustc_hir::intravisit;
77use rustc_hir:: intravisit:: Visitor ;
88use rustc_hir:: Node ;
99use rustc_middle:: hir:: map:: Map ;
10- use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts , Subst } ;
10+ use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts } ;
1111use rustc_middle:: ty:: util:: IntTypeExt ;
1212use rustc_middle:: ty:: { self , DefIdTree , Ty , TyCtxt , TypeFoldable } ;
1313use rustc_session:: parse:: feature_err;
@@ -369,13 +369,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
369369 struct ConstraintLocator < ' tcx > {
370370 tcx : TyCtxt < ' tcx > ,
371371 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 > ) > ,
379374 }
380375
381376 impl ConstraintLocator < ' _ > {
@@ -407,14 +402,15 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
407402
408403 // FIXME(oli-obk): trace the actual span from inference to improve errors.
409404 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 ( ) {
416412 if let ty:: Param ( p) = ty. kind {
417- if index_map . insert ( p, idx ) . is_some ( ) {
413+ if !used_params . insert ( p) {
418414 // There was already an entry for `p`, meaning a generic parameter
419415 // was used twice.
420416 self . tcx . sess . span_err (
@@ -428,62 +424,28 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
428424 return ;
429425 }
430426 } else {
431- self . tcx . sess . delay_span_bug (
427+ let param = opaque_generics. param_at ( i, self . tcx ) ;
428+ self . tcx . sess . span_err (
432429 span,
433430 & 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,
436436 ) ,
437437 ) ;
438+ has_errors = true ;
438439 }
439440 }
440441 }
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 {
487449 debug ! ( "find_opaque_ty_constraints: span={:?}" , span) ;
488450 // Found different concrete types for the opaque type.
489451 let mut err = self . tcx . sess . struct_span_err (
@@ -496,34 +458,9 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
496458 ) ;
497459 err. span_note ( prev_span, "previous use here" ) ;
498460 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 ( ) ;
524461 }
525462 } else {
526- self . found = Some ( ( span, concrete_type, indices ) ) ;
463+ self . found = Some ( ( span, concrete_type) ) ;
527464 }
528465 } else {
529466 debug ! (
@@ -606,7 +543,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
606543 }
607544
608545 match locator. found {
609- Some ( ( _, ty, _ ) ) => ty,
546+ Some ( ( _, ty) ) => ty,
610547 None => {
611548 let span = tcx. def_span ( def_id) ;
612549 tcx. sess . span_err ( span, "could not find defining uses" ) ;
0 commit comments