1
+ use rustc_data_structures:: fx:: FxHashMap ;
1
2
use rustc_errors:: ErrorGuaranteed ;
2
- use rustc_infer:: infer:: nll_relate :: { NllTypeRelating , NllTypeRelatingDelegate } ;
3
- use rustc_infer:: infer:: NllRegionVariableOrigin ;
4
- use rustc_infer:: traits:: PredicateObligations ;
3
+ use rustc_infer:: infer:: type_variable :: { TypeVariableOrigin , TypeVariableOriginKind } ;
4
+ use rustc_infer:: infer:: { NllRegionVariableOrigin , ObligationEmittingRelation } ;
5
+ use rustc_infer:: traits:: { Obligation , PredicateObligations } ;
5
6
use rustc_middle:: mir:: ConstraintCategory ;
6
7
use rustc_middle:: traits:: query:: NoSolution ;
7
- use rustc_middle:: ty:: relate:: TypeRelation ;
8
- use rustc_middle:: ty:: { self , Ty } ;
8
+ use rustc_middle:: traits:: ObligationCause ;
9
+ use rustc_middle:: ty:: fold:: FnMutDelegate ;
10
+ use rustc_middle:: ty:: relate:: { Relate , RelateResult , TypeRelation } ;
11
+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitableExt } ;
9
12
use rustc_span:: symbol:: sym;
10
13
use rustc_span:: { Span , Symbol } ;
11
14
@@ -32,12 +35,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
32
35
locations : Locations ,
33
36
category : ConstraintCategory < ' tcx > ,
34
37
) -> Result < ( ) , NoSolution > {
35
- NllTypeRelating :: new (
36
- self . infcx ,
37
- NllTypeRelatingDelegate :: new ( self , locations, category, UniverseInfo :: relate ( a, b) ) ,
38
- v,
39
- )
40
- . relate ( a, b) ?;
38
+ NllTypeRelating :: new ( self , locations, category, UniverseInfo :: relate ( a, b) , v)
39
+ . relate ( a, b) ?;
41
40
Ok ( ( ) )
42
41
}
43
42
@@ -50,16 +49,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
50
49
category : ConstraintCategory < ' tcx > ,
51
50
) -> Result < ( ) , NoSolution > {
52
51
NllTypeRelating :: new (
53
- self . infcx ,
54
- NllTypeRelatingDelegate :: new ( self , locations, category, UniverseInfo :: other ( ) ) ,
52
+ self ,
53
+ locations,
54
+ category,
55
+ UniverseInfo :: other ( ) ,
55
56
ty:: Variance :: Invariant ,
56
57
)
57
58
. relate ( a, b) ?;
58
59
Ok ( ( ) )
59
60
}
60
61
}
61
62
62
- struct NllTypeRelatingDelegate < ' me , ' bccx , ' tcx > {
63
+ pub struct NllTypeRelating < ' me , ' bccx , ' tcx > {
63
64
type_checker : & ' me mut TypeChecker < ' bccx , ' tcx > ,
64
65
65
66
/// Where (and why) is this relation taking place?
@@ -71,26 +72,177 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
71
72
/// Information so that error reporting knows what types we are relating
72
73
/// when reporting a bound region error.
73
74
universe_info : UniverseInfo < ' tcx > ,
75
+
76
+ /// How are we relating `a` and `b`?
77
+ ///
78
+ /// - Covariant means `a <: b`.
79
+ /// - Contravariant means `b <: a`.
80
+ /// - Invariant means `a == b`.
81
+ /// - Bivariant means that it doesn't matter.
82
+ ambient_variance : ty:: Variance ,
83
+
84
+ ambient_variance_info : ty:: VarianceDiagInfo < ' tcx > ,
74
85
}
75
86
76
- impl < ' me , ' bccx , ' tcx > NllTypeRelatingDelegate < ' me , ' bccx , ' tcx > {
77
- fn new (
87
+ impl < ' me , ' bccx , ' tcx > NllTypeRelating < ' me , ' bccx , ' tcx > {
88
+ pub fn new (
78
89
type_checker : & ' me mut TypeChecker < ' bccx , ' tcx > ,
79
90
locations : Locations ,
80
91
category : ConstraintCategory < ' tcx > ,
81
92
universe_info : UniverseInfo < ' tcx > ,
93
+ ambient_variance : ty:: Variance ,
82
94
) -> Self {
83
- Self { type_checker, locations, category, universe_info }
95
+ Self {
96
+ type_checker,
97
+ locations,
98
+ category,
99
+ universe_info,
100
+ ambient_variance,
101
+ ambient_variance_info : ty:: VarianceDiagInfo :: default ( ) ,
102
+ }
84
103
}
85
- }
86
104
87
- impl < ' tcx > NllTypeRelatingDelegate < ' tcx > for NllTypeRelatingDelegate < ' _ , ' _ , ' tcx > {
88
- fn span ( & self ) -> Span {
89
- self . locations . span ( self . type_checker . body )
105
+ fn ambient_covariance ( & self ) -> bool {
106
+ match self . ambient_variance {
107
+ ty:: Variance :: Covariant | ty:: Variance :: Invariant => true ,
108
+ ty:: Variance :: Contravariant | ty:: Variance :: Bivariant => false ,
109
+ }
90
110
}
91
111
92
- fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > {
93
- self . type_checker . param_env
112
+ fn ambient_contravariance ( & self ) -> bool {
113
+ match self . ambient_variance {
114
+ ty:: Variance :: Contravariant | ty:: Variance :: Invariant => true ,
115
+ ty:: Variance :: Covariant | ty:: Variance :: Bivariant => false ,
116
+ }
117
+ }
118
+
119
+ fn relate_opaques ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> RelateResult < ' tcx , ( ) > {
120
+ let infcx = self . type_checker . infcx ;
121
+ debug_assert ! ( !infcx. next_trait_solver( ) ) ;
122
+ let ( a, b) = if self . a_is_expected ( ) { ( a, b) } else { ( b, a) } ;
123
+ // `handle_opaque_type` cannot handle subtyping, so to support subtyping
124
+ // we instead eagerly generalize here. This is a bit of a mess but will go
125
+ // away once we're using the new solver.
126
+ let mut enable_subtyping = |ty, ty_is_expected| {
127
+ let ty_vid = infcx. next_ty_var_id_in_universe (
128
+ TypeVariableOrigin {
129
+ kind : TypeVariableOriginKind :: MiscVariable ,
130
+ span : self . span ( ) ,
131
+ } ,
132
+ ty:: UniverseIndex :: ROOT ,
133
+ ) ;
134
+
135
+ let variance = if ty_is_expected {
136
+ self . ambient_variance
137
+ } else {
138
+ self . ambient_variance . xform ( ty:: Contravariant )
139
+ } ;
140
+
141
+ self . type_checker . infcx . instantiate_ty_var (
142
+ self ,
143
+ ty_is_expected,
144
+ ty_vid,
145
+ variance,
146
+ ty,
147
+ ) ?;
148
+ Ok ( infcx. resolve_vars_if_possible ( Ty :: new_infer ( infcx. tcx , ty:: TyVar ( ty_vid) ) ) )
149
+ } ;
150
+
151
+ let ( a, b) = match ( a. kind ( ) , b. kind ( ) ) {
152
+ ( & ty:: Alias ( ty:: Opaque , ..) , _) => ( a, enable_subtyping ( b, false ) ?) ,
153
+ ( _, & ty:: Alias ( ty:: Opaque , ..) ) => ( enable_subtyping ( a, true ) ?, b) ,
154
+ _ => unreachable ! (
155
+ "expected at least one opaque type in `relate_opaques`, got {a} and {b}."
156
+ ) ,
157
+ } ;
158
+ let cause = ObligationCause :: dummy_with_span ( self . span ( ) ) ;
159
+ let obligations =
160
+ infcx. handle_opaque_type ( a, b, true , & cause, self . param_env ( ) ) ?. obligations ;
161
+ self . register_obligations ( obligations) ;
162
+ Ok ( ( ) )
163
+ }
164
+
165
+ fn enter_forall < T , U > (
166
+ & mut self ,
167
+ binder : ty:: Binder < ' tcx , T > ,
168
+ f : impl FnOnce ( & mut Self , T ) -> U ,
169
+ ) -> U
170
+ where
171
+ T : ty:: TypeFoldable < TyCtxt < ' tcx > > + Copy ,
172
+ {
173
+ let value = if let Some ( inner) = binder. no_bound_vars ( ) {
174
+ inner
175
+ } else {
176
+ let infcx = self . type_checker . infcx ;
177
+ let mut lazy_universe = None ;
178
+ let delegate = FnMutDelegate {
179
+ regions : & mut |br : ty:: BoundRegion | {
180
+ // The first time this closure is called, create a
181
+ // new universe for the placeholders we will make
182
+ // from here out.
183
+ let universe = lazy_universe. unwrap_or_else ( || {
184
+ let universe = self . create_next_universe ( ) ;
185
+ lazy_universe = Some ( universe) ;
186
+ universe
187
+ } ) ;
188
+
189
+ let placeholder = ty:: PlaceholderRegion { universe, bound : br } ;
190
+ debug ! ( ?placeholder) ;
191
+ let placeholder_reg = self . next_placeholder_region ( placeholder) ;
192
+ debug ! ( ?placeholder_reg) ;
193
+
194
+ placeholder_reg
195
+ } ,
196
+ types : & mut |_bound_ty : ty:: BoundTy | {
197
+ unreachable ! ( "we only replace regions in nll_relate, not types" )
198
+ } ,
199
+ consts : & mut |_bound_var : ty:: BoundVar , _ty| {
200
+ unreachable ! ( "we only replace regions in nll_relate, not consts" )
201
+ } ,
202
+ } ;
203
+
204
+ infcx. tcx . replace_bound_vars_uncached ( binder, delegate)
205
+ } ;
206
+
207
+ debug ! ( ?value) ;
208
+ f ( self , value)
209
+ }
210
+
211
+ #[ instrument( skip( self ) , level = "debug" ) ]
212
+ fn instantiate_binder_with_existentials < T > ( & mut self , binder : ty:: Binder < ' tcx , T > ) -> T
213
+ where
214
+ T : ty:: TypeFoldable < TyCtxt < ' tcx > > + Copy ,
215
+ {
216
+ if let Some ( inner) = binder. no_bound_vars ( ) {
217
+ return inner;
218
+ }
219
+
220
+ let infcx = self . type_checker . infcx ;
221
+ let mut reg_map = FxHashMap :: default ( ) ;
222
+ let delegate = FnMutDelegate {
223
+ regions : & mut |br : ty:: BoundRegion | {
224
+ if let Some ( ex_reg_var) = reg_map. get ( & br) {
225
+ return * ex_reg_var;
226
+ } else {
227
+ let ex_reg_var = self . next_existential_region_var ( true , br. kind . get_name ( ) ) ;
228
+ debug ! ( ?ex_reg_var) ;
229
+ reg_map. insert ( br, ex_reg_var) ;
230
+
231
+ ex_reg_var
232
+ }
233
+ } ,
234
+ types : & mut |_bound_ty : ty:: BoundTy | {
235
+ unreachable ! ( "we only replace regions in nll_relate, not types" )
236
+ } ,
237
+ consts : & mut |_bound_var : ty:: BoundVar , _ty| {
238
+ unreachable ! ( "we only replace regions in nll_relate, not consts" )
239
+ } ,
240
+ } ;
241
+
242
+ let replaced = infcx. tcx . replace_bound_vars_uncached ( binder, delegate) ;
243
+ debug ! ( ?replaced) ;
244
+
245
+ replaced
94
246
}
95
247
96
248
fn create_next_universe ( & mut self ) -> ty:: UniverseIndex {
@@ -163,6 +315,249 @@ impl<'tcx> NllTypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tc
163
315
} ,
164
316
) ;
165
317
}
318
+ }
319
+
320
+ impl < ' bccx , ' tcx > TypeRelation < ' tcx > for NllTypeRelating < ' _ , ' bccx , ' tcx > {
321
+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
322
+ self . type_checker . infcx . tcx
323
+ }
324
+
325
+ fn tag ( & self ) -> & ' static str {
326
+ "nll::subtype"
327
+ }
328
+
329
+ fn a_is_expected ( & self ) -> bool {
330
+ true
331
+ }
332
+
333
+ #[ instrument( skip( self , info) , level = "trace" , ret) ]
334
+ fn relate_with_variance < T : Relate < ' tcx > > (
335
+ & mut self ,
336
+ variance : ty:: Variance ,
337
+ info : ty:: VarianceDiagInfo < ' tcx > ,
338
+ a : T ,
339
+ b : T ,
340
+ ) -> RelateResult < ' tcx , T > {
341
+ let old_ambient_variance = self . ambient_variance ;
342
+ self . ambient_variance = self . ambient_variance . xform ( variance) ;
343
+ self . ambient_variance_info = self . ambient_variance_info . xform ( info) ;
344
+
345
+ debug ! ( ?self . ambient_variance) ;
346
+ // In a bivariant context this always succeeds.
347
+ let r =
348
+ if self . ambient_variance == ty:: Variance :: Bivariant { a } else { self . relate ( a, b) ? } ;
349
+
350
+ self . ambient_variance = old_ambient_variance;
351
+
352
+ Ok ( r)
353
+ }
354
+
355
+ #[ instrument( skip( self ) , level = "debug" ) ]
356
+ fn tys ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
357
+ let infcx = self . type_checker . infcx ;
358
+
359
+ let a = self . type_checker . infcx . shallow_resolve ( a) ;
360
+ assert ! ( !b. has_non_region_infer( ) , "unexpected inference var {:?}" , b) ;
361
+
362
+ if a == b {
363
+ return Ok ( a) ;
364
+ }
365
+
366
+ match ( a. kind ( ) , b. kind ( ) ) {
367
+ ( _, & ty:: Infer ( ty:: TyVar ( _) ) ) => {
368
+ span_bug ! (
369
+ self . span( ) ,
370
+ "should not be relating type variables on the right in MIR typeck"
371
+ ) ;
372
+ }
373
+
374
+ ( & ty:: Infer ( ty:: TyVar ( a_vid) ) , _) => {
375
+ infcx. instantiate_ty_var ( self , true , a_vid, self . ambient_variance , b) ?
376
+ }
377
+
378
+ (
379
+ & ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id : a_def_id, .. } ) ,
380
+ & ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id : b_def_id, .. } ) ,
381
+ ) if a_def_id == b_def_id || infcx. next_trait_solver ( ) => {
382
+ infcx. super_combine_tys ( self , a, b) . map ( |_| ( ) ) . or_else ( |err| {
383
+ // This behavior is only there for the old solver, the new solver
384
+ // shouldn't ever fail. Instead, it unconditionally emits an
385
+ // alias-relate goal.
386
+ assert ! ( !self . type_checker. infcx. next_trait_solver( ) ) ;
387
+ self . tcx ( ) . dcx ( ) . span_delayed_bug (
388
+ self . span ( ) ,
389
+ "failure to relate an opaque to itself should result in an error later on" ,
390
+ ) ;
391
+ if a_def_id. is_local ( ) { self . relate_opaques ( a, b) } else { Err ( err) }
392
+ } ) ?;
393
+ }
394
+ ( & ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) , _)
395
+ | ( _, & ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) )
396
+ if def_id. is_local ( ) && !self . type_checker . infcx . next_trait_solver ( ) =>
397
+ {
398
+ self . relate_opaques ( a, b) ?;
399
+ }
400
+
401
+ _ => {
402
+ debug ! ( ?a, ?b, ?self . ambient_variance) ;
403
+
404
+ // Will also handle unification of `IntVar` and `FloatVar`.
405
+ self . type_checker . infcx . super_combine_tys ( self , a, b) ?;
406
+ }
407
+ }
408
+
409
+ Ok ( a)
410
+ }
411
+
412
+ #[ instrument( skip( self ) , level = "trace" ) ]
413
+ fn regions (
414
+ & mut self ,
415
+ a : ty:: Region < ' tcx > ,
416
+ b : ty:: Region < ' tcx > ,
417
+ ) -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
418
+ debug ! ( ?self . ambient_variance) ;
419
+
420
+ if self . ambient_covariance ( ) {
421
+ // Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`.
422
+ self . push_outlives ( a, b, self . ambient_variance_info ) ;
423
+ }
424
+
425
+ if self . ambient_contravariance ( ) {
426
+ // Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`.
427
+ self . push_outlives ( b, a, self . ambient_variance_info ) ;
428
+ }
429
+
430
+ Ok ( a)
431
+ }
432
+
433
+ fn consts (
434
+ & mut self ,
435
+ a : ty:: Const < ' tcx > ,
436
+ b : ty:: Const < ' tcx > ,
437
+ ) -> RelateResult < ' tcx , ty:: Const < ' tcx > > {
438
+ let a = self . type_checker . infcx . shallow_resolve ( a) ;
439
+ assert ! ( !a. has_non_region_infer( ) , "unexpected inference var {:?}" , a) ;
440
+ assert ! ( !b. has_non_region_infer( ) , "unexpected inference var {:?}" , b) ;
441
+
442
+ self . type_checker . infcx . super_combine_consts ( self , a, b)
443
+ }
444
+
445
+ #[ instrument( skip( self ) , level = "trace" ) ]
446
+ fn binders < T > (
447
+ & mut self ,
448
+ a : ty:: Binder < ' tcx , T > ,
449
+ b : ty:: Binder < ' tcx , T > ,
450
+ ) -> RelateResult < ' tcx , ty:: Binder < ' tcx , T > >
451
+ where
452
+ T : Relate < ' tcx > ,
453
+ {
454
+ // We want that
455
+ //
456
+ // ```
457
+ // for<'a> fn(&'a u32) -> &'a u32 <:
458
+ // fn(&'b u32) -> &'b u32
459
+ // ```
460
+ //
461
+ // but not
462
+ //
463
+ // ```
464
+ // fn(&'a u32) -> &'a u32 <:
465
+ // for<'b> fn(&'b u32) -> &'b u32
466
+ // ```
467
+ //
468
+ // We therefore proceed as follows:
469
+ //
470
+ // - Instantiate binders on `b` universally, yielding a universe U1.
471
+ // - Instantiate binders on `a` existentially in U1.
472
+
473
+ debug ! ( ?self . ambient_variance) ;
474
+
475
+ if let ( Some ( a) , Some ( b) ) = ( a. no_bound_vars ( ) , b. no_bound_vars ( ) ) {
476
+ // Fast path for the common case.
477
+ self . relate ( a, b) ?;
478
+ return Ok ( ty:: Binder :: dummy ( a) ) ;
479
+ }
480
+
481
+ if self . ambient_covariance ( ) {
482
+ // Covariance, so we want `for<..> A <: for<..> B` --
483
+ // therefore we compare any instantiation of A (i.e., A
484
+ // instantiated with existentials) against every
485
+ // instantiation of B (i.e., B instantiated with
486
+ // universals).
487
+
488
+ // Reset the ambient variance to covariant. This is needed
489
+ // to correctly handle cases like
490
+ //
491
+ // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32)
492
+ //
493
+ // Somewhat surprisingly, these two types are actually
494
+ // **equal**, even though the one on the right looks more
495
+ // polymorphic. The reason is due to subtyping. To see it,
496
+ // consider that each function can call the other:
497
+ //
498
+ // - The left function can call the right with `'b` and
499
+ // `'c` both equal to `'a`
500
+ //
501
+ // - The right function can call the left with `'a` set to
502
+ // `{P}`, where P is the point in the CFG where the call
503
+ // itself occurs. Note that `'b` and `'c` must both
504
+ // include P. At the point, the call works because of
505
+ // subtyping (i.e., `&'b u32 <: &{P} u32`).
506
+ let variance = std:: mem:: replace ( & mut self . ambient_variance , ty:: Variance :: Covariant ) ;
507
+
508
+ // Note: the order here is important. Create the placeholders first, otherwise
509
+ // we assign the wrong universe to the existential!
510
+ self . enter_forall ( b, |this, b| {
511
+ let a = this. instantiate_binder_with_existentials ( a) ;
512
+ this. relate ( a, b)
513
+ } ) ?;
514
+
515
+ self . ambient_variance = variance;
516
+ }
517
+
518
+ if self . ambient_contravariance ( ) {
519
+ // Contravariance, so we want `for<..> A :> for<..> B`
520
+ // -- therefore we compare every instantiation of A (i.e.,
521
+ // A instantiated with universals) against any
522
+ // instantiation of B (i.e., B instantiated with
523
+ // existentials). Opposite of above.
524
+
525
+ // Reset ambient variance to contravariance. See the
526
+ // covariant case above for an explanation.
527
+ let variance =
528
+ std:: mem:: replace ( & mut self . ambient_variance , ty:: Variance :: Contravariant ) ;
529
+
530
+ self . enter_forall ( a, |this, a| {
531
+ let b = this. instantiate_binder_with_existentials ( b) ;
532
+ this. relate ( a, b)
533
+ } ) ?;
534
+
535
+ self . ambient_variance = variance;
536
+ }
537
+
538
+ Ok ( a)
539
+ }
540
+ }
541
+
542
+ impl < ' bccx , ' tcx > ObligationEmittingRelation < ' tcx > for NllTypeRelating < ' _ , ' bccx , ' tcx > {
543
+ fn span ( & self ) -> Span {
544
+ self . locations . span ( self . type_checker . body )
545
+ }
546
+
547
+ fn param_env ( & self ) -> ty:: ParamEnv < ' tcx > {
548
+ self . type_checker . param_env
549
+ }
550
+
551
+ fn register_predicates ( & mut self , obligations : impl IntoIterator < Item : ty:: ToPredicate < ' tcx > > ) {
552
+ self . register_obligations (
553
+ obligations
554
+ . into_iter ( )
555
+ . map ( |to_pred| {
556
+ Obligation :: new ( self . tcx ( ) , ObligationCause :: dummy ( ) , self . param_env ( ) , to_pred)
557
+ } )
558
+ . collect ( ) ,
559
+ ) ;
560
+ }
166
561
167
562
fn register_obligations ( & mut self , obligations : PredicateObligations < ' tcx > ) {
168
563
let _: Result < _ , ErrorGuaranteed > = self . type_checker . fully_perform_op (
@@ -176,4 +571,32 @@ impl<'tcx> NllTypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tc
176
571
} ,
177
572
) ;
178
573
}
574
+
575
+ fn alias_relate_direction ( & self ) -> ty:: AliasRelationDirection {
576
+ unreachable ! ( "manually overridden to handle ty::Variance::Contravariant ambient variance" )
577
+ }
578
+
579
+ fn register_type_relate_obligation ( & mut self , a : Ty < ' tcx > , b : Ty < ' tcx > ) {
580
+ self . register_predicates ( [ ty:: Binder :: dummy ( match self . ambient_variance {
581
+ ty:: Variance :: Covariant => ty:: PredicateKind :: AliasRelate (
582
+ a. into ( ) ,
583
+ b. into ( ) ,
584
+ ty:: AliasRelationDirection :: Subtype ,
585
+ ) ,
586
+ // a :> b is b <: a
587
+ ty:: Variance :: Contravariant => ty:: PredicateKind :: AliasRelate (
588
+ b. into ( ) ,
589
+ a. into ( ) ,
590
+ ty:: AliasRelationDirection :: Subtype ,
591
+ ) ,
592
+ ty:: Variance :: Invariant => ty:: PredicateKind :: AliasRelate (
593
+ a. into ( ) ,
594
+ b. into ( ) ,
595
+ ty:: AliasRelationDirection :: Equate ,
596
+ ) ,
597
+ ty:: Variance :: Bivariant => {
598
+ unreachable ! ( "cannot defer an alias-relate goal with Bivariant variance (yet?)" )
599
+ }
600
+ } ) ] ) ;
601
+ }
179
602
}
0 commit comments