@@ -660,125 +660,143 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
660660 return Err ( TypeError :: Mismatch ) ;
661661 }
662662 } else {
663- let mut selcx = traits:: SelectionContext :: new ( self ) ;
664- // Use a FIFO queue for this custom fulfillment procedure.
665- //
666- // A Vec (or SmallVec) is not a natural choice for a queue. However,
667- // this code path is hot, and this queue usually has a max length of 1
668- // and almost never more than 3. By using a SmallVec we avoid an
669- // allocation, at the (very small) cost of (occasionally) having to
670- // shift subsequent elements down when removing the front element.
671- let mut queue: SmallVec < [ PredicateObligation < ' tcx > ; 4 ] > = smallvec ! [ obligation] ;
672-
673- // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
674- // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
675- // inference might unify those two inner type variables later.
676- let traits = [ coerce_unsized_did, unsize_did] ;
677- while !queue. is_empty ( ) {
678- let obligation = queue. remove ( 0 ) ;
679- let trait_pred = match obligation. predicate . kind ( ) . no_bound_vars ( ) {
680- Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( trait_pred) ) )
681- if traits. contains ( & trait_pred. def_id ( ) ) =>
682- {
683- self . resolve_vars_if_possible ( trait_pred)
684- }
685- // Eagerly process alias-relate obligations in new trait solver,
686- // since these can be emitted in the process of solving trait goals,
687- // but we need to constrain vars before processing goals mentioning
688- // them.
689- Some ( ty:: PredicateKind :: AliasRelate ( ..) ) => {
690- let ocx = ObligationCtxt :: new ( self ) ;
691- ocx. register_obligation ( obligation) ;
692- if !ocx. try_evaluate_obligations ( ) . is_empty ( ) {
693- return Err ( TypeError :: Mismatch ) ;
694- }
695- coercion. obligations . extend ( ocx. into_pending_obligations ( ) ) ;
696- continue ;
697- }
698- _ => {
699- coercion. obligations . push ( obligation) ;
700- continue ;
663+ self . coerece_unsized_old_solver (
664+ obligation,
665+ & mut coercion,
666+ coerce_unsized_did,
667+ unsize_did,
668+ ) ?;
669+ }
670+
671+ Ok ( coercion)
672+ }
673+
674+ fn coerece_unsized_old_solver (
675+ & self ,
676+ obligation : Obligation < ' tcx , ty:: Predicate < ' tcx > > ,
677+ coercion : & mut InferOk < ' tcx , ( Vec < Adjustment < ' tcx > > , Ty < ' tcx > ) > ,
678+ coerce_unsized_did : DefId ,
679+ unsize_did : DefId ,
680+ ) -> Result < ( ) , TypeError < ' tcx > > {
681+ let mut selcx = traits:: SelectionContext :: new ( self ) ;
682+ // Use a FIFO queue for this custom fulfillment procedure.
683+ //
684+ // A Vec (or SmallVec) is not a natural choice for a queue. However,
685+ // this code path is hot, and this queue usually has a max length of 1
686+ // and almost never more than 3. By using a SmallVec we avoid an
687+ // allocation, at the (very small) cost of (occasionally) having to
688+ // shift subsequent elements down when removing the front element.
689+ let mut queue: SmallVec < [ PredicateObligation < ' tcx > ; 4 ] > = smallvec ! [ obligation] ;
690+
691+ // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
692+ // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
693+ // inference might unify those two inner type variables later.
694+ let traits = [ coerce_unsized_did, unsize_did] ;
695+ while !queue. is_empty ( ) {
696+ let obligation = queue. remove ( 0 ) ;
697+ let trait_pred = match obligation. predicate . kind ( ) . no_bound_vars ( ) {
698+ Some ( ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( trait_pred) ) )
699+ if traits. contains ( & trait_pred. def_id ( ) ) =>
700+ {
701+ self . resolve_vars_if_possible ( trait_pred)
702+ }
703+ // Eagerly process alias-relate obligations in new trait solver,
704+ // since these can be emitted in the process of solving trait goals,
705+ // but we need to constrain vars before processing goals mentioning
706+ // them.
707+ Some ( ty:: PredicateKind :: AliasRelate ( ..) ) => {
708+ let ocx = ObligationCtxt :: new ( self ) ;
709+ ocx. register_obligation ( obligation) ;
710+ if !ocx. try_evaluate_obligations ( ) . is_empty ( ) {
711+ return Err ( TypeError :: Mismatch ) ;
701712 }
702- } ;
703- debug ! ( "coerce_unsized resolve step: {:?}" , trait_pred) ;
704- match selcx. select ( & obligation. with ( selcx. tcx ( ) , trait_pred) ) {
705- // Uncertain or unimplemented.
706- Ok ( None ) => {
707- if trait_pred. def_id ( ) == unsize_did {
708- let self_ty = trait_pred. self_ty ( ) ;
709- let unsize_ty = trait_pred. trait_ref . args [ 1 ] . expect_ty ( ) ;
710- debug ! ( "coerce_unsized: ambiguous unsize case for {:?}" , trait_pred) ;
711- match ( self_ty. kind ( ) , unsize_ty. kind ( ) ) {
712- ( & ty:: Infer ( ty:: TyVar ( v) ) , ty:: Dynamic ( ..) )
713- if self . type_var_is_sized ( v) =>
714- {
715- debug ! ( "coerce_unsized: have sized infer {:?}" , v) ;
716- coercion. obligations . push ( obligation) ;
717- // `$0: Unsize<dyn Trait>` where we know that `$0: Sized`, try going
718- // for unsizing.
719- }
720- _ => {
721- // Some other case for `$0: Unsize<Something>`. Note that we
722- // hit this case even if `Something` is a sized type, so just
723- // don't do the coercion.
724- debug ! ( "coerce_unsized: ambiguous unsize" ) ;
725- return Err ( TypeError :: Mismatch ) ;
726- }
713+ coercion. obligations . extend ( ocx. into_pending_obligations ( ) ) ;
714+ continue ;
715+ }
716+ _ => {
717+ coercion. obligations . push ( obligation) ;
718+ continue ;
719+ }
720+ } ;
721+ debug ! ( "coerce_unsized resolve step: {:?}" , trait_pred) ;
722+ match selcx. select ( & obligation. with ( selcx. tcx ( ) , trait_pred) ) {
723+ // Uncertain or unimplemented.
724+ Ok ( None ) => {
725+ if trait_pred. def_id ( ) == unsize_did {
726+ let self_ty = trait_pred. self_ty ( ) ;
727+ let unsize_ty = trait_pred. trait_ref . args [ 1 ] . expect_ty ( ) ;
728+ debug ! ( "coerce_unsized: ambiguous unsize case for {:?}" , trait_pred) ;
729+ match ( self_ty. kind ( ) , unsize_ty. kind ( ) ) {
730+ ( & ty:: Infer ( ty:: TyVar ( v) ) , ty:: Dynamic ( ..) )
731+ if self . type_var_is_sized ( v) =>
732+ {
733+ debug ! ( "coerce_unsized: have sized infer {:?}" , v) ;
734+ coercion. obligations . push ( obligation) ;
735+ // `$0: Unsize<dyn Trait>` where we know that `$0: Sized`, try going
736+ // for unsizing.
737+ }
738+ _ => {
739+ // Some other case for `$0: Unsize<Something>`. Note that we
740+ // hit this case even if `Something` is a sized type, so just
741+ // don't do the coercion.
742+ debug ! ( "coerce_unsized: ambiguous unsize" ) ;
743+ return Err ( TypeError :: Mismatch ) ;
727744 }
728- } else {
729- debug ! ( "coerce_unsized: early return - ambiguous" ) ;
730- return Err ( TypeError :: Mismatch ) ;
731745 }
732- }
733- Err ( SelectionError :: Unimplemented ) => {
734- debug ! ( "coerce_unsized: early return - can't prove obligation" ) ;
746+ } else {
747+ debug ! ( "coerce_unsized: early return - ambiguous" ) ;
735748 return Err ( TypeError :: Mismatch ) ;
736749 }
750+ }
751+ Err ( SelectionError :: Unimplemented ) => {
752+ debug ! ( "coerce_unsized: early return - can't prove obligation" ) ;
753+ return Err ( TypeError :: Mismatch ) ;
754+ }
737755
738- Err ( SelectionError :: TraitDynIncompatible ( _) ) => {
739- // Dyn compatibility errors in coercion will *always* be due to the
740- // fact that the RHS of the coercion is a non-dyn compatible `dyn Trait`
741- // writen in source somewhere (otherwise we will never have lowered
742- // the dyn trait from HIR to middle).
743- //
744- // There's no reason to emit yet another dyn compatibility error,
745- // especially since the span will differ slightly and thus not be
746- // deduplicated at all!
747- self . fcx . set_tainted_by_errors ( self . fcx . dcx ( ) . span_delayed_bug (
748- self . cause . span ,
749- "dyn compatibility during coercion" ,
750- ) ) ;
751- }
752- Err ( err) => {
753- let guar = self . err_ctxt ( ) . report_selection_error (
754- obligation. clone ( ) ,
755- & obligation,
756- & err,
757- ) ;
756+ Err ( SelectionError :: TraitDynIncompatible ( _) ) => {
757+ // Dyn compatibility errors in coercion will *always* be due to the
758+ // fact that the RHS of the coercion is a non-dyn compatible `dyn Trait`
759+ // writen in source somewhere (otherwise we will never have lowered
760+ // the dyn trait from HIR to middle).
761+ //
762+ // There's no reason to emit yet another dyn compatibility error,
763+ // especially since the span will differ slightly and thus not be
764+ // deduplicated at all!
765+ self . fcx . set_tainted_by_errors (
766+ self . fcx
767+ . dcx ( )
768+ . span_delayed_bug ( self . cause . span , "dyn compatibility during coercion" ) ,
769+ ) ;
770+ }
771+ Err ( err) => {
772+ let guar = self . err_ctxt ( ) . report_selection_error (
773+ obligation. clone ( ) ,
774+ & obligation,
775+ & err,
776+ ) ;
777+ self . fcx . set_tainted_by_errors ( guar) ;
778+ // Treat this like an obligation and follow through
779+ // with the unsizing - the lack of a coercion should
780+ // be silent, as it causes a type mismatch later.
781+ }
782+ Ok ( Some ( ImplSource :: UserDefined ( impl_source) ) ) => {
783+ queue. extend ( impl_source. nested ) ;
784+ // Certain incoherent `CoerceUnsized` implementations may cause ICEs,
785+ // so check the impl's validity. Taint the body so that we don't try
786+ // to evaluate these invalid coercions in CTFE. We only need to do this
787+ // for local impls, since upstream impls should be valid.
788+ if impl_source. impl_def_id . is_local ( )
789+ && let Err ( guar) =
790+ self . tcx . ensure_ok ( ) . coerce_unsized_info ( impl_source. impl_def_id )
791+ {
758792 self . fcx . set_tainted_by_errors ( guar) ;
759- // Treat this like an obligation and follow through
760- // with the unsizing - the lack of a coercion should
761- // be silent, as it causes a type mismatch later.
762793 }
763- Ok ( Some ( ImplSource :: UserDefined ( impl_source) ) ) => {
764- queue. extend ( impl_source. nested ) ;
765- // Certain incoherent `CoerceUnsized` implementations may cause ICEs,
766- // so check the impl's validity. Taint the body so that we don't try
767- // to evaluate these invalid coercions in CTFE. We only need to do this
768- // for local impls, since upstream impls should be valid.
769- if impl_source. impl_def_id . is_local ( )
770- && let Err ( guar) =
771- self . tcx . ensure_ok ( ) . coerce_unsized_info ( impl_source. impl_def_id )
772- {
773- self . fcx . set_tainted_by_errors ( guar) ;
774- }
775- }
776- Ok ( Some ( impl_source) ) => queue. extend ( impl_source. nested_obligations ( ) ) ,
777794 }
795+ Ok ( Some ( impl_source) ) => queue. extend ( impl_source. nested_obligations ( ) ) ,
778796 }
779797 }
780798
781- Ok ( coercion )
799+ Ok ( ( ) )
782800 }
783801
784802 /// Applies reborrowing for `Pin`
0 commit comments