@@ -23,7 +23,7 @@ use rustc_trait_selection::traits::misc::{
2323 ConstParamTyImplementationError , CopyImplementationError , InfringingFieldsReason ,
2424 type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
2525} ;
26- use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCtxt } ;
26+ use rustc_trait_selection:: traits:: { self , FulfillmentError , ObligationCause , ObligationCtxt } ;
2727use tracing:: debug;
2828
2929use crate :: errors;
@@ -463,14 +463,11 @@ pub(crate) fn reborrow_info<'tcx>(
463463 let param_env = tcx. param_env ( impl_did) ;
464464 assert ! ( !source. has_escaping_bound_vars( ) ) ;
465465
466- let _cause = ObligationCause :: misc ( span, impl_did) ;
467466 let ( def, args) = match source. kind ( ) {
468- & ty:: Adt ( def, args) if def. is_struct ( ) =>
469- {
470- ( def, args)
471- }
467+ & ty:: Adt ( def, args) if def. is_struct ( ) => ( def, args) ,
472468 _ => {
473- return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceSharedNonStruct { span, trait_name } ) ) ;
469+ // Note: reusing error here as it takes trait_name as argument.
470+ return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceUnsizedNonStruct { span, trait_name } ) ) ;
474471 }
475472 } ;
476473
@@ -481,43 +478,23 @@ pub(crate) fn reborrow_info<'tcx>(
481478 . iter ( )
482479 . filter_map ( |f| {
483480 // Ignore PhantomData fields
484- let unnormalized_ty = tcx. type_of ( f. did ) . instantiate_identity ( ) ;
485- if tcx
486- . try_normalize_erasing_regions (
487- ty:: TypingEnv :: non_body_analysis ( tcx, def. did ( ) ) ,
488- unnormalized_ty,
489- )
490- . unwrap_or ( unnormalized_ty)
491- . is_phantom_data ( )
492- {
481+ let ty = f. ty ( tcx, args) ;
482+ if ty. is_phantom_data ( ) {
493483 return None ;
494484 }
495-
496- let ty = f. ty ( tcx, args) ;
497-
498- // Collect up all fields that were significantly changed.
499485 Some ( ( ty, tcx. def_span ( f. did ) ) )
500486 } )
501487 . collect :: < Vec < _ > > ( ) ;
502488
503489 if lifetimes_count != 1 {
504490 let item = tcx. hir_expect_item ( impl_did) ;
505- let _span = if let ItemKind :: Impl ( hir:: Impl { of_trait : Some ( of_trait) , .. } ) =
506- & item. kind
507- {
491+ let _span = if let ItemKind :: Impl ( hir:: Impl { of_trait : Some ( of_trait) , .. } ) = & item. kind {
508492 of_trait. trait_ref . path . span
509493 } else {
510494 tcx. def_span ( impl_did)
511495 } ;
512496
513- todo ! ( ) ;
514- // let mut lifetimes = args.iter().filter_map(|arg| arg.as_region()).collect::<Vec<_>>();
515- // return Err(tcx.dcx().emit_err(errors::CoerceMulti {
516- // span,
517- // trait_name,
518- // number: lifetimes_count,
519- // fields: todo!(),
520- // }));
497+ return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceSharedMulti { span, trait_name } ) ) ;
521498 }
522499
523500 if data_fields. is_empty ( ) {
@@ -526,9 +503,23 @@ pub(crate) fn reborrow_info<'tcx>(
526503
527504 // We've found some data fields. They must all be either be Copy or Reborrow.
528505 for ( field, span) in data_fields {
529- assert_field_type_is_reborrow ( tcx, & infcx, reborrow_trait, impl_did, param_env, field, span) . or_else ( |err| {
530- assert_field_type_is_copy ( tcx, & infcx, impl_did, param_env, field, span) ?;
531- } )
506+ if assert_field_type_is_reborrow (
507+ tcx,
508+ & infcx,
509+ reborrow_trait,
510+ impl_did,
511+ param_env,
512+ field,
513+ span,
514+ )
515+ . is_ok ( )
516+ {
517+ // Field implements Reborrow.
518+ return Ok ( ( ) ) ;
519+ }
520+
521+ // Field does not implement Reborrow: it must be Copy.
522+ assert_field_type_is_copy ( tcx, & infcx, impl_did, param_env, field, span) ?;
532523 }
533524
534525 Ok ( ( ) )
@@ -542,23 +533,15 @@ fn assert_field_type_is_reborrow<'tcx>(
542533 param_env : ty:: ParamEnv < ' tcx > ,
543534 ty : Ty < ' tcx > ,
544535 span : Span ,
545- ) -> Result < ( ) , ErrorGuaranteed > {
536+ ) -> Result < ( ) , Vec < FulfillmentError < ' tcx > > > {
546537 let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
547538 let cause = traits:: ObligationCause :: misc ( span, impl_did) ;
548- let obligation = Obligation :: new (
549- tcx,
550- cause,
551- param_env,
552- ty:: TraitRef :: new ( tcx, reborrow_trait, [ ty] ) ,
553- ) ;
539+ let obligation =
540+ Obligation :: new ( tcx, cause, param_env, ty:: TraitRef :: new ( tcx, reborrow_trait, [ ty] ) ) ;
554541 ocx. register_obligation ( obligation) ;
555542 let errors = ocx. evaluate_obligations_error_on_ambiguity ( ) ;
556543
557- if !errors. is_empty ( ) {
558- Err ( errors)
559- } else {
560- Ok ( ( ) )
561- }
544+ if !errors. is_empty ( ) { Err ( errors) } else { Ok ( ( ) ) }
562545}
563546
564547pub ( crate ) fn coerce_shared_info < ' tcx > (
@@ -591,49 +574,33 @@ pub(crate) fn coerce_shared_info<'tcx>(
591574 let Some ( ( target, _obligations) ) =
592575 structurally_normalize_ty ( tcx, & infcx, impl_did, span, trait_ref. args . type_at ( 1 ) )
593576 else {
594- // return Err(tcx.dcx().emit_err(todo!()));
595- todo ! ( ) ;
577+ todo ! ( "something went wrong with structurally_normalize_ty" ) ;
596578 } ;
597- debug ! ( "visit_implementation_of_coerce_shared: {:?} -> {:?} (bound)" , source, target) ;
598579
599580 let param_env = tcx. param_env ( impl_did) ;
600581 assert ! ( !source. has_escaping_bound_vars( ) ) ;
601582
602- debug ! ( "visit_implementation_of_coerce_shared: {:?} -> {:?} (free)" , source, target) ;
603-
604- let _cause = ObligationCause :: misc ( span, impl_did) ;
605583 let data = match ( source. kind ( ) , target. kind ( ) ) {
606584 ( & ty:: Adt ( def_a, args_a) , & ty:: Adt ( def_b, args_b) )
607585 if def_a. is_struct ( ) && def_b. is_struct ( ) =>
608586 {
609- // struct FooMut<'a> { a: u32, b: PhantomData<&'a ()> } -> struct FooRef<'a> { a: u32, b: PhantomData<&'a ()> }
610- // struct FooMut<'a> { a: u32, b: PhantomData<&'a ()>, c: u32 } -> struct FooRef<'a> { a: u32, b: PhantomData<&'a ()> }
611- // struct FooMut<'a> { a: u32, b: PhantomData<&'a ()>, c: u32 } -> struct FooRef<'a> { c: u32, a: u32, b: PhantomData<&'a ()> }
612-
613- // Parent { Child, u32, i32 }, Child { u64, u32 } => ParentRef { ChildRef, u32 }, ChildRef { u64 }
614-
587+ // Check that both A and B have exactly one lifetime argument, and that they have the
588+ // same number of data fields that is not more than 1. The eventual intention is to
589+ // support multiple lifetime arguments (with the reborrowed lifetimes inferred from
590+ // usage one way or another) and multiple data fields with B allowed to leave out fields
591+ // from A. The current state is just the simplest choice.
615592 let a_lifetimes_count = args_a. iter ( ) . filter ( |arg| arg. as_region ( ) . is_some ( ) ) . count ( ) ;
616593 let a_data_fields = def_a
617594 . non_enum_variant ( )
618595 . fields
619596 . iter_enumerated ( )
620597 . filter_map ( |( i, f) | {
621- // Ignore PhantomData fields
622- let unnormalized_ty = tcx. type_of ( f. did ) . instantiate_identity ( ) ;
623- if tcx
624- . try_normalize_erasing_regions (
625- ty:: TypingEnv :: non_body_analysis ( tcx, def_a. did ( ) ) ,
626- unnormalized_ty,
627- )
628- . unwrap_or ( unnormalized_ty)
629- . is_phantom_data ( )
630- {
598+ let a = f. ty ( tcx, args_b) ;
599+
600+ if a. is_phantom_data ( ) {
631601 return None ;
632602 }
633603
634- let a = f. ty ( tcx, args_a) ;
635-
636- // Collect up all fields that were significantly changed.
637604 Some ( ( i, a, tcx. def_span ( f. did ) ) )
638605 } )
639606 . collect :: < Vec < _ > > ( ) ;
@@ -649,7 +616,6 @@ pub(crate) fn coerce_shared_info<'tcx>(
649616 return None ;
650617 }
651618
652- // Collect up all fields that were significantly changed.
653619 Some ( ( i, b, tcx. def_span ( f. did ) ) )
654620 } )
655621 . collect :: < Vec < _ > > ( ) ;
@@ -669,29 +635,27 @@ pub(crate) fn coerce_shared_info<'tcx>(
669635 tcx. def_span ( impl_did)
670636 } ;
671637
672- let mut fields = a_data_fields. iter ( ) . map ( |( _, _, s) | * s) . collect :: < Vec < _ > > ( ) ;
673- fields. extend ( b_data_fields. iter ( ) . map ( |( _, _, s) | * s) ) ;
674- return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceMulti {
675- span,
676- trait_name,
677- number : a_data_fields. len ( ) + b_data_fields. len ( ) ,
678- fields : fields. into ( ) ,
679- } ) ) ;
638+ return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceSharedMulti { span, trait_name } ) ) ;
680639 }
681640
682641 let kind = ty:: adjustment:: CoerceSharedInfo { } ;
683642 if a_data_fields. len ( ) == 1 {
643+ // We found one data field for both: we'll attempt to perform CoerceShared between
644+ // them below.
684645 let ( _a_i, a, span_a) = a_data_fields[ 0 ] ;
685646 let ( _b_i, b, span_b) = b_data_fields[ 0 ] ;
686647
687648 Some ( ( a, b, coerce_shared_trait, kind, span_a, span_b) )
688649 } else {
650+ // We found no data fields in either: this is a reborrowable marker type being
651+ // coerced into a shared marker. That is fine too.
689652 None
690653 }
691654 }
692655
693656 _ => {
694- return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceSharedNonStruct { span, trait_name } ) ) ;
657+ // Note: reusing CoerceUnsizedNonStruct error as it takes trait_name as argument.
658+ return Err ( tcx. dcx ( ) . emit_err ( errors:: CoerceUnsizedNonStruct { span, trait_name } ) ) ;
695659 }
696660 } ;
697661
@@ -746,12 +710,8 @@ fn assert_field_type_is_copy<'tcx>(
746710 let copy_trait = tcx. require_lang_item ( LangItem :: Copy , span) ;
747711 let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
748712 let cause = traits:: ObligationCause :: misc ( span, impl_did) ;
749- let obligation = Obligation :: new (
750- tcx,
751- cause,
752- param_env,
753- ty:: TraitRef :: new ( tcx, copy_trait, [ ty] ) ,
754- ) ;
713+ let obligation =
714+ Obligation :: new ( tcx, cause, param_env, ty:: TraitRef :: new ( tcx, copy_trait, [ ty] ) ) ;
755715 ocx. register_obligation ( obligation) ;
756716 let errors = ocx. evaluate_obligations_error_on_ambiguity ( ) ;
757717
0 commit comments