Auto merge of #132460 - lcnr:questionable-uwu, r=compiler-errors

Use `TypingMode` throughout the compiler instead of `ParamEnv`

Hopefully the biggest single PR as part of https://github.com/rust-lang/types-team/issues/128.

## `infcx.typing_env` while defining opaque types

I don't know how'll be able to correctly handle opaque types when using something taking a `TypingEnv` while defining opaque types. To correctly handle the opaques we need to be able to pass in the current `opaque_type_storage` and return constraints, i.e. we need to use a proper canonical query. We should migrate all the queries used during HIR typeck and borrowck where this matters to proper canonical queries. This is

## `layout_of` and `Reveal::All`

We convert the `ParamEnv` to `Reveal::All` right at the start of the `layout_of` query, so I've changed callers of `layout_of` to already use a post analysis `TypingEnv` when encountering it.

ca87b535a0/compiler/rustc_ty_utils/src/layout.rs (L51)

## `Ty::is_[unpin|sized|whatever]`

I haven't migrated `fn is_item_raw` to use `TypingEnv`, will do so in a followup PR, this should significantly reduce the amount of `typing_env.param_env`. At some point there will probably be zero such uses as using the type system while ignoring the `typing_mode` is incorrect.

## `MirPhase` and phase-transitions

When inside of a MIR-body, we can mostly use its `MirPhase` to figure out the right `typing_mode`. This does not work during phase transitions, most notably when transitioning from `Analysis` to `Runtime`:

dae7ac133b/compiler/rustc_mir_transform/src/lib.rs (L606-L625)

All these passes still run with `MirPhase::Analysis`, but we should only use `Reveal::All` once we're run the `RevealAll` pass. This required me to manually construct the right `TypingEnv` in all these passes. Given that it feels somewhat easy to accidentally miss this going forward, I would maybe like to change `Body::phase` to an `Option` and replace it at the start of phase transitions. This then makes it clear that the MIR is currently in a weird state.

r? `@ghost`
This commit is contained in:
bors
2024-11-18 21:07:05 +00:00
240 changed files with 1745 additions and 1341 deletions

View File

@@ -388,7 +388,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
return false;
}
let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx));
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(self.body.typing_env(tcx));
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let body_id = self.body.source.def_id().expect_local();
@@ -398,11 +398,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
ty::BoundConstness::Const
}
};
let const_conditions = ocx.normalize(
&ObligationCause::misc(call_span, body_id),
self.param_env,
const_conditions,
);
let const_conditions =
ocx.normalize(&ObligationCause::misc(call_span, body_id), param_env, const_conditions);
ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, span)| {
Obligation::new(
tcx,
@@ -411,7 +408,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
body_id,
ObligationCauseCode::WhereClause(callee, span),
),
self.param_env,
param_env,
trait_ref.to_host_effect_clause(tcx, host_polarity),
)
}));

View File

@@ -24,17 +24,15 @@ mod resolver;
pub struct ConstCx<'mir, 'tcx> {
pub body: &'mir mir::Body<'tcx>,
pub tcx: TyCtxt<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
pub typing_env: ty::TypingEnv<'tcx>,
pub const_kind: Option<hir::ConstContext>,
}
impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self {
let def_id = body.source.def_id().expect_local();
let param_env = tcx.param_env(def_id);
let typing_env = body.typing_env(tcx);
let const_kind = tcx.hir().body_const_context(body.source.def_id().expect_local());
ConstCx { body, tcx, param_env, const_kind }
ConstCx { body, tcx, typing_env, const_kind }
}
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {

View File

@@ -120,7 +120,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
#[allow(rustc::untranslatable_diagnostic)]
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
let FnCallNonConst { callee, args, span, call_source } = *self;
let ConstCx { tcx, param_env, .. } = *ccx;
let ConstCx { tcx, typing_env, .. } = *ccx;
let caller = ccx.def_id();
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
@@ -146,13 +146,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
}
ty::Adt(..) => {
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
let infcx = tcx.infer_ctxt().build(ccx.body.typing_mode(tcx));
let mut selcx = SelectionContext::new(&infcx);
let implsrc = selcx.select(&obligation);
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
// FIXME(const_trait_impl) revisit this
if !tcx.is_const_trait_impl(data.impl_def_id) {
@@ -166,7 +164,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
};
let call_kind =
call_kind(tcx, ccx.param_env, callee, args, span, call_source.from_hir_call(), None);
call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
debug!(?call_kind);

View File

@@ -32,17 +32,15 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
/// This is separate from the rest of the const checking logic because it must run after drop
/// elaboration.
pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
let def_id = body.source.def_id().expect_local();
let const_kind = tcx.hir().body_const_context(def_id);
if const_kind.is_none() {
let ccx = ConstCx::new(tcx, body);
if ccx.const_kind.is_none() {
return;
}
if tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
if tcx.has_attr(body.source.def_id(), sym::rustc_do_not_const_check) {
return;
}
let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) };
if !checking_enabled(&ccx) {
return;
}

View File

@@ -106,20 +106,24 @@ 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, Some(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 {
typing_mode: 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);
let ocx = ObligationCtxt::new(&infcx);
let obligation = Obligation::new(
cx.tcx,
ObligationCause::dummy_with_span(cx.body.span),
cx.param_env,
param_env,
ty::TraitRef::new(cx.tcx, freeze_def_id, [ty::GenericArg::from(ty)]),
);
// FIXME(#132279): This should eventually use the already defined hidden types.
let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::analysis_in_body(
cx.tcx,
cx.body.source.def_id().expect_local(),
));
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
!errors.is_empty()
@@ -156,7 +160,7 @@ impl Qualif for NeedsDrop {
}
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.needs_drop(cx.tcx, cx.param_env)
ty.needs_drop(cx.tcx, cx.typing_env)
}
fn in_adt_inherently<'tcx>(

View File

@@ -120,7 +120,10 @@ where
///
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
!place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env)
!place
.ty(self.ccx.body, self.ccx.tcx)
.ty
.is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env)
}
}