6
6
7
7
use crate :: mir:: interpret:: { get_slice_bytes, ConstValue , GlobalAlloc , Scalar } ;
8
8
use crate :: ty:: error:: { ExpectedFound , TypeError } ;
9
- use crate :: ty:: subst:: { GenericArg , GenericArgKind , SubstsRef } ;
9
+ use crate :: ty:: subst:: { GenericArg , GenericArgKind , Subst , SubstsRef } ;
10
10
use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
11
11
use rustc_hir as ast;
12
12
use rustc_hir:: def_id:: DefId ;
@@ -59,8 +59,9 @@ pub trait TypeRelation<'tcx>: Sized {
59
59
item_def_id, a_subst, b_subst
60
60
) ;
61
61
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)
64
65
}
65
66
66
67
/// Switch variance for the purpose of relating `a` and `b`.
@@ -116,7 +117,7 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
116
117
relation : & mut R ,
117
118
a : ty:: TypeAndMut < ' tcx > ,
118
119
b : ty:: TypeAndMut < ' tcx > ,
119
- kind : ty :: VarianceDiagMutKind ,
120
+ base_ty : Ty < ' tcx > ,
120
121
) -> RelateResult < ' tcx , ty:: TypeAndMut < ' tcx > > {
121
122
debug ! ( "{}.mts({:?}, {:?})" , relation. tag( ) , a, b) ;
122
123
if a. mutbl != b. mutbl {
@@ -125,7 +126,9 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
125
126
let mutbl = a. mutbl ;
126
127
let ( variance, info) = match mutbl {
127
128
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
+ }
129
132
} ;
130
133
let ty = relation. relate_with_variance ( variance, info, a. ty , b. ty ) ?;
131
134
Ok ( ty:: TypeAndMut { ty, mutbl } )
@@ -134,15 +137,29 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
134
137
135
138
pub fn relate_substs < ' tcx , R : TypeRelation < ' tcx > > (
136
139
relation : & mut R ,
137
- variances : Option < & [ ty:: Variance ] > ,
140
+ variances : Option < ( DefId , & [ ty:: Variance ] ) > ,
138
141
a_subst : SubstsRef < ' tcx > ,
139
142
b_subst : SubstsRef < ' tcx > ,
140
143
) -> RelateResult < ' tcx , SubstsRef < ' tcx > > {
141
144
let tcx = relation. tcx ( ) ;
145
+ let mut cached_ty = None ;
142
146
143
147
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)
146
163
} ) ;
147
164
148
165
tcx. mk_substs ( params)
@@ -436,7 +453,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
436
453
}
437
454
438
455
( & 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 ) ?;
440
457
Ok ( tcx. mk_ptr ( mt) )
441
458
}
442
459
@@ -449,7 +466,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
449
466
) ?;
450
467
let a_mt = ty:: TypeAndMut { ty : a_ty, mutbl : a_mutbl } ;
451
468
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 ) ?;
453
470
Ok ( tcx. mk_ref ( r, mt) )
454
471
}
455
472
0 commit comments