mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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
@ -604,7 +604,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
|
||||
terr: &TypeError<'tcx>,
|
||||
) {
|
||||
match cause.code {
|
||||
match *cause.code() {
|
||||
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
|
||||
let ty = self.resolve_vars_if_possible(root_ty);
|
||||
if ty.is_suggestable() {
|
||||
@ -781,7 +781,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
_ => {
|
||||
if let ObligationCauseCode::BindingObligation(_, binding_span) =
|
||||
cause.code.peel_derives()
|
||||
cause.code().peel_derives()
|
||||
{
|
||||
if matches!(terr, TypeError::RegionsPlaceholderMismatch) {
|
||||
err.span_note(*binding_span, "the lifetime requirement is introduced here");
|
||||
@ -1729,10 +1729,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
_ => exp_found,
|
||||
};
|
||||
debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code);
|
||||
debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code());
|
||||
if let Some(exp_found) = exp_found {
|
||||
let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } =
|
||||
&cause.code
|
||||
cause.code()
|
||||
{
|
||||
// Skip if the root_ty of the pattern is not the same as the expected_ty.
|
||||
// If these types aren't equal then we've probably peeled off a layer of arrays.
|
||||
@ -1827,7 +1827,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
exp_span, exp_found.expected, exp_found.found,
|
||||
);
|
||||
|
||||
if let ObligationCauseCode::CompareImplMethodObligation { .. } = &cause.code {
|
||||
if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1835,7 +1835,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
self.get_impl_future_output_ty(exp_found.expected),
|
||||
self.get_impl_future_output_ty(exp_found.found),
|
||||
) {
|
||||
(Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match &cause.code {
|
||||
(Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() {
|
||||
ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {
|
||||
diag.multipart_suggestion(
|
||||
"consider `await`ing on both `Future`s",
|
||||
@ -1875,7 +1875,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
(Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code {
|
||||
(Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code() {
|
||||
ObligationCauseCode::Pattern { span: Some(span), .. }
|
||||
| ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => {
|
||||
diag.span_suggestion_verbose(
|
||||
@ -1927,7 +1927,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
.map(|field| (field.ident.name, field.ty(self.tcx, expected_substs)))
|
||||
.find(|(_, ty)| same_type_modulo_infer(ty, exp_found.found))
|
||||
{
|
||||
if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code {
|
||||
if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
let suggestion = if expected_def.is_struct() {
|
||||
format!("{}.{}", snippet, name)
|
||||
@ -2064,7 +2064,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
|
||||
trace.cause.code
|
||||
*trace.cause.code()
|
||||
{
|
||||
if let hir::MatchSource::TryDesugar = source {
|
||||
if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
|
||||
@ -2659,7 +2659,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
||||
fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
|
||||
use self::FailureCode::*;
|
||||
use crate::traits::ObligationCauseCode::*;
|
||||
match self.code {
|
||||
match self.code() {
|
||||
CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
|
||||
CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
|
||||
MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
|
||||
@ -2694,7 +2694,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
|
||||
|
||||
fn as_requirement_str(&self) -> &'static str {
|
||||
use crate::traits::ObligationCauseCode::*;
|
||||
match self.code {
|
||||
match self.code() {
|
||||
CompareImplMethodObligation { .. } => "method type is compatible with trait",
|
||||
CompareImplTypeObligation { .. } => "associated type is compatible with trait",
|
||||
ExprAssignable => "expression is assignable",
|
||||
|
@ -31,15 +31,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
};
|
||||
// If we added a "points at argument expression" obligation, we remove it here, we care
|
||||
// about the original obligation only.
|
||||
let code = match &cause.code {
|
||||
let code = match cause.code() {
|
||||
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
|
||||
_ => &cause.code,
|
||||
_ => cause.code(),
|
||||
};
|
||||
let (parent, impl_def_id) = match code {
|
||||
ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id),
|
||||
_ => return None,
|
||||
};
|
||||
let binding_span = match parent.code {
|
||||
let binding_span = match *parent.code() {
|
||||
ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span,
|
||||
_ => return None,
|
||||
};
|
||||
|
@ -208,7 +208,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||
);
|
||||
let mut err = self.tcx().sess.struct_span_err(span, &msg);
|
||||
|
||||
let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code {
|
||||
let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = *cause.code() {
|
||||
err.span_label(span, "doesn't satisfy where-clause");
|
||||
err.span_label(
|
||||
self.tcx().def_span(def_id),
|
||||
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
sup_r,
|
||||
) if **sub_r == RegionKind::ReStatic => {
|
||||
// This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
|
||||
if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
|
||||
if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() {
|
||||
// This may have a closure and it would cause ICE
|
||||
// through `find_param_with_region` (#78262).
|
||||
let anon_reg_sup = tcx.is_suitable_region(sup_r)?;
|
||||
@ -184,7 +184,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
}
|
||||
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
|
||||
if let ObligationCauseCode::ReturnValue(hir_id)
|
||||
| ObligationCauseCode::BlockTailExpression(hir_id) = &cause.code
|
||||
| ObligationCauseCode::BlockTailExpression(hir_id) = cause.code()
|
||||
{
|
||||
let parent_id = tcx.hir().get_parent_item(*hir_id);
|
||||
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) {
|
||||
@ -226,7 +226,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
|
||||
let mut override_error_code = None;
|
||||
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
|
||||
if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
|
||||
if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() {
|
||||
// Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
|
||||
// `'static` lifetime when called as a method on a binding: `bar.qux()`.
|
||||
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
|
||||
@ -235,9 +235,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
|
||||
let code = match &cause.code {
|
||||
ObligationCauseCode::MatchImpl(parent, ..) => &parent.code,
|
||||
_ => &cause.code,
|
||||
let code = match cause.code() {
|
||||
ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
|
||||
_ => cause.code(),
|
||||
};
|
||||
if let (ObligationCauseCode::ItemObligation(item_def_id), None) =
|
||||
(code, override_error_code)
|
||||
|
@ -36,7 +36,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
ValuePairs::Types(sub_expected_found),
|
||||
ValuePairs::Types(sup_expected_found),
|
||||
CompareImplMethodObligation { trait_item_def_id, .. },
|
||||
) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
|
||||
) = (&sub_trace.values, &sup_trace.values, sub_trace.cause.code())
|
||||
{
|
||||
if sup_expected_found == sub_expected_found {
|
||||
self.emit_err(
|
||||
|
@ -359,13 +359,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
match placeholder_origin {
|
||||
infer::Subtype(box ref trace)
|
||||
if matches!(
|
||||
&trace.cause.code.peel_derives(),
|
||||
&trace.cause.code().peel_derives(),
|
||||
ObligationCauseCode::BindingObligation(..)
|
||||
) =>
|
||||
{
|
||||
// Hack to get around the borrow checker because trace.cause has an `Rc`.
|
||||
if let ObligationCauseCode::BindingObligation(_, span) =
|
||||
&trace.cause.code.peel_derives()
|
||||
&trace.cause.code().peel_derives()
|
||||
{
|
||||
let span = *span;
|
||||
let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
|
||||
|
@ -1824,7 +1824,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
||||
where
|
||||
F: FnOnce() -> Self,
|
||||
{
|
||||
match cause.code {
|
||||
match *cause.code() {
|
||||
traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => {
|
||||
SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||
infer::RelateParamBound(
|
||||
cause.span,
|
||||
sup_type,
|
||||
match cause.code.peel_derives() {
|
||||
match cause.code().peel_derives() {
|
||||
ObligationCauseCode::BindingObligation(_, span) => Some(*span),
|
||||
_ => None,
|
||||
},
|
||||
|
@ -81,7 +81,7 @@ impl TraitObligation<'_> {
|
||||
|
||||
// `PredicateObligation` 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!(PredicateObligation<'_>, 32);
|
||||
static_assert_size!(PredicateObligation<'_>, 48);
|
||||
|
||||
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
|
||||
|
||||
|
@ -23,9 +23,7 @@ use rustc_span::{Span, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
|
||||
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
|
||||
|
||||
@ -80,38 +78,14 @@ pub enum Reveal {
|
||||
|
||||
/// The reason why we incurred this obligation; used for error reporting.
|
||||
///
|
||||
/// As the happy path does not care about this struct, storing this on the heap
|
||||
/// ends up increasing performance.
|
||||
/// Non-misc `ObligationCauseCode`s are stored on the heap. This gives the
|
||||
/// best trade-off between keeping the type small (which makes copies cheaper)
|
||||
/// while not doing too many heap allocations.
|
||||
///
|
||||
/// We do not want to intern this as there are a lot of obligation causes which
|
||||
/// only live for a short period of time.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Lift)]
|
||||
pub struct ObligationCause<'tcx> {
|
||||
/// `None` for `ObligationCause::dummy`, `Some` otherwise.
|
||||
data: Option<Lrc<ObligationCauseData<'tcx>>>,
|
||||
}
|
||||
|
||||
const DUMMY_OBLIGATION_CAUSE_DATA: ObligationCauseData<'static> =
|
||||
ObligationCauseData { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation };
|
||||
|
||||
// Correctly format `ObligationCause::dummy`.
|
||||
impl<'tcx> fmt::Debug for ObligationCause<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ObligationCauseData::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Deref for ObligationCause<'tcx> {
|
||||
type Target = ObligationCauseData<'tcx>;
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.data.as_deref().unwrap_or(&DUMMY_OBLIGATION_CAUSE_DATA)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Lift)]
|
||||
pub struct ObligationCauseData<'tcx> {
|
||||
pub struct ObligationCause<'tcx> {
|
||||
pub span: Span,
|
||||
|
||||
/// The ID of the fn body that triggered this obligation. This is
|
||||
@ -122,17 +96,25 @@ pub struct ObligationCauseData<'tcx> {
|
||||
/// information.
|
||||
pub body_id: hir::HirId,
|
||||
|
||||
pub code: ObligationCauseCode<'tcx>,
|
||||
/// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of
|
||||
/// the time). `Some` otherwise.
|
||||
code: Option<Lrc<ObligationCauseCode<'tcx>>>,
|
||||
}
|
||||
|
||||
impl Hash for ObligationCauseData<'_> {
|
||||
// This custom hash function speeds up hashing for `Obligation` deduplication
|
||||
// greatly by skipping the `code` field, which can be large and complex. That
|
||||
// shouldn't affect hash quality much since there are several other fields in
|
||||
// `Obligation` which should be unique enough, especially the predicate itself
|
||||
// which is hashed as an interned pointer. See #90996.
|
||||
impl Hash for ObligationCause<'_> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.body_id.hash(state);
|
||||
self.span.hash(state);
|
||||
std::mem::discriminant(&self.code).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
const MISC_OBLIGATION_CAUSE_CODE: ObligationCauseCode<'static> = MiscObligation;
|
||||
|
||||
impl<'tcx> ObligationCause<'tcx> {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
@ -140,28 +122,32 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||
body_id: hir::HirId,
|
||||
code: ObligationCauseCode<'tcx>,
|
||||
) -> ObligationCause<'tcx> {
|
||||
ObligationCause { data: Some(Lrc::new(ObligationCauseData { span, body_id, code })) }
|
||||
ObligationCause {
|
||||
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> {
|
||||
ObligationCause::new(span, body_id, MiscObligation)
|
||||
}
|
||||
|
||||
pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> {
|
||||
ObligationCause::new(span, hir::CRATE_HIR_ID, MiscObligation)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn dummy() -> ObligationCause<'tcx> {
|
||||
ObligationCause { data: None }
|
||||
ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: None }
|
||||
}
|
||||
|
||||
pub fn make_mut(&mut self) -> &mut ObligationCauseData<'tcx> {
|
||||
Lrc::make_mut(self.data.get_or_insert_with(|| Lrc::new(DUMMY_OBLIGATION_CAUSE_DATA)))
|
||||
pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> {
|
||||
ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: None }
|
||||
}
|
||||
|
||||
pub fn make_mut_code(&mut self) -> &mut ObligationCauseCode<'tcx> {
|
||||
Lrc::make_mut(self.code.get_or_insert_with(|| Lrc::new(MISC_OBLIGATION_CAUSE_CODE)))
|
||||
}
|
||||
|
||||
pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
|
||||
match self.code {
|
||||
match *self.code() {
|
||||
ObligationCauseCode::CompareImplMethodObligation { .. }
|
||||
| ObligationCauseCode::MainFunctionType
|
||||
| ObligationCauseCode::StartFunctionType => {
|
||||
@ -174,6 +160,18 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||
_ => self.span,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn code(&self) -> &ObligationCauseCode<'tcx> {
|
||||
self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE)
|
||||
}
|
||||
|
||||
pub fn clone_code(&self) -> Lrc<ObligationCauseCode<'tcx>> {
|
||||
match &self.code {
|
||||
Some(code) => code.clone(),
|
||||
None => Lrc::new(MISC_OBLIGATION_CAUSE_CODE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
|
||||
|
@ -519,7 +519,7 @@ impl<T> Trait<T> for X {
|
||||
proj_ty,
|
||||
values,
|
||||
body_owner_def_id,
|
||||
&cause.code,
|
||||
cause.code(),
|
||||
);
|
||||
}
|
||||
(_, ty::Projection(proj_ty)) => {
|
||||
|
@ -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(
|
||||
|
@ -1444,7 +1444,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
|
||||
let mut err;
|
||||
let mut unsized_return = false;
|
||||
match cause.code {
|
||||
match *cause.code() {
|
||||
ObligationCauseCode::ReturnNoExpression => {
|
||||
err = struct_span_err!(
|
||||
fcx.tcx.sess,
|
||||
|
@ -232,7 +232,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||
|
||||
inh.register_predicates(obligations);
|
||||
let mut cause = cause.clone();
|
||||
cause.make_mut().span = span;
|
||||
cause.span = span;
|
||||
inh.register_predicate(traits::Obligation::new(cause, param_env, predicate));
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||
let (impl_err_span, trait_err_span) =
|
||||
extract_spans_for_error_reporting(&infcx, &terr, &cause, impl_m, trait_m);
|
||||
|
||||
cause.make_mut().span = impl_err_span;
|
||||
cause.span = impl_err_span;
|
||||
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess,
|
||||
@ -1043,7 +1043,7 @@ crate fn compare_const_impl<'tcx>(
|
||||
|
||||
// Locate the Span containing just the type of the offending impl
|
||||
match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
|
||||
ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span,
|
||||
ImplItemKind::Const(ref ty, _) => cause.span = ty.span,
|
||||
_ => bug!("{:?} is not a impl const", impl_c),
|
||||
}
|
||||
|
||||
|
@ -997,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
result_code
|
||||
}
|
||||
let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(Lrc::new(error.obligation.cause.code.clone())) {
|
||||
let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) {
|
||||
ObligationCauseCode::BuiltinDerivedObligation(code) |
|
||||
ObligationCauseCode::ImplDerivedObligation(code) |
|
||||
ObligationCauseCode::DerivedObligation(code) => {
|
||||
@ -1040,18 +1040,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
// We make sure that only *one* argument matches the obligation failure
|
||||
// and we assign the obligation's span to its expression's.
|
||||
error.obligation.cause.make_mut().span = args[ref_in].span;
|
||||
let code = error.obligation.cause.code.clone();
|
||||
error.obligation.cause.make_mut().code =
|
||||
error.obligation.cause.span = args[ref_in].span;
|
||||
let parent_code = error.obligation.cause.clone_code();
|
||||
*error.obligation.cause.make_mut_code() =
|
||||
ObligationCauseCode::FunctionArgumentObligation {
|
||||
arg_hir_id: args[ref_in].hir_id,
|
||||
call_hir_id: expr.hir_id,
|
||||
parent_code: Lrc::new(code),
|
||||
parent_code,
|
||||
};
|
||||
} else if error.obligation.cause.make_mut().span == call_sp {
|
||||
} else if error.obligation.cause.span == call_sp {
|
||||
// Make function calls point at the callee, not the whole thing.
|
||||
if let hir::ExprKind::Call(callee, _) = expr.kind {
|
||||
error.obligation.cause.make_mut().span = callee.span;
|
||||
error.obligation.cause.span = callee.span;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1092,7 +1092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
if ty == predicate.self_ty() {
|
||||
error.obligation.cause.make_mut().span = hir_ty.span;
|
||||
error.obligation.cause.span = hir_ty.span;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -832,7 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
for (data, p, parent_p) in unsatisfied_predicates
|
||||
.iter()
|
||||
.filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
|
||||
.filter_map(|(p, parent, c)| match c.code {
|
||||
.filter_map(|(p, parent, c)| match c.code() {
|
||||
ObligationCauseCode::ImplDerivedObligation(ref data) => {
|
||||
Some((data, p, parent))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user