diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index e1cab9af046be..0410521034b6b 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -9,7 +9,7 @@ use rustc_errors::ErrorGuaranteed; 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, TypingMode}; use rustc_middle::{bug, mir}; use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; use tracing::instrument; @@ -100,13 +100,14 @@ impl Qualif for HasMutInterior { // Instead we invoke an obligation context manually, and provide the opaque type inference settings // that allow the trait solver to just error out instead of cycling. let freeze_def_id = cx.tcx.require_lang_item(LangItem::Freeze, cx.body.span); - // FIXME(#132279): Once we've got a typing mode which reveals opaque types using the HIR - // typeck results without causing query cycles, we should use this here instead of defining - // opaque types. - let typing_env = ty::TypingEnv::new( - cx.typing_env.param_env, - ty::TypingMode::analysis_in_body(cx.tcx, cx.body.source.def_id().expect_local()), - ); + let did = cx.body.source.def_id().expect_local(); + + let typing_env = if cx.tcx.use_typing_mode_borrowck() { + cx.typing_env + } else { + ty::TypingEnv::new(cx.typing_env.param_env, TypingMode::analysis_in_body(cx.tcx, did)) + }; + let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(typing_env); let ocx = ObligationCtxt::new(&infcx); let obligation = Obligation::new( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b802c3b2e8d40..3c70d03aed0d6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -320,6 +320,35 @@ pub struct InferCtxt<'tcx> { pub obligation_inspector: Cell>>, } +impl<'tcx> Drop for InferCtxt<'tcx> { + fn drop(&mut self) { + let mut inner = self.inner.borrow_mut(); + let opaque_type_storage = &mut inner.opaque_type_storage; + + // No need for the drop bomb when we're in TypingMode::Borrowck, and the InferCtxt doesn't consider regions. + // This is okay since in `Borrowck`, the only reason we care about opaques is in relation to regions. + // In some places *after* typeck, like in lints we use `TypingMode::Borrowck` + // to prevent defining opaque types and we simply don't care about regions. + match self.typing_mode_raw() { + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => {} + // In erased mode, the opaque type storage is always empty + TypingMode::ErasedNotCoherence(..) => {} + TypingMode::Borrowck { .. } => { + if !self.considering_regions { + return; + } + } + } + + if !opaque_type_storage.is_empty() { + ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{opaque_type_storage:?}"))); + } + } +} + /// See the `error_reporting` module for more details. #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub enum ValuePairs<'tcx> { diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 55c00a8695fa5..066d12be320a2 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -3,7 +3,7 @@ use std::ops::Deref; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::bug; -use rustc_middle::ty::{self, OpaqueTypeKey, ProvisionalHiddenType, Ty}; +use rustc_middle::ty::{OpaqueTypeKey, ProvisionalHiddenType, Ty}; use tracing::instrument; use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog}; @@ -121,14 +121,6 @@ impl<'tcx> OpaqueTypeStorage<'tcx> { } } -impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { - fn drop(&mut self) { - if !self.is_empty() { - ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types))); - } - } -} - pub struct OpaqueTypeTable<'a, 'tcx> { storage: &'a mut OpaqueTypeStorage<'tcx>, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 352652413751e..6b0205f9a78a3 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -633,9 +633,14 @@ 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> { - // 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() + if let Some(body_id) = self.enclosing_body + && self.tcx.use_typing_mode_borrowck() + { + let def_id = self.tcx.hir_enclosing_body_owner(body_id.hir_id); + TypingMode::borrowck(self.tcx, def_id) + } else { + TypingMode::non_body_analysis() + } } pub fn typing_env(&self) -> TypingEnv<'tcx> { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 97df4ebc8ae13..6b19aa17c6d6c 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { } let def_id = opaque.def_id.to_def_id(); - let infcx = &cx.tcx.infer_ctxt().build(cx.typing_mode()); + let infcx = &cx.tcx.infer_ctxt().ignoring_regions().build(cx.typing_mode()); // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 6124b92da5c10..49077c3007f4a 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -413,13 +413,36 @@ impl<'tcx> Body<'tcx> { } 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::new( - tcx.param_env(self.source.def_id()), - ty::TypingMode::non_body_analysis(), - ), - MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), + if tcx.use_typing_mode_borrowck() { + match self.phase { + MirPhase::Built if let Some(def_id) = self.source.def_id().as_local() => { + TypingEnv::new( + tcx.param_env(self.source.def_id()), + ty::TypingMode::borrowck(tcx, def_id), + ) + } + MirPhase::Analysis(_) if let Some(def_id) = self.source.def_id().as_local() => { + TypingEnv::new( + tcx.param_env(self.source.def_id()), + ty::TypingMode::post_borrowck_analysis(tcx, def_id), + ) + } + MirPhase::Built | MirPhase::Analysis(_) => { + // This branch happens for drop glue and fn ptr shims. + // FIXME: why do we do any of this analysis on drop glue etc? + // This should ideally all be skipped. + TypingEnv::post_analysis(tcx, self.source.def_id()) + } + MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), + } + } else { + match self.phase { + MirPhase::Built | MirPhase::Analysis(_) => TypingEnv::new( + tcx.param_env(self.source.def_id()), + ty::TypingMode::non_body_analysis(), + ), + MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), + } } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e38e5393d967d..73392d9e6eeaf 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -528,12 +528,6 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout { pub trait HasTypingEnv<'tcx> { fn typing_env(&self) -> ty::TypingEnv<'tcx>; - - /// FIXME(#132279): This method should not be used as in the future - /// everything should take a `TypingEnv` instead. Remove it as that point. - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.typing_env().param_env - } } impl<'tcx> HasDataLayout for TyCtxt<'tcx> {