@@ -1120,15 +1120,8 @@ pub enum TyKind {
11201120 Str ,
11211121 RawPtr ( Box < Ty > , Mutability ) ,
11221122 Ref ( Region , Box < Ty > , Mutability ) ,
1123- #[ custom_arm( FROM_TYPE :: Dynamic ( preds, region) => make_dyn( s, preds, region) , ) ]
1124- Dynamic (
1125- /// Fresh type parameter that we use as the `Self` type in the prediates below.
1126- ParamTy ,
1127- /// Clauses that define the trait object. These clauses use the fresh type parameter above
1128- /// as `Self` type.
1129- GenericPredicates ,
1130- Region ,
1131- ) ,
1123+ #[ custom_arm( FROM_TYPE :: Dynamic ( preds, region) => TyKind :: Dynamic ( resolve_for_dyn( s, preds, |_| ( ) ) , region. sinto( s) ) , ) ]
1124+ Dynamic ( DynBinder < ( ) > , Region ) ,
11321125 #[ custom_arm( FROM_TYPE :: Coroutine ( def_id, generics) => TO_TYPE :: Coroutine ( translate_item_ref( s, * def_id, generics) ) , ) ]
11331126 Coroutine ( ItemRef ) ,
11341127 Never ,
@@ -1144,23 +1137,68 @@ pub enum TyKind {
11441137 Todo ( String ) ,
11451138}
11461139
1147- /// Transform existential predicates into properly resolved predicates.
1140+ /// A representation of `exists<T: Trait1 + Trait2>(value)`: we create a fresh type id and the
1141+ /// appropriate trait clauses. The contained value may refer to the fresh ty and the in-scope trait
1142+ /// clauses. This is used to represent types related to `dyn Trait`.
1143+ #[ derive_group( Serializers ) ]
1144+ #[ derive( Clone , Debug , JsonSchema , Hash , PartialEq , Eq , PartialOrd , Ord ) ]
1145+ pub struct DynBinder < T > {
1146+ /// Fresh type parameter that we use as the `Self` type in the prediates below.
1147+ pub existential_ty : ParamTy ,
1148+ /// Clauses that define the trait object. These clauses use the fresh type parameter above
1149+ /// as `Self` type.
1150+ pub predicates : GenericPredicates ,
1151+ /// The value inside the binder.
1152+ pub val : T ,
1153+ }
1154+
1155+ /// Do trait resolution in the context of the clauses of a `dyn Trait` type.
11481156#[ cfg( feature = "rustc" ) ]
1149- fn make_dyn < ' tcx , S : UnderOwnerState < ' tcx > > (
1157+ fn resolve_for_dyn < ' tcx , S : UnderOwnerState < ' tcx > , R > (
11501158 s : & S ,
1159+ // The predicates in the context.
11511160 epreds : & ' tcx ty:: List < ty:: Binder < ' tcx , ty:: ExistentialPredicate < ' tcx > > > ,
1152- region : & ty:: Region < ' tcx > ,
1153- ) -> TyKind {
1154- let tcx = s. base ( ) . tcx ;
1155- let def_id = s. owner_id ( ) ;
1156- let span = rustc_span:: DUMMY_SP . sinto ( s) ;
1161+ f : impl FnOnce ( & mut PredicateSearcher < ' tcx > ) -> R ,
1162+ ) -> DynBinder < R > {
1163+ fn searcher_for_traits < ' tcx , S : UnderOwnerState < ' tcx > > (
1164+ s : & S ,
1165+ clauses : & Vec < ty:: Clause < ' tcx > > ,
1166+ ) -> PredicateSearcher < ' tcx > {
1167+ let tcx = s. base ( ) . tcx ;
1168+ // Populate a predicate searcher that knows about the `dyn` clauses.
1169+ let mut predicate_searcher = s. with_predicate_searcher ( |ps| ps. clone ( ) ) ;
1170+ predicate_searcher
1171+ . insert_bound_predicates ( clauses. iter ( ) . filter_map ( |clause| clause. as_trait_clause ( ) ) ) ;
1172+ predicate_searcher. set_param_env (
1173+ rustc_trait_selection:: traits:: normalize_param_env_or_error (
1174+ tcx,
1175+ ty:: ParamEnv :: new (
1176+ tcx. mk_clauses_from_iter (
1177+ s. param_env ( )
1178+ . caller_bounds ( )
1179+ . iter ( )
1180+ . chain ( clauses. iter ( ) . copied ( ) ) ,
1181+ ) ,
1182+ ) ,
1183+ rustc_trait_selection:: traits:: ObligationCause :: dummy ( ) ,
1184+ ) ,
1185+ ) ;
1186+ predicate_searcher
1187+ }
11571188
1158- // Pretend there's an extra type in the environment.
1159- let new_param_ty = {
1189+ fn fresh_param_ty < ' tcx , S : UnderOwnerState < ' tcx > > ( s : & S ) -> ty:: ParamTy {
1190+ let tcx = s. base ( ) . tcx ;
1191+ let def_id = s. owner_id ( ) ;
11601192 let generics = tcx. generics_of ( def_id) ;
11611193 let param_count = generics. parent_count + generics. own_params . len ( ) ;
11621194 ty:: ParamTy :: new ( param_count as u32 + 1 , rustc_span:: Symbol :: intern ( "_dyn" ) )
1163- } ;
1195+ }
1196+
1197+ let tcx = s. base ( ) . tcx ;
1198+ let span = rustc_span:: DUMMY_SP . sinto ( s) ;
1199+
1200+ // Pretend there's an extra type in the environment.
1201+ let new_param_ty = fresh_param_ty ( s) ;
11641202 let new_ty = new_param_ty. to_ty ( tcx) ;
11651203
11661204 // Set the new type as the `Self` parameter of our predicates.
@@ -1170,21 +1208,8 @@ fn make_dyn<'tcx, S: UnderOwnerState<'tcx>>(
11701208 . collect ( ) ;
11711209
11721210 // Populate a predicate searcher that knows about the `dyn` clauses.
1173- let mut predicate_searcher = s. with_predicate_searcher ( |ps| ps. clone ( ) ) ;
1174- predicate_searcher
1175- . insert_bound_predicates ( clauses. iter ( ) . filter_map ( |clause| clause. as_trait_clause ( ) ) ) ;
1176- predicate_searcher. set_param_env ( rustc_trait_selection:: traits:: normalize_param_env_or_error (
1177- tcx,
1178- ty:: ParamEnv :: new (
1179- tcx. mk_clauses_from_iter (
1180- s. param_env ( )
1181- . caller_bounds ( )
1182- . iter ( )
1183- . chain ( clauses. iter ( ) . copied ( ) ) ,
1184- ) ,
1185- ) ,
1186- rustc_trait_selection:: traits:: ObligationCause :: dummy ( ) ,
1187- ) ) ;
1211+ let mut predicate_searcher = searcher_for_traits ( s, & clauses) ;
1212+ let val = f ( & mut predicate_searcher) ;
11881213
11891214 // Using the predicate searcher, translate the predicates. Only the projection predicates need
11901215 // to be handled specially.
@@ -1231,9 +1256,11 @@ fn make_dyn<'tcx, S: UnderOwnerState<'tcx>>(
12311256 . collect ( ) ;
12321257
12331258 let predicates = GenericPredicates { predicates } ;
1234- let param_ty = new_param_ty. sinto ( s) ;
1235- let region = region. sinto ( s) ;
1236- TyKind :: Dynamic ( param_ty, predicates, region)
1259+ DynBinder {
1260+ existential_ty : new_param_ty. sinto ( s) ,
1261+ predicates,
1262+ val,
1263+ }
12371264}
12381265
12391266/// Reflects [`ty::CanonicalUserTypeAnnotation`]
@@ -1331,8 +1358,13 @@ pub enum PointerCoercion {
13311358#[ derive_group( Serializers ) ]
13321359#[ derive( Clone , Debug , JsonSchema ) ]
13331360pub enum UnsizingMetadata {
1361+ /// Unsize an array to a slice, storing the length as metadata.
13341362 Length ( ConstantExpr ) ,
1335- VTablePtr ( ImplExpr ) ,
1363+ /// Unsize a non-dyn type to a dyn type, adding a vtable pointer as metadata.
1364+ DirectVTable ( ImplExpr ) ,
1365+ /// Unsize a dyn-type to another dyn-type, (optionally) indexing within the current vtable.
1366+ NestedVTable ( DynBinder < ImplExpr > ) ,
1367+ /// Couldn't compute
13361368 Unknown ,
13371369}
13381370
@@ -1355,35 +1387,44 @@ impl PointerCoercion {
13551387 }
13561388 ty:: adjustment:: PointerCoercion :: ArrayToPointer => PointerCoercion :: ArrayToPointer ,
13571389 ty:: adjustment:: PointerCoercion :: Unsize => {
1358- // We only support unsizing behind references, pointers and boxes for now.
1359- let meta = match ( src_ty. builtin_deref ( true ) , tgt_ty. builtin_deref ( true ) ) {
1360- ( Some ( src_ty) , Some ( tgt_ty) ) => {
1361- let tcx = s. base ( ) . tcx ;
1362- let typing_env = s. typing_env ( ) ;
1363- let ( src_ty, tgt_ty) =
1364- tcx. struct_lockstep_tails_raw ( src_ty, tgt_ty, |ty| {
1365- normalize ( tcx, typing_env, ty)
1366- } ) ;
1367- match tgt_ty. kind ( ) {
1368- ty:: Slice ( _) | ty:: Str => match src_ty. kind ( ) {
1369- ty:: Array ( _, len) => {
1370- let len = len. sinto ( s) ;
1371- UnsizingMetadata :: Length ( len)
1372- }
1373- _ => UnsizingMetadata :: Unknown ,
1374- } ,
1375- ty:: Dynamic ( preds, ..) => {
1376- let pred = preds[ 0 ] . with_self_ty ( tcx, src_ty) ;
1377- let clause = pred. as_trait_clause ( ) . expect (
1378- "the first `ExistentialPredicate` of `TyKind::Dynamic` \
1390+ // TODO: to properly find out what field we want, we should use the query
1391+ // `coerce_unsized_info`, which we call recursively to get the list of fields
1392+ // to go into until we reach a pointer/reference.
1393+ // We should also pass this list of field IDs in the unsizing metadata.
1394+
1395+ let ( Some ( src_ty) , Some ( tgt_ty) ) =
1396+ ( src_ty. builtin_deref ( true ) , tgt_ty. builtin_deref ( true ) )
1397+ else {
1398+ return PointerCoercion :: Unsize ( UnsizingMetadata :: Unknown ) ;
1399+ } ;
1400+
1401+ let tcx = s. base ( ) . tcx ;
1402+ let typing_env = s. typing_env ( ) ;
1403+ let ( src_ty, tgt_ty) = tcx
1404+ . struct_lockstep_tails_raw ( src_ty, tgt_ty, |ty| normalize ( tcx, typing_env, ty) ) ;
1405+
1406+ let meta = match ( & src_ty. kind ( ) , & tgt_ty. kind ( ) ) {
1407+ ( ty:: Array ( _, len) , ty:: Slice ( _) ) => {
1408+ let len = len. sinto ( s) ;
1409+ UnsizingMetadata :: Length ( len)
1410+ }
1411+ ( ty:: Dynamic ( from_preds, _) , ty:: Dynamic ( to_preds, ..) ) => {
1412+ let to_pred = to_preds. principal ( ) . unwrap ( ) . with_self_ty ( tcx, src_ty) ;
1413+ let impl_expr = resolve_for_dyn ( s, from_preds, |searcher| {
1414+ searcher. resolve ( & to_pred, & |_| { } ) . s_unwrap ( s) . sinto ( s)
1415+ } ) ;
1416+ UnsizingMetadata :: NestedVTable ( impl_expr)
1417+ }
1418+ ( _, ty:: Dynamic ( preds, ..) ) => {
1419+ let pred = preds[ 0 ] . with_self_ty ( tcx, src_ty) ;
1420+ let clause = pred. as_trait_clause ( ) . expect (
1421+ "the first `ExistentialPredicate` of `TyKind::Dynamic` \
13791422 should be a trait clause",
1380- ) ;
1381- let tref = clause. rebind ( clause. skip_binder ( ) . trait_ref ) ;
1382- let impl_expr = solve_trait ( s, tref) ;
1383- UnsizingMetadata :: VTablePtr ( impl_expr)
1384- }
1385- _ => UnsizingMetadata :: Unknown ,
1386- }
1423+ ) ;
1424+ let tref = clause. rebind ( clause. skip_binder ( ) . trait_ref ) ;
1425+ let impl_expr = solve_trait ( s, tref) ;
1426+
1427+ UnsizingMetadata :: DirectVTable ( impl_expr)
13871428 }
13881429 _ => UnsizingMetadata :: Unknown ,
13891430 } ;
0 commit comments