stop using ParamEnv::reveal
while handling MIR
This commit is contained in:
parent
563c473e8d
commit
2cde638ac0
14 changed files with 100 additions and 60 deletions
|
@ -589,7 +589,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(body.phase.typing_mode());
|
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
|
||||||
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);
|
||||||
|
|
|
@ -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(body.phase.typing_mode());
|
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
|
||||||
let mut selcx = SelectionContext::new(&infcx);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
let implsrc = selcx.select(&obligation);
|
let implsrc = selcx.select(&obligation);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rustc_errors::DiagCtxtHandle;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_infer::infer::at::ToTrace;
|
use rustc_infer::infer::at::ToTrace;
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::{ObligationCause, Reveal};
|
||||||
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
|
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
|
||||||
use rustc_middle::query::TyCtxtAt;
|
use rustc_middle::query::TyCtxtAt;
|
||||||
use rustc_middle::ty::layout::{
|
use rustc_middle::ty::layout::{
|
||||||
|
@ -116,6 +116,7 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
|
||||||
/// This test should be symmetric, as it is primarily about layout compatibility.
|
/// This test should be symmetric, as it is primarily about layout compatibility.
|
||||||
pub(super) fn mir_assign_valid_types<'tcx>(
|
pub(super) fn mir_assign_valid_types<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typing_mode: TypingMode<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
src: TyAndLayout<'tcx>,
|
src: TyAndLayout<'tcx>,
|
||||||
dest: TyAndLayout<'tcx>,
|
dest: TyAndLayout<'tcx>,
|
||||||
|
@ -124,7 +125,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
|
||||||
// all normal lifetimes are erased, higher-ranked types with their
|
// all normal lifetimes are erased, higher-ranked types with their
|
||||||
// late-bound lifetimes are still around and can lead to type
|
// late-bound lifetimes are still around and can lead to type
|
||||||
// differences.
|
// differences.
|
||||||
if util::relate_types(tcx, param_env, Variance::Covariant, src.ty, dest.ty) {
|
if util::relate_types(tcx, typing_mode, param_env, Variance::Covariant, src.ty, dest.ty) {
|
||||||
// Make sure the layout is equal, too -- just to be safe. Miri really
|
// Make sure the layout is equal, too -- just to be safe. Miri really
|
||||||
// needs layout equality. For performance reason we skip this check when
|
// needs layout equality. For performance reason we skip this check when
|
||||||
// the types are equal. Equal types *can* have different layouts when
|
// the types are equal. Equal types *can* have different layouts when
|
||||||
|
@ -144,6 +145,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
|
||||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||||
pub(super) fn from_known_layout<'tcx>(
|
pub(super) fn from_known_layout<'tcx>(
|
||||||
tcx: TyCtxtAt<'tcx>,
|
tcx: TyCtxtAt<'tcx>,
|
||||||
|
typing_mode: TypingMode<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
known_layout: Option<TyAndLayout<'tcx>>,
|
known_layout: Option<TyAndLayout<'tcx>>,
|
||||||
compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>,
|
compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>,
|
||||||
|
@ -153,7 +155,13 @@ pub(super) fn from_known_layout<'tcx>(
|
||||||
Some(known_layout) => {
|
Some(known_layout) => {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
let check_layout = compute()?;
|
let check_layout = compute()?;
|
||||||
if !mir_assign_valid_types(tcx.tcx, param_env, check_layout, known_layout) {
|
if !mir_assign_valid_types(
|
||||||
|
tcx.tcx,
|
||||||
|
typing_mode,
|
||||||
|
param_env,
|
||||||
|
check_layout,
|
||||||
|
known_layout,
|
||||||
|
) {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
tcx.span,
|
tcx.span,
|
||||||
"expected type differs from actual type.\nexpected: {}\nactual: {}",
|
"expected type differs from actual type.\nexpected: {}\nactual: {}",
|
||||||
|
@ -203,6 +211,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn typing_mode(&self) -> TypingMode<'tcx> {
|
||||||
|
debug_assert_eq!(self.param_env.reveal(), Reveal::All);
|
||||||
|
TypingMode::PostAnalysis
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the span of the currently executed statement/terminator.
|
/// Returns the span of the currently executed statement/terminator.
|
||||||
/// This is the span typically used for error reporting.
|
/// This is the span typically used for error reporting.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -327,7 +340,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(TypingMode::from_param_env(self.param_env));
|
let infcx = self.tcx.infer_ctxt().build(self.typing_mode());
|
||||||
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
|
||||||
|
|
|
@ -773,6 +773,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
)?;
|
)?;
|
||||||
if !mir_assign_valid_types(
|
if !mir_assign_valid_types(
|
||||||
*self.tcx,
|
*self.tcx,
|
||||||
|
self.typing_mode(),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
self.layout_of(normalized_place_ty)?,
|
self.layout_of(normalized_place_ty)?,
|
||||||
op.layout,
|
op.layout,
|
||||||
|
@ -832,7 +833,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let layout =
|
let layout =
|
||||||
from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty).into())?;
|
from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
|
||||||
|
self.layout_of(ty).into()
|
||||||
|
})?;
|
||||||
let imm = match val_val {
|
let imm = match val_val {
|
||||||
mir::ConstValue::Indirect { alloc_id, offset } => {
|
mir::ConstValue::Indirect { alloc_id, offset } => {
|
||||||
// This is const data, no mutation allowed.
|
// This is const data, no mutation allowed.
|
||||||
|
|
|
@ -540,6 +540,7 @@ where
|
||||||
)?;
|
)?;
|
||||||
if !mir_assign_valid_types(
|
if !mir_assign_valid_types(
|
||||||
*self.tcx,
|
*self.tcx,
|
||||||
|
self.typing_mode(),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
self.layout_of(normalized_place_ty)?,
|
self.layout_of(normalized_place_ty)?,
|
||||||
place.layout,
|
place.layout,
|
||||||
|
@ -870,8 +871,13 @@ where
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
// We do NOT compare the types for equality, because well-typed code can
|
// We do NOT compare the types for equality, because well-typed code can
|
||||||
// actually "transmute" `&mut T` to `&T` in an assignment without a cast.
|
// actually "transmute" `&mut T` to `&T` in an assignment without a cast.
|
||||||
let layout_compat =
|
let layout_compat = mir_assign_valid_types(
|
||||||
mir_assign_valid_types(*self.tcx, self.param_env, src.layout(), dest.layout());
|
*self.tcx,
|
||||||
|
self.typing_mode(),
|
||||||
|
self.param_env,
|
||||||
|
src.layout(),
|
||||||
|
dest.layout(),
|
||||||
|
);
|
||||||
if !allow_transmute && !layout_compat {
|
if !allow_transmute && !layout_compat {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
self.cur_span(),
|
self.cur_span(),
|
||||||
|
|
|
@ -596,12 +596,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
return interp_ok(layout);
|
return interp_ok(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
let layout =
|
||||||
let local_ty = frame.body.local_decls[local].ty;
|
from_known_layout(self.tcx, self.typing_mode(), self.param_env, layout, || {
|
||||||
let local_ty =
|
let local_ty = frame.body.local_decls[local].ty;
|
||||||
self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
let local_ty =
|
||||||
self.layout_of(local_ty).into()
|
self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
||||||
})?;
|
self.layout_of(local_ty).into()
|
||||||
|
})?;
|
||||||
|
|
||||||
// Layouts of locals are requested a lot, so we cache them.
|
// Layouts of locals are requested a lot, so we cache them.
|
||||||
state.layout.set(Some(layout));
|
state.layout.set(Some(layout));
|
||||||
|
|
|
@ -8,24 +8,15 @@ use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, TypingMode, 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 `src` is a subtype of `dest`, i.e. `src <: dest`.
|
||||||
///
|
pub fn sub_types<'tcx>(
|
||||||
/// This is used in case we don't know the expected subtyping direction
|
|
||||||
/// and still want to check whether anything is broken.
|
|
||||||
pub fn is_equal_up_to_subtyping<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typing_mode: TypingMode<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
src: Ty<'tcx>,
|
src: Ty<'tcx>,
|
||||||
dest: Ty<'tcx>,
|
dest: Ty<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Fast path.
|
relate_types(tcx, typing_mode, param_env, Variance::Covariant, src, dest)
|
||||||
if src == dest {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for subtyping in either direction.
|
|
||||||
relate_types(tcx, param_env, Variance::Covariant, src, dest)
|
|
||||||
|| relate_types(tcx, param_env, Variance::Covariant, dest, src)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
|
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
|
||||||
|
@ -35,6 +26,7 @@ pub fn is_equal_up_to_subtyping<'tcx>(
|
||||||
/// because we want to check for type equality.
|
/// because we want to check for type equality.
|
||||||
pub fn relate_types<'tcx>(
|
pub fn relate_types<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typing_mode: TypingMode<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
variance: Variance,
|
variance: Variance,
|
||||||
src: Ty<'tcx>,
|
src: Ty<'tcx>,
|
||||||
|
@ -45,8 +37,7 @@ pub fn relate_types<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut builder = tcx.infer_ctxt().ignoring_regions();
|
let mut builder = tcx.infer_ctxt().ignoring_regions();
|
||||||
// FIXME(#132279): This should eventually use the already defined hidden types.
|
let infcx = builder.build(typing_mode);
|
||||||
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);
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod type_name;
|
||||||
|
|
||||||
pub use self::alignment::{is_disaligned, is_within_packed};
|
pub use self::alignment::{is_disaligned, is_within_packed};
|
||||||
pub use self::check_validity_requirement::check_validity_requirement;
|
pub use self::check_validity_requirement::check_validity_requirement;
|
||||||
pub use self::compare_types::{is_equal_up_to_subtyping, relate_types};
|
pub use self::compare_types::{relate_types, sub_types};
|
||||||
pub use self::type_name::type_name;
|
pub use self::type_name::type_name;
|
||||||
|
|
||||||
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
||||||
|
|
|
@ -39,7 +39,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
|
||||||
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
|
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
|
||||||
use crate::ty::visit::TypeVisitableExt;
|
use crate::ty::visit::TypeVisitableExt;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt,
|
self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode,
|
||||||
UserTypeAnnotationIndex,
|
UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -452,6 +452,15 @@ impl<'tcx> Body<'tcx> {
|
||||||
self.basic_blocks.as_mut()
|
self.basic_blocks.as_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> {
|
||||||
|
match self.phase {
|
||||||
|
// FIXME(#132279): the MIR is quite clearly inside of a body, so we
|
||||||
|
// should instead reveal opaques defined by that body here.
|
||||||
|
MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(),
|
||||||
|
MirPhase::Runtime(_) => TypingMode::PostAnalysis,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn local_kind(&self, local: Local) -> LocalKind {
|
pub fn local_kind(&self, local: Local) -> LocalKind {
|
||||||
let index = local.as_usize();
|
let index = local.as_usize();
|
||||||
|
|
|
@ -20,9 +20,7 @@ use smallvec::SmallVec;
|
||||||
use super::{BasicBlock, Const, Local, UserTypeProjection};
|
use super::{BasicBlock, Const, Local, UserTypeProjection};
|
||||||
use crate::mir::coverage::CoverageKind;
|
use crate::mir::coverage::CoverageKind;
|
||||||
use crate::ty::adjustment::PointerCoercion;
|
use crate::ty::adjustment::PointerCoercion;
|
||||||
use crate::ty::{
|
use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex};
|
||||||
self, GenericArgsRef, List, Region, Ty, TyCtxt, TypingMode, UserTypeAnnotationIndex,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Represents the "flavors" of MIR.
|
/// Represents the "flavors" of MIR.
|
||||||
///
|
///
|
||||||
|
@ -103,20 +101,10 @@ impl MirPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typing_mode<'tcx>(&self) -> TypingMode<'tcx> {
|
|
||||||
match self {
|
|
||||||
// FIXME(#132279): the MIR is quite clearly inside of a body, so we
|
|
||||||
// should instead reveal opaques defined by that body here.
|
|
||||||
MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(),
|
|
||||||
MirPhase::Runtime(_) => TypingMode::PostAnalysis,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> {
|
pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> {
|
||||||
match self.typing_mode() {
|
match self {
|
||||||
TypingMode::Coherence => unreachable!(),
|
MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id),
|
||||||
TypingMode::Analysis { defining_opaque_types: _ } => tcx.param_env(body_def_id),
|
MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id),
|
||||||
TypingMode::PostAnalysis => tcx.param_env_reveal_all_normalized(body_def_id),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,8 +244,13 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
// Normally, this shouldn't be required, but trait normalization failure can create a
|
// Normally, this shouldn't be required, but trait normalization failure can create a
|
||||||
// validation ICE.
|
// validation ICE.
|
||||||
let output_type = callee_body.return_ty();
|
let output_type = callee_body.return_ty();
|
||||||
if !util::relate_types(self.tcx, self.param_env, ty::Covariant, output_type, destination_ty)
|
if !util::sub_types(
|
||||||
{
|
self.tcx,
|
||||||
|
caller_body.typing_mode(self.tcx),
|
||||||
|
self.param_env,
|
||||||
|
output_type,
|
||||||
|
destination_ty,
|
||||||
|
) {
|
||||||
trace!(?output_type, ?destination_ty);
|
trace!(?output_type, ?destination_ty);
|
||||||
return Err("failed to normalize return type");
|
return Err("failed to normalize return type");
|
||||||
}
|
}
|
||||||
|
@ -275,8 +280,13 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
|
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
|
||||||
{
|
{
|
||||||
let input_type = callee_body.local_decls[input].ty;
|
let input_type = callee_body.local_decls[input].ty;
|
||||||
if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
|
if !util::sub_types(
|
||||||
{
|
self.tcx,
|
||||||
|
caller_body.typing_mode(self.tcx),
|
||||||
|
self.param_env,
|
||||||
|
input_type,
|
||||||
|
arg_ty,
|
||||||
|
) {
|
||||||
trace!(?arg_ty, ?input_type);
|
trace!(?arg_ty, ?input_type);
|
||||||
return Err("failed to normalize tuple argument type");
|
return Err("failed to normalize tuple argument type");
|
||||||
}
|
}
|
||||||
|
@ -285,8 +295,13 @@ impl<'tcx> Inliner<'tcx> {
|
||||||
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
|
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
|
||||||
let input_type = callee_body.local_decls[input].ty;
|
let input_type = callee_body.local_decls[input].ty;
|
||||||
let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
|
let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
|
||||||
if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
|
if !util::sub_types(
|
||||||
{
|
self.tcx,
|
||||||
|
caller_body.typing_mode(self.tcx),
|
||||||
|
self.param_env,
|
||||||
|
input_type,
|
||||||
|
arg_ty,
|
||||||
|
) {
|
||||||
trace!(?arg_ty, ?input_type);
|
trace!(?arg_ty, ?input_type);
|
||||||
return Err("failed to normalize argument type");
|
return Err("failed to normalize argument type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use rustc_target::spec::abi::Abi;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use rustc_type_ir::Upcast;
|
use rustc_type_ir::Upcast;
|
||||||
|
|
||||||
use crate::util::{is_within_packed, relate_types};
|
use crate::util::{self, is_within_packed};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
enum EdgeKind {
|
enum EdgeKind {
|
||||||
|
@ -583,7 +583,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
Variance::Covariant
|
Variance::Covariant
|
||||||
};
|
};
|
||||||
|
|
||||||
crate::util::relate_types(self.tcx, self.param_env, variance, src, dest)
|
crate::util::relate_types(
|
||||||
|
self.tcx,
|
||||||
|
self.body.typing_mode(self.tcx),
|
||||||
|
self.param_env,
|
||||||
|
variance,
|
||||||
|
src,
|
||||||
|
dest,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the given predicate definitely holds in the param-env of this MIR body.
|
/// Check that the given predicate definitely holds in the param-env of this MIR body.
|
||||||
|
@ -602,7 +609,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let infcx = self.tcx.infer_ctxt().build(self.body.phase.typing_mode());
|
let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx));
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
ocx.register_obligation(Obligation::new(
|
ocx.register_obligation(Obligation::new(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
|
@ -794,10 +801,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProjectionElem::Subtype(ty) => {
|
ProjectionElem::Subtype(ty) => {
|
||||||
if !relate_types(
|
if !util::sub_types(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
|
self.body.typing_mode(self.tcx),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
Variance::Covariant,
|
|
||||||
ty,
|
ty,
|
||||||
place_ref.ty(&self.body.local_decls, self.tcx).ty,
|
place_ref.ty(&self.body.local_decls, self.tcx).ty,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -12,6 +12,13 @@ use crate::{self as ty, Interner};
|
||||||
/// The current typing mode of an inference context. We unfortunately have some
|
/// The current typing mode of an inference context. We unfortunately have some
|
||||||
/// slightly different typing rules depending on the current context. See the
|
/// slightly different typing rules depending on the current context. See the
|
||||||
/// doc comment for each variant for how and why they are used.
|
/// doc comment for each variant for how and why they are used.
|
||||||
|
///
|
||||||
|
/// In most cases you can get the correct typing mode automically via:
|
||||||
|
/// - `mir::Body::typing_mode`
|
||||||
|
/// - `rustc_lint::LateContext::typing_mode`
|
||||||
|
///
|
||||||
|
/// If neither of these functions are available, feel free to reach out to
|
||||||
|
/// t-types for help.
|
||||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
|
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
|
||||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||||
pub enum TypingMode<I: Interner> {
|
pub enum TypingMode<I: Interner> {
|
||||||
|
|
|
@ -420,7 +420,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
|
||||||
TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
|
TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
|
||||||
);
|
);
|
||||||
|
|
||||||
let infcx = tcx.infer_ctxt().build(body.phase.typing_mode());
|
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
|
||||||
let mut selcx = SelectionContext::new(&infcx);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
|
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue