@@ -322,7 +322,7 @@ fn clean_where_predicate<'tcx>(
322
322
let bound_params = wbp
323
323
. bound_generic_params
324
324
. iter ( )
325
- . map ( |param| clean_generic_param ( cx, None , param ) )
325
+ . map ( |param| clean_generic_param ( cx, param , None , None ) )
326
326
. collect ( ) ;
327
327
WherePredicate :: BoundPredicate {
328
328
ty : clean_ty ( wbp. bounded_ty , cx) ,
@@ -503,11 +503,12 @@ fn projection_to_path_segment<'tcx>(
503
503
504
504
fn clean_generic_param_def < ' tcx > (
505
505
def : & ty:: GenericParamDef ,
506
+ variance : Option < ty:: Variance > ,
506
507
cx : & mut DocContext < ' tcx > ,
507
508
) -> GenericParamDef {
508
509
let ( name, kind) = match def. kind {
509
510
ty:: GenericParamDefKind :: Lifetime => {
510
- ( def. name , LifetimeParam { outlives : ThinVec :: new ( ) } . into ( ) )
511
+ ( def. name , LifetimeParam { variance , outlives : ThinVec :: new ( ) } . into ( ) )
511
512
}
512
513
ty:: GenericParamDefKind :: Type { has_default, synthetic, .. } => {
513
514
let default = has_default. then ( || {
@@ -521,6 +522,7 @@ fn clean_generic_param_def<'tcx>(
521
522
(
522
523
def. name ,
523
524
TypeParam {
525
+ variance,
524
526
bounds : ThinVec :: new ( ) , // These are filled in from the where-clause.
525
527
default,
526
528
synthetic,
@@ -556,8 +558,9 @@ fn clean_generic_param_def<'tcx>(
556
558
557
559
fn clean_generic_param < ' tcx > (
558
560
cx : & mut DocContext < ' tcx > ,
559
- generics : Option < & hir:: Generics < ' tcx > > ,
560
561
param : & hir:: GenericParam < ' tcx > ,
562
+ variance : Option < ty:: Variance > ,
563
+ generics : Option < & hir:: Generics < ' tcx > > ,
561
564
) -> GenericParamDef {
562
565
let ( name, kind) = match param. kind {
563
566
hir:: GenericParamKind :: Lifetime { .. } => {
@@ -574,7 +577,7 @@ fn clean_generic_param<'tcx>(
574
577
} else {
575
578
ThinVec :: new ( )
576
579
} ;
577
- ( param. name . ident ( ) . name , LifetimeParam { outlives } . into ( ) )
580
+ ( param. name . ident ( ) . name , LifetimeParam { variance , outlives } . into ( ) )
578
581
}
579
582
hir:: GenericParamKind :: Type { ref default, synthetic } => {
580
583
let bounds = if let Some ( generics) = generics {
@@ -589,7 +592,13 @@ fn clean_generic_param<'tcx>(
589
592
} ;
590
593
(
591
594
param. name . ident ( ) . name ,
592
- TypeParam { bounds, default : default. map ( |t| clean_ty ( t, cx) ) , synthetic } . into ( ) ,
595
+ TypeParam {
596
+ variance,
597
+ bounds,
598
+ default : default. map ( |t| clean_ty ( t, cx) ) ,
599
+ synthetic,
600
+ }
601
+ . into ( ) ,
593
602
)
594
603
}
595
604
hir:: GenericParamKind :: Const { ty, default, is_host_effect } => (
@@ -627,14 +636,42 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
627
636
pub ( crate ) fn clean_generics < ' tcx > (
628
637
generics : & hir:: Generics < ' tcx > ,
629
638
cx : & mut DocContext < ' tcx > ,
630
- _item_def_id : DefId ,
639
+ item_def_id : DefId ,
631
640
) -> Generics {
641
+ // FIXME(fmease): Instead of querying the defkind, we could instead let the caller make the decision
642
+ // NOTE: This would also fix us rendering variances in synthetic impls which use the
643
+ // DefId of the ADT.
644
+ // FIXME(fmease): Add DefKind::TyAlias if type_alias_is_lazy()
645
+ let def_kind = cx. tcx . def_kind ( item_def_id) ;
646
+ let variances = if !generics. params . is_empty ( )
647
+ && let DefKind :: Fn
648
+ | DefKind :: AssocFn
649
+ | DefKind :: Enum
650
+ | DefKind :: Struct
651
+ | DefKind :: Union
652
+ | DefKind :: OpaqueTy = def_kind
653
+ {
654
+ let variances = cx. tcx . variances_of ( item_def_id) ;
655
+ let generics = cx. tcx . generics_of ( item_def_id) ;
656
+
657
+ eprintln ! ( "::: item={item_def_id:?} params={:?}" , generics. params) ;
658
+ eprintln ! ( "--> variances_raw={variances:?}" ) ;
659
+
660
+ Some ( ( variances, generics) )
661
+ } else {
662
+ None
663
+ } ;
664
+
632
665
let impl_trait_params = generics
633
666
. params
634
667
. iter ( )
635
- . filter ( |param| is_impl_trait ( param) )
636
- . map ( |param| {
637
- let param = clean_generic_param ( cx, Some ( generics) , param) ;
668
+ . enumerate ( )
669
+ . filter ( |( _, param) | is_impl_trait ( param) )
670
+ . map ( |( _index, param) | {
671
+ // FIXME: this isn't correct for AssocFn since the variances also contain the parent variances, cut them off
672
+ // let variance = variances.map(|variances| variances[index]); // FIXME(fmease): impl
673
+ let variance = None ;
674
+ let param = clean_generic_param ( cx, param, variance, Some ( generics) ) ;
638
675
let GenericParamDefKind :: Type ( ty_param) = & param. kind else { unreachable ! ( ) } ;
639
676
cx. impl_trait_bounds . insert ( param. def_id . into ( ) , ty_param. bounds . to_vec ( ) ) ;
640
677
param
@@ -692,7 +729,12 @@ pub(crate) fn clean_generics<'tcx>(
692
729
// bounds in the where predicates. If so, we move their bounds into the where predicates
693
730
// while also preventing duplicates.
694
731
for param in generics. params . iter ( ) . filter ( |p| !is_impl_trait ( p) && !is_elided_lifetime ( p) ) {
695
- let mut param = clean_generic_param ( cx, Some ( generics) , param) ;
732
+ let variance = variances. and_then ( |( variances, generics) | {
733
+ let index = generics. param_def_id_to_index . get ( & param. def_id . to_def_id ( ) ) ?;
734
+ Some ( variances[ * index as usize ] )
735
+ } ) ;
736
+ let mut param = clean_generic_param ( cx, param, variance, Some ( generics) ) ;
737
+
696
738
match & mut param. kind {
697
739
GenericParamDefKind :: Lifetime ( lt_param) => {
698
740
if let Some ( region_pred) = region_predicates. get_mut ( & Lifetime ( param. name ) ) {
@@ -746,8 +788,25 @@ fn clean_ty_generics<'tcx>(
746
788
cx : & mut DocContext < ' tcx > ,
747
789
generics : & ty:: Generics ,
748
790
predicates : ty:: GenericPredicates < ' tcx > ,
749
- _item_def_id : DefId ,
791
+ item_def_id : DefId ,
750
792
) -> Generics {
793
+ // FIXME(fmease): Instead of querying the defkind, we could instead let the caller make the decision
794
+ // NOTE: This would also fix us rendering variances in synthetic impls which use the
795
+ // DefId of the ADT.
796
+ // FIXME(fmease): Add DefKind::TyAlias if type_alias_is_lazy()
797
+ let variances = if !generics. params . is_empty ( )
798
+ && let DefKind :: Fn
799
+ | DefKind :: AssocFn
800
+ | DefKind :: Enum
801
+ | DefKind :: Struct
802
+ | DefKind :: Union
803
+ | DefKind :: OpaqueTy = cx. tcx . def_kind ( item_def_id)
804
+ {
805
+ Some ( cx. tcx . variances_of ( item_def_id) )
806
+ } else {
807
+ None
808
+ } ;
809
+
751
810
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
752
811
// since `Clean for ty::Predicate` would consume them.
753
812
let mut impl_trait = BTreeMap :: < ImplTraitParam , Vec < GenericBound > > :: default ( ) ;
@@ -758,22 +817,28 @@ fn clean_ty_generics<'tcx>(
758
817
let stripped_params = generics
759
818
. params
760
819
. iter ( )
761
- . filter_map ( |param| match param. kind {
762
- ty:: GenericParamDefKind :: Lifetime if param. is_anonymous_lifetime ( ) => None ,
763
- ty:: GenericParamDefKind :: Lifetime => Some ( clean_generic_param_def ( param, cx) ) ,
820
+ . filter ( |param| match param. kind {
821
+ ty:: GenericParamDefKind :: Lifetime => !param. is_anonymous_lifetime ( ) ,
764
822
ty:: GenericParamDefKind :: Type { synthetic, .. } => {
765
823
if param. name == kw:: SelfUpper {
766
824
assert_eq ! ( param. index, 0 ) ;
767
- return None ;
825
+ return false ;
768
826
}
769
827
if synthetic {
770
828
impl_trait. insert ( param. index . into ( ) , vec ! [ ] ) ;
771
- return None ;
829
+ return false ;
772
830
}
773
- Some ( clean_generic_param_def ( param , cx ) )
831
+ true
774
832
}
775
- ty:: GenericParamDefKind :: Const { is_host_effect : true , .. } => None ,
776
- ty:: GenericParamDefKind :: Const { .. } => Some ( clean_generic_param_def ( param, cx) ) ,
833
+ ty:: GenericParamDefKind :: Const { is_host_effect, .. } => !is_host_effect,
834
+ } )
835
+ . map ( |param| {
836
+ // FIXME(fmease): We will probably handle AssocFn incorrectly since it has
837
+ // parent generics (we prob need to offset shit)
838
+ let variance = variances
839
+ . map ( |variances| variances[ generics. param_def_id_to_index [ & param. def_id ] as usize ] ) ;
840
+
841
+ clean_generic_param_def ( param, variance, cx)
777
842
} )
778
843
. collect :: < ThinVec < GenericParamDef > > ( ) ;
779
844
@@ -1222,7 +1287,7 @@ fn clean_poly_trait_ref<'tcx>(
1222
1287
. bound_generic_params
1223
1288
. iter ( )
1224
1289
. filter ( |p| !is_elided_lifetime ( p) )
1225
- . map ( |x| clean_generic_param ( cx, None , x ) )
1290
+ . map ( |x| clean_generic_param ( cx, x , None , None ) )
1226
1291
. collect ( ) ,
1227
1292
}
1228
1293
}
@@ -2566,7 +2631,7 @@ fn clean_bare_fn_ty<'tcx>(
2566
2631
. generic_params
2567
2632
. iter ( )
2568
2633
. filter ( |p| !is_elided_lifetime ( p) )
2569
- . map ( |x| clean_generic_param ( cx, None , x ) )
2634
+ . map ( |x| clean_generic_param ( cx, x , None , None ) ) // FIXME(fmease): variance?
2570
2635
. collect ( ) ;
2571
2636
let args = clean_args_from_types_and_names ( cx, bare_fn. decl . inputs , bare_fn. param_names ) ;
2572
2637
let decl = clean_fn_decl_with_args ( cx, bare_fn. decl , None , args) ;
@@ -3152,8 +3217,14 @@ fn clean_bound_vars<'tcx>(
3152
3217
Some ( GenericParamDef {
3153
3218
name,
3154
3219
def_id,
3155
- kind : TypeParam { bounds : ThinVec :: new ( ) , default : None , synthetic : false }
3156
- . into ( ) ,
3220
+ // FIXME(fmease): higher-ranked generic params don't have a variance, right?
3221
+ kind : TypeParam {
3222
+ variance : None ,
3223
+ bounds : ThinVec :: new ( ) ,
3224
+ default : None ,
3225
+ synthetic : false ,
3226
+ }
3227
+ . into ( ) ,
3157
3228
} )
3158
3229
}
3159
3230
// FIXME(non_lifetime_binders): Support higher-ranked const parameters.
0 commit comments