@@ -12,7 +12,10 @@ use super::Selection;
1212use super :: SelectionContext ;
1313use super :: SelectionError ;
1414use super :: { Normalized , NormalizedTy , ProjectionCacheEntry , ProjectionCacheKey } ;
15- use super :: { VtableClosureData , VtableFnPointerData , VtableGeneratorData , VtableImplData } ;
15+ use super :: {
16+ VtableClosureData , VtableDiscriminantKindData , VtableFnPointerData , VtableGeneratorData ,
17+ VtableImplData ,
18+ } ;
1619
1720use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1821use crate :: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
@@ -23,6 +26,7 @@ use rustc_hir::def_id::DefId;
2326use rustc_hir:: lang_items:: { FnOnceTraitLangItem , GeneratorTraitLangItem } ;
2427use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder } ;
2528use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
29+ use rustc_middle:: ty:: util:: IntTypeExt ;
2630use rustc_middle:: ty:: { self , ToPolyTraitRef , ToPredicate , Ty , TyCtxt , WithConstness } ;
2731use rustc_span:: symbol:: { sym, Ident } ;
2832use rustc_span:: DUMMY_SP ;
@@ -1043,6 +1047,46 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
10431047 }
10441048 }
10451049 }
1050+ super :: VtableDiscriminantKind ( ..) => {
1051+ // While `DiscriminantKind` is automatically implemented for every type,
1052+ // the concrete discriminant may not be known yet.
1053+ //
1054+ // Any type with multiple potential discriminant types is therefore not eligible.
1055+ let self_ty = selcx. infcx ( ) . shallow_resolve ( obligation. predicate . self_ty ( ) ) ;
1056+
1057+ match self_ty. kind {
1058+ ty:: Bool
1059+ | ty:: Char
1060+ | ty:: Int ( _)
1061+ | ty:: Uint ( _)
1062+ | ty:: Float ( _)
1063+ | ty:: Adt ( ..)
1064+ | ty:: Foreign ( _)
1065+ | ty:: Str
1066+ | ty:: Array ( ..)
1067+ | ty:: Slice ( _)
1068+ | ty:: RawPtr ( ..)
1069+ | ty:: Ref ( ..)
1070+ | ty:: FnDef ( ..)
1071+ | ty:: FnPtr ( ..)
1072+ | ty:: Dynamic ( ..)
1073+ | ty:: Closure ( ..)
1074+ | ty:: Generator ( ..)
1075+ | ty:: GeneratorWitness ( ..)
1076+ | ty:: Never
1077+ | ty:: Tuple ( ..)
1078+ // Integers and floats always have `u8` as their discriminant.
1079+ | ty:: Infer ( ty:: InferTy :: IntVar ( _) | ty:: InferTy :: FloatVar ( ..) ) => true ,
1080+
1081+ ty:: Projection ( ..)
1082+ | ty:: Opaque ( ..)
1083+ | ty:: Param ( ..)
1084+ | ty:: Bound ( ..)
1085+ | ty:: Placeholder ( ..)
1086+ | ty:: Infer ( ..)
1087+ | ty:: Error => false ,
1088+ }
1089+ }
10461090 super :: VtableParam ( ..) => {
10471091 // This case tell us nothing about the value of an
10481092 // associated type. Consider:
@@ -1124,13 +1168,15 @@ fn confirm_select_candidate<'cx, 'tcx>(
11241168 super :: VtableGenerator ( data) => confirm_generator_candidate ( selcx, obligation, data) ,
11251169 super :: VtableClosure ( data) => confirm_closure_candidate ( selcx, obligation, data) ,
11261170 super :: VtableFnPointer ( data) => confirm_fn_pointer_candidate ( selcx, obligation, data) ,
1171+ super :: VtableDiscriminantKind ( data) => {
1172+ confirm_discriminant_kind_candidate ( selcx, obligation, data)
1173+ }
11271174 super :: VtableObject ( _) => confirm_object_candidate ( selcx, obligation, obligation_trait_ref) ,
11281175 super :: VtableAutoImpl ( ..)
11291176 | super :: VtableParam ( ..)
11301177 | super :: VtableBuiltin ( ..)
1131- | super :: VtableTraitAlias ( ..) =>
1132- // we don't create Select candidates with this kind of resolution
1133- {
1178+ | super :: VtableTraitAlias ( ..) => {
1179+ // we don't create Select candidates with this kind of resolution
11341180 span_bug ! (
11351181 obligation. cause. span,
11361182 "Cannot project an associated type from `{:?}`" ,
@@ -1259,6 +1305,37 @@ fn confirm_generator_candidate<'cx, 'tcx>(
12591305 . with_addl_obligations ( obligations)
12601306}
12611307
1308+ fn confirm_discriminant_kind_candidate < ' cx , ' tcx > (
1309+ selcx : & mut SelectionContext < ' cx , ' tcx > ,
1310+ obligation : & ProjectionTyObligation < ' tcx > ,
1311+ _: VtableDiscriminantKindData ,
1312+ ) -> Progress < ' tcx > {
1313+ let tcx = selcx. tcx ( ) ;
1314+
1315+ let self_ty = selcx. infcx ( ) . shallow_resolve ( obligation. predicate . self_ty ( ) ) ;
1316+ let substs = tcx. mk_substs ( [ self_ty. into ( ) ] . iter ( ) ) ;
1317+
1318+ let assoc_items = tcx. associated_items ( tcx. lang_items ( ) . discriminant_kind_trait ( ) . unwrap ( ) ) ;
1319+ // FIXME: emit an error if the trait definition is wrong
1320+ let discriminant_def_id = assoc_items. in_definition_order ( ) . next ( ) . unwrap ( ) . def_id ;
1321+
1322+ let discriminant_ty = match self_ty. kind {
1323+ // Use the discriminant type for enums.
1324+ ty:: Adt ( adt, _) if adt. is_enum ( ) => adt. repr . discr_type ( ) . to_ty ( tcx) ,
1325+ // Default to `i32` for generators.
1326+ ty:: Generator ( ..) => tcx. types . i32 ,
1327+ // Use `u8` for all other types.
1328+ _ => tcx. types . u8 ,
1329+ } ;
1330+
1331+ let predicate = ty:: ProjectionPredicate {
1332+ projection_ty : ty:: ProjectionTy { substs, item_def_id : discriminant_def_id } ,
1333+ ty : discriminant_ty,
1334+ } ;
1335+
1336+ confirm_param_env_candidate ( selcx, obligation, ty:: Binder :: bind ( predicate) )
1337+ }
1338+
12621339fn confirm_fn_pointer_candidate < ' cx , ' tcx > (
12631340 selcx : & mut SelectionContext < ' cx , ' tcx > ,
12641341 obligation : & ProjectionTyObligation < ' tcx > ,
0 commit comments