@@ -1143,6 +1143,39 @@ pub enum TyKind {
11431143 #[ todo]
11441144 Todo ( String ) ,
11451145}
1146+ #[ cfg( feature = "rustc" ) ]
1147+ fn searcher_for_traits < ' tcx , S : UnderOwnerState < ' tcx > > (
1148+ s : & S ,
1149+ clauses : & Vec < ty:: Clause < ' tcx > > ,
1150+ ) -> PredicateSearcher < ' tcx > {
1151+ let tcx = s. base ( ) . tcx ;
1152+ // Populate a predicate searcher that knows about the `dyn` clauses.
1153+ let mut predicate_searcher = s. with_predicate_searcher ( |ps| ps. clone ( ) ) ;
1154+ predicate_searcher
1155+ . insert_bound_predicates ( clauses. iter ( ) . filter_map ( |clause| clause. as_trait_clause ( ) ) ) ;
1156+ predicate_searcher. set_param_env ( rustc_trait_selection:: traits:: normalize_param_env_or_error (
1157+ tcx,
1158+ ty:: ParamEnv :: new (
1159+ tcx. mk_clauses_from_iter (
1160+ s. param_env ( )
1161+ . caller_bounds ( )
1162+ . iter ( )
1163+ . chain ( clauses. iter ( ) . copied ( ) ) ,
1164+ ) ,
1165+ ) ,
1166+ rustc_trait_selection:: traits:: ObligationCause :: dummy ( ) ,
1167+ ) ) ;
1168+ predicate_searcher
1169+ }
1170+
1171+ #[ cfg( feature = "rustc" ) ]
1172+ fn fresh_param_ty < ' tcx , S : UnderOwnerState < ' tcx > > ( s : & S ) -> ty:: ParamTy {
1173+ let tcx = s. base ( ) . tcx ;
1174+ let def_id = s. owner_id ( ) ;
1175+ let generics = tcx. generics_of ( def_id) ;
1176+ let param_count = generics. parent_count + generics. own_params . len ( ) ;
1177+ ty:: ParamTy :: new ( param_count as u32 + 1 , rustc_span:: Symbol :: intern ( "_dyn" ) )
1178+ }
11461179
11471180/// Transform existential predicates into properly resolved predicates.
11481181#[ cfg( feature = "rustc" ) ]
@@ -1152,15 +1185,10 @@ fn make_dyn<'tcx, S: UnderOwnerState<'tcx>>(
11521185 region : & ty:: Region < ' tcx > ,
11531186) -> TyKind {
11541187 let tcx = s. base ( ) . tcx ;
1155- let def_id = s. owner_id ( ) ;
11561188 let span = rustc_span:: DUMMY_SP . sinto ( s) ;
11571189
11581190 // Pretend there's an extra type in the environment.
1159- let new_param_ty = {
1160- let generics = tcx. generics_of ( def_id) ;
1161- let param_count = generics. parent_count + generics. own_params . len ( ) ;
1162- ty:: ParamTy :: new ( param_count as u32 + 1 , rustc_span:: Symbol :: intern ( "_dyn" ) )
1163- } ;
1191+ let new_param_ty = fresh_param_ty ( s) ;
11641192 let new_ty = new_param_ty. to_ty ( tcx) ;
11651193
11661194 // Set the new type as the `Self` parameter of our predicates.
@@ -1170,21 +1198,7 @@ fn make_dyn<'tcx, S: UnderOwnerState<'tcx>>(
11701198 . collect ( ) ;
11711199
11721200 // 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- ) ) ;
1201+ let mut predicate_searcher = searcher_for_traits ( s, & clauses) ;
11881202
11891203 // Using the predicate searcher, translate the predicates. Only the projection predicates need
11901204 // to be handled specially.
@@ -1331,8 +1345,13 @@ pub enum PointerCoercion {
13311345#[ derive_group( Serializers ) ]
13321346#[ derive( Clone , Debug , JsonSchema ) ]
13331347pub enum UnsizingMetadata {
1348+ /// Unsize an array to a slice, storing the length as metadata.
13341349 Length ( ConstantExpr ) ,
1335- VTablePtr ( ImplExpr ) ,
1350+ /// Unsize a non-dyn type to a dyn type, adding a vtable pointer as metadata.
1351+ DirectVTable ( ImplExpr ) ,
1352+ /// Unsize a dyn-type to another dyn-type, (optionally) indexing within the current vtable.
1353+ NestedVTable ( ImplExpr ) ,
1354+ /// Couldn't compute
13361355 Unknown ,
13371356}
13381357
@@ -1355,35 +1374,54 @@ impl PointerCoercion {
13551374 }
13561375 ty:: adjustment:: PointerCoercion :: ArrayToPointer => PointerCoercion :: ArrayToPointer ,
13571376 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` \
1377+ // TODO: to properly find out what field we want, we should use the query
1378+ // `coerce_unsized_info`, which we call recursively to get the list of fields
1379+ // to go into until we reach a pointer/reference.
1380+ // We should also pass this list of field IDs in the unsizing metadata.
1381+
1382+ let ( Some ( src_ty) , Some ( tgt_ty) ) =
1383+ ( src_ty. builtin_deref ( true ) , tgt_ty. builtin_deref ( true ) )
1384+ else {
1385+ return PointerCoercion :: Unsize ( UnsizingMetadata :: Unknown ) ;
1386+ } ;
1387+
1388+ let tcx = s. base ( ) . tcx ;
1389+ let typing_env = s. typing_env ( ) ;
1390+ let ( src_ty, tgt_ty) = tcx
1391+ . struct_lockstep_tails_raw ( src_ty, tgt_ty, |ty| normalize ( tcx, typing_env, ty) ) ;
1392+
1393+ let meta = match ( & src_ty. kind ( ) , & tgt_ty. kind ( ) ) {
1394+ ( ty:: Array ( _, len) , ty:: Slice ( _) ) => {
1395+ let len = len. sinto ( s) ;
1396+ UnsizingMetadata :: Length ( len)
1397+ }
1398+ ( ty:: Dynamic ( from_preds, _) , ty:: Dynamic ( to_preds, ..) ) => {
1399+ let src_ty = fresh_param_ty ( s) . to_ty ( tcx) ;
1400+ let to_pred = to_preds[ 0 ] . with_self_ty ( tcx, src_ty) ;
1401+ let from_preds: Vec < ty:: Clause < ' tcx > > = from_preds
1402+ . iter ( )
1403+ . map ( |p| p. clone ( ) . with_self_ty ( tcx, src_ty) )
1404+ . collect :: < Vec < _ > > ( ) ;
1405+ let mut searcher = searcher_for_traits ( s, & from_preds) ;
1406+ let impl_expr = searcher
1407+ . resolve (
1408+ & to_pred. as_trait_clause ( ) . unwrap ( ) . to_poly_trait_ref ( ) ,
1409+ & |_| { } ,
1410+ )
1411+ . s_unwrap ( s)
1412+ . sinto ( s) ;
1413+ UnsizingMetadata :: NestedVTable ( impl_expr)
1414+ }
1415+ ( _, ty:: Dynamic ( preds, ..) ) => {
1416+ let pred = preds[ 0 ] . with_self_ty ( tcx, src_ty) ;
1417+ let clause = pred. as_trait_clause ( ) . expect (
1418+ "the first `ExistentialPredicate` of `TyKind::Dynamic` \
13791419 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- }
1420+ ) ;
1421+ let tref = clause. rebind ( clause. skip_binder ( ) . trait_ref ) ;
1422+ let impl_expr = solve_trait ( s, tref) ;
1423+
1424+ UnsizingMetadata :: DirectVTable ( impl_expr)
13871425 }
13881426 _ => UnsizingMetadata :: Unknown ,
13891427 } ;
0 commit comments