@@ -58,6 +58,7 @@ use rustc_middle::ty::error::TypeError;
58
58
use rustc_middle:: ty:: { self , AliasTy , GenericArgsRef , Ty , TyCtxt , TypeVisitableExt } ;
59
59
use rustc_span:: { BytePos , DUMMY_SP , DesugaringKind , Span } ;
60
60
use rustc_trait_selection:: infer:: InferCtxtExt as _;
61
+ use rustc_trait_selection:: traits:: EvaluationResult :: * ;
61
62
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
62
63
use rustc_trait_selection:: traits:: {
63
64
self , NormalizeExt , ObligationCause , ObligationCauseCode , ObligationCtxt ,
@@ -599,18 +600,25 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
599
600
ty:: TraitRef :: new ( self . tcx , coerce_unsized_did, [ coerce_source, coerce_target] ) ,
600
601
) ;
601
602
602
- // If the root `Source: CoerceUnsized<Target>` obligation can't possibly hold,
603
- // we don't have to assume that this is unsizing coercion (it will always lead to an error)
604
- //
605
- // However, we don't want to bail early all the time, since the unholdable obligations
606
- // may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id<This = U>`),
607
- // so we only bail if there (likely) is another way to convert the types.
608
- if let & ty:: RawPtr ( source_pointee, _) = coerce_source. kind ( )
609
- && let & ty:: RawPtr ( target_pointee, _) = target. kind ( )
610
- {
611
- if !self . infcx . predicate_may_hold ( & root_obligation) {
612
- if let Some ( dyn_metadata_adt_def_id) =
613
- self . tcx . lang_items ( ) . get ( LangItem :: DynMetadata )
603
+ match self . infcx . evaluate_obligation_no_overflow ( & root_obligation) {
604
+ // Fast path if we're definitely able to coerce. This allows us to use the
605
+ // cache of the `FulfillmentContext` and avoids manual calls to select.
606
+ EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToOkModuloOpaqueTypes => {
607
+ coercion. obligations . push ( root_obligation) ;
608
+ return Ok ( coercion) ;
609
+ }
610
+ EvaluatedToAmbig | EvaluatedToAmbigStackDependent => { }
611
+ EvaluatedToErr => {
612
+ // If the root `Source: CoerceUnsized<Target>` obligation can't possibly hold,
613
+ // we don't have to assume that this is unsizing coercion (it will always lead to an error)
614
+ //
615
+ // However, we don't want to bail early all the time, since the unholdable obligations
616
+ // may be interesting for diagnostics (such as trying to coerce `&T` to `&dyn Id<This = U>`),
617
+ // so we only bail if there (likely) is another way to convert the types.
618
+ if let & ty:: RawPtr ( source_pointee, _) = coerce_source. kind ( )
619
+ && let & ty:: RawPtr ( target_pointee, _) = target. kind ( )
620
+ && let Some ( dyn_metadata_adt_def_id) =
621
+ self . tcx . lang_items ( ) . get ( LangItem :: DynMetadata )
614
622
&& let Some ( metadata_type_def_id) =
615
623
self . tcx . lang_items ( ) . get ( LangItem :: Metadata )
616
624
{
0 commit comments