1
Fork 0

Eliminate ObligationCauseData.

This makes `Obligation` two words bigger, but avoids allocating a lot of
the time.

I previously tried this in #73983 and it didn't help much, but local
timings look more promising now.
This commit is contained in:
Nicholas Nethercote 2021-11-11 12:01:12 +11:00 committed by Nicholas Nethercote
parent e95e084a14
commit f09b1facd0
22 changed files with 135 additions and 139 deletions

View file

@ -205,7 +205,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code(
&mut err,
&obligation.predicate,
&obligation.cause.code,
obligation.cause.code(),
&mut vec![],
&mut Default::default(),
);
@ -255,7 +255,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// If this obligation was generated as a result of well-formedness checking, see if we
// can get a better error message by performing HIR-based well-formedness checking.
if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
root_obligation.cause.code.peel_derives()
root_obligation.cause.code().peel_derives()
{
if let Some(cause) = self
.tcx
@ -272,7 +272,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
| ObligationCauseCode::CompareImplTypeObligation {
impl_item_def_id,
trait_item_def_id,
} = obligation.cause.code
} = *obligation.cause.code()
{
self.report_extra_impl_obligation(
span,
@ -295,7 +295,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
let trait_ref = trait_predicate.to_poly_trait_ref();
let (post_message, pre_message, type_def) = self
.get_parent_trait_ref(&obligation.cause.code)
.get_parent_trait_ref(obligation.cause.code())
.map(|(t, s)| {
(
format!(" in `{}`", t),
@ -376,17 +376,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
let explanation =
if obligation.cause.code == ObligationCauseCode::MainFunctionType {
"consider using `()`, or a `Result`".to_owned()
} else {
format!(
"{}the trait `{}` is not implemented for `{}`",
pre_message,
trait_ref.print_only_trait_path(),
trait_ref.skip_binder().self_ty(),
)
};
let explanation = if let ObligationCauseCode::MainFunctionType =
obligation.cause.code()
{
"consider using `()`, or a `Result`".to_owned()
} else {
format!(
"{}the trait `{}` is not implemented for `{}`",
pre_message,
trait_ref.print_only_trait_path(),
trait_ref.skip_binder().self_ty(),
)
};
if self.suggest_add_reference_to_arg(
&obligation,
@ -1305,7 +1306,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
);
let is_normalized_ty_expected = !matches!(
obligation.cause.code.peel_derives(),
obligation.cause.code().peel_derives(),
ObligationCauseCode::ItemObligation(_)
| ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ObjectCastObligation(_)
@ -1620,9 +1621,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
let predicate = self.resolve_vars_if_possible(obligation.predicate);
let span = obligation.cause.span;
debug!(
?predicate, ?obligation.cause.code,
);
debug!(?predicate, obligation.cause.code = tracing::field::debug(&obligation.cause.code()));
// Ambiguity errors are often caused as fallout from earlier errors.
// We ignore them if this `infcx` is tainted in some cases below.
@ -1717,13 +1716,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
}
}
if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
if let ObligationCauseCode::ItemObligation(def_id) = *obligation.cause.code() {
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
} else if let (
Ok(ref snippet),
ObligationCauseCode::BindingObligation(ref def_id, _),
) =
(self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
(self.tcx.sess.source_map().span_to_snippet(span), obligation.cause.code())
{
let generics = self.tcx.generics_of(*def_id);
if generics.params.iter().any(|p| p.name != kw::SelfUpper)
@ -2006,7 +2005,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code(
err,
&obligation.predicate,
&obligation.cause.code,
obligation.cause.code(),
&mut vec![],
&mut Default::default(),
);
@ -2019,15 +2018,16 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
err: &mut DiagnosticBuilder<'tcx>,
obligation: &PredicateObligation<'tcx>,
) {
let (pred, item_def_id, span) =
match (obligation.predicate.kind().skip_binder(), obligation.cause.code.peel_derives())
{
(
ty::PredicateKind::Trait(pred),
&ObligationCauseCode::BindingObligation(item_def_id, span),
) => (pred, item_def_id, span),
_ => return,
};
let (pred, item_def_id, span) = match (
obligation.predicate.kind().skip_binder(),
obligation.cause.code().peel_derives(),
) {
(
ty::PredicateKind::Trait(pred),
&ObligationCauseCode::BindingObligation(item_def_id, span),
) => (pred, item_def_id, span),
_ => return,
};
debug!(
"suggest_unsized_bound_if_applicable: pred={:?} item_def_id={:?} span={:?}",
pred, item_def_id, span

View file

@ -129,7 +129,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
)];
match obligation.cause.code {
match obligation.cause.code() {
ObligationCauseCode::BuiltinDerivedObligation(..)
| ObligationCauseCode::ImplDerivedObligation(..)
| ObligationCauseCode::DerivedObligation(..) => {}
@ -141,7 +141,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
if let ObligationCauseCode::ItemObligation(item)
| ObligationCauseCode::BindingObligation(item, _) = obligation.cause.code
| ObligationCauseCode::BindingObligation(item, _) = *obligation.cause.code()
{
// FIXME: maybe also have some way of handling methods
// from other traits? That would require name resolution,

View file

@ -9,7 +9,6 @@ use crate::traits::normalize_projection_type;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
};
@ -497,7 +496,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
) {
// It only make sense when suggesting dereferences for arguments
let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
&obligation.cause.code
obligation.cause.code()
{
parent_code.clone()
} else {
@ -662,7 +661,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
_ => return,
};
if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) {
if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
{
// When the obligation error has been ensured to have been caused by
// an argument, the `obligation.cause.span` points at the expression
// of the argument, so we can provide a suggestion. Otherwise, we give
@ -688,13 +688,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let span = obligation.cause.span;
let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
&obligation.cause.code
obligation.cause.code()
{
parent_code.clone()
&parent_code
} else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
span.ctxt().outer_expn_data().kind
{
Lrc::new(obligation.cause.code.clone())
obligation.cause.code()
} else {
return false;
};
@ -805,10 +805,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return false;
};
if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
if let ObligationCauseCode::ImplDerivedObligation(obligation) = code {
try_borrowing(obligation.parent_trait_ref, &[])
} else if let ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ItemObligation(_) = &*code
| ObligationCauseCode::ItemObligation(_) = code
{
try_borrowing(*poly_trait_ref, &never_suggest_borrow)
} else {
@ -886,7 +886,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
) {
let span = obligation.cause.span;
if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code.peel_derives() {
if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() {
let hir = self.tcx.hir();
if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) {
if let hir::Node::Expr(expr) = node {
@ -945,7 +945,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
) {
let points_at_arg = matches!(
obligation.cause.code,
obligation.cause.code(),
ObligationCauseCode::FunctionArgumentObligation { .. },
);
@ -1072,7 +1072,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
) -> bool {
match obligation.cause.code.peel_derives() {
match obligation.cause.code().peel_derives() {
// Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
ObligationCauseCode::SizedReturnType => {}
_ => return false,
@ -1267,7 +1267,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
) {
match obligation.cause.code.peel_derives() {
match obligation.cause.code().peel_derives() {
ObligationCauseCode::SizedReturnType => {}
_ => return,
}
@ -1461,7 +1461,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
};
let mut generator = None;
let mut outer_generator = None;
let mut next_code = Some(&obligation.cause.code);
let mut next_code = Some(obligation.cause.code());
let mut seen_upvar_tys_infer_tuple = false;

View file

@ -96,7 +96,7 @@ pub struct PendingPredicateObligation<'tcx> {
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PendingPredicateObligation<'_>, 56);
static_assert_size!(PendingPredicateObligation<'_>, 72);
impl<'a, 'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.

View file

@ -29,7 +29,6 @@ use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@ -2384,7 +2383,7 @@ impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
// by using -Z verbose or just a CLI argument.
let derived_cause = DerivedObligationCause {
parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
parent_code: Lrc::new(obligation.cause.code.clone()),
parent_code: obligation.cause.clone_code(),
};
let derived_code = variant(derived_cause);
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)

View file

@ -232,7 +232,7 @@ pub fn predicates_for_generics<'tcx>(
debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| {
let cause = match cause.code {
let cause = match *cause.code() {
traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new(
cause.span,
cause.body_id,

View file

@ -1,7 +1,6 @@
use crate::infer::InferCtxt;
use crate::opaque_types::required_region_bounds;
use crate::traits;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
@ -227,7 +226,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
if let Some(impl_item_span) =
items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span)
{
cause.make_mut().span = impl_item_span;
cause.span = impl_item_span;
}
}
}
@ -242,7 +241,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span)
})
{
cause.make_mut().span = impl_item_span;
cause.span = impl_item_span;
}
}
}
@ -302,9 +301,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let derived_cause = traits::DerivedObligationCause {
// FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate
parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref),
parent_code: Lrc::new(obligation.cause.code.clone()),
parent_code: obligation.cause.clone_code(),
};
cause.make_mut().code =
*cause.make_mut_code() =
traits::ObligationCauseCode::DerivedObligation(derived_cause);
}
extend_cause_with_original_assoc_item_obligation(
@ -343,7 +342,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) =
item.map(|i| &i.kind)
{
new_cause.make_mut().span = self_ty.span;
new_cause.span = self_ty.span;
}
}
traits::Obligation::with_depth(