mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
introduce TypingModeEqWrapper and make TypingMode !Eq
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, AdtDef, Ty};
|
||||
use rustc_middle::ty::{self, AdtDef, Ty, TypingModeEqWrapper};
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
|
||||
use tracing::instrument;
|
||||
@@ -104,10 +104,10 @@ fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
// typeck results without causing query cycles, we should use this here instead of defining
|
||||
// opaque types.
|
||||
let typing_env = ty::TypingEnv {
|
||||
typing_mode: ty::TypingMode::analysis_in_body(
|
||||
typing_mode: TypingModeEqWrapper(ty::TypingMode::analysis_in_body(
|
||||
cx.tcx,
|
||||
cx.body.source.def_id().expect_local(),
|
||||
),
|
||||
)),
|
||||
param_env: cx.typing_env.param_env,
|
||||
};
|
||||
let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env);
|
||||
|
||||
@@ -371,10 +371,20 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
|
||||
// This shouldn't be used for statics, since statics are conceptually places,
|
||||
// not values -- so what we do here could break pointer identity.
|
||||
assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
|
||||
// Const eval always happens in PostAnalysis mode . See the comment in
|
||||
// `InterpCx::new` for more details.
|
||||
debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis);
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
match key.typing_env.typing_mode.0 {
|
||||
ty::TypingMode::PostAnalysis => {}
|
||||
ty::TypingMode::Coherence
|
||||
| ty::TypingMode::Analysis { .. }
|
||||
| ty::TypingMode::Borrowck { .. }
|
||||
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
|
||||
bug!(
|
||||
"Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we format the instance even if we do not print it.
|
||||
// This serves as a regression test against an ICE on printing.
|
||||
// The next two lines concatenated contain some discussion:
|
||||
|
||||
@@ -236,9 +236,18 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
cid: GlobalId<'tcx>,
|
||||
) -> EvalToValTreeResult<'tcx> {
|
||||
// Const eval always happens in PostAnalysis mode . See the comment in
|
||||
// `InterpCx::new` for more details.
|
||||
debug_assert_eq!(typing_env.typing_mode, ty::TypingMode::PostAnalysis);
|
||||
#[cfg(debug_assertions)]
|
||||
match typing_env.typing_mode.0 {
|
||||
ty::TypingMode::PostAnalysis => {}
|
||||
ty::TypingMode::Coherence
|
||||
| ty::TypingMode::Analysis { .. }
|
||||
| ty::TypingMode::Borrowck { .. }
|
||||
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
|
||||
bug!(
|
||||
"Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
|
||||
)
|
||||
}
|
||||
}
|
||||
let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?;
|
||||
|
||||
// FIXME Need to provide a span to `eval_to_valtree`
|
||||
|
||||
@@ -243,7 +243,21 @@ pub fn new(
|
||||
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
|
||||
// types that are not specified in the opaque type. We also use MIR bodies whose opaque types have
|
||||
// already been revealed, so we'd be able to at least partially observe the hidden types anyways.
|
||||
debug_assert_matches!(typing_env.typing_mode, ty::TypingMode::PostAnalysis);
|
||||
debug_assert_matches!(typing_env.typing_mode.0, ty::TypingMode::PostAnalysis);
|
||||
if cfg!(debug_assertions) {
|
||||
match typing_env.typing_mode.0 {
|
||||
ty::TypingMode::PostAnalysis => {}
|
||||
ty::TypingMode::Coherence
|
||||
| ty::TypingMode::Analysis { .. }
|
||||
| ty::TypingMode::Borrowck { .. }
|
||||
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
|
||||
use rustc_middle::bug;
|
||||
|
||||
bug!("Const eval should always happens in PostAnalysis mode.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InterpCx {
|
||||
machine,
|
||||
tcx: tcx.at(root_span),
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
self, BoundVar, GenericArg, InferConst, List, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_type_ir::TypingModeEqWrapper;
|
||||
use smallvec::SmallVec;
|
||||
use tracing::debug;
|
||||
|
||||
@@ -72,7 +73,7 @@ pub fn canonicalize_query<V>(
|
||||
query_state,
|
||||
)
|
||||
.unchecked_map(|(param_env, value)| param_env.and(value));
|
||||
CanonicalQueryInput { canonical, typing_mode: self.typing_mode() }
|
||||
CanonicalQueryInput { canonical, typing_mode: TypingModeEqWrapper(self.typing_mode()) }
|
||||
}
|
||||
|
||||
/// Canonicalizes a query *response* `V`. When we canonicalize a
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
|
||||
};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||
use rustc_type_ir::TypingModeEqWrapper;
|
||||
use snapshot::undo_log::InferCtxtUndoLogs;
|
||||
use tracing::{debug, instrument};
|
||||
use type_variable::TypeVariableOrigin;
|
||||
@@ -564,7 +565,7 @@ pub fn build_with_canonical<T>(
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
let infcx = self.build(input.typing_mode);
|
||||
let infcx = self.build(input.typing_mode.0);
|
||||
let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
|
||||
(infcx, value, args)
|
||||
}
|
||||
@@ -573,7 +574,7 @@ pub fn build_with_typing_env(
|
||||
mut self,
|
||||
TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>,
|
||||
) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) {
|
||||
(self.build(typing_mode), param_env)
|
||||
(self.build(typing_mode.0), param_env)
|
||||
}
|
||||
|
||||
pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
|
||||
@@ -1376,7 +1377,7 @@ pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
|
||||
| ty::TypingMode::PostBorrowckAnalysis { .. }
|
||||
| ty::TypingMode::PostAnalysis) => mode,
|
||||
};
|
||||
ty::TypingEnv { typing_mode, param_env }
|
||||
ty::TypingEnv { typing_mode: TypingModeEqWrapper(typing_mode), param_env }
|
||||
}
|
||||
|
||||
/// Similar to [`Self::canonicalize_query`], except that it returns
|
||||
|
||||
@@ -24,8 +24,12 @@
|
||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||
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::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
|
||||
use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintExpectationId, LintId};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode, TypingModeEqWrapper,
|
||||
};
|
||||
use rustc_session::lint::{
|
||||
CheckLintNameResult, FutureIncompatibleInfo, Lint, LintExpectationId, LintId,
|
||||
};
|
||||
use rustc_session::{DynLintStore, Session};
|
||||
use rustc_span::edit_distance::find_best_match_for_names;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
@@ -637,7 +641,10 @@ pub fn typing_mode(&self) -> TypingMode<'tcx> {
|
||||
}
|
||||
|
||||
pub fn typing_env(&self) -> TypingEnv<'tcx> {
|
||||
TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
|
||||
TypingEnv {
|
||||
typing_mode: TypingModeEqWrapper(self.typing_mode()),
|
||||
param_env: self.param_env,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
|
||||
use crate::ty::{
|
||||
self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypeVisitableExt,
|
||||
TypingEnv, UserTypeAnnotationIndex,
|
||||
TypingEnv, TypingModeEqWrapper, UserTypeAnnotationIndex,
|
||||
};
|
||||
|
||||
mod basic_blocks;
|
||||
@@ -416,7 +416,7 @@ pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
|
||||
match self.phase {
|
||||
// FIXME(#132279): we should reveal the opaques defined in the body during analysis.
|
||||
MirPhase::Built | MirPhase::Analysis(_) => TypingEnv {
|
||||
typing_mode: ty::TypingMode::non_body_analysis(),
|
||||
typing_mode: TypingModeEqWrapper(ty::TypingMode::non_body_analysis()),
|
||||
param_env: tcx.param_env(self.source.def_id()),
|
||||
},
|
||||
MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()),
|
||||
|
||||
@@ -105,7 +105,8 @@
|
||||
AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy,
|
||||
BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig,
|
||||
InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst,
|
||||
PlaceholderRegion, PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs,
|
||||
PlaceholderRegion, PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode,
|
||||
TypingModeEqWrapper, UpvarArgs,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
@@ -980,7 +981,7 @@ pub struct ParamEnvAnd<'tcx, T> {
|
||||
pub struct TypingEnv<'tcx> {
|
||||
#[type_foldable(identity)]
|
||||
#[type_visitable(ignore)]
|
||||
pub typing_mode: TypingMode<'tcx>,
|
||||
pub typing_mode: TypingModeEqWrapper<'tcx>,
|
||||
pub param_env: ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
@@ -993,7 +994,10 @@ impl<'tcx> TypingEnv<'tcx> {
|
||||
/// use `TypingMode::PostAnalysis`, they may still have where-clauses
|
||||
/// in scope.
|
||||
pub fn fully_monomorphized() -> TypingEnv<'tcx> {
|
||||
TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::empty() }
|
||||
TypingEnv {
|
||||
typing_mode: TypingModeEqWrapper(TypingMode::PostAnalysis),
|
||||
param_env: ParamEnv::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a typing environment for use during analysis outside of a body.
|
||||
@@ -1006,7 +1010,10 @@ pub fn non_body_analysis(
|
||||
def_id: impl IntoQueryKey<DefId>,
|
||||
) -> TypingEnv<'tcx> {
|
||||
let def_id = def_id.into_query_key();
|
||||
TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) }
|
||||
TypingEnv {
|
||||
typing_mode: TypingModeEqWrapper(TypingMode::non_body_analysis()),
|
||||
param_env: tcx.param_env(def_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> TypingEnv<'tcx> {
|
||||
@@ -1018,8 +1025,12 @@ pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey<DefId>) -> Typ
|
||||
/// opaque types in the `param_env`.
|
||||
pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> {
|
||||
let TypingEnv { typing_mode, param_env } = self;
|
||||
if let TypingMode::PostAnalysis = typing_mode {
|
||||
return self;
|
||||
match typing_mode.0 {
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => {}
|
||||
TypingMode::PostAnalysis => return self,
|
||||
}
|
||||
|
||||
// No need to reveal opaques with the new solver enabled,
|
||||
@@ -1029,7 +1040,7 @@ pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx>
|
||||
} else {
|
||||
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(param_env.caller_bounds()))
|
||||
};
|
||||
TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env }
|
||||
TypingEnv { typing_mode: TypingModeEqWrapper(TypingMode::PostAnalysis), param_env }
|
||||
}
|
||||
|
||||
/// Combine this typing environment with the given `value` to be used by
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
|
||||
pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
|
||||
pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
|
||||
pub type TypingModeEqWrapper<'tcx> = ir::TypingModeEqWrapper<TyCtxt<'tcx>>;
|
||||
pub type Placeholder<'tcx, T> = ir::Placeholder<TyCtxt<'tcx>, T>;
|
||||
pub type PlaceholderRegion<'tcx> = ir::PlaceholderRegion<TyCtxt<'tcx>>;
|
||||
pub type PlaceholderType<'tcx> = ir::PlaceholderType<TyCtxt<'tcx>>;
|
||||
|
||||
@@ -548,7 +548,16 @@ fn move_paths_for_fields(
|
||||
let subpath = self.elaborator.field_subpath(variant_path, field_idx);
|
||||
let tcx = self.tcx();
|
||||
|
||||
assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis);
|
||||
match self.elaborator.typing_env().typing_mode.0 {
|
||||
ty::TypingMode::PostAnalysis => {}
|
||||
ty::TypingMode::Coherence
|
||||
| ty::TypingMode::Analysis { .. }
|
||||
| ty::TypingMode::Borrowck { .. }
|
||||
| ty::TypingMode::PostBorrowckAnalysis { .. } => {
|
||||
bug!()
|
||||
}
|
||||
}
|
||||
|
||||
let field_ty = field.ty(tcx, args);
|
||||
// We silently leave an unnormalized type here to support polymorphic drop
|
||||
// elaboration for users of rustc internal APIs
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use rustc_type_ir::relate::solver_relating::RelateExt;
|
||||
use rustc_type_ir::{
|
||||
self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner,
|
||||
TypeFoldable,
|
||||
TypeFoldable, TypingModeEqWrapper,
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
@@ -66,7 +66,10 @@ pub(super) fn canonicalize_goal<D, I>(
|
||||
predefined_opaques_in_body: delegate.cx().mk_predefined_opaques_in_body(opaque_types),
|
||||
},
|
||||
);
|
||||
let query_input = ty::CanonicalQueryInput { canonical, typing_mode: delegate.typing_mode() };
|
||||
let query_input = ty::CanonicalQueryInput {
|
||||
canonical,
|
||||
typing_mode: TypingModeEqWrapper(delegate.typing_mode()),
|
||||
};
|
||||
(orig_values, query_input)
|
||||
}
|
||||
|
||||
|
||||
@@ -466,15 +466,20 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>(
|
||||
// as we may want to weaken inference guidance in the future and don't want
|
||||
// to worry about causing major performance regressions when doing so.
|
||||
// See trait-system-refactor-initiative#226 for some ideas here.
|
||||
if TypingMode::Coherence == self.typing_mode()
|
||||
|| !candidates.iter().any(|c| {
|
||||
let assemble_impls = match self.typing_mode() {
|
||||
TypingMode::Coherence => true,
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => !candidates.iter().any(|c| {
|
||||
matches!(
|
||||
c.source,
|
||||
CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)
|
||||
| CandidateSource::AliasBound(_)
|
||||
) && has_no_inference_or_external_constraints(c.result)
|
||||
})
|
||||
{
|
||||
}),
|
||||
};
|
||||
if assemble_impls {
|
||||
self.assemble_impl_candidates(goal, &mut candidates);
|
||||
self.assemble_object_bound_candidates(goal, &mut candidates);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ fn initial_provisional_result(
|
||||
// See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` for an
|
||||
// example where this would matter. We likely should change these cycles to `NoSolution`
|
||||
// even in coherence once this is a bit more settled.
|
||||
PathKind::Inductive => match input.typing_mode {
|
||||
PathKind::Inductive => match input.typing_mode.0 {
|
||||
TypingMode::Coherence => {
|
||||
response_no_constraints(cx, input, Certainty::overflow(false))
|
||||
}
|
||||
|
||||
@@ -25,11 +25,17 @@ pub fn evaluate_host_effect_obligation<'tcx>(
|
||||
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||
obligation: &HostEffectObligation<'tcx>,
|
||||
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
||||
if selcx.infcx.typing_mode() == TypingMode::Coherence {
|
||||
span_bug!(
|
||||
obligation.cause.span,
|
||||
"should not select host obligation in old solver in intercrate mode"
|
||||
);
|
||||
match selcx.infcx.typing_mode() {
|
||||
TypingMode::Coherence => {
|
||||
span_bug!(
|
||||
obligation.cause.span,
|
||||
"should not select host obligation in old solver in intercrate mode"
|
||||
);
|
||||
}
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => {}
|
||||
}
|
||||
|
||||
let ref obligation = selcx.infcx.resolve_vars_if_possible(obligation.clone());
|
||||
|
||||
@@ -154,7 +154,7 @@ fn resolve_associated_item<'tcx>(
|
||||
// and the obligation is monomorphic, otherwise passes such as
|
||||
// transmute checking and polymorphic MIR optimizations could
|
||||
// get a result which isn't correct for all monomorphizations.
|
||||
match typing_env.typing_mode {
|
||||
match typing_env.typing_mode.0 {
|
||||
ty::TypingMode::Coherence
|
||||
| ty::TypingMode::Analysis { .. }
|
||||
| ty::TypingMode::Borrowck { .. }
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
use crate::data_structures::HashMap;
|
||||
use crate::inherent::*;
|
||||
use crate::{self as ty, Interner, TypingMode, UniverseIndex};
|
||||
use crate::{self as ty, Interner, TypingModeEqWrapper, UniverseIndex};
|
||||
|
||||
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, V)]
|
||||
#[derive_where(Copy; I: Interner, V: Copy)]
|
||||
@@ -21,7 +21,7 @@
|
||||
)]
|
||||
pub struct CanonicalQueryInput<I: Interner, V> {
|
||||
pub canonical: Canonical<I, V>,
|
||||
pub typing_mode: TypingMode<I>,
|
||||
pub typing_mode: TypingModeEqWrapper<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, V: Eq> Eq for CanonicalQueryInput<I, V> {}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
|
||||
@@ -18,11 +20,28 @@
|
||||
///
|
||||
/// If neither of these functions are available, feel free to reach out to
|
||||
/// t-types for help.
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
|
||||
///
|
||||
/// Because typing rules get subtly different based on what typing mode we're in,
|
||||
/// subtle enough that changing the behavior of typing modes can sometimes cause
|
||||
/// changes that we don't even have tests for, we'd like to enforce the rule that
|
||||
/// any place where we specialize behavior based on the typing mode, we match
|
||||
/// *exhaustively* on the typing mode. That way, it's easy to determine all the
|
||||
/// places that must change when anything about typing modes changes.
|
||||
///
|
||||
/// Hence, `TypingMode` does not implement `Eq`, though [`TypingModeEqWrapper`] is available
|
||||
/// in the rare case that you do need this. Most cases where this currently matters is
|
||||
/// where we pass typing modes through the query system and want to cache based on it.
|
||||
/// See also `#[rustc_must_match_exhaustively]`, which tries to detect non-exhaustive
|
||||
/// matches.
|
||||
///
|
||||
/// Since matching on typing mode to single out `Coherence` is so common, and `Coherence`
|
||||
/// is so different from the other modes: see also [`is_coherence`](TypingMode::is_coherence)
|
||||
#[derive_where(Clone, Copy, Hash, Debug; I: Interner)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
#[cfg_attr(not(bootstrap), rustc_must_match_exhaustively)]
|
||||
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
|
||||
@@ -90,9 +109,64 @@ pub enum TypingMode<I: Interner> {
|
||||
PostAnalysis,
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for TypingMode<I> {}
|
||||
/// We want to highly discourage using equality checks on typing modes.
|
||||
/// Instead you should match, **exhaustively**, so when we ever modify the enum we get a compile
|
||||
/// error. Only use `TypingModeEqWrapper` when you really really really have to.
|
||||
/// Prefer unwrapping `TypingModeEqWrapper` in apis that should return a `TypingMode` whenever
|
||||
/// possible, and if you ever get an `TypingModeEqWrapper`, prefer unwrapping it and matching on it **exhaustively**.
|
||||
#[derive_where(Clone, Copy, Debug; I: Interner)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub struct TypingModeEqWrapper<I: Interner>(pub TypingMode<I>);
|
||||
|
||||
impl<I: Interner> Hash for TypingModeEqWrapper<I> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> PartialEq for TypingModeEqWrapper<I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0, other.0) {
|
||||
(TypingMode::Coherence, TypingMode::Coherence) => true,
|
||||
(
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators: l },
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators: r },
|
||||
) => l == r,
|
||||
(
|
||||
TypingMode::Borrowck { defining_opaque_types: l },
|
||||
TypingMode::Borrowck { defining_opaque_types: r },
|
||||
) => l == r,
|
||||
(
|
||||
TypingMode::PostBorrowckAnalysis { defined_opaque_types: l },
|
||||
TypingMode::PostBorrowckAnalysis { defined_opaque_types: r },
|
||||
) => l == r,
|
||||
(TypingMode::PostAnalysis, TypingMode::PostAnalysis) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for TypingModeEqWrapper<I> {}
|
||||
|
||||
impl<I: Interner> TypingMode<I> {
|
||||
/// There are a bunch of places in the compiler where we single out `Coherence`,
|
||||
/// and alter behavior. We'd like to *always* match on `TypingMode` exhaustively,
|
||||
/// but not having this method leads to a bunch of noisy code.
|
||||
///
|
||||
/// See also the documentation on [`TypingMode`] about exhaustive matching.
|
||||
pub fn is_coherence(&self) -> bool {
|
||||
match self {
|
||||
TypingMode::Coherence => true,
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Analysis outside of a body does not define any opaque types.
|
||||
pub fn non_body_analysis() -> TypingMode<I> {
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
|
||||
@@ -127,6 +201,7 @@ pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
|
||||
|
||||
pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
|
||||
let defined_opaque_types = cx.opaque_types_defined_by(body_def_id);
|
||||
|
||||
if defined_opaque_types.is_empty() {
|
||||
TypingMode::non_body_analysis()
|
||||
} else {
|
||||
@@ -322,6 +397,13 @@ pub fn may_use_unstable_feature<'a, I: Interner, Infcx>(
|
||||
// Note: `feature_bound_holds_in_crate` does not consider a feature to be enabled
|
||||
// if we are in std/core even if there is a corresponding `feature` attribute on the crate.
|
||||
|
||||
(infcx.typing_mode() == TypingMode::PostAnalysis)
|
||||
|| infcx.cx().features().feature_bound_holds_in_crate(symbol)
|
||||
match infcx.typing_mode() {
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. } => {
|
||||
infcx.cx().features().feature_bound_holds_in_crate(symbol)
|
||||
}
|
||||
TypingMode::PostAnalysis => true,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user