Use InternedObligationCauseCode everywhere

This commit is contained in:
Oli Scherer 2022-05-10 12:01:56 +00:00
parent 213c17486e
commit 824e9e47f7
4 changed files with 33 additions and 42 deletions

View File

@ -97,9 +97,7 @@ pub struct ObligationCause<'tcx> {
/// information. /// information.
pub body_id: hir::HirId, pub body_id: hir::HirId,
/// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of code: InternedObligationCauseCode<'tcx>,
/// the time). `Some` otherwise.
code: Option<Lrc<ObligationCauseCode<'tcx>>>,
} }
// This custom hash function speeds up hashing for `Obligation` deduplication // This custom hash function speeds up hashing for `Obligation` deduplication
@ -123,11 +121,7 @@ pub fn new(
body_id: hir::HirId, body_id: hir::HirId,
code: ObligationCauseCode<'tcx>, code: ObligationCauseCode<'tcx>,
) -> ObligationCause<'tcx> { ) -> ObligationCause<'tcx> {
ObligationCause { ObligationCause { span, body_id, code: code.into() }
span,
body_id,
code: if code == MISC_OBLIGATION_CAUSE_CODE { None } else { Some(Lrc::new(code)) },
}
} }
pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> { pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
@ -136,11 +130,11 @@ pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
#[inline(always)] #[inline(always)]
pub fn dummy() -> ObligationCause<'tcx> { pub fn dummy() -> ObligationCause<'tcx> {
ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: None } ObligationCause::dummy_with_span(DUMMY_SP)
} }
pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> { pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> {
ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: None } ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: Default::default() }
} }
pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span { pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
@ -160,14 +154,14 @@ pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
#[inline] #[inline]
pub fn code(&self) -> &ObligationCauseCode<'tcx> { pub fn code(&self) -> &ObligationCauseCode<'tcx> {
self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE) &self.code
} }
pub fn map_code( pub fn map_code(
&mut self, &mut self,
f: impl FnOnce(InternedObligationCauseCode<'tcx>) -> Lrc<ObligationCauseCode<'tcx>>, f: impl FnOnce(InternedObligationCauseCode<'tcx>) -> ObligationCauseCode<'tcx>,
) { ) {
self.code = Some(f(InternedObligationCauseCode { code: self.code.take() })); self.code = f(std::mem::take(&mut self.code)).into();
} }
pub fn derived_cause( pub fn derived_cause(
@ -188,10 +182,8 @@ pub fn derived_cause(
// NOTE(flaper87): As of now, it keeps track of the whole error // NOTE(flaper87): As of now, it keeps track of the whole error
// chain. Ideally, we should have a way to configure this either // chain. Ideally, we should have a way to configure this either
// by using -Z verbose or just a CLI argument. // by using -Z verbose or just a CLI argument.
self.code = Some( self.code =
variant(DerivedObligationCause { parent_trait_pred, parent_code: self.code.take() }) variant(DerivedObligationCause { parent_trait_pred, parent_code: self.code }).into();
.into(),
);
self self
} }
} }
@ -203,11 +195,19 @@ pub struct UnifyReceiverContext<'tcx> {
pub substs: SubstsRef<'tcx>, pub substs: SubstsRef<'tcx>,
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, Default)]
pub struct InternedObligationCauseCode<'tcx> { pub struct InternedObligationCauseCode<'tcx> {
/// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of
/// the time). `Some` otherwise.
code: Option<Lrc<ObligationCauseCode<'tcx>>>, code: Option<Lrc<ObligationCauseCode<'tcx>>>,
} }
impl<'tcx> From<ObligationCauseCode<'tcx>> for InternedObligationCauseCode<'tcx> {
fn from(code: ObligationCauseCode<'tcx>) -> Self {
Self { code: if code == MISC_OBLIGATION_CAUSE_CODE { None } else { Some(Lrc::new(code)) } }
}
}
impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> { impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
type Target = ObligationCauseCode<'tcx>; type Target = ObligationCauseCode<'tcx>;
@ -454,7 +454,7 @@ pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
BuiltinDerivedObligation(derived) BuiltinDerivedObligation(derived)
| DerivedObligation(derived) | DerivedObligation(derived)
| ImplDerivedObligation(box ImplDerivedObligationCause { derived, .. }) => { | ImplDerivedObligation(box ImplDerivedObligationCause { derived, .. }) => {
Some((derived.parent_code(), Some(derived.parent_trait_pred))) Some((&derived.parent_code, Some(derived.parent_trait_pred)))
} }
_ => None, _ => None,
} }
@ -508,15 +508,7 @@ pub struct DerivedObligationCause<'tcx> {
pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>, pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
/// The parent trait had this cause. /// The parent trait had this cause.
parent_code: Option<Lrc<ObligationCauseCode<'tcx>>>, pub parent_code: InternedObligationCauseCode<'tcx>,
}
impl<'tcx> DerivedObligationCause<'tcx> {
/// Get a reference to the derived obligation cause's parent code.
#[must_use]
pub fn parent_code(&self) -> &ObligationCauseCode<'tcx> {
self.parent_code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE)
}
} }
#[derive(Clone, Debug, TypeFoldable, Lift)] #[derive(Clone, Debug, TypeFoldable, Lift)]

View File

@ -1868,7 +1868,7 @@ fn get_parent_trait_ref(
match code { match code {
ObligationCauseCode::BuiltinDerivedObligation(data) => { ObligationCauseCode::BuiltinDerivedObligation(data) => {
let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
match self.get_parent_trait_ref(data.parent_code()) { match self.get_parent_trait_ref(&data.parent_code) {
Some(t) => Some(t), Some(t) => Some(t),
None => { None => {
let ty = parent_trait_ref.skip_binder().self_ty(); let ty = parent_trait_ref.skip_binder().self_ty();

View File

@ -1683,7 +1683,7 @@ fn maybe_note_obligation_cause_for_async_await(
_ => {} _ => {}
} }
next_code = Some(cause.derived.parent_code()); next_code = Some(&cause.derived.parent_code);
} }
ObligationCauseCode::DerivedObligation(derived_obligation) ObligationCauseCode::DerivedObligation(derived_obligation)
| ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => { | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
@ -1715,7 +1715,7 @@ fn maybe_note_obligation_cause_for_async_await(
_ => {} _ => {}
} }
next_code = Some(derived_obligation.parent_code()); next_code = Some(&derived_obligation.parent_code);
} }
_ => break, _ => break,
} }
@ -2365,7 +2365,7 @@ fn note_obligation_cause_code<T>(
let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) { let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) {
false false
} else { } else {
if let ObligationCauseCode::BuiltinDerivedObligation(data) = data.parent_code() if let ObligationCauseCode::BuiltinDerivedObligation(data) = &*data.parent_code
{ {
let parent_trait_ref = let parent_trait_ref =
self.resolve_vars_if_possible(data.parent_trait_pred); self.resolve_vars_if_possible(data.parent_trait_pred);
@ -2392,14 +2392,14 @@ fn note_obligation_cause_code<T>(
obligated_types.push(ty); obligated_types.push(ty);
let parent_predicate = parent_trait_ref.to_predicate(tcx); let parent_predicate = parent_trait_ref.to_predicate(tcx);
if !self.is_recursive_obligation(obligated_types, data.parent_code()) { if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
// #74711: avoid a stack overflow // #74711: avoid a stack overflow
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&parent_predicate, &parent_predicate,
param_env, param_env,
data.parent_code(), &data.parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
) )
@ -2410,7 +2410,7 @@ fn note_obligation_cause_code<T>(
err, err,
&parent_predicate, &parent_predicate,
param_env, param_env,
&cause_code.peel_derives(), cause_code.peel_derives(),
obligated_types, obligated_types,
seen_requirements, seen_requirements,
) )
@ -2461,7 +2461,7 @@ fn note_obligation_cause_code<T>(
// We don't want to point at the ADT saying "required because it appears within // We don't want to point at the ADT saying "required because it appears within
// the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`. // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`.
while let ObligationCauseCode::BuiltinDerivedObligation(derived) = while let ObligationCauseCode::BuiltinDerivedObligation(derived) =
data.parent_code() &*data.parent_code
{ {
let child_trait_ref = let child_trait_ref =
self.resolve_vars_if_possible(derived.parent_trait_pred); self.resolve_vars_if_possible(derived.parent_trait_pred);
@ -2474,7 +2474,7 @@ fn note_obligation_cause_code<T>(
parent_trait_pred = child_trait_ref; parent_trait_pred = child_trait_ref;
} }
} }
while let ObligationCauseCode::ImplDerivedObligation(child) = data.parent_code() { while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code {
// Skip redundant recursive obligation notes. See `ui/issue-20413.rs`. // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
let child_trait_pred = let child_trait_pred =
self.resolve_vars_if_possible(child.derived.parent_trait_pred); self.resolve_vars_if_possible(child.derived.parent_trait_pred);
@ -2505,7 +2505,7 @@ fn note_obligation_cause_code<T>(
err, err,
&parent_predicate, &parent_predicate,
param_env, param_env,
data.parent_code(), &data.parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
) )
@ -2520,7 +2520,7 @@ fn note_obligation_cause_code<T>(
err, err,
&parent_predicate, &parent_predicate,
param_env, param_env,
data.parent_code(), &data.parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
) )

View File

@ -1606,9 +1606,9 @@ fn unpeel_to_top<'a, 'tcx>(
let mut result_code = code; let mut result_code = code;
loop { loop {
let parent = match code { let parent = match code {
ObligationCauseCode::ImplDerivedObligation(c) => c.derived.parent_code(), ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
ObligationCauseCode::BuiltinDerivedObligation(c) ObligationCauseCode::BuiltinDerivedObligation(c)
| ObligationCauseCode::DerivedObligation(c) => c.parent_code(), | ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
_ => break result_code, _ => break result_code,
}; };
(result_code, code) = (code, parent); (result_code, code) = (code, parent);
@ -1670,7 +1670,6 @@ fn unpeel_to_top<'a, 'tcx>(
call_hir_id: expr.hir_id, call_hir_id: expr.hir_id,
parent_code, parent_code,
} }
.into()
}); });
} else if error.obligation.cause.span == call_sp { } else if error.obligation.cause.span == call_sp {
// Make function calls point at the callee, not the whole thing. // Make function calls point at the callee, not the whole thing.