1
Fork 0

use TypingEnv when no infcx is available

the behavior of the type system not only depends on the current
assumptions, but also the currentnphase of the compiler. This is
mostly necessary as we need to decide whether and how to reveal
opaque types. We track this via the `TypingMode`.
This commit is contained in:
lcnr 2024-11-15 13:53:31 +01:00
parent 1ceaa90413
commit bb93c23c08
33 changed files with 83 additions and 79 deletions

View file

@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
},
_ => return,
}
&& let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.param_env, fn_id, fn_gen_args)
&& let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_id, fn_gen_args)
// TODO: This check currently bails if the local variable has no initializer.
// That is overly conservative - the lint should fire even if there was no initializer,
// but the variable has been initialized before `lhs` was evaluated.

View file

@ -62,7 +62,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -
})
.is_some_and(|assoc_item| {
let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, []));
let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
let nty = cx.tcx.normalize_erasing_regions(cx.typing_env(), proj);
nty.is_bool()
})

View file

@ -17,7 +17,7 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
use rustc_session::impl_lint_pass;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
@ -755,7 +755,8 @@ impl TyCoercionStability {
DefinedTy::Hir(ty) => Self::for_hir_ty(ty),
DefinedTy::Mir(ty) => Self::for_mir_ty(
cx.tcx,
ty.param_env,
// FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead.
ty::TypingEnv::from_param_env(ty.param_env),
cx.tcx.instantiate_bound_regions_with_erased(ty.value),
for_return,
),
@ -823,12 +824,12 @@ impl TyCoercionStability {
}
}
fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self {
fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self {
let ty::Ref(_, mut ty, _) = *ty.kind() else {
return Self::None;
};
ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
loop {
break match *ty.kind() {
ty::Ref(_, ref_ty, _) => {

View file

@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
sym::mem_forget if is_copy => return,
sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return,
sym::mem_drop
if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
if !(arg_ty.needs_drop(cx.tcx, cx.typing_env())
|| is_must_use_func_call(cx, arg)
|| is_must_use_ty(cx, arg_ty)
|| drop_is_single_call_in_arm) =>
@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
(DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span))
},
sym::mem_forget => {
if arg_ty.needs_drop(cx.tcx, cx.param_env) {
if arg_ty.needs_drop(cx.tcx, cx.typing_env()) {
(
MEM_FORGET,
Cow::Owned(format!(

View file

@ -70,7 +70,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe
.instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output());
let ret_ty = cx
.tcx
.try_normalize_erasing_regions(cx.param_env, ret_ty)
.try_normalize_erasing_regions(cx.typing_env(), ret_ty)
.unwrap_or(ret_ty);
if cx
.tcx

View file

@ -215,7 +215,7 @@ impl {self_ty_without_ref} {{
&& implements_trait(cx, ret_ty, iterator_did, &[])
&& let Some(iter_ty) = make_normalized_projection(
cx.tcx,
cx.param_env,
cx.typing_env(),
iterator_did,
sym::Item,
[ret_ty],

View file

@ -4,7 +4,7 @@ use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ParamEnv};
use rustc_middle::ty;
use rustc_session::impl_lint_pass;
use rustc_span::{BytePos, Pos, Span};
@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let ty::Array(element_type, cst) = ty.kind()
&& let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx
.try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree()
.try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_valtree()
&& let element_count = element_count.to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)

View file

@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture {
&& let ty = cx.typeck_results().expr_ty(arg)
&& let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
&& implements_trait(cx, ty, future_trait_def_id, &[])
&& let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
&& let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty))
&& let size = layout.layout.size()
&& size >= Size::from_bytes(self.future_size_threshold)
{

View file

@ -150,11 +150,11 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
}
let mir = cx.tcx.optimized_mir(def_id);
let param_env = cx.tcx.param_env(def_id);
let typing_env = mir.typing_env(cx.tcx);
let sizes_of_locals = || {
mir.local_decls.iter().filter_map(|local| {
let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?;
let layout = cx.tcx.layout_of(typing_env.as_query_input(local.ty)).ok()?;
Some((local, layout.size.bytes()))
})
};

View file

@ -151,7 +151,7 @@ fn is_ref_iterable<'tcx>(
// Using by value won't consume anything
if implements_trait(cx, self_ty, trait_id, &[])
&& let Some(ty) =
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
&& ty == res_ty
{
return Some((AdjustKind::None, self_ty));
@ -168,7 +168,7 @@ fn is_ref_iterable<'tcx>(
};
if implements_trait(cx, self_ty, trait_id, &[])
&& let Some(ty) =
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
&& ty == res_ty
{
return Some((AdjustKind::reborrow(mutbl), self_ty));
@ -181,7 +181,7 @@ fn is_ref_iterable<'tcx>(
// Attempt to borrow
let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl);
if implements_trait(cx, self_ty, trait_id, &[])
&& let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty])
&& let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty])
&& ty == res_ty
{
return Some((AdjustKind::borrow(mutbl), self_ty));
@ -204,7 +204,7 @@ fn is_ref_iterable<'tcx>(
&& target != self_ty
&& implements_trait(cx, target, trait_id, &[])
&& let Some(ty) =
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
&& ty == res_ty
{
Some((AdjustKind::auto_reborrow(mutbl), target))
@ -222,7 +222,7 @@ fn is_ref_iterable<'tcx>(
if is_copy(cx, target)
&& implements_trait(cx, target, trait_id, &[])
&& let Some(ty) =
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
&& ty == res_ty
{
Some((AdjustKind::Deref, target))
@ -240,7 +240,7 @@ fn is_ref_iterable<'tcx>(
if self_ty.is_ref()
&& implements_trait(cx, target, trait_id, &[])
&& let Some(ty) =
make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target])
make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target])
&& ty == res_ty
{
Some((AdjustKind::auto_borrow(mutbl), target))

View file

@ -203,10 +203,10 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool {
if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator)
&& let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
&& let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, sym::Item, [iter_ty])
&& let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty])
&& let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty])
&& let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
cx.typing_env(),
Ty::new_projection_from_args(cx.tcx, into_iter_item_proj.def_id, into_iter_item_proj.args),
)
{
@ -237,7 +237,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
)
&& let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
&& let proj_ty = Ty::new_projection_from_args(cx.tcx, iter_item.def_id, args)
&& let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
&& let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), proj_ty)
{
item_ty == EarlyBinder::bind(search_ty).instantiate(cx.tcx, cx.typeck_results().node_args(call_id))
} else {

View file

@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
arg: &'tcx Expr<'_>,
) {
let typeck_results = cx.typeck_results();
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results);
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck_results);
if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id)
&& (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id))
{

View file

@ -578,7 +578,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
if output_ty.contains(param_ty) {
if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions(
new_subst,
cx.param_env,
cx.typing_env(),
bound_fn_sig.rebind(output_ty),
) {
expr = parent_expr;

View file

@ -7,7 +7,7 @@ use super::ZST_OFFSET;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind()
&& let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty))
&& let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*ty))
&& layout.is_zst()
{
span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");

View file

@ -421,7 +421,7 @@ fn replace_types<'tcx>(
.expect_ty(cx.tcx)
.to_ty(cx.tcx);
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), projection)
&& args[term_param_ty.index as usize] != GenericArg::from(projected_ty)
{
deque.push_back((*term_param_ty, projected_ty));

View file

@ -278,23 +278,23 @@ impl<'tcx> NonCopyConst<'tcx> {
fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
let args = cx.typeck_results().node_args(hir_id);
let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP);
Self::is_value_unfrozen_raw(cx, result, ty)
}
pub fn const_eval_resolve(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ct: ty::UnevaluatedConst<'tcx>,
span: Span,
) -> EvalToValTreeResult<'tcx> {
match ty::Instance::try_resolve(tcx, param_env, ct.def, ct.args) {
match ty::Instance::try_resolve(tcx, typing_env, ct.def, ct.args) {
Ok(Some(instance)) => {
let cid = GlobalId {
instance,
promoted: None,
};
tcx.const_eval_global_id_for_typeck(param_env, cid, span)
tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span)
},
Ok(None) => Err(ErrorHandled::TooGeneric(span)),
Err(err) => Err(ErrorHandled::Reported(err.into(), span)),
@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
// Normalize assoc types because ones originated from generic params
// bounded other traits could have their bound.
let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
if self.interior_mut.is_interior_mut_ty(cx, normalized)
// When there's no default value, lint it only according to its type;
// in other words, lint consts whose value *could* be unfrozen, not definitely is.
@ -361,12 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
.trait_item_def_id
&& cx
.tcx
.layout_of(cx.tcx.param_env(of_trait_def_id).and(
.layout_of(ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id).as_query_input(
// Normalize assoc types because ones originated from generic params
// bounded other traits could have their bound at the trait defs;
// and, in that case, the definition is *not* generic.
cx.tcx.normalize_erasing_regions(
cx.tcx.param_env(of_trait_def_id),
ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id),
cx.tcx.type_of(of_assoc_item).instantiate_identity(),
),
))
@ -376,7 +376,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
// similar to unknown layouts.
// e.g. `layout_of(...).is_err() || has_frozen_variant(...);`
&& let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity()
&& let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty)
&& let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty)
&& self.interior_mut.is_interior_mut_ty(cx, normalized)
&& Self::is_value_unfrozen_poly(cx, *body_id, normalized)
{
@ -386,7 +386,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
ItemKind::Impl(Impl { of_trait: None, .. }) => {
let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity();
// Normalize assoc types originated from generic params.
let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
if self.interior_mut.is_interior_mut_ty(cx, normalized)
&& Self::is_value_unfrozen_poly(cx, *body_id, normalized)

View file

@ -26,7 +26,7 @@ fn comparison_to_const<'tcx>(
if let ExprKind::Binary(operator, left, right) = expr.kind
&& let Ok(cmp_op) = CmpOp::try_from(operator.node)
{
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck);
match (ecx.eval(left), ecx.eval(right)) {
(Some(_), Some(_)) => None,
(_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),

View file

@ -39,7 +39,7 @@ fn check_op<'tcx>(
other: &Expr<'tcx>,
parent: &Expr<'tcx>,
) {
if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) {
if ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), tck).eval_simple(op) == Some(Constant::Int(0)) {
if different_types(tck, other, parent) {
return;
}

View file

@ -17,8 +17,7 @@ pub(crate) fn check<'tcx>(
right: &'tcx Expr<'_>,
) {
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) {
let typeck = cx.typeck_results();
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
let ecx = ConstEvalCtxt::new(cx);
let left_is_local = match ecx.eval_with_source(left) {
Some((c, s)) if !is_allowed(&c) => s.is_local(),
Some(_) => return,

View file

@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
});
} else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
cx.typing_env(),
Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
) {
if deref_ty == expr_ty {

View file

@ -391,7 +391,7 @@ fn check_final_expr<'tcx>(
if let Some(inner) = inner {
if for_each_unconsumed_temporary(cx, inner, |temporary_ty| {
if temporary_ty.has_significant_drop(cx.tcx, cx.param_env)
if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env())
&& temporary_ty
.walk()
.any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))

View file

@ -154,7 +154,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
let ty = self
.cx
.tcx
.try_normalize_erasing_regions(self.cx.param_env, ty)
.try_normalize_erasing_regions(self.cx.typing_env(), ty)
.unwrap_or(ty);
match self.type_cache.entry(ty) {
Entry::Occupied(e) => return *e.get(),

View file

@ -58,7 +58,7 @@ fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item:
&& let Some(last_field) = data.fields().last()
&& let field_ty = cx
.tcx
.normalize_erasing_regions(cx.param_env, cx.tcx.type_of(last_field.def_id).instantiate_identity())
.normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity())
&& let ty::Array(_, array_len) = *field_ty.kind()
&& let Some(0) = array_len.try_to_target_usize(cx.tcx)
{

View file

@ -88,8 +88,8 @@ pub(super) fn check<'tcx>(
&& is_normalizable(cx, cx.param_env, to_ty)
// we only want to lint if the target type has a niche that is larger than the one of the source type
// e.g. `u8` to `NonZero<u8>` should lint, but `NonZero<u8>` to `u8` should not
&& let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty))
&& let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty))
&& let Ok(from_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(from_ty))
&& let Ok(to_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(to_ty))
&& match (from_layout.largest_niche, to_layout.largest_niche) {
(Some(from_niche), Some(to_niche)) => !range_fully_contained(from_niche.valid_range, to_niche.valid_range),
(None, Some(_)) => true,

View file

@ -244,7 +244,7 @@ enum ReducedTy<'tcx> {
/// Reduce structs containing a single non-zero sized field to it's contained type.
fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> {
loop {
ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty);
ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
return match *ty.kind() {
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
ReducedTy::TypeErasure { raw_ptr_only: false }
@ -297,8 +297,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
}
fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty)
&& let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty)
&& let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty))
{
layout.layout.size().bytes() == 0
} else {

View file

@ -4,10 +4,11 @@ use rustc_middle::ty::Ty;
// check if the component types of the transmuted collection and the result have different ABI,
// size or alignment
pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool {
if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from)
&& let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to)
&& let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from))
&& let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to))
let typing_env = cx.typing_env();
if let Ok(from) = cx.tcx.try_normalize_erasing_regions(typing_env, from)
&& let Ok(to) = cx.tcx.try_normalize_erasing_regions(typing_env, to)
&& let Ok(from_layout) = cx.tcx.layout_of(typing_env.as_query_input(from))
&& let Ok(to_layout) = cx.tcx.layout_of(typing_env.as_query_input(to))
{
from_layout.size != to_layout.size || from_layout.align.abi != to_layout.align.abi
} else {

View file

@ -46,7 +46,7 @@ impl LateLintPass<'_> for UninhabitedReferences {
if let ExprKind::Unary(UnOp::Deref, _) = expr.kind {
let ty = cx.typeck_results().expr_ty_adjusted(expr);
if ty.is_privately_uninhabited(cx.tcx, cx.param_env) {
if ty.is_privately_uninhabited(cx.tcx, cx.typing_env()) {
span_lint(
cx,
UNINHABITED_REFERENCES,
@ -71,7 +71,7 @@ impl LateLintPass<'_> for UninhabitedReferences {
}
if let FnRetTy::Return(hir_ty) = fndecl.output
&& let TyKind::Ref(_, mut_ty) = hir_ty.kind
&& lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env)
&& lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.typing_env())
{
span_lint(
cx,

View file

@ -18,7 +18,7 @@ use rustc_lexer::tokenize;
use rustc_lint::LateContext;
use rustc_middle::mir::ConstValue;
use rustc_middle::mir::interpret::{Scalar, alloc_range};
use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
use rustc_middle::ty::{self, FloatTy, IntTy, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::symbol::Ident;
@ -387,7 +387,7 @@ impl Ord for FullInt {
/// See the module level documentation for some context.
pub struct ConstEvalCtxt<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
typeck: &'tcx TypeckResults<'tcx>,
source: Cell<ConstantSource>,
}
@ -398,17 +398,17 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
pub fn new(cx: &LateContext<'tcx>) -> Self {
Self {
tcx: cx.tcx,
param_env: cx.param_env,
typing_env: cx.typing_env(),
typeck: cx.typeck_results(),
source: Cell::new(ConstantSource::Local),
}
}
/// Creates an evaluation context.
pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self {
pub fn with_env(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self {
Self {
tcx,
param_env,
typing_env,
typeck,
source: Cell::new(ConstantSource::Local),
}
@ -643,7 +643,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
let args = self.typeck.node_args(id);
let result = self
.tcx
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
.const_eval_resolve(self.typing_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
.ok()
.map(|val| mir::Const::from_value(val, ty))?;
f(self, result)

View file

@ -105,7 +105,7 @@ fn res_has_significant_drop(res: Res, cx: &LateContext<'_>, e: &Expr<'_>) -> boo
{
cx.typeck_results()
.expr_ty(e)
.has_significant_drop(cx.tcx, cx.param_env)
.has_significant_drop(cx.tcx, cx.typing_env())
} else {
false
}

View file

@ -297,8 +297,8 @@ impl HirEqInterExpr<'_, '_, '_> {
if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results
&& typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right)
&& let (Some(l), Some(r)) = (
ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left),
ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right),
ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_lhs).eval_simple(left),
ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_rhs).eval_simple(right),
)
&& l == r
{
@ -813,7 +813,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
#[expect(clippy::too_many_lines)]
pub fn hash_expr(&mut self, e: &Expr<'_>) {
let simple_const = self.maybe_typeck_results.and_then(|typeck_results| {
ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e)
ConstEvalCtxt::with_env(self.cx.tcx, self.cx.typing_env(), typeck_results).eval_simple(e)
});
// const hashing may result in the same hash as some unrelated node, so add a sort of

View file

@ -1631,7 +1631,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
}
let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
if let Some(Constant::Int(v)) =
ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e)
ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e)
{
return value == v;
}

View file

@ -142,7 +142,7 @@ fn check_rvalue<'tcx>(
// We cannot allow this for now.
return Err((span, "unsizing casts are only allowed for references right now".into()));
};
let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id));
let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(tcx, def_id));
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
check_operand(tcx, op, span, body, msrv)?;
// Casting/coercing things to slices is fine.
@ -408,15 +408,17 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
return true;
}
let (infcx, param_env) =
tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx));
// FIXME(const_trait_impl) constness
let obligation = Obligation::new(
tcx,
ObligationCause::dummy_with_span(body.span),
ConstCx::new(tcx, body).param_env,
param_env,
TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
);
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
let mut selcx = SelectionContext::new(&infcx);
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
return false;
@ -434,5 +436,5 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
ocx.select_all_or_error().is_empty()
}
!ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env)
!ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env)
}

View file

@ -467,7 +467,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
if !seen.insert(ty) {
return false;
}
if !ty.has_significant_drop(cx.tcx, cx.param_env) {
if !ty.has_significant_drop(cx.tcx, cx.typing_env()) {
false
}
// Check for std types which implement drop, but only for memory allocation.
@ -575,8 +575,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
/// Checks if a given type looks safe to be uninitialized.
pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
let typing_env = cx.typing_env().with_reveal_all_normalized(cx.tcx);
cx.tcx
.check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty)))
.check_validity_requirement((ValidityRequirement::Uninit, typing_env.as_query_input(ty)))
.unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty))
}
@ -725,7 +726,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
_ => None,
}
},
ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) {
ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) {
Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty),
_ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)),
},
@ -1111,12 +1112,12 @@ pub fn make_projection<'tcx>(
/// succeeds as well as everything checked by `make_projection`.
pub fn make_normalized_projection<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
container_id: DefId,
assoc_ty: Symbol,
args: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
) -> Option<Ty<'tcx>> {
fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> {
#[cfg(debug_assertions)]
if let Some((i, arg)) = ty
.args
@ -1132,7 +1133,7 @@ pub fn make_normalized_projection<'tcx>(
);
return None;
}
match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) {
match tcx.try_normalize_erasing_regions(typing_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) {
Ok(ty) => Some(ty),
Err(e) => {
debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}");
@ -1140,7 +1141,7 @@ pub fn make_normalized_projection<'tcx>(
},
}
}
helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?)
helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?)
}
/// Helper to check if given type has inner mutability such as [`std::cell::Cell`] or
@ -1300,7 +1301,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl
if let Some(deref_did) = cx.tcx.lang_items().deref_trait()
&& implements_trait(cx, ty, deref_did, &[])
{
make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty])
make_normalized_projection(cx.tcx, cx.typing_env(), deref_did, sym::Target, [ty])
} else {
None
}