TypingMode 🤔

This commit is contained in:
lcnr 2024-10-18 00:28:43 +02:00
parent 2dece5bb62
commit f51ec110a7
75 changed files with 513 additions and 506 deletions

View File

@ -34,7 +34,7 @@ use rustc_infer::infer::{
use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::impls::{
@ -440,7 +440,7 @@ pub struct BorrowckInferCtxt<'tcx> {
impl<'tcx> BorrowckInferCtxt<'tcx> { impl<'tcx> BorrowckInferCtxt<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
let infcx = tcx.infer_ctxt().with_opaque_type_inference(def_id).build(); let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, def_id));
BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) } BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
} }

View File

@ -9,6 +9,7 @@ use rustc_macros::extension;
use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
TypingMode,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@ -340,14 +341,13 @@ fn check_opaque_type_well_formed<'tcx>(
parent_def_id = tcx.local_parent(parent_def_id); parent_def_id = tcx.local_parent(parent_def_id);
} }
// FIXME(-Znext-solver): We probably should use `&[]` instead of // FIXME(#132279): This should eventually use the already defined hidden types
// and prepopulate this `InferCtxt` with known opaque values, rather than // instead. Alternatively we'll entirely remove this function given we also check
// allowing opaque types to be defined and checking them after the fact. // the opaque in `check_opaque_meets_bounds` later.
let infcx = tcx let infcx = tcx
.infer_ctxt() .infer_ctxt()
.with_next_trait_solver(next_trait_solver) .with_next_trait_solver(next_trait_solver)
.with_opaque_type_inference(parent_def_id) .build(TypingMode::analysis_in_body(tcx, parent_def_id));
.build();
let ocx = ObligationCtxt::new_with_diagnostics(&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);
@ -517,7 +517,9 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
}, },
); );
let infcx = tcx.infer_ctxt().build(); // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're
// in a body here.
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| { let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {

View File

@ -21,7 +21,7 @@ use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode};
use rustc_session::Session; use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -119,7 +119,7 @@ pub fn validate_trivial_unsize<'tcx>(
) -> bool { ) -> bool {
match (source_data.principal(), target_data.principal()) { match (source_data.principal(), target_data.principal()) {
(Some(hr_source_principal), Some(hr_target_principal)) => { (Some(hr_source_principal), Some(hr_target_principal)) => {
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
let universe = infcx.universe(); let universe = infcx.universe();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
infcx.enter_forall(hr_target_principal, |target_principal| { infcx.enter_forall(hr_target_principal, |target_principal| {

View File

@ -16,7 +16,7 @@ use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt, TypingMode};
use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::storage::always_storage_live_locals;
@ -593,7 +593,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// Typeck only does a "non-const" check since it operates on HIR and cannot distinguish // Typeck only does a "non-const" check since it operates on HIR and cannot distinguish
// 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(TypingMode::from_param_env(param_env));
let ocx = ObligationCtxt::new_with_diagnostics(&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);

View File

@ -12,7 +12,7 @@ use rustc_middle::mir::CallSource;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty, self, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty, TypingMode,
suggest_constraining_type_param, suggest_constraining_type_param,
}; };
use rustc_middle::util::{CallDesugaringKind, CallKind, call_kind}; use rustc_middle::util::{CallDesugaringKind, CallKind, call_kind};
@ -116,7 +116,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
let obligation = let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
let mut selcx = SelectionContext::new(&infcx); let mut selcx = SelectionContext::new(&infcx);
let implsrc = selcx.select(&obligation); let implsrc = selcx.select(&obligation);

View File

@ -114,11 +114,11 @@ impl Qualif for HasMutInterior {
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]), ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
); );
let infcx = cx // FIXME(#132279): This should eventually use the already defined hidden types.
.tcx let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body(
.infer_ctxt() cx.tcx,
.with_opaque_type_inference(cx.body.source.def_id().expect_local()) cx.body.source.def_id().expect_local(),
.build(); ));
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(obligation); ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error(); let errors = ocx.select_all_or_error();

View File

@ -9,7 +9,9 @@ use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{ use rustc_middle::ty::layout::{
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
}; };
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance}; use rustc_middle::ty::{
self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypingMode, Variance,
};
use rustc_middle::{mir, span_bug}; use rustc_middle::{mir, span_bug};
use rustc_session::Limit; use rustc_session::Limit;
use rustc_span::Span; use rustc_span::Span;
@ -325,7 +327,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return true; return true;
} }
// Slow path: spin up an inference context to check if these traits are sufficiently equal. // Slow path: spin up an inference context to check if these traits are sufficiently equal.
let infcx = self.tcx.infer_ctxt().build(); let infcx = self.tcx.infer_ctxt().build(TypingMode::from_param_env(self.param_env));
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy_with_span(self.cur_span()); let cause = ObligationCause::dummy_with_span(self.cur_span());
// equate the two trait refs after normalization // equate the two trait refs after normalization

View File

@ -5,7 +5,7 @@
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance}; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, Variance};
use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::ObligationCtxt;
/// Returns whether the two types are equal up to subtyping. /// Returns whether the two types are equal up to subtyping.
@ -45,7 +45,8 @@ pub fn relate_types<'tcx>(
} }
let mut builder = tcx.infer_ctxt().ignoring_regions(); let mut builder = tcx.infer_ctxt().ignoring_regions();
let infcx = builder.build(); // FIXME(#132279): This should eventually use the already defined hidden types.
let infcx = builder.build(TypingMode::from_param_env(param_env));
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy(); let cause = ObligationCause::dummy();
let src = ocx.normalize(&cause, param_env, src); let src = ocx.normalize(&cause, param_env, src);

View File

@ -30,6 +30,7 @@ use rustc_trait_selection::traits;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::fold::TypeFoldable;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use ty::TypingMode;
use {rustc_attr as attr, rustc_hir as hir}; use {rustc_attr as attr, rustc_hir as hir};
use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty}; use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
@ -276,7 +277,8 @@ 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(); // FIXME(#132279): This should eventually use the already defined hidden types.
let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor));
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let args = match *origin { let args = match *origin {
@ -1675,8 +1677,8 @@ pub(super) fn check_coroutine_obligations(
// typeck writeback gives us predicates with their regions erased. // typeck writeback gives us predicates with their regions erased.
// As borrowck already has checked lifetimes, we do not need to do it again. // As borrowck already has checked lifetimes, we do not need to do it again.
.ignoring_regions() .ignoring_regions()
.with_opaque_type_inference(def_id) // FIXME(#132279): This should eventually use the already defined hidden types.
.build(); .build(TypingMode::analysis_in_body(tcx, def_id));
let ocx = ObligationCtxt::new_with_diagnostics(&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 {

View File

@ -17,7 +17,7 @@ use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeVisitableExt, Upcast, TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::Span; use rustc_span::Span;
@ -228,7 +228,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);
debug!(caller_bounds=?param_env.caller_bounds()); debug!(caller_bounds=?param_env.caller_bounds());
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(infcx); let ocx = ObligationCtxt::new_with_diagnostics(infcx);
// Create obligations for each predicate declared by the impl // Create obligations for each predicate declared by the impl
@ -516,7 +516,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id), ObligationCause::misc(tcx.def_span(impl_m_def_id), impl_m_def_id),
); );
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(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.
@ -1196,7 +1196,7 @@ fn compare_self_type<'tcx>(
let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0); let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
match ExplicitSelf::determine(self_arg_ty, can_eq_self) { match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
@ -1801,7 +1801,7 @@ fn compare_const_predicate_entailment<'tcx>(
ObligationCause::misc(impl_ct_span, impl_ct_def_id), ObligationCause::misc(impl_ct_span, impl_ct_def_id),
); );
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity(); let impl_ct_own_bounds = impl_ct_predicates.instantiate_own_identity();
@ -1951,7 +1951,7 @@ fn compare_type_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);
debug!(caller_bounds=?param_env.caller_bounds()); debug!(caller_bounds=?param_env.caller_bounds());
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
for (predicate, span) in impl_ty_own_bounds { for (predicate, span) in impl_ty_own_bounds {
@ -2036,7 +2036,7 @@ pub(super) fn check_type_bounds<'tcx>(
let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id); let impl_ty_args = GenericArgs::identity_for_item(tcx, impl_ty.def_id);
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(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
// A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR, // A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR,

View File

@ -8,7 +8,7 @@ use rustc_middle::span_bug;
use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::traits::{ObligationCause, Reveal};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, TypeVisitableExt, TypeVisitor, TypingMode,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::regions::InferCtxtRegionExt;
@ -132,7 +132,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing);
let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy()); let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy());
let ref infcx = tcx.infer_ctxt().build(); let ref infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
// Normalize the bounds. This has two purposes: // Normalize the bounds. This has two purposes:

View File

@ -9,7 +9,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::util::CheckRegions;
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypingMode};
use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{self, ObligationCtxt}; use rustc_trait_selection::traits::{self, ObligationCtxt};
@ -124,7 +124,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
adt_def_id: LocalDefId, adt_def_id: LocalDefId,
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(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let impl_span = tcx.def_span(drop_impl_def_id.to_def_id()); let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());

View File

@ -4,7 +4,7 @@ use rustc_hir as hir;
use rustc_hir::Node; use rustc_hir::Node;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
use rustc_session::config::EntryFnType; use rustc_session::config::EntryFnType;
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
@ -128,7 +128,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
tcx.dcx().emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span }); tcx.dcx().emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
return; return;
}; };
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let cause = traits::ObligationCause::new( let cause = traits::ObligationCause::new(
return_ty_span, return_ty_span,
main_diagnostics_def_id, main_diagnostics_def_id,

View File

@ -85,7 +85,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _};
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::def_id::CRATE_DEF_ID;
@ -530,7 +530,7 @@ fn suggestion_signature<'tcx>(
let ty = tcx.type_of(assoc.def_id).instantiate_identity(); let ty = tcx.type_of(assoc.def_id).instantiate_identity();
let val = tcx let val = tcx
.infer_ctxt() .infer_ctxt()
.build() .build(TypingMode::non_body_analysis())
.err_ctxt() .err_ctxt()
.ty_kind_suggestion(tcx.param_env(assoc.def_id), ty) .ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
.unwrap_or_else(|| "value".to_string()); .unwrap_or_else(|| "value".to_string());
@ -620,7 +620,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(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(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

@ -17,7 +17,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
@ -106,7 +106,7 @@ where
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>, F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
{ {
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(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(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 };
@ -765,7 +765,7 @@ fn test_region_obligations<'tcx>(
// Unfortunately, we have to use a new `InferCtxt` each call, because // Unfortunately, we have to use a new `InferCtxt` each call, because
// region constraints get added and solved there and we need to test each // region constraints get added and solved there and we need to test each
// call individually. // call individually.
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
add_constraints(&infcx); add_constraints(&infcx);

View File

@ -15,7 +15,9 @@ use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::Obligation; use rustc_infer::traits::Obligation;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_params}; use rustc_middle::ty::{
self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params,
};
use rustc_span::{DUMMY_SP, Span}; use rustc_span::{DUMMY_SP, Span};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::misc::{ use rustc_trait_selection::traits::misc::{
@ -213,7 +215,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
let param_env = tcx.param_env(impl_did); let param_env = tcx.param_env(impl_did);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let cause = ObligationCause::misc(span, impl_did); let cause = ObligationCause::misc(span, impl_did);
// Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw
@ -354,7 +356,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let cause = ObligationCause::misc(span, impl_did); let cause = ObligationCause::misc(span, impl_did);
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
mt_b: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>,

View File

@ -7,7 +7,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION; use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::def_id::{DefId, LocalDefId};
@ -302,7 +302,7 @@ fn orphan_check<'tcx>(
} }
// (1) Instantiate all generic params with fresh inference vars. // (1) Instantiate all generic params with fresh inference vars.
let infcx = tcx.infer_ctxt().intercrate(true).build(); let infcx = tcx.infer_ctxt().build(TypingMode::Coherence);
let cause = traits::ObligationCause::dummy(); let cause = traits::ObligationCause::dummy();
let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id()); let args = infcx.fresh_args_for_item(cause.span, impl_def_id.to_def_id());
let trait_ref = trait_ref.instantiate(tcx, args); let trait_ref = trait_ref.instantiate(tcx, args);

View File

@ -34,7 +34,7 @@ use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt}; use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, Span}; use rustc_span::{DUMMY_SP, Span};
@ -1438,9 +1438,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
recovered_ret_ty = Some(suggestable_ret_ty); recovered_ret_ty = Some(suggestable_ret_ty);
} else if let Some(sugg) = } else if let Some(sugg) = suggest_impl_trait(
suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty) &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
{ tcx.param_env(def_id),
ret_ty,
) {
diag.span_suggestion( diag.span_suggestion(
ty.span, ty.span,
"replace with an appropriate return type", "replace with an appropriate return type",

View File

@ -39,7 +39,7 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
TypeVisitableExt, TypeVisitableExt, TypingMode,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@ -1300,7 +1300,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some(infcx) => infcx, Some(infcx) => infcx,
None => { None => {
assert!(!self_ty.has_infer()); assert!(!self_ty.has_infer());
infcx_ = tcx.infer_ctxt().ignoring_regions().build(); infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
&infcx_ &infcx_
} }
}; };
@ -1492,7 +1492,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
infcx infcx
} else { } else {
assert!(!qself_ty.has_infer()); assert!(!qself_ty.has_infer());
infcx_ = tcx.infer_ctxt().build(); infcx_ = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
&infcx_ &infcx_
}; };

View File

@ -5,7 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt, TypingMode};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt}; use rustc_trait_selection::traits::{self, ObligationCtxt};
use tracing::debug; use tracing::debug;
@ -68,7 +68,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(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let tcx_ty = self.icx.lower_ty(ty); let tcx_ty = self.icx.lower_ty(ty);

View File

@ -72,7 +72,9 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::specialization_graph::Node; use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{
self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt, TypingMode,
};
use rustc_span::{ErrorGuaranteed, Span}; use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
@ -195,7 +197,7 @@ fn get_impl_args(
impl1_def_id: LocalDefId, impl1_def_id: LocalDefId,
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(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(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);
@ -409,7 +411,7 @@ fn check_predicates<'tcx>(
// Include the well-formed predicates of the type parameters of the impl. // Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args { for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args {
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let obligations = let obligations =
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span) wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
.unwrap(); .unwrap();

View File

@ -8,7 +8,7 @@ use rustc_hir::{HirId, HirIdMap};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::LocalDefIdMap; use rustc_span::def_id::LocalDefIdMap;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@ -81,7 +81,8 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
let infcx = tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(def_id).build(); let infcx =
tcx.infer_ctxt().ignoring_regions().build(TypingMode::analysis_in_body(tcx, def_id));
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner)); let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
TypeckRootCtxt { TypeckRootCtxt {

View File

@ -28,7 +28,7 @@
use relate::lattice::{LatticeOp, LatticeOpKind}; use relate::lattice::{LatticeOp, LatticeOpKind};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate; use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate;
use rustc_middle::ty::{Const, ImplSubject}; use rustc_middle::ty::{Const, ImplSubject, TypingMode};
use super::*; use super::*;
use crate::infer::relate::type_relating::TypeRelating; use crate::infer::relate::type_relating::TypeRelating;
@ -67,16 +67,9 @@ impl<'tcx> InferCtxt<'tcx> {
/// variables in the same state. This can be used to "branch off" many tests from the same /// variables in the same state. This can be used to "branch off" many tests from the same
/// common state. /// common state.
pub fn fork(&self) -> Self { pub fn fork(&self) -> Self {
self.fork_with_intercrate(self.intercrate)
}
/// Forks the inference context, creating a new inference context with the same inference
/// variables in the same state, except possibly changing the intercrate mode. This can be
/// used to "branch off" many tests from the same common state. Used in negative coherence.
pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
Self { Self {
tcx: self.tcx, tcx: self.tcx,
defining_opaque_types: self.defining_opaque_types, typing_mode: self.typing_mode,
considering_regions: self.considering_regions, considering_regions: self.considering_regions,
skip_leak_check: self.skip_leak_check, skip_leak_check: self.skip_leak_check,
inner: self.inner.clone(), inner: self.inner.clone(),
@ -87,11 +80,36 @@ impl<'tcx> InferCtxt<'tcx> {
reported_signature_mismatch: self.reported_signature_mismatch.clone(), reported_signature_mismatch: self.reported_signature_mismatch.clone(),
tainted_by_errors: self.tainted_by_errors.clone(), tainted_by_errors: self.tainted_by_errors.clone(),
universe: self.universe.clone(), universe: self.universe.clone(),
intercrate,
next_trait_solver: self.next_trait_solver, next_trait_solver: self.next_trait_solver,
obligation_inspector: self.obligation_inspector.clone(), obligation_inspector: self.obligation_inspector.clone(),
} }
} }
/// Forks the inference context, creating a new inference context with the same inference
/// variables in the same state, except possibly changing the intercrate mode. This can be
/// used to "branch off" many tests from the same common state. Used in negative coherence.
pub fn fork_with_typing_mode(&self, typing_mode: TypingMode<'tcx>) -> Self {
// Unlike `fork`, this invalidates all cache entries as they may depend on the
// typing mode.
let forked = Self {
tcx: self.tcx,
typing_mode,
considering_regions: self.considering_regions,
skip_leak_check: self.skip_leak_check,
inner: self.inner.clone(),
lexical_region_resolutions: self.lexical_region_resolutions.clone(),
selection_cache: Default::default(),
evaluation_cache: Default::default(),
reported_trait_errors: self.reported_trait_errors.clone(),
reported_signature_mismatch: self.reported_signature_mismatch.clone(),
tainted_by_errors: self.tainted_by_errors.clone(),
universe: self.universe.clone(),
next_trait_solver: self.next_trait_solver,
obligation_inspector: self.obligation_inspector.clone(),
};
forked.inner.borrow_mut().projection_cache().clear();
forked
}
} }
pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy { pub trait ToTrace<'tcx>: Relate<TyCtxt<'tcx>> + Copy {

View File

@ -46,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> {
V: TypeFoldable<TyCtxt<'tcx>>, V: TypeFoldable<TyCtxt<'tcx>>,
{ {
let (param_env, value) = value.into_parts(); let (param_env, value) = value.into_parts();
let param_env = self.tcx.canonical_param_env_cache.get_or_insert( let canonical_param_env = self.tcx.canonical_param_env_cache.get_or_insert(
self.tcx, self.tcx,
param_env, param_env,
query_state, query_state,
@ -64,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> {
); );
let canonical = Canonicalizer::canonicalize_with_base( let canonical = Canonicalizer::canonicalize_with_base(
param_env, canonical_param_env,
value, value,
Some(self), Some(self),
self.tcx, self.tcx,
@ -72,7 +72,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_state, query_state,
) )
.unchecked_map(|(param_env, value)| param_env.and(value)); .unchecked_map(|(param_env, value)| param_env.and(value));
CanonicalQueryInput { canonical, defining_opaque_types: self.defining_opaque_types() } CanonicalQueryInput { canonical, typing_mode: self.typing_mode(param_env) }
} }
/// Canonicalizes a query *response* `V`. When we canonicalize a /// Canonicalizes a query *response* `V`. When we canonicalize a

View File

@ -1,7 +1,6 @@
///! Definition of `InferCtxtLike` from the librarified type layer. ///! Definition of `InferCtxtLike` from the librarified type layer.
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::DefId;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::solve::SolverMode;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
@ -21,11 +20,11 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.next_trait_solver self.next_trait_solver
} }
fn solver_mode(&self) -> ty::solve::SolverMode { fn typing_mode(
match self.intercrate { &self,
true => SolverMode::Coherence, param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
false => SolverMode::Normal, ) -> ty::TypingMode<'tcx> {
} self.typing_mode(param_env_for_debug_assertion)
} }
fn universe(&self) -> ty::UniverseIndex { fn universe(&self) -> ty::UniverseIndex {
@ -91,10 +90,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
} }
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
self.defining_opaque_types()
}
fn next_ty_infer(&self) -> Ty<'tcx> { fn next_ty_infer(&self) -> Ty<'tcx> {
self.next_ty_var(DUMMY_SP) self.next_ty_var(DUMMY_SP)
} }

View File

@ -38,11 +38,12 @@ use rustc_middle::ty::fold::{
use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid, TypingMode,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::Span; use rustc_span::Span;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_type_ir::solve::Reveal;
use snapshot::undo_log::InferCtxtUndoLogs; use snapshot::undo_log::InferCtxtUndoLogs;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use type_variable::TypeVariableOrigin; use type_variable::TypeVariableOrigin;
@ -243,8 +244,9 @@ impl<'tcx> InferCtxtInner<'tcx> {
pub struct InferCtxt<'tcx> { pub struct InferCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>, pub tcx: TyCtxt<'tcx>,
/// The `DefIds` of the opaque types that may have their hidden types constrained. /// The mode of this inference context, see the struct documentation
defining_opaque_types: &'tcx ty::List<LocalDefId>, /// for more details.
typing_mode: TypingMode<'tcx>,
/// Whether this inference context should care about region obligations in /// Whether this inference context should care about region obligations in
/// the root universe. Most notably, this is used during hir typeck as region /// the root universe. Most notably, this is used during hir typeck as region
@ -296,26 +298,6 @@ pub struct InferCtxt<'tcx> {
/// bound. /// bound.
universe: Cell<ty::UniverseIndex>, universe: Cell<ty::UniverseIndex>,
/// During coherence we have to assume that other crates may add
/// additional impls which we currently don't know about.
///
/// To deal with this evaluation, we should be conservative
/// and consider the possibility of impls from outside this crate.
/// This comes up primarily when resolving ambiguity. Imagine
/// there is some trait reference `$0: Bar` where `$0` is an
/// inference variable. If `intercrate` is true, then we can never
/// say for sure that this reference is not implemented, even if
/// there are *no impls at all for `Bar`*, because `$0` could be
/// bound to some type that in a downstream crate that implements
/// `Bar`.
///
/// Outside of coherence, we set this to false because we are only
/// interested in types that the user could actually have written.
/// In other words, we consider `$0: Bar` to be unimplemented if
/// there is no type that the user could *actually name* that
/// would satisfy it. This avoids crippling inference, basically.
pub intercrate: bool,
next_trait_solver: bool, next_trait_solver: bool,
pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>, pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
@ -529,11 +511,8 @@ pub struct RegionObligation<'tcx> {
/// Used to configure inference contexts before their creation. /// Used to configure inference contexts before their creation.
pub struct InferCtxtBuilder<'tcx> { pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
defining_opaque_types: &'tcx ty::List<LocalDefId>,
considering_regions: bool, considering_regions: bool,
skip_leak_check: bool, skip_leak_check: bool,
/// Whether we are in coherence mode.
intercrate: bool,
/// Whether we should use the new trait solver in the local inference context, /// Whether we should use the new trait solver in the local inference context,
/// which affects things like which solver is used in `predicate_may_hold`. /// which affects things like which solver is used in `predicate_may_hold`.
next_trait_solver: bool, next_trait_solver: bool,
@ -544,37 +523,19 @@ impl<'tcx> TyCtxt<'tcx> {
fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
InferCtxtBuilder { InferCtxtBuilder {
tcx: self, tcx: self,
defining_opaque_types: ty::List::empty(),
considering_regions: true, considering_regions: true,
skip_leak_check: false, skip_leak_check: false,
intercrate: false,
next_trait_solver: self.next_trait_solver_globally(), next_trait_solver: self.next_trait_solver_globally(),
} }
} }
} }
impl<'tcx> InferCtxtBuilder<'tcx> { impl<'tcx> InferCtxtBuilder<'tcx> {
/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
/// you need to call this function. Otherwise the opaque type will be treated opaquely.
///
/// It is only meant to be called in two places, for typeck
/// (via `Inherited::build`) and for the inference context used
/// in mir borrowck.
pub fn with_opaque_type_inference(mut self, defining_anchor: LocalDefId) -> Self {
self.defining_opaque_types = self.tcx.opaque_types_defined_by(defining_anchor);
self
}
pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self { pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
self.next_trait_solver = next_trait_solver; self.next_trait_solver = next_trait_solver;
self self
} }
pub fn intercrate(mut self, intercrate: bool) -> Self {
self.intercrate = intercrate;
self
}
pub fn ignoring_regions(mut self) -> Self { pub fn ignoring_regions(mut self) -> Self {
self.considering_regions = false; self.considering_regions = false;
self self
@ -600,24 +561,17 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
where where
T: TypeFoldable<TyCtxt<'tcx>>, T: TypeFoldable<TyCtxt<'tcx>>,
{ {
self.defining_opaque_types = input.defining_opaque_types; let infcx = self.build(input.typing_mode);
let infcx = self.build();
let (value, args) = infcx.instantiate_canonical(span, &input.canonical); let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
(infcx, value, args) (infcx, value, args)
} }
pub fn build(&mut self) -> InferCtxt<'tcx> { pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
let InferCtxtBuilder { let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
tcx, *self;
defining_opaque_types,
considering_regions,
skip_leak_check,
intercrate,
next_trait_solver,
} = *self;
InferCtxt { InferCtxt {
tcx, tcx,
defining_opaque_types, typing_mode,
considering_regions, considering_regions,
skip_leak_check, skip_leak_check,
inner: RefCell::new(InferCtxtInner::new()), inner: RefCell::new(InferCtxtInner::new()),
@ -628,7 +582,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
reported_signature_mismatch: Default::default(), reported_signature_mismatch: Default::default(),
tainted_by_errors: Cell::new(None), tainted_by_errors: Cell::new(None),
universe: Cell::new(ty::UniverseIndex::ROOT), universe: Cell::new(ty::UniverseIndex::ROOT),
intercrate,
next_trait_solver, next_trait_solver,
obligation_inspector: Cell::new(None), obligation_inspector: Cell::new(None),
} }
@ -659,14 +612,30 @@ impl<'tcx> InferCtxt<'tcx> {
self.tcx.dcx().taintable_handle(&self.tainted_by_errors) self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
} }
pub fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
self.defining_opaque_types
}
pub fn next_trait_solver(&self) -> bool { pub fn next_trait_solver(&self) -> bool {
self.next_trait_solver self.next_trait_solver
} }
#[inline(always)]
pub fn typing_mode(
&self,
param_env_for_debug_assertion: ty::ParamEnv<'tcx>,
) -> TypingMode<'tcx> {
if cfg!(debug_assertions) {
match (param_env_for_debug_assertion.reveal(), self.typing_mode) {
(Reveal::All, TypingMode::PostAnalysis)
| (Reveal::UserFacing, TypingMode::Coherence | TypingMode::Analysis { .. }) => {}
(r, t) => unreachable!("TypingMode x Reveal mismatch: {r:?} {t:?}"),
}
}
self.typing_mode
}
#[inline(always)]
pub fn typing_mode_unchecked(&self) -> TypingMode<'tcx> {
self.typing_mode
}
pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T { pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener()) t.fold_with(&mut self.freshener())
} }
@ -1029,8 +998,12 @@ impl<'tcx> InferCtxt<'tcx> {
#[inline(always)] #[inline(always)]
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool { pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
let Some(id) = id.into().as_local() else { return false }; match self.typing_mode_unchecked() {
self.defining_opaque_types.contains(&id) TypingMode::Analysis { defining_opaque_types } => {
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
}
TypingMode::Coherence | TypingMode::PostAnalysis => false,
}
} }
pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {

View File

@ -2,6 +2,7 @@ use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::bug;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::solve::Goal; use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -100,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> {
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
let def_id = def_id.expect_local(); let def_id = def_id.expect_local();
if self.intercrate { if let ty::TypingMode::Coherence = self.typing_mode(param_env) {
// See comment on `insert_hidden_type` for why this is sufficient in coherence // See comment on `insert_hidden_type` for why this is sufficient in coherence
return Some(self.register_hidden_type( return Some(self.register_hidden_type(
OpaqueTypeKey { def_id, args }, OpaqueTypeKey { def_id, args },
@ -519,12 +520,14 @@ impl<'tcx> InferCtxt<'tcx> {
// value being folded. In simple cases like `-> impl Foo`, // value being folded. In simple cases like `-> impl Foo`,
// these are the same span, but not in cases like `-> (impl // these are the same span, but not in cases like `-> (impl
// Foo, impl Bar)`. // Foo, impl Bar)`.
if self.intercrate { match self.typing_mode(param_env) {
ty::TypingMode::Coherence => {
// During intercrate we do not define opaque types but instead always // During intercrate we do not define opaque types but instead always
// force ambiguity unless the hidden type is known to not implement // force ambiguity unless the hidden type is known to not implement
// our trait. // our trait.
goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous)) goals.push(Goal::new(self.tcx, param_env, ty::PredicateKind::Ambiguous));
} else { }
ty::TypingMode::Analysis { .. } => {
let prev = self let prev = self
.inner .inner
.borrow_mut() .borrow_mut()
@ -540,7 +543,9 @@ impl<'tcx> InferCtxt<'tcx> {
.map(Goal::from), .map(Goal::from),
); );
} }
}; }
ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"),
}
Ok(()) Ok(())
} }

View File

@ -9,6 +9,7 @@ use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::visit::MaxUniverse; use rustc_middle::ty::visit::MaxUniverse;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
TypingMode,
}; };
use rustc_span::Span; use rustc_span::Span;
use tracing::{debug, instrument, warn}; use tracing::{debug, instrument, warn};
@ -519,7 +520,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
// //
// cc trait-system-refactor-initiative#108 // cc trait-system-refactor-initiative#108
if self.infcx.next_trait_solver() if self.infcx.next_trait_solver()
&& !self.infcx.intercrate && !matches!(
self.infcx.typing_mode_unchecked(),
TypingMode::Coherence
)
&& self.in_alias && self.in_alias
{ {
inner.type_variables().equate(vid, new_var_id); inner.type_variables().equate(vid, new_var_id);
@ -650,7 +654,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
// See the comment for type inference variables // See the comment for type inference variables
// for more details. // for more details.
if self.infcx.next_trait_solver() if self.infcx.next_trait_solver()
&& !self.infcx.intercrate && !matches!(
self.infcx.typing_mode_unchecked(),
TypingMode::Coherence
)
&& self.in_alias && self.in_alias
{ {
variable_table.union(vid, new_var_id); variable_table.union(vid, new_var_id);

View File

@ -31,7 +31,7 @@ use rustc_middle::bug;
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef};
use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::lint::FutureIncompatibilityReason;
// hardwired lints from rustc_lint_defs // hardwired lints from rustc_lint_defs
pub use rustc_session::lint::builtin::*; pub use rustc_session::lint::builtin::*;
@ -604,7 +604,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
&& cx && cx
.tcx .tcx
.infer_ctxt() .infer_ctxt()
.build() .build(cx.typing_mode())
.type_implements_trait(iter_trait, [ty], cx.param_env) .type_implements_trait(iter_trait, [ty], cx.param_env)
.must_apply_modulo_regions() .must_apply_modulo_regions()
{ {
@ -648,7 +648,9 @@ fn type_implements_negative_copy_modulo_regions<'tcx>(
predicate: pred.upcast(tcx), predicate: pred.upcast(tcx),
}; };
tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation) tcx.infer_ctxt()
.build(TypingMode::non_body_analysis())
.predicate_must_hold_modulo_regions(&obligation)
} }
declare_lint! { declare_lint! {

View File

@ -14,11 +14,12 @@ use rustc_feature::Features;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_infer::traits::Reveal;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths}; use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt}; use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingMode};
use rustc_session::lint::{ use rustc_session::lint::{
BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId, BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
}; };
@ -698,6 +699,15 @@ impl LintContext for EarlyContext<'_> {
} }
impl<'tcx> LateContext<'tcx> { impl<'tcx> LateContext<'tcx> {
/// The typing mode of the currently visited node. Use this when
/// building a new `InferCtxt`.
pub fn typing_mode(&self) -> TypingMode<'tcx> {
debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
// FIXME(#132279): In case we're in a body, we should use a typing
// mode which reveals the opaque types defined by that body.
TypingMode::non_body_analysis()
}
/// Gets the type-checking results for the current body, /// Gets the type-checking results for the current body,
/// or `None` if outside a body. /// or `None` if outside a body.
pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> {

View File

@ -166,7 +166,7 @@ fn suggest_question_mark<'tcx>(
} }
let ty = args.type_at(0); let ty = args.type_at(0);
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let body_def_id = cx.tcx.hir().body_owner_def_id(body_id); let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);

View File

@ -15,7 +15,7 @@ use rustc_middle::ty::relate::{
Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::lint::FutureIncompatibilityReason;
@ -184,7 +184,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
}), }),
outlives_env: LazyCell::new(|| { outlives_env: LazyCell::new(|| {
let param_env = tcx.param_env(parent_def_id); let param_env = tcx.param_env(parent_def_id);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
let implied_bounds = let implied_bounds =

View File

@ -157,7 +157,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String), Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
); );
let infcx = cx.tcx.infer_ctxt().build(); let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
let suggest_display = is_str let suggest_display = is_str
|| cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| { || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
infcx.type_implements_trait(t, [ty], cx.param_env).may_apply() infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()

View File

@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
} }
let def_id = opaque.def_id.to_def_id(); let def_id = opaque.def_id.to_def_id();
let infcx = &cx.tcx.infer_ctxt().build(); let infcx = &cx.tcx.infer_ctxt().build(cx.typing_mode());
// For every projection predicate in the opaque type's explicit bounds, // For every projection predicate in the opaque type's explicit bounds,
// check that the type that we're assigning actually satisfies the bounds // check that the type that we're assigning actually satisfies the bounds
// of the associated type. // of the associated type.

View File

@ -323,7 +323,7 @@ macro_rules! define_callbacks {
// Increase this limit if necessary, but do try to keep the size low if possible // Increase this limit if necessary, but do try to keep the size low if possible
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
const _: () = { const _: () = {
if mem::size_of::<Key<'static>>() > 72 { if mem::size_of::<Key<'static>>() > 80 {
panic!("{}", concat!( panic!("{}", concat!(
"the query `", "the query `",
stringify!($name), stringify!($name),

View File

@ -54,7 +54,6 @@ use rustc_type_ir::TyKind::*;
use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::lang_items::TraitSolverLangItem;
pub use rustc_type_ir::lift::Lift; pub use rustc_type_ir::lift::Lift;
use rustc_type_ir::solve::SolverMode;
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph}; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph};
use tracing::{debug, trace}; use tracing::{debug, trace};
@ -170,15 +169,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
tracked.get(self) tracked.get(self)
} }
fn with_global_cache<R>( fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R {
self, f(&mut *self.new_solver_evaluation_cache.lock())
mode: SolverMode,
f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
) -> R {
match mode {
SolverMode::Normal => f(&mut *self.new_solver_evaluation_cache.lock()),
SolverMode::Coherence => f(&mut *self.new_solver_coherence_evaluation_cache.lock()),
}
} }
fn evaluation_is_concurrent(&self) -> bool { fn evaluation_is_concurrent(&self) -> bool {
@ -629,6 +621,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
) -> ty::Binder<'tcx, T> { ) -> ty::Binder<'tcx, T> {
self.anonymize_bound_vars(binder) self.anonymize_bound_vars(binder)
} }
fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::DefiningOpaqueTypes {
self.opaque_types_defined_by(defining_anchor)
}
} }
macro_rules! bidirectional_lang_item_map { macro_rules! bidirectional_lang_item_map {
@ -1334,7 +1330,6 @@ pub struct GlobalCtxt<'tcx> {
/// Caches the results of goal evaluation in the new solver. /// Caches the results of goal evaluation in the new solver.
pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>, pub new_solver_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
pub new_solver_coherence_evaluation_cache: Lock<search_graph::GlobalCache<TyCtxt<'tcx>>>,
pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>, pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
@ -1561,7 +1556,6 @@ impl<'tcx> TyCtxt<'tcx> {
selection_cache: Default::default(), selection_cache: Default::default(),
evaluation_cache: Default::default(), evaluation_cache: Default::default(),
new_solver_evaluation_cache: Default::default(), new_solver_evaluation_cache: Default::default(),
new_solver_coherence_evaluation_cache: Default::default(),
canonical_param_env_cache: Default::default(), canonical_param_env_cache: Default::default(),
data_layout, data_layout,
alloc_map: Lock::new(interpret::AllocMap::new()), alloc_map: Lock::new(interpret::AllocMap::new()),

View File

@ -100,7 +100,7 @@ pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::{ pub use self::sty::{
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
}; };
pub use self::trait_def::TraitDef; pub use self::trait_def::TraitDef;
pub use self::typeck_results::{ pub use self::typeck_results::{

View File

@ -40,6 +40,7 @@ pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>; pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>; pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
pub trait Article { pub trait Article {
fn article(&self) -> &'static str; fn article(&self) -> &'static str;

View File

@ -16,7 +16,7 @@ use rustc_middle::middle::region;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::TyCtxtAt;
use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir}; use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
@ -500,7 +500,9 @@ fn construct_fn<'tcx>(
); );
} }
let infcx = tcx.infer_ctxt().build(); // FIXME(#132279): This should be able to reveal opaque
// types defined during HIR typeck.
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let mut builder = Builder::new( let mut builder = Builder::new(
thir, thir,
infcx, infcx,
@ -578,7 +580,9 @@ fn construct_const<'a, 'tcx>(
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
}; };
let infcx = tcx.infer_ctxt().build(); // FIXME(#132279): We likely want to be able to use the hidden types of
// opaques used by this function here.
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let mut builder = let mut builder =
Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None); Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None);

View File

@ -7,7 +7,7 @@ use rustc_infer::traits::Obligation;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::ObligationCause;
@ -36,7 +36,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
) -> Box<Pat<'tcx>> { ) -> Box<Pat<'tcx>> {
let infcx = self.tcx.infer_ctxt().build(); // FIXME(#132279): We likely want to be able to reveal the hidden types
// of opaques defined in this function here.
let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let mut convert = ConstToPat::new(self, id, span, infcx); let mut convert = ConstToPat::new(self, id, span, infcx);
convert.to_pat(c, ty) convert.to_pat(c, ty)
} }

View File

@ -64,7 +64,7 @@ use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::Analysis;
@ -1501,7 +1501,11 @@ fn check_field_tys_sized<'tcx>(
return; return;
} }
let infcx = tcx.infer_ctxt().ignoring_regions().build(); // FIXME(#132279): @lcnr believes that we may want to support coroutines
// whose `Sized`-ness relies on the hidden types of opaques defined by the
// parent function. In this case we'd have to be able to reveal only these
// opaques here.
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
let param_env = tcx.param_env(def_id); let param_env = tcx.param_env(def_id);
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);

View File

@ -12,7 +12,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt, self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
Variance, TypingMode, Variance,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_target::abi::{FIRST_VARIANT, Size}; use rustc_target::abi::{FIRST_VARIANT, Size};
@ -606,7 +606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return true; return true;
} }
let infcx = self.tcx.infer_ctxt().build(); let infcx = self.tcx.infer_ctxt().build(TypingMode::from_param_env(self.param_env));
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(Obligation::new( ocx.register_obligation(Obligation::new(
self.tcx, self.tcx,

View File

@ -1,7 +1,7 @@
use std::ops::Deref; use std::ops::Deref;
use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::solve::{Certainty, Goal, NoSolution, SolverMode}; use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized { pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized {
@ -15,7 +15,6 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
fn build_with_canonical<V>( fn build_with_canonical<V>(
cx: Self::Interner, cx: Self::Interner,
solver_mode: SolverMode,
canonical: &ty::CanonicalQueryInput<Self::Interner, V>, canonical: &ty::CanonicalQueryInput<Self::Interner, V>,
) -> (Self, V, ty::CanonicalVarValues<Self::Interner>) ) -> (Self, V, ty::CanonicalVarValues<Self::Interner>)
where where
@ -93,7 +92,6 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
fn fetch_eligible_assoc_item( fn fetch_eligible_assoc_item(
&self, &self,
param_env: <Self::Interner as Interner>::ParamEnv,
goal_trait_ref: ty::TraitRef<Self::Interner>, goal_trait_ref: ty::TraitRef<Self::Interner>,
trait_assoc_def_id: <Self::Interner as Interner>::DefId, trait_assoc_def_id: <Self::Interner as Interner>::DefId,
impl_def_id: <Self::Interner as Interner>::DefId, impl_def_id: <Self::Interner as Interner>::DefId,

View File

@ -8,14 +8,14 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::inspect; use rustc_type_ir::solve::inspect;
use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::visit::TypeVisitableExt as _;
use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate}; use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate};
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use crate::delegate::SolverDelegate; use crate::delegate::SolverDelegate;
use crate::solve::inspect::ProbeKind; use crate::solve::inspect::ProbeKind;
use crate::solve::{ use crate::solve::{
BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource, BuiltinImplSource, CandidateSource, CanonicalResponse, Certainty, EvalCtxt, Goal, GoalSource,
MaybeCause, NoSolution, QueryResult, SolverMode, MaybeCause, NoSolution, QueryResult,
}; };
/// A candidate is a possible way to prove a goal. /// A candidate is a possible way to prove a goal.
@ -328,11 +328,12 @@ where
let mut candidates = vec![]; let mut candidates = vec![];
if self.solver_mode() == SolverMode::Coherence { if let TypingMode::Coherence = self.typing_mode(goal.param_env) {
if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) { if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) {
return vec![candidate]; return vec![candidate];
} }
} }
self.assemble_impl_candidates(goal, &mut candidates); self.assemble_impl_candidates(goal, &mut candidates);
self.assemble_builtin_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates);
@ -343,9 +344,12 @@ where
self.assemble_param_env_candidates(goal, &mut candidates); self.assemble_param_env_candidates(goal, &mut candidates);
if self.solver_mode() == SolverMode::Normal { match self.typing_mode(goal.param_env) {
TypingMode::Coherence => {}
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
self.discard_impls_shadowed_by_env(goal, &mut candidates); self.discard_impls_shadowed_by_env(goal, &mut candidates);
} }
}
candidates candidates
} }

View File

@ -55,6 +55,7 @@ where
&self, &self,
goal: Goal<I, T>, goal: Goal<I, T>,
) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) { ) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
let param_env_for_debug_assertion = goal.param_env;
let opaque_types = self.delegate.clone_opaque_types_for_query_response(); let opaque_types = self.delegate.clone_opaque_types_for_query_response();
let (goal, opaque_types) = let (goal, opaque_types) =
(goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate)); (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
@ -73,7 +74,7 @@ where
); );
let query_input = ty::CanonicalQueryInput { let query_input = ty::CanonicalQueryInput {
canonical, canonical,
defining_opaque_types: self.delegate.defining_opaque_types(), typing_mode: self.typing_mode(param_env_for_debug_assertion),
}; };
(orig_values, query_input) (orig_values, query_input)
} }

View File

@ -10,7 +10,7 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner}; use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypingMode};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use tracing::{instrument, trace}; use tracing::{instrument, trace};
@ -21,7 +21,6 @@ use crate::solve::search_graph::SearchGraph;
use crate::solve::{ use crate::solve::{
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
SolverMode,
}; };
pub(super) mod canonical; pub(super) mod canonical;
@ -215,8 +214,8 @@ where
D: SolverDelegate<Interner = I>, D: SolverDelegate<Interner = I>,
I: Interner, I: Interner,
{ {
pub(super) fn solver_mode(&self) -> SolverMode { pub(super) fn typing_mode(&self, param_env_for_debug_assertion: I::ParamEnv) -> TypingMode<I> {
self.search_graph.solver_mode() self.delegate.typing_mode(param_env_for_debug_assertion)
} }
pub(super) fn set_is_normalizes_to_goal(&mut self) { pub(super) fn set_is_normalizes_to_goal(&mut self) {
@ -232,7 +231,7 @@ where
generate_proof_tree: GenerateProofTree, generate_proof_tree: GenerateProofTree,
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
) -> (R, Option<inspect::GoalEvaluation<I>>) { ) -> (R, Option<inspect::GoalEvaluation<I>>) {
let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth); let mut search_graph = SearchGraph::new(root_depth);
let mut ecx = EvalCtxt { let mut ecx = EvalCtxt {
delegate, delegate,
@ -279,7 +278,7 @@ where
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
) -> R { ) -> R {
let (ref delegate, input, var_values) = let (ref delegate, input, var_values) =
SolverDelegate::build_with_canonical(cx, search_graph.solver_mode(), &canonical_input); SolverDelegate::build_with_canonical(cx, &canonical_input);
let mut ecx = EvalCtxt { let mut ecx = EvalCtxt {
delegate, delegate,
@ -942,21 +941,11 @@ where
pub(super) fn fetch_eligible_assoc_item( pub(super) fn fetch_eligible_assoc_item(
&self, &self,
param_env: I::ParamEnv,
goal_trait_ref: ty::TraitRef<I>, goal_trait_ref: ty::TraitRef<I>,
trait_assoc_def_id: I::DefId, trait_assoc_def_id: I::DefId,
impl_def_id: I::DefId, impl_def_id: I::DefId,
) -> Result<Option<I::DefId>, NoSolution> { ) -> Result<Option<I::DefId>, NoSolution> {
self.delegate.fetch_eligible_assoc_item( self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
param_env,
goal_trait_ref,
trait_assoc_def_id,
impl_def_id,
)
}
pub(super) fn can_define_opaque_ty(&self, def_id: I::LocalDefId) -> bool {
self.delegate.defining_opaque_types().contains(&def_id)
} }
pub(super) fn insert_hidden_type( pub(super) fn insert_hidden_type(

View File

@ -6,7 +6,7 @@ mod weak_types;
use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _}; use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _};
use tracing::instrument; use tracing::instrument;
use crate::delegate::SolverDelegate; use crate::delegate::SolverDelegate;
@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
use crate::solve::inspect::ProbeKind; use crate::solve::inspect::ProbeKind;
use crate::solve::{ use crate::solve::{
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
NoSolution, QueryResult, Reveal, NoSolution, QueryResult,
}; };
impl<D, I> EvalCtxt<'_, D> impl<D, I> EvalCtxt<'_, D>
@ -71,21 +71,21 @@ where
Ok(()) Ok(())
} }
ty::AliasTermKind::OpaqueTy => { ty::AliasTermKind::OpaqueTy => {
match param_env.reveal() { match self.typing_mode(param_env) {
// In user-facing mode, paques are only rigid if we may not define it. // Opaques are never rigid outside of analysis mode.
Reveal::UserFacing => { TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution),
// During analysis, opaques are only rigid if we may not define it.
TypingMode::Analysis { defining_opaque_types } => {
if rigid_alias if rigid_alias
.def_id .def_id
.as_local() .as_local()
.is_some_and(|def_id| self.can_define_opaque_ty(def_id)) .is_some_and(|def_id| defining_opaque_types.contains(&def_id))
{ {
Err(NoSolution) Err(NoSolution)
} else { } else {
Ok(()) Ok(())
} }
} }
// Opaques are never rigid in reveal-all mode.
Reveal::All => Err(NoSolution),
} }
} }
// FIXME(generic_const_exprs): we would need to support generic consts here // FIXME(generic_const_exprs): we would need to support generic consts here
@ -252,7 +252,6 @@ where
// return ambiguity this would otherwise be incomplete, resulting in // return ambiguity this would otherwise be incomplete, resulting in
// unsoundness during coherence (#105782). // unsoundness during coherence (#105782).
let Some(target_item_def_id) = ecx.fetch_eligible_assoc_item( let Some(target_item_def_id) = ecx.fetch_eligible_assoc_item(
goal.param_env,
goal_trait_ref, goal_trait_ref,
goal.predicate.def_id(), goal.predicate.def_id(),
impl_def_id, impl_def_id,

View File

@ -4,12 +4,10 @@
use rustc_index::bit_set::GrowableBitSet; use rustc_index::bit_set::GrowableBitSet;
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, Interner}; use rustc_type_ir::{self as ty, Interner, TypingMode};
use crate::delegate::SolverDelegate; use crate::delegate::SolverDelegate;
use crate::solve::{ use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect};
Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect,
};
impl<D, I> EvalCtxt<'_, D> impl<D, I> EvalCtxt<'_, D>
where where
@ -24,17 +22,27 @@ where
let opaque_ty = goal.predicate.alias; let opaque_ty = goal.predicate.alias;
let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const");
match (goal.param_env.reveal(), self.solver_mode()) { match self.typing_mode(goal.param_env) {
(Reveal::UserFacing, SolverMode::Normal) => { TypingMode::Coherence => {
let Some(opaque_ty_def_id) = opaque_ty.def_id.as_local() else { // An impossible opaque type bound is the only way this goal will fail
// e.g. assigning `impl Copy := NotCopy`
self.add_item_bounds_for_hidden_type(
opaque_ty.def_id,
opaque_ty.args,
goal.param_env,
expected,
);
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
TypingMode::Analysis { defining_opaque_types } => {
let Some(def_id) = opaque_ty.def_id.as_local() else {
return Err(NoSolution); return Err(NoSolution);
}; };
// FIXME: at some point we should call queries without defining
// new opaque types but having the existing opaque type definitions. if !defining_opaque_types.contains(&def_id) {
// This will require moving this below "Prefer opaques registered already".
if !self.can_define_opaque_ty(opaque_ty_def_id) {
return Err(NoSolution); return Err(NoSolution);
} }
// FIXME: This may have issues when the args contain aliases... // FIXME: This may have issues when the args contain aliases...
match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) { match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => { Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
@ -48,8 +56,7 @@ where
Ok(()) => {} Ok(()) => {}
} }
// Prefer opaques registered already. // Prefer opaques registered already.
let opaque_type_key = let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
ty::OpaqueTypeKey { def_id: opaque_ty_def_id, args: opaque_ty.args };
// FIXME: This also unifies the previous hidden type with the expected. // FIXME: This also unifies the previous hidden type with the expected.
// //
// If that fails, we insert `expected` as a new hidden type instead of // If that fails, we insert `expected` as a new hidden type instead of
@ -69,7 +76,7 @@ where
} }
ecx.eq(goal.param_env, candidate_ty, expected)?; ecx.eq(goal.param_env, candidate_ty, expected)?;
ecx.add_item_bounds_for_hidden_type( ecx.add_item_bounds_for_hidden_type(
candidate_key.def_id.into(), def_id.into(),
candidate_key.args, candidate_key.args,
goal.param_env, goal.param_env,
candidate_ty, candidate_ty,
@ -82,25 +89,14 @@ where
// FIXME: should we use `inject_hidden_type_unchecked` here? // FIXME: should we use `inject_hidden_type_unchecked` here?
self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?; self.insert_hidden_type(opaque_type_key, goal.param_env, expected)?;
self.add_item_bounds_for_hidden_type( self.add_item_bounds_for_hidden_type(
opaque_ty.def_id, def_id.into(),
opaque_ty.args, opaque_ty.args,
goal.param_env, goal.param_env,
expected, expected,
); );
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} }
(Reveal::UserFacing, SolverMode::Coherence) => { TypingMode::PostAnalysis => {
// An impossible opaque type bound is the only way this goal will fail
// e.g. assigning `impl Copy := NotCopy`
self.add_item_bounds_for_hidden_type(
opaque_ty.def_id,
opaque_ty.args,
goal.param_env,
expected,
);
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
(Reveal::All, _) => {
// FIXME: Add an assertion that opaque type storage is empty. // FIXME: Add an assertion that opaque type storage is empty.
let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args);
self.eq(goal.param_env, expected, actual)?; self.eq(goal.param_env, expected, actual)?;

View File

@ -6,7 +6,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*; use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::visit::TypeVisitableExt as _;
use rustc_type_ir::{self as ty, Interner, TraitPredicate, Upcast as _, elaborate}; use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
use tracing::{instrument, trace}; use tracing::{instrument, trace};
use crate::delegate::SolverDelegate; use crate::delegate::SolverDelegate;
@ -15,7 +15,7 @@ use crate::solve::assembly::{self, Candidate};
use crate::solve::inspect::ProbeKind; use crate::solve::inspect::ProbeKind;
use crate::solve::{ use crate::solve::{
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause, BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
NoSolution, QueryResult, Reveal, SolverMode, NoSolution, QueryResult,
}; };
impl<D, I> assembly::GoalKind<D> for TraitPredicate<I> impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
@ -67,9 +67,9 @@ where
let maximal_certainty = match (impl_polarity, goal.predicate.polarity) { let maximal_certainty = match (impl_polarity, goal.predicate.polarity) {
// In intercrate mode, this is ambiguous. But outside of intercrate, // In intercrate mode, this is ambiguous. But outside of intercrate,
// it's not a real impl. // it's not a real impl.
(ty::ImplPolarity::Reservation, _) => match ecx.solver_mode() { (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode(goal.param_env) {
SolverMode::Coherence => Certainty::AMBIGUOUS, TypingMode::Coherence => Certainty::AMBIGUOUS,
SolverMode::Normal => return Err(NoSolution), TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution),
}, },
// Impl matches polarity // Impl matches polarity
@ -167,32 +167,31 @@ where
return result; return result;
} }
// Don't call `type_of` on a local TAIT that's in the defining scope, // We only look into opaque types during analysis for opaque types
// since that may require calling `typeck` on the same item we're // outside of their defining scope. Doing so for opaques in the
// defining scope may require calling `typeck` on the same item we're
// currently type checking, which will result in a fatal cycle that // currently type checking, which will result in a fatal cycle that
// ideally we want to avoid, since we can make progress on this goal // ideally we want to avoid, since we can make progress on this goal
// via an alias bound or a locally-inferred hidden type instead. // via an alias bound or a locally-inferred hidden type instead.
//
// Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since
// we already normalize the self type in
// `assemble_candidates_after_normalizing_self_ty`, and we'd
// just be registering an identical candidate here.
//
// We always return `Err(NoSolution)` here in `SolverMode::Coherence`
// since we'll always register an ambiguous candidate in
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
// the TAIT.
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
if matches!(goal.param_env.reveal(), Reveal::All) match ecx.typing_mode(goal.param_env) {
|| matches!(ecx.solver_mode(), SolverMode::Coherence) TypingMode::Coherence | TypingMode::PostAnalysis => {
|| opaque_ty unreachable!("rigid opaque outside of analysis: {goal:?}");
}
TypingMode::Analysis { defining_opaque_types } => {
if opaque_ty
.def_id .def_id
.as_local() .as_local()
.is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) .is_some_and(|def_id| defining_opaque_types.contains(&def_id))
{ {
return Err(NoSolution); return Err(NoSolution);
} }
} }
}
}
// We want to make sure
debug_assert!(!matches!(ecx.typing_mode(), TypingMode::Coherence));
ecx.probe_and_evaluate_goal_for_constituent_tys( ecx.probe_and_evaluate_goal_for_constituent_tys(
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),

View File

@ -25,7 +25,7 @@ use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::{ use rustc_session::lint::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
@ -2267,7 +2267,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let def_id = hir_id.expect_owner().def_id; let def_id = hir_id.expect_owner().def_id;
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let span = tcx.def_span(def_id); let span = tcx.def_span(def_id);

View File

@ -2,6 +2,7 @@ use rustc_abi::{HasDataLayout, TargetDataLayout};
use rustc_ast::Attribute; use rustc_ast::Attribute;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_middle::infer::canonical::ir::TypingMode;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers}; use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers};
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
@ -54,7 +55,7 @@ pub fn ensure_wf<'tcx>(
param_env, param_env,
pred, pred,
); );
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
let ocx = traits::ObligationCtxt::new_with_diagnostics(&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();

View File

@ -7,13 +7,13 @@ use rustc_infer::infer::canonical::{
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues, Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues,
}; };
use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::solve::Goal; use rustc_infer::traits::solve::Goal;
use rustc_infer::traits::{ObligationCause, Reveal};
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_type_ir::solve::{Certainty, NoSolution, SolverMode}; use rustc_type_ir::TypingMode;
use tracing::trace; use rustc_type_ir::solve::{Certainty, NoSolution};
use crate::traits::specialization_graph; use crate::traits::specialization_graph;
@ -47,7 +47,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
fn build_with_canonical<V>( fn build_with_canonical<V>(
interner: TyCtxt<'tcx>, interner: TyCtxt<'tcx>,
solver_mode: SolverMode,
canonical: &CanonicalQueryInput<'tcx, V>, canonical: &CanonicalQueryInput<'tcx, V>,
) -> (Self, V, CanonicalVarValues<'tcx>) ) -> (Self, V, CanonicalVarValues<'tcx>)
where where
@ -56,10 +55,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
let (infcx, value, vars) = interner let (infcx, value, vars) = interner
.infer_ctxt() .infer_ctxt()
.with_next_trait_solver(true) .with_next_trait_solver(true)
.intercrate(match solver_mode {
SolverMode::Normal => false,
SolverMode::Coherence => true,
})
.build_with_canonical(DUMMY_SP, canonical); .build_with_canonical(DUMMY_SP, canonical);
(SolverDelegate(infcx), value, vars) (SolverDelegate(infcx), value, vars)
} }
@ -195,7 +190,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
fn fetch_eligible_assoc_item( fn fetch_eligible_assoc_item(
&self, &self,
param_env: ty::ParamEnv<'tcx>,
goal_trait_ref: ty::TraitRef<'tcx>, goal_trait_ref: ty::TraitRef<'tcx>,
trait_assoc_def_id: DefId, trait_assoc_def_id: DefId,
impl_def_id: DefId, impl_def_id: DefId,
@ -211,12 +205,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
// and the obligation is monomorphic, otherwise passes such as // and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could // transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations. // get a result which isn't correct for all monomorphizations.
if param_env.reveal() == Reveal::All { match self.typing_mode_unchecked() {
TypingMode::Coherence | TypingMode::Analysis { .. } => false,
TypingMode::PostAnalysis => {
let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref);
!poly_trait_ref.still_further_specializable() !poly_trait_ref.still_further_specializable()
} else { }
trace!(?node_item.item.def_id, "not eligible due to default");
false
} }
}; };

View File

@ -10,6 +10,7 @@ use rustc_infer::infer::DefineOpaqueTypes;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::{Region, RegionVid}; use rustc_middle::ty::{Region, RegionVid};
use tracing::debug; use tracing::debug;
use ty::TypingMode;
use super::*; use super::*;
use crate::errors::UnableToConstructConstantValue; use crate::errors::UnableToConstructConstantValue;
@ -79,7 +80,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]); let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let mut selcx = SelectionContext::new(&infcx); let mut selcx = SelectionContext::new(&infcx);
for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] { for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] {
let result = selcx.select(&Obligation::new( let result = selcx.select(&Obligation::new(
@ -99,7 +100,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
} }
} }
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let mut fresh_preds = FxIndexSet::default(); let mut fresh_preds = FxIndexSet::default();
// Due to the way projections are handled by SelectionContext, we need to run // Due to the way projections are handled by SelectionContext, we need to run

View File

@ -18,7 +18,7 @@ use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
pub use rustc_next_trait_solver::coherence::*; pub use rustc_next_trait_solver::coherence::*;
use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -195,9 +195,8 @@ fn overlap<'tcx>(
let infcx = tcx let infcx = tcx
.infer_ctxt() .infer_ctxt()
.skip_leak_check(skip_leak_check.is_yes()) .skip_leak_check(skip_leak_check.is_yes())
.intercrate(true)
.with_next_trait_solver(tcx.next_trait_solver_in_coherence()) .with_next_trait_solver(tcx.next_trait_solver_in_coherence())
.build(); .build(TypingMode::Coherence);
let selcx = &mut SelectionContext::new(&infcx); let selcx = &mut SelectionContext::new(&infcx);
if track_ambiguity_causes.is_yes() { if track_ambiguity_causes.is_yes() {
selcx.enable_tracking_intercrate_ambiguity_causes(); selcx.enable_tracking_intercrate_ambiguity_causes();
@ -419,7 +418,7 @@ fn impl_intersection_has_negative_obligation(
// N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates // N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates
// do not need intercrate mode enabled. // do not need intercrate mode enabled.
let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build(); let ref infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(TypingMode::Coherence);
let root_universe = infcx.universe(); let root_universe = infcx.universe();
assert_eq!(root_universe, ty::UniverseIndex::ROOT); assert_eq!(root_universe, ty::UniverseIndex::ROOT);
@ -570,7 +569,9 @@ fn try_prove_negated_where_clause<'tcx>(
// the *existence* of a negative goal, not the non-existence of a positive goal. // the *existence* of a negative goal, not the non-existence of a positive goal.
// Without this, we over-eagerly register coherence ambiguity candidates when // Without this, we over-eagerly register coherence ambiguity candidates when
// impl candidates do exist. // impl candidates do exist.
let ref infcx = root_infcx.fork_with_intercrate(false); // FIXME(#132279): `TypingMode::non_body_analysis` is a bit questionable here as it
// would cause us to reveal opaque types to leak their auto traits.
let ref infcx = root_infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);
ocx.register_obligation(Obligation::new( ocx.register_obligation(Obligation::new(
infcx.tcx, infcx.tcx,
@ -714,7 +715,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
// It is only relevant that a goal is unknowable if it would have otherwise // It is only relevant that a goal is unknowable if it would have otherwise
// failed. // failed.
let non_intercrate_infcx = infcx.fork_with_intercrate(false); // FIXME(#132279): Forking with `TypingMode::non_body_analysis` is a bit questionable
// as it would allow us to reveal opaque types, potentially causing unexpected
// cycles.
let non_intercrate_infcx = infcx.fork_with_typing_mode(TypingMode::non_body_analysis());
if non_intercrate_infcx.predicate_may_hold(&Obligation::new( if non_intercrate_infcx.predicate_may_hold(&Obligation::new(
infcx.tcx, infcx.tcx,
ObligationCause::dummy(), ObligationCause::dummy(),

View File

@ -14,7 +14,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt, self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt,
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, Upcast, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
@ -718,7 +718,7 @@ fn receiver_is_dispatchable<'tcx>(
Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
}; };
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
// the receiver is dispatchable iff the obligation holds // the receiver is dispatchable iff the obligation holds
infcx.predicate_must_hold_modulo_regions(&obligation) infcx.predicate_must_hold_modulo_regions(&obligation)
} }

View File

@ -13,7 +13,7 @@ use rustc_middle::bug;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt}; use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt, TypingMode};
use thin_vec::ThinVec; use thin_vec::ThinVec;
use tracing::{debug, debug_span, instrument}; use tracing::{debug, debug_span, instrument};
@ -760,7 +760,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
stalled_on: &mut Vec<TyOrConstInferVar>, stalled_on: &mut Vec<TyOrConstInferVar>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> { ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx; let infcx = self.selcx.infcx;
if obligation.predicate.is_global() && !self.selcx.is_intercrate() { if obligation.predicate.is_global()
&& !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
{
// no type variables present, can use evaluation for better caching. // no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too. // FIXME: consider caching errors too.
if infcx.predicate_must_hold_considering_regions(obligation) { if infcx.predicate_must_hold_considering_regions(obligation) {
@ -813,11 +815,13 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
stalled_on: &mut Vec<TyOrConstInferVar>, stalled_on: &mut Vec<TyOrConstInferVar>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> { ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let tcx = self.selcx.tcx(); let tcx = self.selcx.tcx();
let infcx = self.selcx.infcx;
if obligation.predicate.is_global() && !self.selcx.is_intercrate() { if obligation.predicate.is_global()
&& !matches!(infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
{
// no type variables present, can use evaluation for better caching. // no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too. // FIXME: consider caching errors too.
if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) { if infcx.predicate_must_hold_considering_regions(obligation) {
if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation( if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation(
&mut self.selcx, &mut self.selcx,
&project_obligation, &project_obligation,
@ -825,8 +829,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
// If `predicate_must_hold_considering_regions` succeeds, then we've // If `predicate_must_hold_considering_regions` succeeds, then we've
// evaluated all sub-obligations. We can therefore mark the 'root' // evaluated all sub-obligations. We can therefore mark the 'root'
// obligation as complete, and skip evaluating sub-obligations. // obligation as complete, and skip evaluating sub-obligations.
self.selcx infcx
.infcx
.inner .inner
.borrow_mut() .borrow_mut()
.projection_cache() .projection_cache()

View File

@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use super::outlives_bounds::InferCtxtExt; use super::outlives_bounds::InferCtxtExt;
use crate::regions::InferCtxtRegionExt; use crate::regions::InferCtxtRegionExt;
@ -143,7 +143,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
let mut infringing_inner_tys = vec![]; let mut infringing_inner_tys = vec![];
for inner_ty in inner_tys { for inner_ty in inner_tys {
// We use an ocx per inner ty for better diagnostics // We use an ocx per inner ty for better diagnostics
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
ocx.register_bound( ocx.register_bound(
@ -200,7 +200,7 @@ pub fn all_fields_implement_trait<'tcx>(
for variant in adt.variants() { for variant in adt.variants() {
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(TypingMode::non_body_analysis());
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
let unnormalized_ty = field.ty(tcx, args); let unnormalized_ty = field.ty(tcx, args);

View File

@ -34,7 +34,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast, self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, TypingMode,
Upcast,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
@ -274,7 +275,7 @@ fn do_normalize_predicates<'tcx>(
// by wfcheck anyway, so I'm not sure we have to check // by wfcheck anyway, so I'm not sure we have to check
// them here too, and we will remove this function when // them here too, and we will remove this function when
// we move over to lazy normalization *anyway*. // we move over to lazy normalization *anyway*.
let infcx = tcx.infer_ctxt().ignoring_regions().build(); let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let predicates = ocx.normalize(&cause, elaborated_env, predicates); let predicates = ocx.normalize(&cause, elaborated_env, predicates);
@ -475,11 +476,11 @@ pub fn normalize_param_env_or_error<'tcx>(
/// Normalizes the predicates and checks whether they hold in an empty environment. If this /// Normalizes the predicates and checks whether they hold in an empty environment. If this
/// returns true, then either normalize encountered an error or one of the predicates did not /// returns true, then either normalize encountered an error or one of the predicates did not
/// hold. Used when creating vtables to check for unsatisfiable methods. /// hold. Used when creating vtables to check for unsatisfiable methods. This should not be
/// used during analysis.
pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool { pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
debug!("impossible_predicates(predicates={:?})", predicates); debug!("impossible_predicates(predicates={:?})", predicates);
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
let infcx = tcx.infer_ctxt().build();
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates); let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates);
@ -568,8 +569,11 @@ fn is_impossible_associated_item(
// since that method *may* have some substitutions where the predicates hold. // since that method *may* have some substitutions where the predicates hold.
// //
// This replicates the logic we use in coherence. // This replicates the logic we use in coherence.
let infcx = let infcx = tcx
tcx.infer_ctxt().ignoring_regions().with_next_trait_solver(true).intercrate(true).build(); .infer_ctxt()
.ignoring_regions()
.with_next_trait_solver(true)
.build(TypingMode::Coherence);
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id); let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id);

View File

@ -334,11 +334,6 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
) -> Result<Option<Term<'tcx>>, InProgress> { ) -> Result<Option<Term<'tcx>>, InProgress> {
let infcx = selcx.infcx; let infcx = selcx.infcx;
debug_assert!(!selcx.infcx.next_trait_solver()); debug_assert!(!selcx.infcx.next_trait_solver());
// Don't use the projection cache in intercrate mode -
// the `infcx` may be re-used between intercrate in non-intercrate
// mode, which could lead to using incorrect cache results.
let use_cache = !selcx.is_intercrate();
let projection_term = infcx.resolve_vars_if_possible(projection_term); let projection_term = infcx.resolve_vars_if_possible(projection_term);
let cache_key = ProjectionCacheKey::new(projection_term, param_env); let cache_key = ProjectionCacheKey::new(projection_term, param_env);
@ -349,13 +344,8 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
// would not benefit from caching when proving `T: Trait<U=Foo>` // would not benefit from caching when proving `T: Trait<U=Foo>`
// bounds. It might be the case that we want two distinct caches, // bounds. It might be the case that we want two distinct caches,
// or else another kind of cache entry. // or else another kind of cache entry.
let cache_entry = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
let cache_result = if use_cache { match cache_entry {
infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
} else {
Ok(())
};
match cache_result {
Ok(()) => debug!("no cache"), Ok(()) => debug!("no cache"),
Err(ProjectionCacheEntry::Ambiguous) => { Err(ProjectionCacheEntry::Ambiguous) => {
// If we found ambiguity the last time, that means we will continue // If we found ambiguity the last time, that means we will continue
@ -378,10 +368,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
// Cache that normalizing this projection resulted in a cycle. This // Cache that normalizing this projection resulted in a cycle. This
// should ensure that, unless this happens within a snapshot that's // should ensure that, unless this happens within a snapshot that's
// rolled back, fulfillment or evaluation will notice the cycle. // rolled back, fulfillment or evaluation will notice the cycle.
if use_cache {
infcx.inner.borrow_mut().projection_cache().recur(cache_key); infcx.inner.borrow_mut().projection_cache().recur(cache_key);
}
return Err(InProgress); return Err(InProgress);
} }
Err(ProjectionCacheEntry::Recur) => { Err(ProjectionCacheEntry::Recur) => {
@ -445,26 +432,20 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
let mut deduped = SsoHashSet::with_capacity(result.obligations.len()); let mut deduped = SsoHashSet::with_capacity(result.obligations.len());
result.obligations.retain(|obligation| deduped.insert(obligation.clone())); result.obligations.retain(|obligation| deduped.insert(obligation.clone()));
if use_cache {
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
}
obligations.extend(result.obligations); obligations.extend(result.obligations);
Ok(Some(result.value)) Ok(Some(result.value))
} }
Ok(Projected::NoProgress(projected_ty)) => { Ok(Projected::NoProgress(projected_ty)) => {
let result = let result =
Normalized { value: projected_ty, obligations: PredicateObligations::new() }; Normalized { value: projected_ty, obligations: PredicateObligations::new() };
if use_cache {
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone()); infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
}
// No need to extend `obligations`. // No need to extend `obligations`.
Ok(Some(result.value)) Ok(Some(result.value))
} }
Err(ProjectionError::TooManyCandidates) => { Err(ProjectionError::TooManyCandidates) => {
debug!("opt_normalize_projection_type: too many candidates"); debug!("opt_normalize_projection_type: too many candidates");
if use_cache {
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
}
Ok(None) Ok(None)
} }
Err(ProjectionError::TraitSelectionError(_)) => { Err(ProjectionError::TraitSelectionError(_)) => {
@ -473,10 +454,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>(
// just return `ty::err` but add the obligation `T : // just return `ty::err` but add the obligation `T :
// Trait`, which when processed will cause the error to be // Trait`, which when processed will cause the error to be
// reported later // reported later
if use_cache {
infcx.inner.borrow_mut().projection_cache().error(cache_key); infcx.inner.borrow_mut().projection_cache().error(cache_key);
}
let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); let result = normalize_to_error(selcx, param_env, projection_term, cause, depth);
obligations.extend(result.obligations); obligations.extend(result.obligations);
Ok(Some(result.value)) Ok(Some(result.value))

View File

@ -87,7 +87,6 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(result) Ok(result)
}) })
} else { } else {
assert!(!self.intercrate);
let c_pred = let c_pred =
self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values); self.canonicalize_query(param_env.and(obligation.predicate), &mut _orig_values);
self.tcx.at(obligation.cause.span).evaluate_obligation(c_pred) self.tcx.at(obligation.cause.span).evaluate_obligation(c_pred)

View File

@ -16,7 +16,7 @@ use rustc_infer::traits::{
Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError, Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
}; };
use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
@ -790,7 +790,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// //
// Note that this is only sound as projection candidates of opaque types // Note that this is only sound as projection candidates of opaque types
// are always applicable for auto traits. // are always applicable for auto traits.
} else if self.infcx.intercrate { } else if let TypingMode::Coherence =
self.infcx.typing_mode(obligation.param_env)
{
// We do not emit auto trait candidates for opaque types in coherence. // We do not emit auto trait candidates for opaque types in coherence.
// Doing so can result in weird dependency cycles. // Doing so can result in weird dependency cycles.
candidates.ambiguous = true; candidates.ambiguous = true;
@ -930,7 +932,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Option<ty::PolyExistentialTraitRef<'tcx>> { ) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
// Don't drop any candidates in intercrate mode, as it's incomplete. // Don't drop any candidates in intercrate mode, as it's incomplete.
// (Not that it matters, since `Unsize` is not a stable trait.) // (Not that it matters, since `Unsize` is not a stable trait.)
if self.infcx.intercrate { //
// FIXME(@lcnr): This should probably only trigger during analysis,
// disabling candidates during codegen is also questionable.
if let TypingMode::Coherence = self.infcx.typing_mode(param_env) {
return None; return None;
} }

View File

@ -2,6 +2,7 @@
//! //!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
use std::assert_matches::assert_matches;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -28,7 +29,7 @@ use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
Upcast, TypingMode, Upcast,
}; };
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -222,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Enables tracking of intercrate ambiguity causes. See /// Enables tracking of intercrate ambiguity causes. See
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more. /// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
assert!(self.is_intercrate()); assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence);
assert!(self.intercrate_ambiguity_causes.is_none()); assert!(self.intercrate_ambiguity_causes.is_none());
self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
@ -234,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
pub fn take_intercrate_ambiguity_causes( pub fn take_intercrate_ambiguity_causes(
&mut self, &mut self,
) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> { ) -> FxIndexSet<IntercrateAmbiguityCause<'tcx>> {
assert!(self.is_intercrate()); assert_matches!(self.infcx.typing_mode_unchecked(), TypingMode::Coherence);
self.intercrate_ambiguity_causes.take().unwrap_or_default() self.intercrate_ambiguity_causes.take().unwrap_or_default()
} }
@ -242,10 +243,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.tcx self.infcx.tcx
} }
pub fn is_intercrate(&self) -> bool {
self.infcx.intercrate
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Selection // Selection
// //
@ -1029,7 +1026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
previous_stack: TraitObligationStackList<'o, 'tcx>, previous_stack: TraitObligationStackList<'o, 'tcx>,
mut obligation: PolyTraitObligation<'tcx>, mut obligation: PolyTraitObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> { ) -> Result<EvaluationResult, OverflowError> {
if !self.is_intercrate() if !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
&& obligation.is_global() && obligation.is_global()
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param()) && obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param())
{ {
@ -1312,14 +1309,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<EvaluationResult> { ) -> Option<EvaluationResult> {
// Neither the global nor local cache is aware of intercrate
// mode, so don't do any caching. In particular, we might
// re-use the same `InferCtxt` with both an intercrate
// and non-intercrate `SelectionContext`
if self.is_intercrate() {
return None;
}
let tcx = self.tcx(); let tcx = self.tcx();
if self.can_use_global_caches(param_env) { if self.can_use_global_caches(param_env) {
if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) { if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) {
@ -1342,14 +1331,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return; return;
} }
// Neither the global nor local cache is aware of intercrate
// mode, so don't do any caching. In particular, we might
// re-use the same `InferCtxt` with both an intercrate
// and non-intercrate `SelectionContext`
if self.is_intercrate() {
return;
}
if self.can_use_global_caches(param_env) && !trait_pred.has_infer() { if self.can_use_global_caches(param_env) && !trait_pred.has_infer() {
debug!(?trait_pred, ?result, "insert_evaluation_cache global"); debug!(?trait_pred, ?result, "insert_evaluation_cache global");
// This may overwrite the cache with the same value // This may overwrite the cache with the same value
@ -1476,13 +1457,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> { fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
debug!("is_knowable(intercrate={:?})", self.is_intercrate()); let obligation = &stack.obligation;
match self.infcx.typing_mode(obligation.param_env) {
if !self.is_intercrate() { TypingMode::Coherence => {}
return Ok(()); TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()),
} }
let obligation = &stack.obligation; debug!("is_knowable()");
let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
// Okay to skip binder because of the nature of the // Okay to skip binder because of the nature of the
@ -1502,25 +1484,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return false; return false;
} }
match self.infcx.typing_mode(param_env) {
// Avoid using the global cache during coherence and just rely // Avoid using the global cache during coherence and just rely
// on the local cache. This effectively disables caching // on the local cache. It is really just a simplification to
// during coherence. It is really just a simplification to
// avoid us having to fear that coherence results "pollute" // avoid us having to fear that coherence results "pollute"
// the master cache. Since coherence executes pretty quickly, // the master cache. Since coherence executes pretty quickly,
// it's not worth going to more trouble to increase the // it's not worth going to more trouble to increase the
// hit-rate, I don't think. // hit-rate, I don't think.
if self.is_intercrate() { TypingMode::Coherence => false,
return false;
}
// Avoid using the global cache when we're defining opaque types // Avoid using the global cache when we're defining opaque types
// as their hidden type may impact the result of candidate selection. // as their hidden type may impact the result of candidate selection.
if !self.infcx.defining_opaque_types().is_empty() { TypingMode::Analysis { defining_opaque_types } => defining_opaque_types.is_empty(),
return false; // The global cache is only used if there are no opaque types in
// the defining scope or we're outside of analysis.
//
// FIXME(#132279): This is still incorrect as we treat opaque types
// and default associated items differently between these two modes.
TypingMode::PostAnalysis => true,
} }
// Otherwise, we can use the global cache.
true
} }
fn check_candidate_cache( fn check_candidate_cache(
@ -1528,13 +1509,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> { ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
// Neither the global nor local cache is aware of intercrate
// mode, so don't do any caching. In particular, we might
// re-use the same `InferCtxt` with both an intercrate
// and non-intercrate `SelectionContext`
if self.is_intercrate() {
return None;
}
let tcx = self.tcx(); let tcx = self.tcx();
let pred = cache_fresh_trait_pred.skip_binder(); let pred = cache_fresh_trait_pred.skip_binder();
@ -1566,13 +1540,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&self, &self,
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>, result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
) -> bool { ) -> bool {
// Neither the global nor local cache is aware of intercrate
// mode, so don't do any caching. In particular, we might
// re-use the same `InferCtxt` with both an intercrate
// and non-intercrate `SelectionContext`
if self.is_intercrate() {
return false;
}
match result { match result {
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(), Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(),
_ => true, _ => true,
@ -2541,7 +2508,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
})?; })?;
nested_obligations.extend(obligations); nested_obligations.extend(obligations);
if !self.is_intercrate() && impl_trait_header.polarity == ty::ImplPolarity::Reservation { if impl_trait_header.polarity == ty::ImplPolarity::Reservation
&& !matches!(self.infcx.typing_mode(obligation.param_env), TypingMode::Coherence)
{
debug!("reservation impls only apply in intercrate mode"); debug!("reservation impls only apply in intercrate mode");
return Err(()); return Err(());
} }

View File

@ -19,7 +19,9 @@ use rustc_infer::infer::DefineOpaqueTypes;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::query::LocalCrate; use rustc_middle::query::LocalCrate;
use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{
self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt, TypingMode,
};
use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS}; use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym};
use specialization_graph::GraphExt; use specialization_graph::GraphExt;
@ -184,7 +186,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
let penv = tcx.param_env(impl1_def_id); let penv = tcx.param_env(impl1_def_id);
// Create an infcx, taking the predicates of impl1 as assumptions: // Create an infcx, taking the predicates of impl1 as assumptions:
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
// Attempt to prove that impl2 applies, given all of the above. // Attempt to prove that impl2 applies, given all of the above.
fulfill_implication( fulfill_implication(

View File

@ -9,7 +9,8 @@ use rustc_infer::traits::util::PredicateSet;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry, self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast,
VtblEntry,
}; };
use rustc_span::{DUMMY_SP, Span, sym}; use rustc_span::{DUMMY_SP, Span, sym};
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
@ -439,7 +440,7 @@ fn trait_refs_are_compatible<'tcx>(
return false; return false;
} }
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let hr_source_principal = let hr_source_principal =

View File

@ -6,7 +6,7 @@
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::traits::CodegenObligationError; use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
@ -30,7 +30,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
// Do the initial selection for the obligation. This yields the // Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl. // shallow result we are looking for -- that is, what specific impl.
let infcx = tcx.infer_ctxt().ignoring_regions().build(); let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::from_param_env(param_env));
let mut selcx = SelectionContext::new(&infcx); let mut selcx = SelectionContext::new(&infcx);
let obligation_cause = ObligationCause::dummy(); let obligation_cause = ObligationCause::dummy();

View File

@ -1,7 +1,7 @@
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode};
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::{Normalized, ObligationCause}; use rustc_trait_selection::traits::{Normalized, ObligationCause};
use tracing::debug; use tracing::debug;
@ -22,7 +22,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Par
goal: ParamEnvAnd<'tcx, T>, goal: ParamEnvAnd<'tcx, T>,
) -> Result<T, NoSolution> { ) -> Result<T, NoSolution> {
let ParamEnvAnd { param_env, value } = goal; let ParamEnvAnd { param_env, value } = goal;
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
let cause = ObligationCause::dummy(); let cause = ObligationCause::dummy();
match infcx.at(&cause, param_env).query_normalize(value) { match infcx.at(&cause, param_env).query_normalize(value) {
Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => { Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {

View File

@ -3,7 +3,7 @@
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
@ -29,7 +29,7 @@ fn is_item_raw<'tcx>(
) -> bool { ) -> bool {
let (param_env, ty) = query.into_parts(); let (param_env, ty) = query.into_parts();
let trait_def_id = tcx.require_lang_item(item, None); let trait_def_id = tcx.require_lang_item(item, None);
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id) traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
} }

View File

@ -6,7 +6,7 @@ use rustc_middle::bug;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
use rustc_middle::ty::util::AsyncDropGlueMorphology; use rustc_middle::ty::util::AsyncDropGlueMorphology;
use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_span::sym; use rustc_span::sym;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_type_ir::ClosureKind; use rustc_type_ir::ClosureKind;
@ -130,7 +130,7 @@ fn resolve_associated_item<'tcx>(
.unwrap_or_else(|| { .unwrap_or_else(|| {
bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
}); });
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis);
let param_env = param_env.with_reveal_all_normalized(tcx); let param_env = param_env.with_reveal_all_normalized(tcx);
let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
let args = translate_args( let args = translate_args(

View File

@ -1,7 +1,7 @@
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
/// This method returns true if and only if `adt_ty` itself has been marked as /// This method returns true if and only if `adt_ty` itself has been marked as
@ -11,7 +11,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
/// Note that this does *not* recursively check if the substructure of `adt_ty` /// Note that this does *not* recursively check if the substructure of `adt_ty`
/// implements the trait. /// implements the trait.
fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool { fn has_structural_eq_impl<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
let infcx = &tcx.infer_ctxt().build(); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let cause = ObligationCause::dummy(); let cause = ObligationCause::dummy();
let ocx = ObligationCtxt::new(infcx); let ocx = ObligationCtxt::new(infcx);

View File

@ -8,7 +8,7 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use crate::inherent::*; use crate::inherent::*;
use crate::{self as ty, Interner, UniverseIndex}; use crate::{self as ty, Interner, TypingMode, UniverseIndex};
#[derive_where(Clone; I: Interner, V: Clone)] #[derive_where(Clone; I: Interner, V: Clone)]
#[derive_where(Hash; I: Interner, V: Hash)] #[derive_where(Hash; I: Interner, V: Hash)]
@ -19,7 +19,7 @@ use crate::{self as ty, Interner, UniverseIndex};
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub struct CanonicalQueryInput<I: Interner, V> { pub struct CanonicalQueryInput<I: Interner, V> {
pub canonical: Canonical<I, V>, pub canonical: Canonical<I, V>,
pub defining_opaque_types: I::DefiningOpaqueTypes, pub typing_mode: TypingMode<I>,
} }
/// A "canonicalized" type `V` is one where all free inference /// A "canonicalized" type `V` is one where all free inference

View File

@ -1,9 +1,68 @@
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use crate::fold::TypeFoldable; use crate::fold::TypeFoldable;
use crate::inherent::*;
use crate::relate::RelateResult; use crate::relate::RelateResult;
use crate::relate::combine::PredicateEmittingRelation; use crate::relate::combine::PredicateEmittingRelation;
use crate::solve::SolverMode; use crate::solve::Reveal;
use crate::{self as ty, Interner}; use crate::{self as ty, Interner};
/// The current typing mode of an inference context. We unfortunately have some
/// slightly different typing rules depending on the current context. See the
/// doc comment for each variant for how and why they are used.
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum TypingMode<I: Interner> {
/// When checking whether impls overlap, we check whether any obligations
/// are guaranteed to never hold when unifying the impls. This requires us
/// to be complete: we must never fail to prove something which may actually
/// hold.
///
/// In this typing mode we bail with ambiguity in case its not knowable
/// whether a trait goal may hold, e.g. because the trait may get implemented
/// in a downstream or sibling crate.
///
/// We also have to be careful when generalizing aliases inside of higher-ranked
/// types to not unnecessarily constrain any inference variables.
Coherence,
/// Analysis includes type inference, checking that items are well-formed, and
/// pretty much everything else which may emit proper type errors to the user.
///
/// We only normalize opaque types which may get defined by the current body,
/// which are stored in `defining_opaque_types`.
Analysis { defining_opaque_types: I::DefiningOpaqueTypes },
/// After analysis, mostly during codegen and MIR optimizations, we're able to
/// reveal all opaque types.
PostAnalysis,
}
impl<I: Interner> TypingMode<I> {
/// Analysis outside of a body does not define any opaque types.
pub fn non_body_analysis() -> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types: Default::default() }
}
/// While typechecking a body, we need to be able to define the opaque
/// types defined by that body.
pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
}
/// FIXME(#132279): Using this function is questionable as the `param_env`
/// does not track `defining_opaque_types` and whether we're in coherence mode.
/// Many uses of this function should also use a not-yet implemented typing mode
/// which reveals already defined opaque types in the future. This function will
/// get completely removed at some point.
pub fn from_param_env(param_env: I::ParamEnv) -> TypingMode<I> {
match param_env.reveal() {
Reveal::UserFacing => TypingMode::non_body_analysis(),
Reveal::All => TypingMode::PostAnalysis,
}
}
}
pub trait InferCtxtLike: Sized { pub trait InferCtxtLike: Sized {
type Interner: Interner; type Interner: Interner;
fn cx(&self) -> Self::Interner; fn cx(&self) -> Self::Interner;
@ -16,7 +75,10 @@ pub trait InferCtxtLike: Sized {
true true
} }
fn solver_mode(&self) -> SolverMode; fn typing_mode(
&self,
param_env_for_debug_assertion: <Self::Interner as Interner>::ParamEnv,
) -> TypingMode<Self::Interner>;
fn universe(&self) -> ty::UniverseIndex; fn universe(&self) -> ty::UniverseIndex;
fn create_next_universe(&self) -> ty::UniverseIndex; fn create_next_universe(&self) -> ty::UniverseIndex;
@ -43,8 +105,6 @@ pub trait InferCtxtLike: Sized {
vid: ty::RegionVid, vid: ty::RegionVid,
) -> <Self::Interner as Interner>::Region; ) -> <Self::Interner as Interner>::Region;
fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty; fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
fn next_const_infer(&self) -> <Self::Interner as Interner>::Const; fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
fn fresh_args_for_item( fn fresh_args_for_item(

View File

@ -11,9 +11,7 @@ use crate::inherent::*;
use crate::ir_print::IrPrint; use crate::ir_print::IrPrint;
use crate::lang_items::TraitSolverLangItem; use crate::lang_items::TraitSolverLangItem;
use crate::relate::Relate; use crate::relate::Relate;
use crate::solve::{ use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult};
CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode,
};
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, search_graph}; use crate::{self as ty, search_graph};
@ -130,11 +128,7 @@ pub trait Interner:
type Clause: Clause<Self>; type Clause: Clause<Self>;
type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags; type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
fn with_global_cache<R>( fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R;
self,
mode: SolverMode,
f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
) -> R;
fn evaluation_is_concurrent(&self) -> bool; fn evaluation_is_concurrent(&self) -> bool;
@ -298,6 +292,11 @@ pub trait Interner:
self, self,
binder: ty::Binder<Self, T>, binder: ty::Binder<Self, T>,
) -> ty::Binder<Self, T>; ) -> ty::Binder<Self, T>;
fn opaque_types_defined_by(
self,
defining_anchor: Self::LocalDefId,
) -> Self::DefiningOpaqueTypes;
} }
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
@ -414,12 +413,8 @@ impl<I: Interner> search_graph::Cx for I {
fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, I::DepNodeIndex) { fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, I::DepNodeIndex) {
I::with_cached_task(self, task) I::with_cached_task(self, task)
} }
fn with_global_cache<R>( fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R {
self, I::with_global_cache(self, f)
mode: SolverMode,
f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
) -> R {
I::with_global_cache(self, mode, f)
} }
fn evaluation_is_concurrent(&self) -> bool { fn evaluation_is_concurrent(&self) -> bool {
self.evaluation_is_concurrent() self.evaluation_is_concurrent()

View File

@ -6,9 +6,9 @@ use super::{
}; };
use crate::error::TypeError; use crate::error::TypeError;
use crate::inherent::*; use crate::inherent::*;
use crate::solve::{Goal, SolverMode}; use crate::solve::Goal;
use crate::visit::TypeVisitableExt as _; use crate::visit::TypeVisitableExt as _;
use crate::{self as ty, InferCtxtLike, Interner, Upcast}; use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast};
pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>: pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
TypeRelation<I> TypeRelation<I>
@ -128,19 +128,19 @@ where
} }
(ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => {
match infcx.solver_mode() {
SolverMode::Normal => {
assert!(!infcx.next_trait_solver()); assert!(!infcx.next_trait_solver());
structurally_relate_tys(relation, a, b) match infcx.typing_mode(relation.param_env()) {
}
// During coherence, opaque types should be treated as *possibly* // During coherence, opaque types should be treated as *possibly*
// equal to any other type (except for possibly itinfcx). This is an // equal to any other type. This is an
// extremely heavy hammer, but can be relaxed in a forwards-compatible // extremely heavy hammer, but can be relaxed in a forwards-compatible
// way later. // way later.
SolverMode::Coherence => { TypingMode::Coherence => {
relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
Ok(a) Ok(a)
} }
TypingMode::Analysis { .. } | TypingMode::PostAnalysis => {
structurally_relate_tys(relation, a, b)
}
} }
} }

View File

@ -22,7 +22,6 @@ use rustc_index::{Idx, IndexVec};
use tracing::debug; use tracing::debug;
use crate::data_structures::HashMap; use crate::data_structures::HashMap;
use crate::solve::SolverMode;
mod global_cache; mod global_cache;
use global_cache::CacheData; use global_cache::CacheData;
@ -48,11 +47,7 @@ pub trait Cx: Copy {
fn get_tracked<T: Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T; fn get_tracked<T: Debug + Clone>(self, tracked: &Self::Tracked<T>) -> T;
fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex); fn with_cached_task<T>(self, task: impl FnOnce() -> T) -> (T, Self::DepNodeIndex);
fn with_global_cache<R>( fn with_global_cache<R>(self, f: impl FnOnce(&mut GlobalCache<Self>) -> R) -> R;
self,
mode: SolverMode,
f: impl FnOnce(&mut GlobalCache<Self>) -> R,
) -> R;
fn evaluation_is_concurrent(&self) -> bool; fn evaluation_is_concurrent(&self) -> bool;
} }
@ -358,7 +353,6 @@ struct ProvisionalCacheEntry<X: Cx> {
} }
pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> { pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> {
mode: SolverMode,
root_depth: AvailableDepth, root_depth: AvailableDepth,
/// The stack of goals currently being computed. /// The stack of goals currently being computed.
/// ///
@ -374,9 +368,8 @@ pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> {
} }
impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
pub fn new(mode: SolverMode, root_depth: usize) -> SearchGraph<D> { pub fn new(root_depth: usize) -> SearchGraph<D> {
Self { Self {
mode,
root_depth: AvailableDepth(root_depth), root_depth: AvailableDepth(root_depth),
stack: Default::default(), stack: Default::default(),
provisional_cache: Default::default(), provisional_cache: Default::default(),
@ -384,10 +377,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
} }
} }
pub fn solver_mode(&self) -> SolverMode {
self.mode
}
/// Lazily update the stack entry for the parent goal. /// Lazily update the stack entry for the parent goal.
/// This behavior is shared between actually evaluating goals /// This behavior is shared between actually evaluating goals
/// and using existing global cache entries to make sure they /// and using existing global cache entries to make sure they
@ -829,7 +818,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
input: X::Input, input: X::Input,
available_depth: AvailableDepth, available_depth: AvailableDepth,
) -> Option<X::Result> { ) -> Option<X::Result> {
cx.with_global_cache(self.mode, |cache| { cx.with_global_cache(|cache| {
cache cache
.get(cx, input, available_depth, |nested_goals| { .get(cx, input, available_depth, |nested_goals| {
Self::candidate_is_applicable( Self::candidate_is_applicable(
@ -852,7 +841,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
input: X::Input, input: X::Input,
available_depth: AvailableDepth, available_depth: AvailableDepth,
) -> Option<X::Result> { ) -> Option<X::Result> {
cx.with_global_cache(self.mode, |cache| { cx.with_global_cache(|cache| {
let CacheData { result, additional_depth, encountered_overflow, nested_goals } = cache let CacheData { result, additional_depth, encountered_overflow, nested_goals } = cache
.get(cx, input, available_depth, |nested_goals| { .get(cx, input, available_depth, |nested_goals| {
Self::candidate_is_applicable( Self::candidate_is_applicable(
@ -1041,7 +1030,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
) { ) {
let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len(); let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len();
debug!(?final_entry, ?result, "insert global cache"); debug!(?final_entry, ?result, "insert global cache");
cx.with_global_cache(self.mode, |cache| { cx.with_global_cache(|cache| {
cache.insert( cache.insert(
cx, cx,
input, input,

View File

@ -58,19 +58,6 @@ pub enum Reveal {
All, All,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SolverMode {
/// Ordinary trait solving, using everywhere except for coherence.
Normal,
/// Trait solving during coherence. There are a few notable differences
/// between coherence and ordinary trait solving.
///
/// Most importantly, trait solving during coherence must not be incomplete,
/// i.e. return `Err(NoSolution)` for goals for which a solution exists.
/// This means that we must not make any guesses or arbitrary choices.
Coherence,
}
pub type CanonicalInput<I, T = <I as Interner>::Predicate> = pub type CanonicalInput<I, T = <I as Interner>::Predicate> =
ty::CanonicalQueryInput<I, QueryInput<I, T>>; ty::CanonicalQueryInput<I, QueryInput<I, T>>;
pub type CanonicalResponse<I> = Canonical<I, Response<I>>; pub type CanonicalResponse<I> = Canonical<I, Response<I>>;