66
77use crate :: mir:: interpret:: { get_slice_bytes, ConstValue , GlobalAlloc , Scalar } ;
88use crate :: ty:: error:: { ExpectedFound , TypeError } ;
9- use crate :: ty:: subst:: { GenericArg , GenericArgKind , SubstsRef } ;
9+ use crate :: ty:: subst:: { GenericArg , GenericArgKind , Subst , SubstsRef } ;
1010use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
1111use rustc_hir as ast;
1212use rustc_hir:: def_id:: DefId ;
@@ -59,8 +59,9 @@ pub trait TypeRelation<'tcx>: Sized {
5959 item_def_id, a_subst, b_subst
6060 ) ;
6161
62- let opt_variances = self . tcx ( ) . variances_of ( item_def_id) ;
63- relate_substs ( self , Some ( opt_variances) , a_subst, b_subst)
62+ let tcx = self . tcx ( ) ;
63+ let opt_variances = tcx. variances_of ( item_def_id) ;
64+ relate_substs ( self , Some ( ( item_def_id, opt_variances) ) , a_subst, b_subst)
6465 }
6566
6667 /// Switch variance for the purpose of relating `a` and `b`.
@@ -116,7 +117,7 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
116117 relation : & mut R ,
117118 a : ty:: TypeAndMut < ' tcx > ,
118119 b : ty:: TypeAndMut < ' tcx > ,
119- kind : ty :: VarianceDiagMutKind ,
120+ base_ty : Ty < ' tcx > ,
120121) -> RelateResult < ' tcx , ty:: TypeAndMut < ' tcx > > {
121122 debug ! ( "{}.mts({:?}, {:?})" , relation. tag( ) , a, b) ;
122123 if a. mutbl != b. mutbl {
@@ -125,7 +126,9 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
125126 let mutbl = a. mutbl ;
126127 let ( variance, info) = match mutbl {
127128 ast:: Mutability :: Not => ( ty:: Covariant , ty:: VarianceDiagInfo :: None ) ,
128- ast:: Mutability :: Mut => ( ty:: Invariant , ty:: VarianceDiagInfo :: Mut { kind, ty : a. ty } ) ,
129+ ast:: Mutability :: Mut => {
130+ ( ty:: Invariant , ty:: VarianceDiagInfo :: Invariant { ty : base_ty, param_index : 0 } )
131+ }
129132 } ;
130133 let ty = relation. relate_with_variance ( variance, info, a. ty , b. ty ) ?;
131134 Ok ( ty:: TypeAndMut { ty, mutbl } )
@@ -134,15 +137,29 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
134137
135138pub fn relate_substs < ' tcx , R : TypeRelation < ' tcx > > (
136139 relation : & mut R ,
137- variances : Option < & [ ty:: Variance ] > ,
140+ variances : Option < ( DefId , & [ ty:: Variance ] ) > ,
138141 a_subst : SubstsRef < ' tcx > ,
139142 b_subst : SubstsRef < ' tcx > ,
140143) -> RelateResult < ' tcx , SubstsRef < ' tcx > > {
141144 let tcx = relation. tcx ( ) ;
145+ let mut cached_ty = None ;
142146
143147 let params = iter:: zip ( a_subst, b_subst) . enumerate ( ) . map ( |( i, ( a, b) ) | {
144- let variance = variances. map_or ( ty:: Invariant , |v| v[ i] ) ;
145- relation. relate_with_variance ( variance, ty:: VarianceDiagInfo :: default ( ) , a, b)
148+ let ( variance, variance_info) = match variances {
149+ Some ( ( ty_def_id, variances) ) => {
150+ let variance = variances[ i] ;
151+ let variance_info = if variance == ty:: Invariant {
152+ let ty =
153+ cached_ty. get_or_insert_with ( || tcx. type_of ( ty_def_id) . subst ( tcx, a_subst) ) ;
154+ ty:: VarianceDiagInfo :: Invariant { ty, param_index : i. try_into ( ) . unwrap ( ) }
155+ } else {
156+ ty:: VarianceDiagInfo :: default ( )
157+ } ;
158+ ( variance, variance_info)
159+ }
160+ None => ( ty:: Invariant , ty:: VarianceDiagInfo :: default ( ) ) ,
161+ } ;
162+ relation. relate_with_variance ( variance, variance_info, a, b)
146163 } ) ;
147164
148165 tcx. mk_substs ( params)
@@ -436,7 +453,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
436453 }
437454
438455 ( & ty:: RawPtr ( a_mt) , & ty:: RawPtr ( b_mt) ) => {
439- let mt = relate_type_and_mut ( relation, a_mt, b_mt, ty :: VarianceDiagMutKind :: RawPtr ) ?;
456+ let mt = relate_type_and_mut ( relation, a_mt, b_mt, a ) ?;
440457 Ok ( tcx. mk_ptr ( mt) )
441458 }
442459
@@ -449,7 +466,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
449466 ) ?;
450467 let a_mt = ty:: TypeAndMut { ty : a_ty, mutbl : a_mutbl } ;
451468 let b_mt = ty:: TypeAndMut { ty : b_ty, mutbl : b_mutbl } ;
452- let mt = relate_type_and_mut ( relation, a_mt, b_mt, ty :: VarianceDiagMutKind :: Ref ) ?;
469+ let mt = relate_type_and_mut ( relation, a_mt, b_mt, a ) ?;
453470 Ok ( tcx. mk_ref ( r, mt) )
454471 }
455472
0 commit comments