Shrink ObligationCauseCode by boxing IfExpression.

The reduction in `memcpy` calls outweighs the cost of the extra
allocations, for a net performance win.
This commit is contained in:
Nicholas Nethercote 2019-09-09 12:40:54 +10:00
parent b972ac818c
commit 2e3b079836
5 changed files with 25 additions and 18 deletions

View file

@ -55,7 +55,8 @@ use crate::hir::def_id::DefId;
use crate::hir::Node;
use crate::infer::opaque_types;
use crate::middle::region;
use crate::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode};
use crate::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
use crate::traits::{ObligationCauseCode};
use crate::ty::error::TypeError;
use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
@ -681,7 +682,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
},
ObligationCauseCode::IfExpression { then, outer, semicolon } => {
ObligationCauseCode::IfExpression(box IfExpressionCause { then, outer, semicolon }) => {
err.span_label(then, "expected because of this");
outer.map(|sp| err.span_label(sp, "if and else have incompatible types"));
if let Some(sp) = semicolon {

View file

@ -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<'_>, 144);
static_assert_size!(PendingPredicateObligation<'_>, 136);
impl<'a, 'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.

View file

@ -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<'_>, 120);
static_assert_size!(PredicateObligation<'_>, 112);
/// The reason why we incurred this obligation; used for error reporting.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@ -234,11 +234,7 @@ pub enum ObligationCauseCode<'tcx> {
MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
/// Computing common supertype in an if expression
IfExpression {
then: Span,
outer: Option<Span>,
semicolon: Option<Span>,
},
IfExpression(Box<IfExpressionCause>),
/// Computing common supertype of an if expression with no else counter-part
IfExpressionWithNoElse,
@ -270,7 +266,7 @@ 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<'_>, 40);
static_assert_size!(ObligationCauseCode<'_>, 32);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct MatchExpressionArmCause<'tcx> {
@ -281,6 +277,13 @@ pub struct MatchExpressionArmCause<'tcx> {
pub discrim_hir_id: hir::HirId,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct IfExpressionCause {
pub then: Span,
pub outer: Option<Span>,
pub semicolon: Option<Span>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DerivedObligationCause<'tcx> {
/// The trait reference of the parent obligation that led to the

View file

@ -528,11 +528,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
super::MatchExpressionArmPattern { span, ty } => {
tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
}
super::IfExpression { then, outer, semicolon } => Some(super::IfExpression {
then,
outer,
semicolon,
}),
super::IfExpression(box super::IfExpressionCause { then, outer, semicolon }) => {
Some(super::IfExpression(box super::IfExpressionCause {
then,
outer,
semicolon,
}))
}
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
super::MainFunctionType => Some(super::MainFunctionType),
super::StartFunctionType => Some(super::StartFunctionType),

View file

@ -2,7 +2,8 @@ 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::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode};
use rustc::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
use rustc::traits::{ObligationCauseCode};
use rustc::ty::Ty;
use syntax_pos::Span;
@ -347,11 +348,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Finally construct the cause:
self.cause(error_sp, ObligationCauseCode::IfExpression {
self.cause(error_sp, ObligationCauseCode::IfExpression(box IfExpressionCause {
then: then_sp,
outer: outer_sp,
semicolon: remove_semicolon,
})
}))
}
fn demand_discriminant_type(