use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance};
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate};
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::normalize::AtExt;
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
- let (param_env, AscribeUserType { mir_ty, def_id, user_substs }) = key.into_parts();
-
- debug!(
- "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
- mir_ty, def_id, user_substs
- );
+ type_op_ascribe_user_type_with_span(infcx, fulfill_cx, key, None)
+ })
+}
- let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
- cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
+/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
+/// this query can be re-run to better track the span of the obligation cause, and improve the error
+/// message. Do not call directly unless you're in that very specific context.
+pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
+ infcx: &'a InferCtxt<'a, 'tcx>,
+ fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
+ key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
+ span: Option<Span>,
+) -> Result<(), NoSolution> {
+ let (param_env, AscribeUserType { mir_ty, def_id, user_substs }) = key.into_parts();
+ debug!(
+ "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
+ mir_ty, def_id, user_substs
+ );
- Ok(())
- })
+ let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
+ cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?;
+ Ok(())
}
struct AscribeUserTypeCx<'me, 'tcx> {
Ok(())
}
- fn prove_predicate(&mut self, predicate: Predicate<'tcx>) {
+ fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) {
+ let cause = if let Some(span) = span {
+ ObligationCause::dummy_with_span(span)
+ } else {
+ ObligationCause::dummy()
+ };
self.fulfill_cx.register_predicate_obligation(
self.infcx,
- Obligation::new(ObligationCause::dummy(), self.param_env, predicate),
+ Obligation::new(cause, self.param_env, predicate),
);
}
mir_ty: Ty<'tcx>,
def_id: DefId,
user_substs: UserSubsts<'tcx>,
+ span: Option<Span>,
) -> Result<(), NoSolution> {
let UserSubsts { user_self_ty, substs } = user_substs;
let tcx = self.tcx();
// outlives" error messages.
let instantiated_predicates =
self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+ debug!(?instantiated_predicates.predicates);
for instantiated_predicate in instantiated_predicates.predicates {
let instantiated_predicate = self.normalize(instantiated_predicate);
- self.prove_predicate(instantiated_predicate);
+ self.prove_predicate(instantiated_predicate, span);
}
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
self.prove_predicate(
ty::PredicateKind::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
+ span,
);
}
// them? This would only be relevant if some input
// type were ill-formed but did not appear in `ty`,
// which...could happen with normalization...
- self.prove_predicate(ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()));
+ self.prove_predicate(
+ ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
+ span,
+ );
Ok(())
}
}
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
- let (param_env, ProvePredicate { predicate }) = key.into_parts();
- fulfill_cx.register_predicate_obligation(
- infcx,
- Obligation::new(ObligationCause::dummy(), param_env, predicate),
- );
+ type_op_prove_predicate_with_span(infcx, fulfill_cx, key, None);
Ok(())
})
}
+
+/// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
+/// this query can be re-run to better track the span of the obligation cause, and improve the error
+/// message. Do not call directly unless you're in that very specific context.
+pub fn type_op_prove_predicate_with_span<'a, 'tcx: 'a>(
+ infcx: &'a InferCtxt<'a, 'tcx>,
+ fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
+ key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
+ span: Option<Span>,
+) {
+ let cause = if let Some(span) = span {
+ ObligationCause::dummy_with_span(span)
+ } else {
+ ObligationCause::dummy()
+ };
+ let (param_env, ProvePredicate { predicate }) = key.into_parts();
+ fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate));
+}