Shrink ObligationCauseCode by boxing MatchExpressionArm.
The reduction in `memcpy` calls greatly outweighs the cost of the extra allocations, for a net performance win.
This commit is contained in:
parent
c1b9a46f60
commit
b972ac818c
5 changed files with 42 additions and 34 deletions
|
|
@ -55,7 +55,7 @@ use crate::hir::def_id::DefId;
|
|||
use crate::hir::Node;
|
||||
use crate::infer::opaque_types;
|
||||
use crate::middle::region;
|
||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use crate::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode};
|
||||
use crate::ty::error::TypeError;
|
||||
use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
|
||||
|
|
@ -624,13 +624,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::MatchExpressionArm {
|
||||
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
|
||||
source,
|
||||
ref prior_arms,
|
||||
last_ty,
|
||||
discrim_hir_id,
|
||||
..
|
||||
} => match source {
|
||||
}) => match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => {
|
||||
let msg = "`if let` arms have incompatible types";
|
||||
err.span_label(cause.span, msg);
|
||||
|
|
@ -1622,13 +1622,15 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
use crate::traits::ObligationCauseCode::*;
|
||||
match self.code {
|
||||
CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
|
||||
MatchExpressionArm { source, .. } => Error0308(match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types",
|
||||
hir::MatchSource::TryDesugar => {
|
||||
"try expression alternatives have incompatible types"
|
||||
}
|
||||
_ => "match arms have incompatible types",
|
||||
}),
|
||||
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =>
|
||||
Error0308(match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } =>
|
||||
"`if let` arms have incompatible types",
|
||||
hir::MatchSource::TryDesugar => {
|
||||
"try expression alternatives have incompatible types"
|
||||
}
|
||||
_ => "match arms have incompatible types",
|
||||
}),
|
||||
IfExpression { .. } => Error0308("if and else have incompatible types"),
|
||||
IfExpressionWithNoElse => Error0317("if may be missing an else clause"),
|
||||
MainFunctionType => Error0580("main function has wrong type"),
|
||||
|
|
@ -1656,7 +1658,7 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
match self.code {
|
||||
CompareImplMethodObligation { .. } => "method type is compatible with trait",
|
||||
ExprAssignable => "expression is assignable",
|
||||
MatchExpressionArm { source, .. } => match source {
|
||||
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
|
||||
_ => "match arms have compatible types",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ pub struct PendingPredicateObligation<'tcx> {
|
|||
|
||||
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert_size!(PendingPredicateObligation<'_>, 160);
|
||||
static_assert_size!(PendingPredicateObligation<'_>, 144);
|
||||
|
||||
impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
/// Creates a new fulfillment context.
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
|
|||
|
||||
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert_size!(PredicateObligation<'_>, 136);
|
||||
static_assert_size!(PredicateObligation<'_>, 120);
|
||||
|
||||
/// The reason why we incurred this obligation; used for error reporting.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
|
|
@ -151,7 +151,8 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
ObligationCauseCode::StartFunctionType => {
|
||||
tcx.sess.source_map().def_span(self.span)
|
||||
}
|
||||
ObligationCauseCode::MatchExpressionArm { arm_span, .. } => arm_span,
|
||||
ObligationCauseCode::MatchExpressionArm(
|
||||
box MatchExpressionArmCause { arm_span, .. }) => arm_span,
|
||||
_ => self.span,
|
||||
}
|
||||
}
|
||||
|
|
@ -227,13 +228,7 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
ExprAssignable,
|
||||
|
||||
/// Computing common supertype in the arms of a match expression
|
||||
MatchExpressionArm {
|
||||
arm_span: Span,
|
||||
source: hir::MatchSource,
|
||||
prior_arms: Vec<Span>,
|
||||
last_ty: Ty<'tcx>,
|
||||
discrim_hir_id: hir::HirId,
|
||||
},
|
||||
MatchExpressionArm(Box<MatchExpressionArmCause<'tcx>>),
|
||||
|
||||
/// Computing common supertype in the pattern guard for the arms of a match expression
|
||||
MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
|
||||
|
|
@ -275,7 +270,16 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
|
||||
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert_size!(ObligationCauseCode<'_>, 56);
|
||||
static_assert_size!(ObligationCauseCode<'_>, 40);
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct MatchExpressionArmCause<'tcx> {
|
||||
pub arm_span: Span,
|
||||
pub source: hir::MatchSource,
|
||||
pub prior_arms: Vec<Span>,
|
||||
pub last_ty: Ty<'tcx>,
|
||||
pub discrim_hir_id: hir::HirId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct DerivedObligationCause<'tcx> {
|
||||
|
|
|
|||
|
|
@ -508,21 +508,21 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
|||
trait_item_def_id,
|
||||
}),
|
||||
super::ExprAssignable => Some(super::ExprAssignable),
|
||||
super::MatchExpressionArm {
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
ref prior_arms,
|
||||
last_ty,
|
||||
discrim_hir_id,
|
||||
} => {
|
||||
}) => {
|
||||
tcx.lift(&last_ty).map(|last_ty| {
|
||||
super::MatchExpressionArm {
|
||||
super::MatchExpressionArm(box super::MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source,
|
||||
prior_arms: prior_arms.clone(),
|
||||
last_ty,
|
||||
discrim_hir_id,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
super::MatchExpressionArmPattern { span, ty } => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::check::{FnCtxt, Expectation, Diverges, Needs};
|
|||
use crate::check::coercion::CoerceMany;
|
||||
use rustc::hir::{self, ExprKind};
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode};
|
||||
use rustc::ty::Ty;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
|
@ -146,13 +146,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// The reason for the first arm to fail is not that the match arms diverge,
|
||||
// but rather that there's a prior obligation that doesn't hold.
|
||||
0 => (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id)),
|
||||
_ => (expr.span, ObligationCauseCode::MatchExpressionArm {
|
||||
arm_span,
|
||||
source: match_src,
|
||||
prior_arms: other_arms.clone(),
|
||||
last_ty: prior_arm_ty.unwrap(),
|
||||
discrim_hir_id: discrim.hir_id,
|
||||
}),
|
||||
_ => (expr.span,
|
||||
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
|
||||
arm_span,
|
||||
source: match_src,
|
||||
prior_arms: other_arms.clone(),
|
||||
last_ty: prior_arm_ty.unwrap(),
|
||||
discrim_hir_id: discrim.hir_id,
|
||||
})
|
||||
),
|
||||
};
|
||||
let cause = self.cause(span, code);
|
||||
coercion.coerce(self, &cause, &arm.body, arm_ty);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue