Skip to content

Commit 41aaf68

Browse files
Fast path for coercions
1 parent d1d8e38 commit 41aaf68

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
4646
use rustc_infer::infer::relate::RelateResult;
4747
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
4848
use rustc_infer::traits::{
49-
IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
49+
EvaluationResult, IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
5050
PredicateObligations, SelectionError,
5151
};
5252
use rustc_middle::span_bug;
@@ -597,6 +597,28 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
597597

598598
// Create an obligation for `Source: CoerceUnsized<Target>`.
599599
let cause = self.cause(self.cause.span, ObligationCauseCode::Coercion { source, target });
600+
let obligation = Obligation::new(
601+
self.tcx,
602+
cause,
603+
self.fcx.param_env,
604+
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]),
605+
);
606+
607+
match self.evaluate_obligation_no_overflow(&obligation) {
608+
EvaluationResult::EvaluatedToOk
609+
| EvaluationResult::EvaluatedToOkModuloRegions
610+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes => {
611+
coercion.obligations.push(obligation);
612+
return Ok(coercion);
613+
}
614+
EvaluationResult::EvaluatedToErr => {
615+
return Err(TypeError::Mismatch);
616+
}
617+
EvaluationResult::EvaluatedToAmbig
618+
| EvaluationResult::EvaluatedToAmbigStackDependent => {
619+
// Continue...
620+
}
621+
}
600622

601623
// Use a FIFO queue for this custom fulfillment procedure.
602624
//
@@ -605,12 +627,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
605627
// and almost never more than 3. By using a SmallVec we avoid an
606628
// allocation, at the (very small) cost of (occasionally) having to
607629
// shift subsequent elements down when removing the front element.
608-
let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new(
609-
self.tcx,
610-
cause,
611-
self.fcx.param_env,
612-
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
613-
)];
630+
let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![obligation];
614631

615632
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
616633
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where

0 commit comments

Comments
 (0)