Skip to content

Commit 363d339

Browse files
committed
alternative 2
1 parent e57808d commit 363d339

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+20-12
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use rustc_middle::ty::error::TypeError;
5858
use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
5959
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
6060
use rustc_trait_selection::infer::InferCtxtExt as _;
61+
use rustc_trait_selection::traits::EvaluationResult::*;
6162
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
6263
use rustc_trait_selection::traits::{
6364
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
@@ -599,18 +600,25 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
599600
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]),
600601
);
601602

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)
614622
&& let Some(metadata_type_def_id) =
615623
self.tcx.lang_items().get(LangItem::Metadata)
616624
{

0 commit comments

Comments
 (0)