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:
parent
e95e084a14
commit
f09b1facd0
22 changed files with 135 additions and 139 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue