Auto merge of #96892 - oli-obk:🐌_obligation_cause_code_🐌, r=estebank
Clean up derived obligation creation r? `@estebank` working on fixing the perf regression from https://github.com/rust-lang/rust/pull/91030#issuecomment-1083360210
This commit is contained in:
commit
c1d65eaa45
11 changed files with 176 additions and 219 deletions
|
@ -69,7 +69,7 @@ impl<'tcx> PredicateObligation<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraitObligation<'_> {
|
impl<'tcx> TraitObligation<'tcx> {
|
||||||
/// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
|
/// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
match (self.predicate.skip_binder().constness, self.param_env.constness()) {
|
match (self.predicate.skip_binder().constness, self.param_env.constness()) {
|
||||||
|
@ -77,6 +77,13 @@ impl TraitObligation<'_> {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn derived_cause(
|
||||||
|
&self,
|
||||||
|
variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
|
||||||
|
) -> ObligationCause<'tcx> {
|
||||||
|
self.cause.clone().derived_cause(self.predicate, variant)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
|
|
|
@ -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 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||||
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,15 +130,12 @@ impl<'tcx> 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
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 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 {
|
pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
|
||||||
|
@ -164,14 +155,37 @@ impl<'tcx> ObligationCause<'tcx> {
|
||||||
|
|
||||||
#[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 clone_code(&self) -> Lrc<ObligationCauseCode<'tcx>> {
|
pub fn map_code(
|
||||||
match &self.code {
|
&mut self,
|
||||||
Some(code) => code.clone(),
|
f: impl FnOnce(InternedObligationCauseCode<'tcx>) -> ObligationCauseCode<'tcx>,
|
||||||
None => Lrc::new(MISC_OBLIGATION_CAUSE_CODE),
|
) {
|
||||||
}
|
self.code = f(std::mem::take(&mut self.code)).into();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn derived_cause(
|
||||||
|
mut self,
|
||||||
|
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
|
variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
|
||||||
|
) -> ObligationCause<'tcx> {
|
||||||
|
/*!
|
||||||
|
* Creates a cause for obligations that are derived from
|
||||||
|
* `obligation` by a recursive search (e.g., for a builtin
|
||||||
|
* bound, or eventually a `auto trait Foo`). If `obligation`
|
||||||
|
* is itself a derived obligation, this is just a clone, but
|
||||||
|
* otherwise we create a "derived obligation" cause so as to
|
||||||
|
* keep track of the original root obligation for error
|
||||||
|
* reporting.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NOTE(flaper87): As of now, it keeps track of the whole error
|
||||||
|
// chain. Ideally, we should have a way to configure this either
|
||||||
|
// by using -Z verbose or just a CLI argument.
|
||||||
|
self.code =
|
||||||
|
variant(DerivedObligationCause { parent_trait_pred, parent_code: self.code }).into();
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +196,30 @@ pub struct UnifyReceiverContext<'tcx> {
|
||||||
pub substs: SubstsRef<'tcx>,
|
pub substs: SubstsRef<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, Default)]
|
||||||
|
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>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ObligationCauseCode<'tcx> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn into(self) -> InternedObligationCauseCode<'tcx> {
|
||||||
|
InternedObligationCauseCode {
|
||||||
|
code: if let MISC_OBLIGATION_CAUSE_CODE = self { None } else { Some(Lrc::new(self)) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
|
||||||
|
type Target = ObligationCauseCode<'tcx>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
|
||||||
pub enum ObligationCauseCode<'tcx> {
|
pub enum ObligationCauseCode<'tcx> {
|
||||||
/// Not well classified or should be obvious from the span.
|
/// Not well classified or should be obvious from the span.
|
||||||
|
@ -269,7 +307,7 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
/// The node of the function call.
|
/// The node of the function call.
|
||||||
call_hir_id: hir::HirId,
|
call_hir_id: hir::HirId,
|
||||||
/// The obligation introduced by this argument.
|
/// The obligation introduced by this argument.
|
||||||
parent_code: Lrc<ObligationCauseCode<'tcx>>,
|
parent_code: InternedObligationCauseCode<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Error derived when matching traits/impls; see ObligationCause for more details
|
/// Error derived when matching traits/impls; see ObligationCause for more details
|
||||||
|
@ -404,25 +442,27 @@ pub struct ImplDerivedObligationCause<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObligationCauseCode<'_> {
|
impl<'tcx> ObligationCauseCode<'tcx> {
|
||||||
// Return the base obligation, ignoring derived obligations.
|
// Return the base obligation, ignoring derived obligations.
|
||||||
pub fn peel_derives(&self) -> &Self {
|
pub fn peel_derives(&self) -> &Self {
|
||||||
let mut base_cause = self;
|
let mut base_cause = self;
|
||||||
loop {
|
while let Some((parent_code, _)) = base_cause.parent() {
|
||||||
match base_cause {
|
base_cause = parent_code;
|
||||||
BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
|
|
||||||
| DerivedObligation(DerivedObligationCause { parent_code, .. })
|
|
||||||
| FunctionArgumentObligation { parent_code, .. } => {
|
|
||||||
base_cause = &parent_code;
|
|
||||||
}
|
|
||||||
ImplDerivedObligation(obligation_cause) => {
|
|
||||||
base_cause = &*obligation_cause.derived.parent_code;
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
base_cause
|
base_cause
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
|
||||||
|
match self {
|
||||||
|
FunctionArgumentObligation { parent_code, .. } => Some((parent_code, None)),
|
||||||
|
BuiltinDerivedObligation(derived)
|
||||||
|
| DerivedObligation(derived)
|
||||||
|
| ImplDerivedObligation(box ImplDerivedObligationCause { derived, .. }) => {
|
||||||
|
Some((&derived.parent_code, Some(derived.parent_trait_pred)))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
|
@ -472,7 +512,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.
|
||||||
pub parent_code: Lrc<ObligationCauseCode<'tcx>>,
|
pub parent_code: InternedObligationCauseCode<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, TypeFoldable, Lift)]
|
#[derive(Clone, Debug, TypeFoldable, Lift)]
|
||||||
|
|
|
@ -2,11 +2,10 @@ pub mod on_unimplemented;
|
||||||
pub mod suggestions;
|
pub mod suggestions;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
DerivedObligationCause, EvaluationResult, FulfillmentContext, FulfillmentError,
|
EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode,
|
||||||
FulfillmentErrorCode, ImplDerivedObligationCause, MismatchedProjectionTypes, Obligation,
|
MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
|
||||||
ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
|
OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
|
||||||
OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
|
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
|
||||||
TraitNotObjectSafe,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
||||||
|
@ -684,42 +683,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let mut code = obligation.cause.code();
|
let mut code = obligation.cause.code();
|
||||||
let mut trait_pred = trait_predicate;
|
let mut trait_pred = trait_predicate;
|
||||||
let mut peeled = false;
|
let mut peeled = false;
|
||||||
loop {
|
while let Some((parent_code, parent_trait_pred)) = code.parent() {
|
||||||
match &*code {
|
code = parent_code;
|
||||||
ObligationCauseCode::FunctionArgumentObligation {
|
if let Some(parent_trait_pred) = parent_trait_pred {
|
||||||
parent_code,
|
trait_pred = parent_trait_pred;
|
||||||
..
|
peeled = true;
|
||||||
} => {
|
}
|
||||||
code = &parent_code;
|
|
||||||
}
|
|
||||||
ObligationCauseCode::ImplDerivedObligation(
|
|
||||||
box ImplDerivedObligationCause {
|
|
||||||
derived:
|
|
||||||
DerivedObligationCause {
|
|
||||||
parent_code,
|
|
||||||
parent_trait_pred,
|
|
||||||
},
|
|
||||||
..
|
|
||||||
},
|
|
||||||
)
|
|
||||||
| ObligationCauseCode::BuiltinDerivedObligation(
|
|
||||||
DerivedObligationCause {
|
|
||||||
parent_code,
|
|
||||||
parent_trait_pred,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
| ObligationCauseCode::DerivedObligation(
|
|
||||||
DerivedObligationCause {
|
|
||||||
parent_code,
|
|
||||||
parent_trait_pred,
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
peeled = true;
|
|
||||||
code = &parent_code;
|
|
||||||
trait_pred = *parent_trait_pred;
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
let def_id = trait_pred.def_id();
|
let def_id = trait_pred.def_id();
|
||||||
// Mention *all* the `impl`s for the *top most* obligation, the
|
// Mention *all* the `impl`s for the *top most* obligation, the
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{
|
use super::{
|
||||||
DerivedObligationCause, EvaluationResult, ImplDerivedObligationCause, Obligation,
|
EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
|
||||||
ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext,
|
SelectionContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::autoderef::Autoderef;
|
use crate::autoderef::Autoderef;
|
||||||
|
@ -623,28 +623,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let span = obligation.cause.span;
|
let span = obligation.cause.span;
|
||||||
let mut real_trait_pred = trait_pred;
|
let mut real_trait_pred = trait_pred;
|
||||||
let mut code = obligation.cause.code();
|
let mut code = obligation.cause.code();
|
||||||
loop {
|
while let Some((parent_code, parent_trait_pred)) = code.parent() {
|
||||||
match &code {
|
code = parent_code;
|
||||||
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
|
if let Some(parent_trait_pred) = parent_trait_pred {
|
||||||
code = &parent_code;
|
real_trait_pred = parent_trait_pred;
|
||||||
}
|
}
|
||||||
ObligationCauseCode::ImplDerivedObligation(box ImplDerivedObligationCause {
|
|
||||||
derived: DerivedObligationCause { parent_code, parent_trait_pred },
|
|
||||||
..
|
|
||||||
})
|
|
||||||
| ObligationCauseCode::BuiltinDerivedObligation(DerivedObligationCause {
|
|
||||||
parent_code,
|
|
||||||
parent_trait_pred,
|
|
||||||
})
|
|
||||||
| ObligationCauseCode::DerivedObligation(DerivedObligationCause {
|
|
||||||
parent_code,
|
|
||||||
parent_trait_pred,
|
|
||||||
}) => {
|
|
||||||
code = &parent_code;
|
|
||||||
real_trait_pred = *parent_trait_pred;
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
};
|
|
||||||
let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else {
|
let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -1669,7 +1652,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
|
debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
|
||||||
match code {
|
match code {
|
||||||
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
|
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => {
|
||||||
next_code = Some(parent_code.as_ref());
|
next_code = Some(parent_code);
|
||||||
}
|
}
|
||||||
ObligationCauseCode::ImplDerivedObligation(cause) => {
|
ObligationCauseCode::ImplDerivedObligation(cause) => {
|
||||||
let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
|
let ty = cause.derived.parent_trait_pred.skip_binder().self_ty();
|
||||||
|
@ -1700,7 +1683,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
next_code = Some(cause.derived.parent_code.as_ref());
|
next_code = Some(&cause.derived.parent_code);
|
||||||
}
|
}
|
||||||
ObligationCauseCode::DerivedObligation(derived_obligation)
|
ObligationCauseCode::DerivedObligation(derived_obligation)
|
||||||
| ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
|
| ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => {
|
||||||
|
@ -1732,7 +1715,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
next_code = Some(derived_obligation.parent_code.as_ref());
|
next_code = Some(&derived_obligation.parent_code);
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
|
@ -2382,8 +2365,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
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(ref data) =
|
if let ObligationCauseCode::BuiltinDerivedObligation(data) = &*data.parent_code
|
||||||
*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);
|
||||||
|
@ -2428,7 +2410,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
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,
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,17 +17,15 @@ use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
|
|
||||||
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
|
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
|
||||||
use crate::traits::select::TraitObligationExt;
|
|
||||||
use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
|
use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
BuiltinDerivedObligation, DerivedObligationCause, ImplDerivedObligation,
|
BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
|
||||||
ImplDerivedObligationCause, ImplSource, ImplSourceAutoImplData, ImplSourceBuiltinData,
|
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
|
||||||
ImplSourceClosureData, ImplSourceConstDestructData, ImplSourceDiscriminantKindData,
|
ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
|
||||||
ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData,
|
ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
|
||||||
ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
|
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
|
||||||
ObjectCastObligation, Obligation, ObligationCause, OutputTypeParameterMismatch,
|
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
|
||||||
PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation,
|
SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
|
||||||
Unimplemented, VtblSegment,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::BuiltinImplConditions;
|
use super::BuiltinImplConditions;
|
||||||
|
@ -1128,21 +1126,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let substs = self.rematch_impl(impl_def_id, &new_obligation);
|
let substs = self.rematch_impl(impl_def_id, &new_obligation);
|
||||||
debug!(?substs, "impl substs");
|
debug!(?substs, "impl substs");
|
||||||
|
|
||||||
let derived = DerivedObligationCause {
|
let cause = obligation.derived_cause(|derived| {
|
||||||
parent_trait_pred: obligation.predicate,
|
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
||||||
parent_code: obligation.cause.clone_code(),
|
derived,
|
||||||
};
|
impl_def_id,
|
||||||
let derived_code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
span: obligation.cause.span,
|
||||||
derived,
|
}))
|
||||||
impl_def_id,
|
});
|
||||||
span: obligation.cause.span,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let cause = ObligationCause::new(
|
|
||||||
obligation.cause.span,
|
|
||||||
obligation.cause.body_id,
|
|
||||||
derived_code,
|
|
||||||
);
|
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.vtable_impl(
|
self.vtable_impl(
|
||||||
impl_def_id,
|
impl_def_id,
|
||||||
|
|
|
@ -14,9 +14,9 @@ use super::util;
|
||||||
use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
|
use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
|
||||||
use super::wf;
|
use super::wf;
|
||||||
use super::{
|
use super::{
|
||||||
DerivedObligationCause, ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause,
|
ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
|
||||||
Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, PredicateObligation,
|
ObligationCause, ObligationCauseCode, Overflow, PredicateObligation, Selection, SelectionError,
|
||||||
Selection, SelectionError, SelectionResult, TraitObligation, TraitQueryMode,
|
SelectionResult, TraitObligation, TraitQueryMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
||||||
|
@ -2314,17 +2314,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
debug!(?predicates);
|
debug!(?predicates);
|
||||||
assert_eq!(predicates.parent, None);
|
assert_eq!(predicates.parent, None);
|
||||||
let mut obligations = Vec::with_capacity(predicates.predicates.len());
|
let mut obligations = Vec::with_capacity(predicates.predicates.len());
|
||||||
let parent_code = cause.clone_code();
|
|
||||||
for (predicate, span) in predicates.predicates {
|
for (predicate, span) in predicates.predicates {
|
||||||
let span = *span;
|
let span = *span;
|
||||||
let derived =
|
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
|
||||||
DerivedObligationCause { parent_trait_pred, parent_code: parent_code.clone() };
|
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
||||||
let code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
derived,
|
||||||
derived,
|
impl_def_id: def_id,
|
||||||
impl_def_id: def_id,
|
span,
|
||||||
span,
|
}))
|
||||||
}));
|
});
|
||||||
let cause = ObligationCause::new(cause.span, cause.body_id, code);
|
|
||||||
let predicate = normalize_with_depth_to(
|
let predicate = normalize_with_depth_to(
|
||||||
self,
|
self,
|
||||||
param_env,
|
param_env,
|
||||||
|
@ -2340,42 +2338,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait TraitObligationExt<'tcx> {
|
|
||||||
fn derived_cause(
|
|
||||||
&self,
|
|
||||||
variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
|
|
||||||
) -> ObligationCause<'tcx>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
|
|
||||||
fn derived_cause(
|
|
||||||
&self,
|
|
||||||
variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
|
|
||||||
) -> ObligationCause<'tcx> {
|
|
||||||
/*!
|
|
||||||
* Creates a cause for obligations that are derived from
|
|
||||||
* `obligation` by a recursive search (e.g., for a builtin
|
|
||||||
* bound, or eventually a `auto trait Foo`). If `obligation`
|
|
||||||
* is itself a derived obligation, this is just a clone, but
|
|
||||||
* otherwise we create a "derived obligation" cause so as to
|
|
||||||
* keep track of the original root obligation for error
|
|
||||||
* reporting.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let obligation = self;
|
|
||||||
|
|
||||||
// NOTE(flaper87): As of now, it keeps track of the whole error
|
|
||||||
// chain. Ideally, we should have a way to configure this either
|
|
||||||
// by using -Z verbose or just a CLI argument.
|
|
||||||
let derived_cause = DerivedObligationCause {
|
|
||||||
parent_trait_pred: obligation.predicate,
|
|
||||||
parent_code: obligation.cause.clone_code(),
|
|
||||||
};
|
|
||||||
let derived_code = variant(derived_cause);
|
|
||||||
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
|
impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
|
||||||
fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
|
fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
|
||||||
TraitObligationStackList::with(self)
|
TraitObligationStackList::with(self)
|
||||||
|
|
|
@ -294,30 +294,22 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
|
let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
|
||||||
|
|
||||||
debug!("compute_trait_ref obligations {:?}", obligations);
|
debug!("compute_trait_ref obligations {:?}", obligations);
|
||||||
let cause = self.cause(traits::MiscObligation);
|
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
let depth = self.recursion_depth;
|
let depth = self.recursion_depth;
|
||||||
|
|
||||||
let item = self.item;
|
let item = self.item;
|
||||||
|
|
||||||
let extend = |obligation: traits::PredicateObligation<'tcx>| {
|
let extend = |traits::PredicateObligation { predicate, mut cause, .. }| {
|
||||||
let mut cause = cause.clone();
|
if let Some(parent_trait_pred) = predicate.to_opt_poly_trait_pred() {
|
||||||
if let Some(parent_trait_pred) = obligation.predicate.to_opt_poly_trait_pred() {
|
cause = cause.derived_cause(
|
||||||
let derived_cause = traits::DerivedObligationCause {
|
|
||||||
parent_trait_pred,
|
parent_trait_pred,
|
||||||
parent_code: obligation.cause.clone_code(),
|
traits::ObligationCauseCode::DerivedObligation,
|
||||||
};
|
);
|
||||||
*cause.make_mut_code() =
|
|
||||||
traits::ObligationCauseCode::DerivedObligation(derived_cause);
|
|
||||||
}
|
}
|
||||||
extend_cause_with_original_assoc_item_obligation(
|
extend_cause_with_original_assoc_item_obligation(
|
||||||
tcx,
|
tcx, trait_ref, item, &mut cause, predicate,
|
||||||
trait_ref,
|
|
||||||
item,
|
|
||||||
&mut cause,
|
|
||||||
obligation.predicate,
|
|
||||||
);
|
);
|
||||||
traits::Obligation::with_depth(cause, depth, param_env, obligation.predicate)
|
traits::Obligation::with_depth(cause, depth, param_env, predicate)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Elaborate::All = elaborate {
|
if let Elaborate::All = elaborate {
|
||||||
|
@ -339,17 +331,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
.filter(|(_, arg)| !arg.has_escaping_bound_vars())
|
.filter(|(_, arg)| !arg.has_escaping_bound_vars())
|
||||||
.map(|(i, arg)| {
|
.map(|(i, arg)| {
|
||||||
let mut new_cause = cause.clone();
|
let mut cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||||
// The first subst is the self ty - use the correct span for it.
|
// The first subst is the self ty - use the correct span for it.
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) =
|
if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) =
|
||||||
item.map(|i| &i.kind)
|
item.map(|i| &i.kind)
|
||||||
{
|
{
|
||||||
new_cause.span = self_ty.span;
|
cause.span = self_ty.span;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traits::Obligation::with_depth(
|
traits::Obligation::with_depth(
|
||||||
new_cause,
|
cause,
|
||||||
depth,
|
depth,
|
||||||
param_env,
|
param_env,
|
||||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
|
ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
|
||||||
|
|
|
@ -12,7 +12,6 @@ use crate::check::{
|
||||||
use crate::structured_errors::StructuredDiagnostic;
|
use crate::structured_errors::StructuredDiagnostic;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::sync::Lrc;
|
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticId, MultiSpan};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticId, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||||
|
@ -1596,24 +1595,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Peel derived obligation, because it's the type that originally
|
// Peel derived obligation, because it's the type that originally
|
||||||
// started this inference chain that matters, not the one we wound
|
// started this inference chain that matters, not the one we wound
|
||||||
// up with at the end.
|
// up with at the end.
|
||||||
fn unpeel_to_top(
|
fn unpeel_to_top<'a, 'tcx>(
|
||||||
mut code: Lrc<ObligationCauseCode<'_>>,
|
mut code: &'a ObligationCauseCode<'tcx>,
|
||||||
) -> Lrc<ObligationCauseCode<'_>> {
|
) -> &'a ObligationCauseCode<'tcx> {
|
||||||
let mut result_code = code.clone();
|
let mut result_code = code;
|
||||||
loop {
|
loop {
|
||||||
let parent = match &*code {
|
let parent = match code {
|
||||||
ObligationCauseCode::ImplDerivedObligation(c) => {
|
ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
|
||||||
c.derived.parent_code.clone()
|
|
||||||
}
|
|
||||||
ObligationCauseCode::BuiltinDerivedObligation(c)
|
ObligationCauseCode::BuiltinDerivedObligation(c)
|
||||||
| ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(),
|
| ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
|
||||||
_ => break,
|
_ => break result_code,
|
||||||
};
|
};
|
||||||
result_code = std::mem::replace(&mut code, parent);
|
(result_code, code) = (code, parent);
|
||||||
}
|
}
|
||||||
result_code
|
|
||||||
}
|
}
|
||||||
let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) {
|
let self_: ty::subst::GenericArg<'_> = match unpeel_to_top(error.obligation.cause.code()) {
|
||||||
ObligationCauseCode::BuiltinDerivedObligation(code) |
|
ObligationCauseCode::BuiltinDerivedObligation(code) |
|
||||||
ObligationCauseCode::DerivedObligation(code) => {
|
ObligationCauseCode::DerivedObligation(code) => {
|
||||||
code.parent_trait_pred.self_ty().skip_binder().into()
|
code.parent_trait_pred.self_ty().skip_binder().into()
|
||||||
|
@ -1663,13 +1659,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// We make sure that only *one* argument matches the obligation failure
|
// We make sure that only *one* argument matches the obligation failure
|
||||||
// and we assign the obligation's span to its expression's.
|
// and we assign the obligation's span to its expression's.
|
||||||
error.obligation.cause.span = args[ref_in].span;
|
error.obligation.cause.span = args[ref_in].span;
|
||||||
let parent_code = error.obligation.cause.clone_code();
|
error.obligation.cause.map_code(|parent_code| {
|
||||||
*error.obligation.cause.make_mut_code() =
|
|
||||||
ObligationCauseCode::FunctionArgumentObligation {
|
ObligationCauseCode::FunctionArgumentObligation {
|
||||||
arg_hir_id: args[ref_in].hir_id,
|
arg_hir_id: args[ref_in].hir_id,
|
||||||
call_hir_id: expr.hir_id,
|
call_hir_id: expr.hir_id,
|
||||||
parent_code,
|
parent_code,
|
||||||
};
|
}
|
||||||
|
});
|
||||||
} 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.
|
||||||
if let hir::ExprKind::Call(callee, _) = expr.kind {
|
if let hir::ExprKind::Call(callee, _) = expr.kind {
|
||||||
|
|
|
@ -2,10 +2,18 @@ error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
|
||||||
--> $DIR/hr-associated-type-projection-1.rs:13:33
|
--> $DIR/hr-associated-type-projection-1.rs:13:33
|
||||||
|
|
|
|
||||||
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
|
||||||
| - this type parameter ^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `T`
|
| - this type parameter ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
|
||||||
|
|
|
|
||||||
= note: expected associated type `<T as Deref>::Target`
|
= note: expected type parameter `T`
|
||||||
found type parameter `T`
|
found associated type `<T as Deref>::Target`
|
||||||
|
note: required by a bound in `UnsafeCopy`
|
||||||
|
--> $DIR/hr-associated-type-projection-1.rs:3:64
|
||||||
|
|
|
||||||
|
LL | trait UnsafeCopy<'a, T: Copy>
|
||||||
|
| ---------- required by a bound in this
|
||||||
|
LL | where
|
||||||
|
LL | for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
|
||||||
|
| ^^^^^^^^^^ required by this bound in `UnsafeCopy`
|
||||||
help: consider further restricting this bound
|
help: consider further restricting this bound
|
||||||
|
|
|
|
||||||
LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<'_, T> for T {
|
LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<'_, T> for T {
|
||||||
|
|
|
@ -2,8 +2,13 @@ error[E0310]: the parameter type `T` may not live long enough
|
||||||
--> $DIR/builtin-superkinds-self-type.rs:10:16
|
--> $DIR/builtin-superkinds-self-type.rs:10:16
|
||||||
|
|
|
|
||||||
LL | impl <T: Sync> Foo for T { }
|
LL | impl <T: Sync> Foo for T { }
|
||||||
| ^^^ ...so that the type `T` will meet its required lifetime bounds
|
| ^^^ ...so that the type `T` will meet its required lifetime bounds...
|
||||||
|
|
|
|
||||||
|
note: ...that is required by this bound
|
||||||
|
--> $DIR/builtin-superkinds-self-type.rs:6:24
|
||||||
|
|
|
||||||
|
LL | trait Foo : Sized+Sync+'static {
|
||||||
|
| ^^^^^^^
|
||||||
help: consider adding an explicit lifetime bound...
|
help: consider adding an explicit lifetime bound...
|
||||||
|
|
|
|
||||||
LL | impl <T: Sync + 'static> Foo for T { }
|
LL | impl <T: Sync + 'static> Foo for T { }
|
||||||
|
|
|
@ -2,7 +2,13 @@ error[E0271]: type mismatch resolving `<std::vec::IntoIter<i32> as Iterator>::It
|
||||||
--> $DIR/assoc-type-in-superbad.rs:12:16
|
--> $DIR/assoc-type-in-superbad.rs:12:16
|
||||||
|
|
|
|
||||||
LL | type Key = u32;
|
LL | type Key = u32;
|
||||||
| ^^^ expected `i32`, found `u32`
|
| ^^^ expected `u32`, found `i32`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Foo`
|
||||||
|
--> $DIR/assoc-type-in-superbad.rs:7:25
|
||||||
|
|
|
||||||
|
LL | pub trait Foo: Iterator<Item=<Self as Foo>::Key> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue