Opt-in diagnostics reporting to avoid doing extra work in the new solver

This commit is contained in:
Michael Goulet 2024-06-01 14:51:31 -04:00
parent 54b2b7d460
commit eb0a70a557
31 changed files with 200 additions and 107 deletions

View File

@ -1347,7 +1347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return; return;
}; };
// Try to find predicates on *generic params* that would allow copying `ty` // Try to find predicates on *generic params* that would allow copying `ty`
let ocx = ObligationCtxt::new(self.infcx); let ocx = ObligationCtxt::new_with_diagnostics(self.infcx);
let cause = ObligationCause::misc(span, self.mir_def_id()); let cause = ObligationCause::misc(span, self.mir_def_id());
ocx.register_bound(cause, self.param_env, ty, def_id); ocx.register_bound(cause, self.param_env, ty, def_id);

View File

@ -340,7 +340,7 @@ fn check_opaque_type_well_formed<'tcx>(
.with_next_trait_solver(next_trait_solver) .with_next_trait_solver(next_trait_solver)
.with_opaque_type_inference(parent_def_id) .with_opaque_type_inference(parent_def_id)
.build(); .build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let identity_args = GenericArgs::identity_for_item(tcx, def_id); let identity_args = GenericArgs::identity_for_item(tcx, def_id);
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without // Require that the hidden type actually fulfills all the bounds of the opaque type, even without

View File

@ -735,7 +735,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// which path expressions are getting called on and which path expressions are only used // which path expressions are getting called on and which path expressions are only used
// as function pointers. This is required for correctness. // as function pointers. This is required for correctness.
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args); let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args);
let cause = ObligationCause::new( let cause = ObligationCause::new(

View File

@ -342,7 +342,7 @@ fn check_opaque_meets_bounds<'tcx>(
let param_env = tcx.param_env(defining_use_anchor); let param_env = tcx.param_env(defining_use_anchor);
let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build(); let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let args = match *origin { let args = match *origin {
hir::OpaqueTyOrigin::FnReturn(parent) hir::OpaqueTyOrigin::FnReturn(parent)
@ -1727,7 +1727,7 @@ pub(super) fn check_coroutine_obligations(
.with_opaque_type_inference(def_id) .with_opaque_type_inference(def_id)
.build(); .build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
for (predicate, cause) in &typeck_results.coroutine_stalled_predicates { for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate)); ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
} }

View File

@ -10,7 +10,7 @@ use rustc_hir::intravisit;
use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_hir::{GenericParamKind, ImplItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util; use rustc_infer::traits::{util, FulfillmentErrorLike};
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::util::ExplicitSelf;
@ -225,7 +225,7 @@ fn compare_method_predicate_entailment<'tcx>(
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds()); debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
@ -493,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
); );
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
// Normalize the impl signature with fresh variables for lifetime inference. // Normalize the impl signature with fresh variables for lifetime inference.
let misc_cause = ObligationCause::misc(return_span, impl_m_def_id); let misc_cause = ObligationCause::misc(return_span, impl_m_def_id);
@ -764,17 +764,23 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
Ok(&*tcx.arena.alloc(remapped_types)) Ok(&*tcx.arena.alloc(remapped_types))
} }
struct ImplTraitInTraitCollector<'a, 'tcx> { struct ImplTraitInTraitCollector<'a, 'tcx, E>
ocx: &'a ObligationCtxt<'a, 'tcx>, where
E: FulfillmentErrorLike<'tcx>,
{
ocx: &'a ObligationCtxt<'a, 'tcx, E>,
types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>, types: FxIndexMap<DefId, (Ty<'tcx>, ty::GenericArgsRef<'tcx>)>,
span: Span, span: Span,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId, body_id: LocalDefId,
} }
impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> { impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E>
where
E: FulfillmentErrorLike<'tcx>,
{
fn new( fn new(
ocx: &'a ObligationCtxt<'a, 'tcx>, ocx: &'a ObligationCtxt<'a, 'tcx, E>,
span: Span, span: Span,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body_id: LocalDefId, body_id: LocalDefId,
@ -783,7 +789,10 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
} }
} }
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> { impl<'tcx, E> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx, E>
where
E: FulfillmentErrorLike<'tcx>,
{
fn interner(&self) -> TyCtxt<'tcx> { fn interner(&self) -> TyCtxt<'tcx> {
self.ocx.infcx.tcx self.ocx.infcx.tcx
} }
@ -1777,7 +1786,7 @@ fn compare_const_predicate_entailment<'tcx>(
); );
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args); let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
for (predicate, span) in impl_ct_own_bounds { for (predicate, span) in impl_ct_own_bounds {
@ -1910,7 +1919,7 @@ fn compare_type_predicate_entailment<'tcx>(
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing); let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds()); debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
@ -1977,7 +1986,7 @@ pub(super) fn check_type_bounds<'tcx>(
let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args); let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized // span for an impl's associated type. Instead, for these, use the def_span for the synthesized

View File

@ -123,7 +123,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
adt_to_impl_args: GenericArgsRef<'tcx>, adt_to_impl_args: GenericArgsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
// Take the param-env of the adt and instantiate the args that show up in // Take the param-env of the adt and instantiate the args that show up in
// the implementation's self type. This gives us the assumptions that the // the implementation's self type. This gives us the assumptions that the

View File

@ -133,7 +133,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
main_diagnostics_def_id, main_diagnostics_def_id,
ObligationCauseCode::MainFunctionType, ObligationCauseCode::MainFunctionType,
); );
let ocx = traits::ObligationCtxt::new(&infcx); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
let norm_return_ty = ocx.normalize(&cause, param_env, return_ty); let norm_return_ty = ocx.normalize(&cause, param_env, return_ty);
ocx.register_bound(cause, param_env, norm_return_ty, term_did); ocx.register_bound(cause, param_env, norm_return_ty, term_did);
let errors = ocx.select_all_or_error(); let errors = ocx.select_all_or_error();

View File

@ -599,7 +599,7 @@ pub fn check_function_signature<'tcx>(
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
let actual_sig = tcx.fn_sig(fn_id).instantiate_identity(); let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();

View File

@ -37,7 +37,7 @@ use rustc_trait_selection::traits::misc::{
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
}; };
use rustc_type_ir::TypeFlags; use rustc_type_ir::TypeFlags;
@ -45,13 +45,13 @@ use std::cell::LazyCell;
use std::ops::{ControlFlow, Deref}; use std::ops::{ControlFlow, Deref};
pub(super) struct WfCheckingCtxt<'a, 'tcx> { pub(super) struct WfCheckingCtxt<'a, 'tcx> {
pub(super) ocx: ObligationCtxt<'a, 'tcx>, pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
span: Span, span: Span,
body_def_id: LocalDefId, body_def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
} }
impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> { impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {
type Target = ObligationCtxt<'a, 'tcx>; type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.ocx &self.ocx
} }
@ -106,7 +106,7 @@ where
{ {
let param_env = tcx.param_env(body_def_id); let param_env = tcx.param_env(body_def_id);
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env }; let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };

View File

@ -267,7 +267,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
.join(", "), .join(", "),
})); }));
} else { } else {
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
for field in coerced_fields { for field in coerced_fields {
ocx.register_obligation(Obligation::new( ocx.register_obligation(Obligation::new(
tcx, tcx,
@ -480,7 +480,7 @@ pub fn coerce_unsized_info<'tcx>(
}; };
// Register an obligation for `A: Trait<B>`. // Register an obligation for `A: Trait<B>`.
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let cause = traits::ObligationCause::misc(span, impl_did); let cause = traits::ObligationCause::misc(span, impl_did);
let obligation = Obligation::new( let obligation = Obligation::new(
tcx, tcx,

View File

@ -1298,7 +1298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.copied() .copied()
.filter(|&(impl_, _)| { .filter(|&(impl_, _)| {
infcx.probe(|_| { infcx.probe(|_| {
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty); let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
let impl_args = infcx.fresh_args_for_item(span, impl_); let impl_args = infcx.fresh_args_for_item(span, impl_);

View File

@ -67,7 +67,7 @@ fn diagnostic_hir_wf_check<'tcx>(
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
let infcx = self.tcx.infer_ctxt().build(); let infcx = self.tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let tcx_ty = self.icx.lower_ty(ty); let tcx_ty = self.icx.lower_ty(ty);
// This visitor can walk into binders, resulting in the `tcx_ty` to // This visitor can walk into binders, resulting in the `tcx_ty` to

View File

@ -196,7 +196,7 @@ fn get_impl_args(
impl2_node: Node, impl2_node: Node,
) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> { ) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> {
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
let param_env = tcx.param_env(impl1_def_id); let param_env = tcx.param_env(impl1_def_id);
let impl1_span = tcx.def_span(impl1_def_id); let impl1_span = tcx.def_span(impl1_def_id);
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?; let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;

View File

@ -3049,7 +3049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.commit_if_ok(|snapshot| { self.commit_if_ok(|snapshot| {
let outer_universe = self.universe(); let outer_universe = self.universe();
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new_with_diagnostics(self);
let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id); let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
let impl_trait_ref = let impl_trait_ref =
self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args); self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args);

View File

@ -1390,7 +1390,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let mut result = ProbeResult::Match; let mut result = ProbeResult::Match;
let cause = &self.misc(self.span); let cause = &self.misc(self.span);
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new_with_diagnostics(self);
let mut trait_predicate = None; let mut trait_predicate = None;
let (mut xform_self_ty, mut xform_ret_ty); let (mut xform_self_ty, mut xform_ret_ty);

View File

@ -928,7 +928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (obligation, _) = let (obligation, _) =
self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
// FIXME: This should potentially just add the obligation to the `FnCtxt` // FIXME: This should potentially just add the obligation to the `FnCtxt`
let ocx = ObligationCtxt::new(&self.infcx); let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
Err(ocx.select_all_or_error()) Err(ocx.select_all_or_error())
} }

View File

@ -1608,7 +1608,7 @@ fn check_field_tys_sized<'tcx>(
let infcx = tcx.infer_ctxt().ignoring_regions().build(); let infcx = tcx.infer_ctxt().ignoring_regions().build();
let param_env = tcx.param_env(def_id); let param_env = tcx.param_env(def_id);
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
for field_ty in &coroutine_layout.field_tys { for field_ty in &coroutine_layout.field_tys {
ocx.register_bound( ocx.register_bound(
ObligationCause::new( ObligationCause::new(

View File

@ -2321,7 +2321,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let span = tcx.def_span(def_id); let span = tcx.def_span(def_id);
let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id()); let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id());

View File

@ -54,7 +54,7 @@ pub fn ensure_wf<'tcx>(
pred, pred,
); );
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = traits::ObligationCtxt::new(&infcx); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error(); let errors = ocx.select_all_or_error();
if !errors.is_empty() { if !errors.is_empty() {

View File

@ -1,14 +1,16 @@
use crate::solve::NextSolverError;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::{self, ObligationCtxt, SelectionContext}; use crate::traits::{
self, FromSolverError, Obligation, ObligationCause, ObligationCtxt, OldSolverError,
SelectionContext,
};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::traits::Obligation;
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::arena::ArenaAllocatable; use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, Upcast}; use rustc_middle::ty::{GenericArg, Upcast};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -94,7 +96,7 @@ impl<'tcx> InferCtxt<'tcx> {
ty::TraitRef::new(self.tcx, trait_def_id, [ty]), ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
)) { )) {
Ok(Some(selection)) => { Ok(Some(selection)) => {
let ocx = ObligationCtxt::new(self); let ocx = ObligationCtxt::new_with_diagnostics(self);
ocx.register_obligations(selection.nested_obligations()); ocx.register_obligations(selection.nested_obligations());
Some(ocx.select_all_or_error()) Some(ocx.select_all_or_error())
} }
@ -122,19 +124,21 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
/// bound for the closure and in part because it is convenient to /// bound for the closure and in part because it is convenient to
/// have `'tcx` be free on this function so that we can talk about /// have `'tcx` be free on this function so that we can talk about
/// `K: TypeFoldable<TyCtxt<'tcx>>`.) /// `K: TypeFoldable<TyCtxt<'tcx>>`.)
fn enter_canonical_trait_query<K, R>( fn enter_canonical_trait_query<K, R, E>(
self, self,
canonical_key: &Canonical<'tcx, K>, canonical_key: &Canonical<'tcx, K>,
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>, operation: impl FnOnce(&ObligationCtxt<'_, 'tcx, E>, K) -> Result<R, NoSolution>,
) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution> ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
where where
K: TypeFoldable<TyCtxt<'tcx>>, K: TypeFoldable<TyCtxt<'tcx>>,
R: Debug + TypeFoldable<TyCtxt<'tcx>>, R: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>
+ FromSolverError<'tcx, OldSolverError<'tcx>>,
{ {
let (infcx, key, canonical_inference_vars) = let (infcx, key, canonical_inference_vars) =
self.build_with_canonical(DUMMY_SP, canonical_key); self.build_with_canonical(DUMMY_SP, canonical_key);
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_generic(&infcx);
let value = operation(&ocx, key)?; let value = operation(&ocx, key)?;
ocx.make_canonicalized_query_response(canonical_inference_vars, value) ocx.make_canonicalized_query_response(canonical_inference_vars, value)
} }

View File

@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use crate::traits::FulfillmentError; use crate::traits::{FulfillmentError, ScrubbedTraitError};
use super::eval_ctxt::GenerateProofTree; use super::eval_ctxt::GenerateProofTree;
use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
@ -226,6 +226,17 @@ impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tc
} }
} }
impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError {
fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self {
match error {
NextSolverError::TrueError(_) => ScrubbedTraitError::TrueError,
NextSolverError::Ambiguity(_) | NextSolverError::Overflow(_) => {
ScrubbedTraitError::Ambiguity
}
}
}
}
fn fulfillment_error_for_no_solution<'tcx>( fn fulfillment_error_for_no_solution<'tcx>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
root_obligation: PredicateObligation<'tcx>, root_obligation: PredicateObligation<'tcx>,

View File

@ -12,6 +12,7 @@
use rustc_ast_ir::try_visit; use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::visit::VisitorResult;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::FulfillmentErrorLike as _;
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{inspect, QueryResult}; use rustc_middle::traits::solve::{inspect, QueryResult};

View File

@ -360,7 +360,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
let infcx = selcx.infcx; let infcx = selcx.infcx;
if infcx.next_trait_solver() { if infcx.next_trait_solver() {
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
ocx.register_obligations(obligations.iter().cloned()); ocx.register_obligations(obligations.iter().cloned());
let errors_and_ambiguities = ocx.select_all_or_error(); let errors_and_ambiguities = ocx.select_all_or_error();
// We only care about the obligations that are *definitely* true errors. // We only care about the obligations that are *definitely* true errors.

View File

@ -1,8 +1,8 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::Debug; use std::fmt::Debug;
use super::FulfillmentContext;
use super::{FromSolverError, TraitEngine}; use super::{FromSolverError, TraitEngine};
use super::{FulfillmentContext, ScrubbedTraitError};
use crate::regions::InferCtxtRegionExt; use crate::regions::InferCtxtRegionExt;
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
use crate::solve::NextSolverError; use crate::solve::NextSolverError;
@ -21,6 +21,7 @@ use rustc_infer::infer::canonical::{
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::RegionResolutionError;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::FulfillmentErrorLike;
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::arena::ArenaAllocatable; use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
@ -53,20 +54,36 @@ impl<
/// Used if you want to have pleasant experience when dealing /// Used if you want to have pleasant experience when dealing
/// with obligations outside of hir or mir typeck. /// with obligations outside of hir or mir typeck.
pub struct ObligationCtxt<'a, 'tcx> { pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError> {
pub infcx: &'a InferCtxt<'tcx>, pub infcx: &'a InferCtxt<'tcx>,
engine: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>, engine: RefCell<Box<dyn TraitEngine<'tcx, E>>>,
} }
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>> {
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { pub fn new_with_diagnostics(infcx: &'a InferCtxt<'tcx>) -> Self {
// TODO: Self { infcx, engine: RefCell::new(<dyn TraitEngine<'tcx, _>>::new(infcx)) }
Self {
infcx,
engine: RefCell::new(<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>::new(infcx)),
}
} }
}
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError> {
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'tcx, _>>::new(infcx)) }
}
}
impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
{
pub fn new_generic(infcx: &'a InferCtxt<'tcx>) -> Self {
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'tcx, _>>::new(infcx)) }
}
}
impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E>
where
E: FulfillmentErrorLike<'tcx>,
{
pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) { pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation); self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation);
} }
@ -118,26 +135,6 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
self.register_infer_ok_obligations(infer_ok) self.register_infer_ok_obligations(infer_ok)
} }
pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: T,
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
}
pub fn structurally_normalize(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: Ty<'tcx>,
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
self.infcx
.at(cause, param_env)
.structurally_normalize(value, &mut **self.engine.borrow_mut())
}
pub fn eq<T: ToTrace<'tcx>>( pub fn eq<T: ToTrace<'tcx>>(
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
@ -194,12 +191,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
} }
#[must_use] #[must_use]
pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> { pub fn select_where_possible(&self) -> Vec<E> {
self.engine.borrow_mut().select_where_possible(self.infcx) self.engine.borrow_mut().select_where_possible(self.infcx)
} }
#[must_use] #[must_use]
pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> { pub fn select_all_or_error(&self) -> Vec<E> {
self.engine.borrow_mut().select_all_or_error(self.infcx) self.engine.borrow_mut().select_all_or_error(self.infcx)
} }
@ -244,6 +241,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
self.infcx.resolve_regions(outlives_env) self.infcx.resolve_regions(outlives_env)
} }
pub fn make_canonicalized_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
self.infcx.make_canonicalized_query_response(
inference_vars,
answer,
&mut **self.engine.borrow_mut(),
)
}
}
impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> {
pub fn assumed_wf_types_and_report_errors( pub fn assumed_wf_types_and_report_errors(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
@ -252,12 +267,17 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
self.assumed_wf_types(param_env, def_id) self.assumed_wf_types(param_env, def_id)
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors)) .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors))
} }
}
impl<'tcx, E> ObligationCtxt<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
pub fn assumed_wf_types( pub fn assumed_wf_types(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,
) -> Result<FxIndexSet<Ty<'tcx>>, Vec<FulfillmentError<'tcx>>> { ) -> Result<FxIndexSet<Ty<'tcx>>, Vec<E>> {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let mut implied_bounds = FxIndexSet::default(); let mut implied_bounds = FxIndexSet::default();
let mut errors = Vec::new(); let mut errors = Vec::new();
@ -289,19 +309,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) } if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) }
} }
pub fn make_canonicalized_query_response<T>( pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
&self, &self,
inference_vars: CanonicalVarValues<'tcx>, cause: &ObligationCause<'tcx>,
answer: T, param_env: ty::ParamEnv<'tcx>,
) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution> value: T,
where ) -> Result<T, Vec<E>> {
T: Debug + TypeFoldable<TyCtxt<'tcx>>, self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, }
{
self.infcx.make_canonicalized_query_response( pub fn structurally_normalize(
inference_vars, &self,
answer, cause: &ObligationCause<'tcx>,
&mut **self.engine.borrow_mut(), param_env: ty::ParamEnv<'tcx>,
) value: Ty<'tcx>,
) -> Result<Ty<'tcx>, Vec<E>> {
self.infcx
.at(cause, param_env)
.structurally_normalize(value, &mut **self.engine.borrow_mut())
} }
} }

View File

@ -16,13 +16,13 @@ use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt}; use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
use std::marker::PhantomData; use std::marker::PhantomData;
use super::const_evaluatable;
use super::project::{self, ProjectAndUnifyResult}; use super::project::{self, ProjectAndUnifyResult};
use super::select::SelectionContext; use super::select::SelectionContext;
use super::wf; use super::wf;
use super::EvaluationResult; use super::EvaluationResult;
use super::PredicateObligation; use super::PredicateObligation;
use super::Unimplemented; use super::Unimplemented;
use super::{const_evaluatable, ScrubbedTraitError};
use super::{FulfillmentError, FulfillmentErrorCode}; use super::{FulfillmentError, FulfillmentErrorCode};
use crate::traits::project::PolyProjectionObligation; use crate::traits::project::PolyProjectionObligation;
@ -855,3 +855,17 @@ impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx
FulfillmentError::new(obligation, error.error, root_obligation) FulfillmentError::new(obligation, error.error, root_obligation)
} }
} }
impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError {
fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
match error.error {
FulfillmentErrorCode::Select(_)
| FulfillmentErrorCode::Project(_)
| FulfillmentErrorCode::Subtype(_, _)
| FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError,
FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
ScrubbedTraitError::Ambiguity
}
}
}
}

View File

@ -137,7 +137,7 @@ pub fn all_fields_implement_trait<'tcx>(
for field in &variant.fields { for field in &variant.fields {
// Do this per-field to get better error messages. // Do this per-field to get better error messages.
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let ocx = traits::ObligationCtxt::new(&infcx); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
let unnormalized_ty = field.ty(tcx, args); let unnormalized_ty = field.ty(tcx, args);
if unnormalized_ty.references_error() { if unnormalized_ty.references_error() {

View File

@ -46,7 +46,7 @@ pub use self::coherence::{add_placeholder_note, orphan_check_trait_ref, overlapp
pub use self::coherence::{InCrate, IsFirstInputType, UncoveredTyParams}; pub use self::coherence::{InCrate, IsFirstInputType, UncoveredTyParams};
pub use self::coherence::{OrphanCheckErr, OrphanCheckMode, OverlapResult}; pub use self::coherence::{OrphanCheckErr, OrphanCheckMode, OverlapResult};
pub use self::engine::{ObligationCtxt, TraitEngineExt}; pub use self::engine::{ObligationCtxt, TraitEngineExt};
pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation};
pub use self::normalize::NormalizeExt; pub use self::normalize::NormalizeExt;
pub use self::object_safety::hir_ty_lowering_object_safety_violations; pub use self::object_safety::hir_ty_lowering_object_safety_violations;
pub use self::object_safety::is_vtable_safe_method; pub use self::object_safety::is_vtable_safe_method;
@ -70,6 +70,28 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh
pub use rustc_infer::traits::*; pub use rustc_infer::traits::*;
// A trait error without any information in it. You likely want to alternately use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`].
#[derive(Copy, Clone, Debug)]
pub enum ScrubbedTraitError {
TrueError,
Ambiguity,
}
impl ScrubbedTraitError {
fn is_true_error(&self) -> bool {
match self {
ScrubbedTraitError::TrueError => true,
ScrubbedTraitError::Ambiguity => false,
}
}
}
impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError {
fn is_true_error(&self) -> bool {
self.is_true_error()
}
}
pub struct FulfillmentError<'tcx> { pub struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>, pub obligation: PredicateObligation<'tcx>,
pub code: FulfillmentErrorCode<'tcx>, pub code: FulfillmentErrorCode<'tcx>,
@ -450,7 +472,7 @@ pub fn fully_normalize<'tcx, T>(
where where
T: TypeFoldable<TyCtxt<'tcx>>, T: TypeFoldable<TyCtxt<'tcx>>,
{ {
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
debug!(?value); debug!(?value);
let normalized_value = ocx.normalize(&cause, param_env, value); let normalized_value = ocx.normalize(&cause, param_env, value);
debug!(?normalized_value); debug!(?normalized_value);

View File

@ -50,7 +50,8 @@ pub fn codegen_select_candidate<'tcx>(
// Currently, we use a fulfillment context to completely resolve // Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the // all nested obligations. This is because they can inform the
// inference of the impl's type parameters. // inference of the impl's type parameters.
let ocx = ObligationCtxt::new(&infcx); // FIXME(-Znext-solver): Doesn't need diagnostics if new solver.
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let impl_source = selection.map(|obligation| { let impl_source = selection.map(|obligation| {
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
}); });

View File

@ -8,7 +8,7 @@ use rustc_trait_selection::traits::query::{
normalize::NormalizationResult, CanonicalAliasGoal, NoSolution, normalize::NormalizationResult, CanonicalAliasGoal, NoSolution,
}; };
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, FulfillmentErrorCode, ObligationCause, SelectionContext, self, FulfillmentError, FulfillmentErrorCode, ObligationCause, ObligationCtxt, SelectionContext,
}; };
use tracing::debug; use tracing::debug;
@ -29,7 +29,8 @@ fn normalize_canonicalized_projection_ty<'tcx>(
tcx.infer_ctxt().enter_canonical_trait_query( tcx.infer_ctxt().enter_canonical_trait_query(
&goal, &goal,
|ocx, ParamEnvAnd { param_env, value: goal }| { |ocx: &ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>>,
ParamEnvAnd { param_env, value: goal }| {
debug_assert!(!ocx.infcx.next_trait_solver()); debug_assert!(!ocx.infcx.next_trait_solver());
let selcx = &mut SelectionContext::new(ocx.infcx); let selcx = &mut SelectionContext::new(ocx.infcx);
let cause = ObligationCause::dummy(); let cause = ObligationCause::dummy();
@ -73,7 +74,7 @@ fn normalize_canonicalized_weak_ty<'tcx>(
tcx.infer_ctxt().enter_canonical_trait_query( tcx.infer_ctxt().enter_canonical_trait_query(
&goal, &goal,
|ocx, ParamEnvAnd { param_env, value: goal }| { |ocx: &ObligationCtxt<'_, 'tcx>, ParamEnvAnd { param_env, value: goal }| {
let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map( let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map(
|(predicate, span)| { |(predicate, span)| {
traits::Obligation::new( traits::Obligation::new(
@ -99,7 +100,7 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>(
tcx.infer_ctxt().enter_canonical_trait_query( tcx.infer_ctxt().enter_canonical_trait_query(
&goal, &goal,
|ocx, ParamEnvAnd { param_env, value: goal }| { |ocx: &ObligationCtxt<'_, 'tcx>, ParamEnvAnd { param_env, value: goal }| {
let selcx = &mut SelectionContext::new(ocx.infcx); let selcx = &mut SelectionContext::new(ocx.infcx);
let cause = ObligationCause::dummy(); let cause = ObligationCause::dummy();
let mut obligations = vec![]; let mut obligations = vec![];

View File

@ -43,10 +43,13 @@ fn type_op_eq<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { tcx.infer_ctxt().enter_canonical_trait_query(
let (param_env, Eq { a, b }) = key.into_parts(); &canonicalized,
Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) |ocx: &ObligationCtxt<'_, 'tcx>, key| {
}) let (param_env, Eq { a, b }) = key.into_parts();
Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?)
},
)
} }
fn type_op_normalize<'tcx, T>( fn type_op_normalize<'tcx, T>(
@ -95,10 +98,13 @@ fn type_op_subtype<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { tcx.infer_ctxt().enter_canonical_trait_query(
let (param_env, Subtype { sub, sup }) = key.into_parts(); &canonicalized,
Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) |ocx: &ObligationCtxt<'_, 'tcx>, key| {
}) let (param_env, Subtype { sub, sup }) = key.into_parts();
Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?)
},
)
} }
fn type_op_prove_predicate<'tcx>( fn type_op_prove_predicate<'tcx>(

View File

@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
let span = decl.output.span(); let span = decl.output.span();
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let cause = traits::ObligationCause::misc(span, fn_def_id); let cause = traits::ObligationCause::misc(span, fn_def_id);
ocx.register_bound(cause, cx.param_env, ret_ty, send_trait); ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
let send_errors = ocx.select_all_or_error(); let send_errors = ocx.select_all_or_error();