Skip to content

Commit

Permalink
Shrink ObligationCauseCode by boxing MatchExpressionArm.
Browse files Browse the repository at this point in the history
The reduction in `memcpy` calls greatly outweighs the cost of the extra
allocations, for a net performance win.
  • Loading branch information
nnethercote committed Sep 9, 2019
1 parent c1b9a46 commit b972ac8
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 34 deletions.
24 changes: 13 additions & 11 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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"),
Expand Down Expand Up @@ -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",
},
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
24 changes: 14 additions & 10 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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,
}
}
Expand Down Expand Up @@ -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> },
Expand Down Expand Up @@ -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> {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 } => {
Expand Down
18 changes: 10 additions & 8 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit b972ac8

Please sign in to comment.