1
Fork 0

Auto merge of #96840 - cjgillot:query-feed, r=oli-obk

Allow to feed a value in another query's cache and remove `WithOptConstParam`

I used it to remove `WithOptConstParam` queries, as an example.

The idea is that a query (here `typeck(function)`) can write into another query's cache (here `type_of(anon const)`). The dependency node for `type_of` would depend on all the current dependencies of `typeck`.

There is still an issue with cycles: if `type_of(anon const)` is accessed before `typeck(function)`, we will still have the usual cycle.  The way around this issue is to `ensure` that `typeck(function)` is called before accessing `type_of(anon const)`.

When replayed, we may the following cases:
- `typeck` is green, in that case `type_of` is green too, and all is right;
- `type_of` is green, `typeck` may still be marked as red (it depends on strictly more things than `type_of`) -> we verify that the saved value and the re-computed value of `type_of` have the same hash;
- `type_of` is red, then `typeck` is red -> it's the caller responsibility to ensure `typeck` is recomputed *before* `type_of`.

As `anon consts` have their own `DefPathData`, it's not possible to have the def-id of the anon-const point to something outside the original function, but the general case may have to be resolved before using this device more broadly.

There is an open question about loading from the on-disk cache.  If `typeck` is loaded from the on-disk cache, the side-effect does not happen. The regular `type_of` implementation can go and fetch the correct value from the decoded `typeck` results, and the dep-graph will check that the hashes match, but I'm not sure we want to rely on this behaviour.

I specifically allowed to feed the value to `type_of` from inside a call to `type_of`.  In that case, the dep-graph will check that the fingerprints of both values match.

This implementation is still very sensitive to cycles, and requires that we call `typeck(function)` before `typeck(anon const)`.  The reason is that `typeck(anon const)` calls `type_of(anon const)`, which calls `typeck(function)`, which feeds `type_of(anon const)`, and needs to build the MIR so needs `typeck(anon const)`.  The latter call would not cycle, since `type_of(anon const)` has been set, but I'd rather not remove the cycle check.
This commit is contained in:
bors 2023-04-21 08:04:58 +00:00
commit 1f5768bc67
81 changed files with 598 additions and 1197 deletions

View file

@ -6,7 +6,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexSlice;
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_middle::mir::Body;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::TyCtxt;
pub use super::{
facts::{AllFacts as PoloniusInput, RustcFacts},
@ -28,12 +28,9 @@ pub use super::{
/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
///
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
pub fn get_body_with_borrowck_facts(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
) -> BodyWithBorrowckFacts<'_> {
pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()

View file

@ -19,7 +19,7 @@ use rustc_middle::mir::{
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty, TypeckResults};
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_middle::util::CallKind;
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
@ -1350,8 +1350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
finder.visit_expr(body_expr);
let Some((closure_expr, closure)) = finder.res else { return };
let typeck_results: &TypeckResults<'_> =
tcx.typeck_opt_const_arg(self.body.source.with_opt_param().as_local().unwrap());
let typeck_results = tcx.typeck(self.mir_def_id());
// Check that the parent of the closure is a method call,
// with receiver matching with local's type (modulo refs)

View file

@ -119,24 +119,12 @@ impl<'tcx> TyCtxtConsts<'tcx> {
}
pub fn provide(providers: &mut Providers) {
*providers = Providers {
mir_borrowck: |tcx, did| {
if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
tcx.mir_borrowck_const_arg(def)
} else {
mir_borrowck(tcx, ty::WithOptConstParam::unknown(did))
}
},
mir_borrowck_const_arg: |tcx, (did, param_did)| {
mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
},
..*providers
};
*providers = Providers { mir_borrowck, ..*providers };
}
fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &BorrowCheckResult<'_> {
fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.to_def_id()));
if input_body.borrow().should_skip() {
debug!("Skipping borrowck because of injected body");
@ -150,7 +138,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
return tcx.arena.alloc(result);
}
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
let hir_owner = tcx.hir().local_def_id_to_hir_id(def).owner;
let infcx =
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
@ -167,19 +155,19 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
/// If `return_body_with_facts` is true, then return the body with non-erased
/// region ids on which the borrow checking was performed together with Polonius
/// facts.
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
return_body_with_facts: bool,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.with_opt_param().as_local().unwrap();
let def = input_body.source.def_id().expect_local();
debug!(?def);
let tcx = infcx.tcx;
let infcx = BorrowckInferCtxt::new(infcx);
let param_env = tcx.param_env(def.did);
let param_env = tcx.param_env(def);
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
for var_debug_info in &input_body.var_debug_info {
@ -207,7 +195,7 @@ fn do_mir_borrowck<'tcx>(
errors.set_tainted_by_errors(e);
}
let upvars: Vec<_> = tcx
.closure_captures(def.did)
.closure_captures(def)
.iter()
.map(|&captured_place| {
let capture = captured_place.info.capture_kind;
@ -249,7 +237,7 @@ fn do_mir_borrowck<'tcx>(
.iterate_to_fixpoint()
.into_results_cursor(&body);
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def.did).is_fn_or_closure();
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));

View file

@ -61,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
body: &mut Body<'tcx>,
promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
) -> UniversalRegions<'tcx> {
let def = body.source.with_opt_param().as_local().unwrap();
let def = body.source.def_id().expect_local();
debug!(?def);

View file

@ -394,7 +394,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
self.cx.ascribe_user_type(
constant.literal.ty(),
UserType::TypeOf(
uv.def.did,
uv.def,
UserSubsts { substs: uv.substs, user_self_ty: None },
),
locations.span(&self.cx.body),
@ -1766,7 +1766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if let Some(uv) = maybe_uneval {
if uv.promoted.is_none() {
let tcx = self.tcx();
let def_id = uv.def.def_id_for_type_of();
let def_id = uv.def;
if tcx.def_kind(def_id) == DefKind::InlineConst {
let def_id = def_id.expect_local();
let predicates =

View file

@ -226,7 +226,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// known between those regions.
pub fn new(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
@ -388,7 +388,7 @@ impl<'tcx> UniversalRegions<'tcx> {
struct UniversalRegionsBuilder<'cx, 'tcx> {
infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
}
@ -417,12 +417,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let mut indices = self.compute_indices(fr_static, defining_ty);
debug!("build: indices={:?}", indices);
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id());
// If this is a 'root' body (not a closure/generator/inline const), then
// there are no extern regions, so the local regions start at the same
// position as the (empty) sub-list of extern regions
let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id {
first_extern_index
} else {
// If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
@ -433,7 +433,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// }
for_each_late_bound_region_in_recursive_scope(
self.infcx.tcx,
self.infcx.tcx.local_parent(self.mir_def.did),
self.infcx.tcx.local_parent(self.mir_def),
|r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
@ -462,13 +462,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
FR,
self.mir_def.did,
self.mir_def,
bound_inputs_and_output,
&mut indices,
);
// Converse of above, if this is a function/closure then the late-bound regions declared on its
// signature are local.
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| {
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
let region_vid = {
@ -492,7 +492,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
let va_list_did = self.infcx.tcx.require_lang_item(
LangItem::VaList,
Some(self.infcx.tcx.def_span(self.mir_def.did)),
Some(self.infcx.tcx.def_span(self.mir_def)),
);
let reg_vid = self
@ -544,11 +544,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
/// see `DefiningTy` for details.
fn defining_ty(&self) -> DefiningTy<'tcx> {
let tcx = self.infcx.tcx;
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
match tcx.hir().body_owner_kind(self.mir_def.did) {
match tcx.hir().body_owner_kind(self.mir_def) {
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
let defining_ty = tcx.type_of(self.mir_def).subst_identity();
debug!("defining_ty (pre-replacement): {:?}", defining_ty);
@ -562,9 +562,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
_ => span_bug!(
tcx.def_span(self.mir_def.did),
tcx.def_span(self.mir_def),
"expected defining type for `{:?}`: `{:?}`",
self.mir_def.did,
self.mir_def,
defining_ty
),
}
@ -572,10 +572,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
BodyOwnerKind::Const | BodyOwnerKind::Static(..) => {
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
if self.mir_def.did.to_def_id() == typeck_root_def_id {
if self.mir_def.to_def_id() == typeck_root_def_id {
let substs =
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
DefiningTy::Const(self.mir_def.to_def_id(), substs)
} else {
// FIXME this line creates a dependency between borrowck and typeck.
//
@ -587,15 +587,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// below), so that `type_of(inline_const_def_id).substs(substs)` uses the
// proper type with NLL infer vars.
let ty = tcx
.typeck(self.mir_def.did)
.node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
.typeck(self.mir_def)
.node_type(tcx.local_def_id_to_hir_id(self.mir_def));
let substs = InlineConstSubsts::new(
tcx,
InlineConstSubstsParts { parent_substs: identity_substs, ty },
)
.substs;
let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs);
DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs)
DefiningTy::InlineConst(self.mir_def.to_def_id(), substs)
}
}
}
@ -611,7 +611,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
defining_ty: DefiningTy<'tcx>,
) -> UniversalRegionIndices<'tcx> {
let tcx = self.infcx.tcx;
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id());
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
let fr_substs = match defining_ty {
DefiningTy::Closure(_, substs)
@ -647,7 +647,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let tcx = self.infcx.tcx;
match defining_ty {
DefiningTy::Closure(def_id, substs) => {
assert_eq!(self.mir_def.did.to_def_id(), def_id);
assert_eq!(self.mir_def.to_def_id(), def_id);
let closure_sig = substs.as_closure().sig();
let inputs_and_output = closure_sig.inputs_and_output();
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
@ -682,7 +682,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
}
DefiningTy::Generator(def_id, substs, movability) => {
assert_eq!(self.mir_def.did.to_def_id(), def_id);
assert_eq!(self.mir_def.to_def_id(), def_id);
let resume_ty = substs.as_generator().resume_ty();
let output = substs.as_generator().return_ty();
let generator_ty = tcx.mk_generator(def_id, substs, movability);
@ -700,14 +700,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
DefiningTy::Const(def_id, _) => {
// For a constant body, there are no inputs, and one
// "output" (the type of the constant).
assert_eq!(self.mir_def.did.to_def_id(), def_id);
let ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
assert_eq!(self.mir_def.to_def_id(), def_id);
let ty = tcx.type_of(self.mir_def).subst_identity();
let ty = indices.fold_to_region_vids(tcx, ty);
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
DefiningTy::InlineConst(def_id, substs) => {
assert_eq!(self.mir_def.did.to_def_id(), def_id);
assert_eq!(self.mir_def.to_def_id(), def_id);
let ty = substs.as_inline_const().ty();
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}

View file

@ -91,7 +91,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
),
},
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
if fx.tcx.is_static(def.did) =>
if fx.tcx.is_static(def) =>
{
span_bug!(constant.span, "MIR constant refers to static");
}

View file

@ -333,7 +333,7 @@ fn exported_symbols_provider_local(
match *mono_item {
MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => {
if substs.non_erasable_generics().next().is_some() {
let symbol = ExportedSymbol::Generic(def.did, substs);
let symbol = ExportedSymbol::Generic(def, substs);
symbols.push((
symbol,
SymbolExportInfo {

View file

@ -296,12 +296,12 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
}
let cid = key.value;
let def = cid.instance.def.with_opt_param();
let is_static = tcx.is_static(def.did);
let def = cid.instance.def.def_id();
let is_static = tcx.is_static(def);
let mut ecx = InterpCx::new(
tcx,
tcx.def_span(def.did),
tcx.def_span(def),
key.param_env,
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.

View file

@ -375,9 +375,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
match instance {
ty::InstanceDef::Item(def) => {
if ecx.tcx.is_ctfe_mir_available(def.did) {
Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def))
} else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst {
if ecx.tcx.is_ctfe_mir_available(def) {
Ok(ecx.tcx.mir_for_ctfe(def))
} else if ecx.tcx.def_kind(def) == DefKind::AssocConst {
let guar = ecx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
"This is likely a const item that is missing from its impl",
@ -386,7 +386,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
} else {
// `find_mir_or_eval_fn` checks that this is a const fn before even calling us,
// so this should be unreachable.
let path = ecx.tcx.def_path_str(def.did);
let path = ecx.tcx.def_path_str(def);
bug!("trying to call extern function `{path}` at compile-time");
}
}
@ -410,9 +410,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
// Execution might have wandered off into other crates, so we cannot do a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
if !ecx.tcx.is_const_fn_raw(def.did) {
if !ecx.tcx.is_const_fn_raw(def) {
// allow calling functions inside a trait marked with #[const_trait].
if !ecx.tcx.is_const_default_method(def.did) {
if !ecx.tcx.is_const_default_method(def) {
// We certainly do *not* want to actually call the fn
// though, so be sure we return here.
throw_unsup_format!("calling non-const function `{}`", instance)

View file

@ -461,10 +461,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
instance: ty::InstanceDef<'tcx>,
promoted: Option<mir::Promoted>,
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
let def = instance.with_opt_param();
trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
let body = if let Some(promoted) = promoted {
&self.tcx.promoted_mir_opt_const_arg(def)[promoted]
let def = instance.def_id();
&self.tcx.promoted_mir(def)[promoted]
} else {
M::load_mir(self, instance)?
};
@ -502,13 +502,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// The `substs` are assumed to already be in our interpreter "universe" (param_env).
pub(super) fn resolve(
&self,
def: ty::WithOptConstParam<DefId>,
def: DefId,
substs: SubstsRef<'tcx>,
) -> InterpResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def, substs);
trace!("param_env: {:#?}", self.param_env);
trace!("substs: {:#?}", substs);
match ty::Instance::resolve_opt_const_arg(*self.tcx, self.param_env, def, substs) {
match ty::Instance::resolve(*self.tcx, self.param_env, def, substs) {
Ok(Some(instance)) => Ok(instance),
Ok(None) => throw_inval!(TooGeneric),

View file

@ -83,8 +83,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false)
}
ty::FnDef(def_id, substs) => {
let instance =
self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?;
let instance = self.resolve(def_id, substs)?;
(
FnVal::Instance(instance),
self.fn_abi_of_instance(instance, extra_args)?,

View file

@ -36,7 +36,7 @@ where
ty::Closure(def_id, substs)
| ty::Generator(def_id, substs, ..)
| ty::FnDef(def_id, substs) => {
let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
let instance = ty::InstanceDef::Item(def_id);
let unused_params = self.tcx.unused_generic_params(instance);
for (index, subst) in substs.into_iter().enumerate() {
let index = index

View file

@ -874,7 +874,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
debug!("Resolving ({:?}) -> {:?}", callee, instance);
if let Ok(Some(func)) = instance {
if let InstanceDef::Item(def) = func.def {
callee = def.did;
callee = def;
}
}
}

View file

@ -364,9 +364,8 @@ where
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
// Don't peek inside trait associated constants.
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
assert_eq!(def.const_param_did, None, "expected associated const: {def:?}");
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
if promoted.is_none() && cx.tcx.trait_of_item(def).is_none() {
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def);
if !Q::in_qualifs(&qualifs) {
return false;

View file

@ -828,7 +828,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
}
fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
let def = self.source.source.with_opt_param();
let def = self.source.source.def_id();
let mut rvalue = {
let promoted = &mut self.promoted;
let promoted_id = Promoted::new(next_promoted_id);
@ -836,7 +836,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
let mut promoted_operand = |ty, span| {
promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def));
let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) };
Operand::Constant(Box::new(Constant {

View file

@ -488,12 +488,7 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante
abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
debug!("pretty printing THIR tree");
for did in tcx.hir().body_owners() {
let _ = writeln!(
out,
"{:?}:\n{}\n",
did,
tcx.thir_tree(ty::WithOptConstParam::unknown(did))
);
let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did));
}
out
}
@ -503,12 +498,7 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante
abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
debug!("pretty printing THIR flat");
for did in tcx.hir().body_owners() {
let _ = writeln!(
out,
"{:?}:\n{}\n",
did,
tcx.thir_flat(ty::WithOptConstParam::unknown(did))
);
let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did));
}
out
}

View file

@ -447,14 +447,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
ty::Const::from_opt_const_arg_anon_const(
tcx,
ty::WithOptConstParam {
did: ct.value.def_id,
const_param_did: Some(param.def_id),
},
)
.into()
let did = ct.value.def_id;
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
ty::Const::from_anon_const(tcx, did).into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx

View file

@ -55,7 +55,6 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
pub fn provide(providers: &mut Providers) {
resolve_bound_vars::provide(providers);
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,

View file

@ -1,6 +1,6 @@
use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, Node};
@ -16,22 +16,81 @@ use super::ItemCtxt;
use super::{bad_placeholder, is_suggestable_infer_ty};
use crate::errors::UnconstrainedOpaqueType;
/// Computes the relevant generic parameter for a potential generic const argument.
///
/// This should be called using the query `tcx.opt_const_param_of`.
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
use hir::*;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
match tcx.hir().get(hir_id) {
Node::AnonConst(_) => (),
_ => return None,
};
let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() };
let parent_node_id = tcx.hir().parent_id(hir_id);
let parent_node = tcx.hir().get(parent_node_id);
let (generics, arg_idx) = match parent_node {
// Easy case: arrays repeat expressions.
Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
if constant.hir_id() == hir_id =>
{
return tcx.types.usize
}
Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
return tcx.typeck(def_id).node_type(e.hir_id)
}
Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
if anon_const.hir_id == hir_id =>
{
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
return substs.as_inline_const().ty()
}
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const }
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
_ => false,
}) =>
{
return tcx.typeck(def_id).node_type(hir_id)
}
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
return tcx
.adt_def(tcx.hir().get_parent_item(hir_id))
.repr()
.discr_type()
.to_ty(tcx)
}
Node::GenericParam(&GenericParam {
def_id: param_def_id,
kind: GenericParamKind::Const { default: Some(ct), .. },
..
}) if ct.hir_id == hir_id => {
return tcx.type_of(param_def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic")
}
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
if let Node::TraitRef(trait_ref) = tcx.hir().get(
tcx.hir().parent_id(binding_id)
) =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
return tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find trait");
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
);
return if let Some(assoc_item) = assoc_item {
tcx.type_of(assoc_item.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic")
} else {
// FIXME(associated_const_equality): add a useful error message here.
tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find associated const on trait")
}
}
// This match arm is for when the def_id appears in a GAT whose
// path can't be resolved without typechecking e.g.
//
@ -86,11 +145,10 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
tcx.sess.delay_span_bug(
return tcx.ty_error_with_message(
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
return None;
}
}
Node::Expr(&Expr {
@ -103,7 +161,12 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// This may fail in case the method/path does not actually exist.
// As there is no relevant param for `def_id`, we simply return
// `None` here.
let type_dependent_def = tables.type_dependent_def_id(parent_node_id)?;
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unable to find type-dependent def for {:?}", parent_node_id),
);
};
let idx = segment
.args
.and_then(|args| {
@ -140,19 +203,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
tcx.sess.delay_span_bug(
return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
);
return None;
}
}
_ => {
tcx.sess.delay_span_bug(
return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unexpected const parent path {:?}", parent_node),
);
return None;
}
};
@ -171,32 +232,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg)))
}) else {
tcx.sess.delay_span_bug(
return tcx.ty_error_with_message(
tcx.def_span(def_id),
"no arg matching AnonConst in path",
);
return None;
};
let generics = match tcx.res_generics_def_id(segment.res) {
Some(def_id) => tcx.generics_of(def_id),
None => {
tcx.sess.delay_span_bug(
return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
);
return None;
}
};
(generics, arg_index)
}
_ => return None,
_ => return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("unexpected const parent in type_of(): {parent_node:?}"),
),
};
debug!(?parent_node);
debug!(?generics, ?arg_idx);
generics
if let Some(param_def_id) = generics
.params
.iter()
.filter(|param| param.kind.is_ty_or_const())
@ -211,6 +274,14 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
}
_ => None,
})
{
tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
} else {
return tcx.ty_error_with_message(
tcx.def_span(def_id),
&format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
);
}
}
fn get_path_containing_arg_in_pat<'hir>(
@ -415,143 +486,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
tcx.typeck(def_id).node_type(hir_id)
}
Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
// We defer to `type_of` of the corresponding parameter
// for generic arguments.
tcx.type_of(param).subst_identity()
}
Node::AnonConst(_) => {
let parent_node = tcx.hir().get_parent(hir_id);
match parent_node {
Node::Ty(Ty { kind: TyKind::Array(_, constant), .. })
| Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
if constant.hir_id() == hir_id =>
{
tcx.types.usize
}
Node::Ty(Ty { kind: TyKind::Typeof(e), .. }) if e.hir_id == hir_id => {
tcx.typeck(def_id).node_type(e.hir_id)
}
Node::Expr(Expr { kind: ExprKind::ConstBlock(anon_const), .. })
if anon_const.hir_id == hir_id =>
{
let substs = InternalSubsts::identity_for_item(tcx, def_id);
substs.as_inline_const().ty()
}
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const }
| hir::InlineAsmOperand::SymFn { anon_const } => {
anon_const.hir_id == hir_id
}
_ => false,
}) =>
{
tcx.typeck(def_id).node_type(hir_id)
}
Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
}
Node::TypeBinding(TypeBinding {
hir_id: binding_id,
kind: TypeBindingKind::Equality { term: Term::Const(e) },
ident,
..
}) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id)
&& e.hir_id == hir_id =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
tcx,
*ident,
ty::AssocKind::Const,
def_id.to_def_id(),
);
if let Some(assoc_item) = assoc_item {
tcx.type_of(assoc_item.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic")
} else {
// FIXME(associated_const_equality): add a useful error message here.
tcx.ty_error_with_message(
DUMMY_SP,
"Could not find associated const on trait",
)
}
}
Node::TypeBinding(TypeBinding {
hir_id: binding_id,
gen_args,
kind,
ident,
..
}) if let Node::TraitRef(trait_ref) = tcx.hir().get_parent(*binding_id)
&& let Some((idx, _)) =
gen_args.args.iter().enumerate().find(|(_, arg)| {
if let GenericArg::Const(ct) = arg {
ct.value.hir_id == hir_id
} else {
false
}
}) =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
tcx,
*ident,
match kind {
// I think `<A: T>` type bindings requires that `A` is a type
TypeBindingKind::Constraint { .. }
| TypeBindingKind::Equality { term: Term::Ty(..) } => {
ty::AssocKind::Type
}
TypeBindingKind::Equality { term: Term::Const(..) } => {
ty::AssocKind::Const
}
},
def_id.to_def_id(),
);
if let Some(assoc_item) = assoc_item
&& let param = &tcx.generics_of(assoc_item.def_id).params[idx]
&& matches!(param.kind, ty::GenericParamDefKind::Const { .. })
{
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic")
} else {
// FIXME(associated_const_equality): add a useful error message here.
tcx.ty_error_with_message(
DUMMY_SP,
"Could not find const param on associated item",
)
}
}
Node::GenericParam(&GenericParam {
def_id: param_def_id,
kind: GenericParamKind::Const { default: Some(ct), .. },
..
}) if ct.hir_id == hir_id => tcx.type_of(param_def_id).subst_identity(),
x => tcx.ty_error_with_message(
DUMMY_SP,
&format!("unexpected const parent in type_of(): {x:?}"),
),
}
}
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
Node::GenericParam(param) => match &param.kind {
GenericParamKind::Type { default: Some(ty), .. }

View file

@ -420,9 +420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ast_c: &hir::AnonConst,
param_def_id: DefId,
) -> ty::Const<'tcx> {
let const_def =
ty::WithOptConstParam { did: ast_c.def_id, const_param_did: Some(param_def_id) };
let c = ty::Const::from_opt_const_arg_anon_const(self.tcx, const_def);
let did = ast_c.def_id;
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
let c = ty::Const::from_anon_const(self.tcx, did);
self.register_wf_obligation(
c.into(),
self.tcx.hir().span(ast_c.hir_id),

View file

@ -156,21 +156,9 @@ fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
}
fn typeck_const_arg<'tcx>(
tcx: TyCtxt<'tcx>,
(did, param_did): (LocalDefId, DefId),
) -> &ty::TypeckResults<'tcx> {
let fallback = move || tcx.type_of(param_did).subst_identity();
typeck_with_fallback(tcx, did, fallback)
}
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
if let Some(param_did) = tcx.opt_const_param_of(def_id) {
tcx.typeck_const_arg((def_id, param_did))
} else {
let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
typeck_with_fallback(tcx, def_id, fallback)
}
}
/// Used only to get `TypeckResults` for type inference during error recovery.
@ -492,7 +480,6 @@ pub fn provide(providers: &mut Providers) {
method::provide(providers);
*providers = Providers {
typeck_item_bodies,
typeck_const_arg,
typeck,
diagnostic_only_typeck,
has_typeck_results,

View file

@ -1500,7 +1500,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(Some(val)) => Ok(self.tcx.mk_const(val, ty)),
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def.did;
let def_id = unevaluated.def;
span_bug!(
tcx.def_span(def_id),
"unable to construct a constant value for the unevaluated constant {:?}",
@ -1547,8 +1547,8 @@ impl<'tcx> InferCtxt<'tcx> {
substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
}
} else {
substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
param_env = tcx.param_env(unevaluated.def.did);
substs = InternalSubsts::identity_for_item(tcx, unevaluated.def);
param_env = tcx.param_env(unevaluated.def);
}
}

View file

@ -795,8 +795,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
tcx.ensure().has_ffi_unwind_calls(def_id);
if tcx.hir().body_const_context(def_id).is_some() {
tcx.ensure()
.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(def_id));
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
}
}
});

View file

@ -1539,8 +1539,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
let instance =
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
let instance = ty::InstanceDef::Item(def_id.to_def_id());
let unused = tcx.unused_generic_params(instance);
self.tables.unused_generic_params.set(def_id.local_def_index, unused);
}

View file

@ -16,16 +16,13 @@ where
{
let def_ids = dump_mir_def_ids(tcx, single);
let mirs =
def_ids
let mirs = def_ids
.iter()
.flat_map(|def_id| {
if tcx.is_const_fn_raw(*def_id) {
vec![tcx.optimized_mir(*def_id), tcx.mir_for_ctfe(*def_id)]
} else {
vec![tcx.instance_mir(ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
*def_id,
)))]
vec![tcx.instance_mir(ty::InstanceDef::Item(*def_id))]
}
})
.collect::<Vec<_>>();

View file

@ -42,7 +42,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
// variables. We reject those here since `resolve_opt_const_arg`
// variables. We reject those here since `resolve`
// would fail otherwise.
//
// When trying to evaluate constants containing inference variables,
@ -51,7 +51,7 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}
match ty::Instance::resolve_opt_const_arg(
match ty::Instance::resolve(
self, param_env,
// FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
ct.def, ct.substs,
@ -73,7 +73,7 @@ impl<'tcx> TyCtxt<'tcx> {
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
// variables. We reject those here since `resolve_opt_const_arg`
// variables. We reject those here since `resolve`
// would fail otherwise.
//
// When trying to evaluate constants containing inference variables,
@ -82,7 +82,7 @@ impl<'tcx> TyCtxt<'tcx> {
bug!("did not expect inference variables here");
}
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
match ty::Instance::resolve(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None };
self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
@ -94,14 +94,14 @@ impl<'tcx> TyCtxt<'tcx> {
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
let mir_body = self.mir_for_ctfe(ct.def);
if mir_body.is_polymorphic {
let Some(local_def_id) = ct.def.did.as_local() else { return };
let Some(local_def_id) = ct.def.as_local() else { return };
self.struct_span_lint_hir(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
self.hir().local_def_id_to_hir_id(local_def_id),
self.def_span(ct.def.did),
self.def_span(ct.def),
"cannot use constants which depend on generic parameters in types",
|err| err,
)

View file

@ -191,20 +191,13 @@ pub struct MirSource<'tcx> {
impl<'tcx> MirSource<'tcx> {
pub fn item(def_id: DefId) -> Self {
MirSource {
instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
promoted: None,
}
MirSource { instance: InstanceDef::Item(def_id), promoted: None }
}
pub fn from_instance(instance: InstanceDef<'tcx>) -> Self {
MirSource { instance, promoted: None }
}
pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
self.instance.with_opt_param()
}
#[inline]
pub fn def_id(&self) -> DefId {
self.instance.def_id()
@ -2436,16 +2429,6 @@ impl<'tcx> ConstantKind<'tcx> {
Self::Val(val, ty)
}
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
/// converted to a constant, everything else becomes `Unevaluated`.
pub fn from_anon_const(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id), param_env)
}
#[instrument(skip(tcx), level = "debug", ret)]
pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@ -2485,28 +2468,25 @@ impl<'tcx> ConstantKind<'tcx> {
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
.substs;
let uneval = UnevaluatedConst {
def: ty::WithOptConstParam::unknown(def_id).to_global(),
substs,
promoted: None,
};
let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
debug_assert!(!uneval.has_free_regions());
Self::Unevaluated(uneval, ty)
}
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
/// converted to a constant, everything else becomes `Unevaluated`.
#[instrument(skip(tcx), level = "debug", ret)]
fn from_opt_const_arg_anon_const(
pub fn from_anon_const(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
let body_id = match tcx.hir().get_by_def_id(def.did) {
let body_id = match tcx.hir().get_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
_ => span_bug!(
tcx.def_span(def.did.to_def_id()),
"from_anon_const can only process anonymous constants"
),
_ => {
span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants")
}
};
let expr = &tcx.hir().body(body_id).value;
@ -2522,7 +2502,7 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!("expr.kind: {:?}", expr.kind);
let ty = tcx.type_of(def.def_id_for_type_of()).subst_identity();
let ty = tcx.type_of(def).subst_identity();
debug!(?ty);
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@ -2549,7 +2529,7 @@ impl<'tcx> ConstantKind<'tcx> {
_ => {}
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
&& let Some(parent_did) = parent_hir_id.as_owner()
{
@ -2559,15 +2539,14 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!(?parent_substs);
let did = def.did.to_def_id();
let did = def.to_def_id();
let child_substs = InternalSubsts::identity_for_item(tcx, did);
let substs =
tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
debug!(?substs);
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let span = tcx.hir().span(hir_id);
let uneval = UnevaluatedConst::new(def.to_global(), substs);
let span = tcx.def_span(def);
let uneval = UnevaluatedConst::new(did, substs);
debug!(?span, ?param_env);
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@ -2581,8 +2560,8 @@ impl<'tcx> ConstantKind<'tcx> {
// new unevaluated const and error hard later in codegen
Self::Unevaluated(
UnevaluatedConst {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did),
def: did,
substs: InternalSubsts::identity_for_item(tcx, did),
promoted: None,
},
ty,
@ -2607,7 +2586,7 @@ impl<'tcx> ConstantKind<'tcx> {
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
pub def: ty::WithOptConstParam<DefId>,
pub def: DefId,
pub substs: SubstsRef<'tcx>,
pub promoted: Option<Promoted>,
}
@ -2623,10 +2602,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
pub fn new(
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
) -> UnevaluatedConst<'tcx> {
pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
UnevaluatedConst { def, substs, promoted: Default::default() }
}
}

View file

@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> {
// instances into account. The others don't matter for
// the codegen tests and can even make item order
// unstable.
InstanceDef::Item(def) => def.did.as_local().map(Idx::index),
InstanceDef::Item(def) => def.as_local().map(Idx::index),
InstanceDef::VTableShim(..)
| InstanceDef::ReifyShim(..)
| InstanceDef::Intrinsic(..)

View file

@ -298,8 +298,7 @@ pub fn write_mir_pretty<'tcx>(
// are shared between mir_for_ctfe and optimized_mir
write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?;
} else {
let instance_mir =
tcx.instance_mir(ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)));
let instance_mir = tcx.instance_mir(ty::InstanceDef::Item(def_id));
render_body(w, instance_mir)?;
}
}
@ -464,11 +463,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Param(p) => format!("Param({})", p),
ty::ConstKind::Unevaluated(uv) => {
format!(
"Unevaluated({}, {:?})",
self.tcx.def_path_str(uv.def.did),
uv.substs,
)
format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.substs,)
}
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
ty::ConstKind::Error(_) => "Error".to_string(),
@ -481,7 +476,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
ConstantKind::Unevaluated(uv, _) => {
format!(
"Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def.did),
self.tcx.def_path_str(uv.def),
uv.substs,
uv.promoted,
)

View file

@ -1,12 +1,12 @@
//! Values computed by queries that use MIR.
use crate::mir::{Body, ConstantKind, Promoted};
use crate::mir::ConstantKind;
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::{Idx, IndexVec};
use rustc_span::Span;
@ -454,42 +454,3 @@ pub struct CoverageInfo {
/// The total number of coverage region counter expressions added to the MIR `Body`.
pub num_expressions: u32,
}
/// Shims which make dealing with `WithOptConstParam` easier.
///
/// For more information on why this is needed, consider looking
/// at the docs for `WithOptConstParam` itself.
impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mir_const_qualif_opt_const_arg(
self,
def: ty::WithOptConstParam<LocalDefId>,
) -> ConstQualifs {
if let Some(param_did) = def.const_param_did {
self.mir_const_qualif_const_arg((def.did, param_did))
} else {
self.mir_const_qualif(def.did)
}
}
#[inline]
pub fn promoted_mir_opt_const_arg(
self,
def: ty::WithOptConstParam<DefId>,
) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
if let Some((did, param_did)) = def.as_const_arg() {
self.promoted_mir_of_const_arg((did, param_did))
} else {
self.promoted_mir(def.did)
}
}
#[inline]
pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> {
if let Some((did, param_did)) = def.as_const_arg() {
self.mir_for_ctfe_of_const_arg((did, param_did))
} else {
self.mir_for_ctfe(def.did)
}
}
}

View file

@ -174,14 +174,6 @@ impl AsLocalKey for DefId {
}
}
impl Key for ty::WithOptConstParam<LocalDefId> {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.did.default_span(tcx)
}
}
impl Key for SimplifiedType {
type CacheSelector = DefaultCacheSelector<Self>;
@ -313,7 +305,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
(self.0).def.did.default_span(tcx)
(self.0).def.default_span(tcx)
}
}

View file

@ -127,29 +127,6 @@ rustc_queries! {
desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Computes the `DefId` of the corresponding const parameter in case the `key` is a
/// const argument and returns `None` otherwise.
///
/// ```ignore (incomplete)
/// let a = foo::<7>();
/// // ^ Calling `opt_const_param_of` for this argument,
///
/// fn foo<const N: usize>()
/// // ^ returns this `DefId`.
///
/// fn bar() {
/// // ^ While calling `opt_const_param_of` for other bodies returns `None`.
/// }
/// ```
// It looks like caching this query on disk actually slightly
// worsened performance in #74376.
//
// Once const generics are more prevalently used, we might want to
// consider only caching calls returning `Some`.
query opt_const_param_of(key: LocalDefId) -> Option<DefId> {
desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Given the def_id of a const-generic parameter, computes the associated default const
/// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
query const_param_default(param: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
@ -369,26 +346,24 @@ rustc_queries! {
}
/// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
query thir_body(key: ty::WithOptConstParam<LocalDefId>)
-> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed>
{
query thir_body(key: LocalDefId) -> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed> {
// Perf tests revealed that hashing THIR is inefficient (see #85729).
no_hash
desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Create a THIR tree for debugging.
query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
query thir_tree(key: LocalDefId) -> &'tcx String {
no_hash
arena_cache
desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) }
desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Create a list-like THIR representation for debugging.
query thir_flat(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
query thir_flat(key: LocalDefId) -> &'tcx String {
no_hash
arena_cache
desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.did.to_def_id()) }
desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Set of all the `DefId`s in this crate that have MIR associated with
@ -407,31 +382,19 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
query mir_const_qualif_const_arg(
key: (LocalDefId, DefId)
) -> mir::ConstQualifs {
desc {
|tcx| "const checking the const argument `{}`",
tcx.def_path_str(key.0.to_def_id())
}
}
/// Fetch the MIR for a given `DefId` right after it's built - this includes
/// unreachable code.
query mir_built(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.did.to_def_id()) }
query mir_built(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Fetch the MIR for a given `DefId` up till the point where it is
/// ready for const qualification.
///
/// See the README for the `mir` module for details.
query mir_const(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
desc {
|tcx| "preparing {}`{}` for borrow checking",
if key.const_param_did.is_some() { "the const argument " } else { "" },
tcx.def_path_str(key.did.to_def_id()),
}
query mir_const(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
desc { |tcx| "preparing `{}` for borrow checking", tcx.def_path_str(key.to_def_id()) }
no_hash
}
@ -444,22 +407,10 @@ rustc_queries! {
}
separate_provide_extern
}
/// Try to build an abstract representation of the given constant.
query thir_abstract_const_of_const_arg(
key: (LocalDefId, DefId)
) -> Result<Option<ty::Const<'tcx>>, ErrorGuaranteed> {
desc {
|tcx|
"building an abstract representation for the const argument `{}`",
tcx.def_path_str(key.0.to_def_id()),
}
}
query mir_drops_elaborated_and_const_checked(
key: ty::WithOptConstParam<LocalDefId>
) -> &'tcx Steal<mir::Body<'tcx>> {
query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
no_hash
desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) }
desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.to_def_id()) }
}
query mir_for_ctfe(
@ -470,24 +421,12 @@ rustc_queries! {
separate_provide_extern
}
query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
desc {
|tcx| "caching MIR for CTFE of the const argument `{}`",
tcx.def_path_str(key.0.to_def_id())
}
}
query mir_promoted(key: ty::WithOptConstParam<LocalDefId>) ->
(
query mir_promoted(key: LocalDefId) -> (
&'tcx Steal<mir::Body<'tcx>>,
&'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>>
) {
no_hash
desc {
|tcx| "processing MIR for {}`{}`",
if key.const_param_did.is_some() { "the const argument " } else { "" },
tcx.def_path_str(key.did.to_def_id()),
}
desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
}
query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
@ -544,14 +483,6 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
query promoted_mir_of_const_arg(
key: (LocalDefId, DefId)
) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
desc {
|tcx| "optimizing promoted MIR for the const argument `{}`",
tcx.def_path_str(key.0.to_def_id()),
}
}
/// Erases regions from `ty` to yield a new type.
/// Normally you would just use `tcx.erase_regions(value)`,
@ -840,12 +771,6 @@ rustc_queries! {
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
query unsafety_check_result_for_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::UnsafetyCheckResult {
desc {
|tcx| "unsafety-checking the const argument `{}`",
tcx.def_path_str(key.0.to_def_id())
}
}
/// Unsafety-check this `LocalDefId` with THIR unsafeck. This should be
/// used with `-Zthir-unsafeck`.
@ -853,12 +778,6 @@ rustc_queries! {
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
query thir_check_unsafety_for_const_arg(key: (LocalDefId, DefId)) {
desc {
|tcx| "unsafety-checking the const argument `{}`",
tcx.def_path_str(key.0.to_def_id())
}
}
/// Returns the types assumed to be well formed while "inside" of the given item.
///
@ -960,14 +879,6 @@ rustc_queries! {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
query typeck_const_arg(
key: (LocalDefId, DefId)
) -> &'tcx ty::TypeckResults<'tcx> {
desc {
|tcx| "type-checking the const argument `{}`",
tcx.def_path_str(key.0.to_def_id()),
}
}
query diagnostic_only_typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
@ -992,12 +903,6 @@ rustc_queries! {
desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}
query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
desc {
|tcx| "borrow-checking the const argument`{}`",
tcx.def_path_str(key.0.to_def_id())
}
}
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
@ -2117,15 +2022,6 @@ rustc_queries! {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
}
query resolve_instance_of_const_arg(
key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>
) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> {
desc {
"resolving instance of the const argument `{}`",
ty::Instance::new(key.value.0.to_def_id(), key.value.2),
}
}
query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
desc { "revealing opaque types in `{:?}`", key }
}

View file

@ -929,8 +929,8 @@ mod size_asserts {
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 72);
static_assert_size!(PatKind<'_>, 56);
static_assert_size!(Pat<'_>, 64);
static_assert_size!(PatKind<'_>, 48);
static_assert_size!(Stmt<'_>, 56);
static_assert_size!(StmtKind<'_>, 48);
// tidy-alphabetical-end

View file

@ -36,15 +36,8 @@ pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>,
impl<'tcx> TyCtxt<'tcx> {
/// Returns a const without substs applied
pub fn bound_abstract_const(
self,
uv: ty::WithOptConstParam<DefId>,
) -> BoundAbstractConst<'tcx> {
let ac = if let Some((did, param_did)) = uv.as_const_arg() {
self.thir_abstract_const_of_const_arg((did, param_did))
} else {
self.thir_abstract_const(uv.did)
};
pub fn bound_abstract_const(self, uv: DefId) -> BoundAbstractConst<'tcx> {
let ac = self.thir_abstract_const(uv);
Ok(ac?.map(|ac| EarlyBinder(ac)))
}

View file

@ -53,19 +53,12 @@ impl<'tcx> Const<'tcx> {
/// Literals and const generic parameters are eagerly converted to a constant, everything else
/// becomes `Unevaluated`.
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
}
#[instrument(skip(tcx), level = "debug")]
pub fn from_opt_const_arg_anon_const(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> Self {
let body_id = match tcx.hir().get_by_def_id(def.did) {
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
let body_id = match tcx.hir().get_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
_ => span_bug!(
tcx.def_span(def.did.to_def_id()),
tcx.def_span(def.to_def_id()),
"from_anon_const can only process anonymous constants"
),
};
@ -73,17 +66,14 @@ impl<'tcx> Const<'tcx> {
let expr = &tcx.hir().body(body_id).value;
debug!(?expr);
let ty = tcx
.type_of(def.def_id_for_type_of())
.no_bound_vars()
.expect("const parameter types cannot be generic");
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
None => tcx.mk_const(
ty::UnevaluatedConst {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did),
def: def.to_def_id(),
substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
},
ty,
),

View file

@ -17,7 +17,7 @@ use super::ScalarInt;
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
pub def: ty::WithOptConstParam<DefId>,
pub def: DefId,
pub substs: SubstsRef<'tcx>,
}
@ -36,10 +36,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
pub fn new(
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
) -> UnevaluatedConst<'tcx> {
pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
UnevaluatedConst { def, substs }
}
}
@ -224,9 +221,9 @@ impl<'tcx> ConstKind<'tcx> {
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
def: unevaluated.def,
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
})
} else {
tcx.erase_regions(param_env)

View file

@ -13,7 +13,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
use crate::mir::{Body, BorrowCheckResult, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::query::LocalCrate;
use crate::thir::Thir;
use crate::traits;
@ -24,7 +24,7 @@ use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, Visibility,
TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast::{self as ast, attr};
@ -449,6 +449,14 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
}
/// In order to break cycles involving `AnonConst`, we need to set the expected type by side
/// effect. However, we do not want this as a general capability, so this interface restricts
/// to the only allowed case.
pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>) {
debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
TyCtxtFeed { tcx: self, key }.type_of(value)
}
}
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
@ -583,28 +591,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
pub fn typeck_opt_const_arg(
self,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx TypeckResults<'tcx> {
if let Some(param_did) = def.const_param_did {
self.typeck_const_arg((def.did, param_did))
} else {
self.typeck(def.did)
}
}
pub fn mir_borrowck_opt_const_arg(
self,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx BorrowCheckResult<'tcx> {
if let Some(param_did) = def.const_param_did {
self.mir_borrowck_const_arg((def.did, param_did))
} else {
self.mir_borrowck(def.did)
}
}
pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
self.arena.alloc(Steal::new(thir))
}

View file

@ -34,7 +34,7 @@ pub enum InstanceDef<'tcx> {
/// - `fn` items
/// - closures
/// - generators
Item(ty::WithOptConstParam<DefId>),
Item(DefId),
/// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
///
@ -143,7 +143,7 @@ impl<'tcx> Instance<'tcx> {
match self.def {
InstanceDef::Item(def) => tcx
.upstream_monomorphizations_for(def.did)
.upstream_monomorphizations_for(def)
.and_then(|monos| monos.get(&self.substs).cloned()),
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
_ => None,
@ -155,8 +155,8 @@ impl<'tcx> InstanceDef<'tcx> {
#[inline]
pub fn def_id(self) -> DefId {
match self {
InstanceDef::Item(def) => def.did,
InstanceDef::VTableShim(def_id)
InstanceDef::Item(def_id)
| InstanceDef::VTableShim(def_id)
| InstanceDef::ReifyShim(def_id)
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
@ -172,7 +172,7 @@ impl<'tcx> InstanceDef<'tcx> {
/// Returns the `DefId` of instances which might not require codegen locally.
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
match self {
ty::InstanceDef::Item(def) => Some(def.did),
ty::InstanceDef::Item(def) => Some(def),
ty::InstanceDef::DropGlue(def_id, Some(_)) | InstanceDef::ThreadLocalShim(def_id) => {
Some(def_id)
}
@ -188,23 +188,6 @@ impl<'tcx> InstanceDef<'tcx> {
}
}
#[inline]
pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
match self {
InstanceDef::Item(def) => def,
InstanceDef::VTableShim(def_id)
| InstanceDef::ReifyShim(def_id)
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
| InstanceDef::Intrinsic(def_id)
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
| InstanceDef::DropGlue(def_id, _)
| InstanceDef::CloneShim(def_id, _)
| InstanceDef::ThreadLocalShim(def_id)
| InstanceDef::FnPtrAddrShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
}
}
#[inline]
pub fn get_attrs(
&self,
@ -222,7 +205,7 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
use rustc_hir::definitions::DefPathData;
let def_id = match *self {
ty::InstanceDef::Item(def) => def.did,
ty::InstanceDef::Item(def) => def,
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
ty::InstanceDef::ThreadLocalShim(_) => return false,
_ => return true,
@ -273,8 +256,7 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
match *self {
InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
| InstanceDef::Virtual(def_id, _) => {
InstanceDef::Item(def_id) | InstanceDef::Virtual(def_id, _) => {
tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
@ -358,7 +340,7 @@ impl<'tcx> Instance<'tcx> {
def_id,
substs
);
Instance { def: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), substs }
Instance { def: InstanceDef::Item(def_id), substs }
}
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
@ -403,18 +385,21 @@ impl<'tcx> Instance<'tcx> {
/// couldn't complete due to errors elsewhere - this is distinct
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause
#[instrument(level = "debug", skip(tcx))]
pub fn resolve(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
Instance::resolve_opt_const_arg(
tcx,
param_env,
ty::WithOptConstParam::unknown(def_id),
substs,
)
// All regions in the result of this query are erased, so it's
// fine to erase all of the input regions.
// HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
// below is more likely to ignore the bounds in scope (e.g. if the only
// generic parameters mentioned by `substs` were lifetime ones).
let substs = tcx.erase_regions(substs);
tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, substs))))
}
pub fn expect_resolve(
@ -432,31 +417,6 @@ impl<'tcx> Instance<'tcx> {
}
}
// This should be kept up to date with `resolve`.
pub fn resolve_opt_const_arg(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
// All regions in the result of this query are erased, so it's
// fine to erase all of the input regions.
// HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
// below is more likely to ignore the bounds in scope (e.g. if the only
// generic parameters mentioned by `substs` were lifetime ones).
let substs = tcx.erase_regions(substs);
// FIXME(eddyb) should this always use `param_env.with_reveal_all()`?
if let Some((did, param_did)) = def.as_const_arg() {
tcx.resolve_instance_of_const_arg(
tcx.erase_regions(param_env.and((did, param_did, substs))),
)
} else {
tcx.resolve_instance(tcx.erase_regions(param_env.and((def.did, substs))))
}
}
pub fn resolve_for_fn_ptr(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@ -470,7 +430,7 @@ impl<'tcx> Instance<'tcx> {
match resolved.def {
InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
debug!(" => fn pointer created for function with #[track_caller]");
resolved.def = InstanceDef::ReifyShim(def.did);
resolved.def = InstanceDef::ReifyShim(def);
}
InstanceDef::Virtual(def_id, _) => {
debug!(" => fn pointer created for virtual call");
@ -513,23 +473,23 @@ impl<'tcx> Instance<'tcx> {
if resolved.def.requires_caller_location(tcx)
// 2) The caller location parameter comes from having `#[track_caller]`
// on the implementation, and *not* on the trait method.
&& !tcx.should_inherit_track_caller(def.did)
&& !tcx.should_inherit_track_caller(def)
// If the method implementation comes from the trait definition itself
// (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
// then we don't need to generate a shim. This check is needed because
// `should_inherit_track_caller` returns `false` if our method
// implementation comes from the trait block, and not an impl block
&& !matches!(
tcx.opt_associated_item(def.did),
tcx.opt_associated_item(def),
Some(ty::AssocItem {
container: ty::AssocItemContainer::TraitContainer,
..
})
)
{
if tcx.is_closure(def.did) {
if tcx.is_closure(def) {
debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
def.did, def_id, substs);
def, def_id, substs);
// Create a shim for the `FnOnce/FnMut/Fn` method we are calling
// - unlike functions, invoking a closure always goes through a
@ -537,9 +497,9 @@ impl<'tcx> Instance<'tcx> {
resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs };
} else {
debug!(
" => vtable fn pointer created for function with #[track_caller]: {:?}", def.did
" => vtable fn pointer created for function with #[track_caller]: {:?}", def
);
resolved.def = InstanceDef::ReifyShim(def.did);
resolved.def = InstanceDef::ReifyShim(def);
}
}
}
@ -714,11 +674,8 @@ fn polymorphize<'tcx>(
debug!("fold_ty: ty={:?}", ty);
match *ty.kind() {
ty::Closure(def_id, substs) => {
let polymorphized_substs = polymorphize(
self.tcx,
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
substs,
);
let polymorphized_substs =
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty
} else {
@ -726,11 +683,8 @@ fn polymorphize<'tcx>(
}
}
ty::Generator(def_id, substs, movability) => {
let polymorphized_substs = polymorphize(
self.tcx,
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
substs,
);
let polymorphized_substs =
polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty
} else {

View file

@ -1007,7 +1007,7 @@ impl<'tcx> Term<'tcx> {
_ => None,
},
TermKind::Const(ct) => match ct.kind() {
ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def.did, uv.substs)),
ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)),
_ => None,
},
}
@ -1471,135 +1471,6 @@ pub struct BoundConst<'tcx> {
pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
/// A `DefId` which, in case it is a const argument, is potentially bundled with
/// the `DefId` of the generic parameter it instantiates.
///
/// This is used to avoid calls to `type_of` for const arguments during typeck
/// which cause cycle errors.
///
/// ```rust
/// struct A;
/// impl A {
/// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] }
/// // ^ const parameter
/// }
/// struct B;
/// impl B {
/// fn foo<const M: u8>(&self) -> usize { 42 }
/// // ^ const parameter
/// }
///
/// fn main() {
/// let a = A;
/// let _b = a.foo::<{ 3 + 7 }>();
/// // ^^^^^^^^^ const argument
/// }
/// ```
///
/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know
/// which `foo` is used until we know the type of `a`.
///
/// We only know the type of `a` once we are inside of `typeck(main)`.
/// We also end up normalizing the type of `_b` during `typeck(main)` which
/// requires us to evaluate the const argument.
///
/// To evaluate that const argument we need to know its type,
/// which we would get using `type_of(const_arg)`. This requires us to
/// resolve `foo` as it can be either `usize` or `u8` in this example.
/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`,
/// which results in a cycle.
///
/// In short we must not call `type_of(const_arg)` during `typeck(main)`.
///
/// When first creating the `ty::Const` of the const argument inside of `typeck` we have
/// already resolved `foo` so we know which const parameter this argument instantiates.
/// This means that we also know the expected result of `type_of(const_arg)` even if we
/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is
/// trivial to compute.
///
/// If we now want to use that constant in a place which potentially needs its type
/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`,
/// except that instead of a `Ty` we bundle the `DefId` of the const parameter.
/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some`
/// to get the type of `did`.
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(Hash, HashStable)]
pub struct WithOptConstParam<T> {
pub did: T,
/// The `DefId` of the corresponding generic parameter in case `did` is
/// a const argument.
///
/// Note that even if `did` is a const argument, this may still be `None`.
/// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)`
/// to potentially update `param_did` in the case it is `None`.
pub const_param_did: Option<DefId>,
}
impl<T> WithOptConstParam<T> {
/// Creates a new `WithOptConstParam` setting `const_param_did` to `None`.
#[inline(always)]
pub fn unknown(did: T) -> WithOptConstParam<T> {
WithOptConstParam { did, const_param_did: None }
}
}
impl WithOptConstParam<LocalDefId> {
/// Returns `Some((did, param_did))` if `def_id` is a const argument,
/// `None` otherwise.
#[inline(always)]
pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
tcx.opt_const_param_of(did).map(|param_did| (did, param_did))
}
/// In case `self` is unknown but `self.did` is a const argument, this returns
/// a `WithOptConstParam` with the correct `const_param_did`.
#[inline(always)]
pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
if self.const_param_did.is_none() {
if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) {
return Some(WithOptConstParam { did: self.did, const_param_did });
}
}
None
}
pub fn to_global(self) -> WithOptConstParam<DefId> {
WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did }
}
pub fn def_id_for_type_of(self) -> DefId {
if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() }
}
}
impl WithOptConstParam<DefId> {
pub fn as_local(self) -> Option<WithOptConstParam<LocalDefId>> {
self.did
.as_local()
.map(|did| WithOptConstParam { did, const_param_did: self.const_param_did })
}
pub fn as_const_arg(self) -> Option<(LocalDefId, DefId)> {
if let Some(param_did) = self.const_param_did {
if let Some(did) = self.did.as_local() {
return Some((did, param_did));
}
}
None
}
pub fn is_local(self) -> bool {
self.did.is_local()
}
pub fn def_id_for_type_of(self) -> DefId {
self.const_param_did.unwrap_or(self.did)
}
}
/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
/// particular point.
@ -2367,7 +2238,7 @@ impl<'tcx> TyCtxt<'tcx> {
match instance {
ty::InstanceDef::Item(def) => {
debug!("calling def_kind on def: {:?}", def);
let def_kind = self.def_kind(def.did);
let def_kind = self.def_kind(def);
debug!("returned from def_kind: {:?}", def_kind);
match def_kind {
DefKind::Const
@ -2375,13 +2246,10 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::AssocConst
| DefKind::Ctor(..)
| DefKind::AnonConst
| DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
| DefKind::InlineConst => self.mir_for_ctfe(def),
// If the caller wants `mir_for_ctfe` of a function they should not be using
// `instance_mir`, so we'll assume const fn also wants the optimized version.
_ => {
assert_eq!(def.const_param_did, None);
self.optimized_mir(def.did)
}
_ => self.optimized_mir(def),
}
}
ty::InstanceDef::VTableShim(..)

View file

@ -1328,13 +1328,13 @@ pub trait PrettyPrinter<'tcx>:
match ct.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
match self.tcx().def_kind(def.did) {
match self.tcx().def_kind(def) {
DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(def.did, substs))
p!(print_value_path(def, substs))
}
DefKind::AnonConst => {
if def.is_local()
&& let span = self.tcx().def_span(def.did)
&& let span = self.tcx().def_span(def)
&& let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
{
p!(write("{}", snip))
@ -1344,7 +1344,7 @@ pub trait PrettyPrinter<'tcx>:
// cause printing to enter an infinite recursion if the anon const is in the self type i.e.
// `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {`
// where we would try to print `<[T; /* print `constant#0` again */] as Default>::{constant#0}`
p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose()))
p!(write("{}::{}", self.tcx().crate_name(def.krate), self.tcx().def_path(def).to_string_no_crate_verbose()))
}
}
defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),

View file

@ -76,6 +76,9 @@ use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_query_system::ich::StableHashingContext;
#[derive(Default)]
pub struct QuerySystem<'tcx> {
pub arenas: QueryArenas<'tcx>,
@ -477,7 +480,7 @@ macro_rules! define_feedable {
$(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
$(#[$attr])*
#[inline(always)]
pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
pub fn $name(self, value: query_provided::$name<'tcx>) {
let key = self.key().into_query_param();
let tcx = self.tcx;
@ -485,14 +488,26 @@ macro_rules! define_feedable {
let value = restore::<$V>(erased);
let cache = &tcx.query_system.caches.$name;
let hasher: Option<fn(&mut StableHashingContext<'_>, &_) -> _> = hash_result!([$($modifiers)*]);
match try_get_cached(tcx, cache, &key) {
Some(old) => {
let old = restore::<$V>(old);
if let Some(hasher) = hasher {
let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx|
(hasher(&mut hcx, &value), hasher(&mut hcx, &old))
);
assert_eq!(
old_hash, value_hash,
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
)
} else {
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
)
}
}
None => {
let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
let dep_node_index = tcx.dep_graph.with_feed_task(
@ -503,7 +518,6 @@ macro_rules! define_feedable {
hash_result!([$($modifiers)*]),
);
cache.complete(key, erased, dep_node_index);
value
}
}
}

View file

@ -78,7 +78,7 @@ pub fn as_constant_inner<'tcx>(
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta);
let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let uneval = mir::UnevaluatedConst::new(def_id, substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty, span, literal }
@ -90,7 +90,7 @@ pub fn as_constant_inner<'tcx>(
Constant { user_ty: None, span, literal }
}
ExprKind::ConstBlock { did: def_id, substs } => {
let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let uneval = mir::UnevaluatedConst::new(def_id, substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty: None, span, literal }

View file

@ -32,38 +32,20 @@ use super::lints;
pub(crate) fn mir_built(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
def: LocalDefId,
) -> &rustc_data_structures::steal::Steal<Body<'_>> {
if let Some(def) = def.try_upgrade(tcx) {
return tcx.mir_built(def);
}
let mut body = mir_build(tcx, def);
if def.const_param_did.is_some() {
assert!(matches!(body.source.instance, ty::InstanceDef::Item(_)));
body.source = MirSource::from_instance(ty::InstanceDef::Item(def.to_global()));
}
tcx.alloc_steal_mir(body)
tcx.alloc_steal_mir(mir_build(tcx, def))
}
/// Construct the MIR for a given `DefId`.
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
match def {
ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
tcx.ensure_with_value().thir_check_unsafety_for_const_arg((did, const_param_did));
tcx.ensure_with_value().thir_abstract_const_of_const_arg((did, const_param_did));
}
ty::WithOptConstParam { did, const_param_did: None } => {
tcx.ensure_with_value().thir_check_unsafety(did);
tcx.ensure_with_value().thir_abstract_const(did);
tcx.ensure_with_value().check_match(did);
}
}
tcx.ensure_with_value().thir_check_unsafety(def);
tcx.ensure_with_value().thir_abstract_const(def);
tcx.ensure_with_value().check_match(def);
let body = match tcx.thir_body(def) {
Err(error_reported) => construct_error(tcx, def.did, error_reported),
Err(error_reported) => construct_error(tcx, def, error_reported),
Ok((thir, expr)) => {
// We ran all queries that depended on THIR at the beginning
// of `mir_build`, so now we can steal it
@ -161,8 +143,7 @@ struct Builder<'a, 'tcx> {
thir: &'a Thir<'tcx>,
cfg: CFG<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
def_id: DefId,
def_id: LocalDefId,
hir_id: hir::HirId,
parent_module: DefId,
check_overflow: bool,
@ -428,26 +409,26 @@ macro_rules! unpack {
fn construct_fn<'tcx>(
tcx: TyCtxt<'tcx>,
fn_def: ty::WithOptConstParam<LocalDefId>,
fn_def: LocalDefId,
thir: &Thir<'tcx>,
expr: ExprId,
fn_sig: ty::FnSig<'tcx>,
) -> Body<'tcx> {
let span = tcx.def_span(fn_def.did);
let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did);
let generator_kind = tcx.generator_kind(fn_def.did);
let span = tcx.def_span(fn_def);
let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def);
let generator_kind = tcx.generator_kind(fn_def);
// The representation of thir for `-Zunpretty=thir-tree` relies on
// the entry expression being the last element of `thir.exprs`.
assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
// Figure out what primary body this item has.
let body_id = tcx.hir().body_owned_by(fn_def.did);
let body_id = tcx.hir().body_owned_by(fn_def);
let span_with_body = tcx.hir().span_with_body(fn_id);
let return_ty_span = tcx
.hir()
.fn_decl_by_hir_id(fn_id)
.unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def.did))
.unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", fn_def))
.output
.span();
@ -457,7 +438,7 @@ fn construct_fn<'tcx>(
};
let mut abi = fn_sig.abi;
if let DefKind::Closure = tcx.def_kind(fn_def.did) {
if let DefKind::Closure = tcx.def_kind(fn_def) {
// HACK(eddyb) Avoid having RustCall on closures,
// as it adds unnecessary (and wrong) auto-tupling.
abi = Abi::Rust;
@ -483,7 +464,7 @@ fn construct_fn<'tcx>(
{
return custom::build_custom_mir(
tcx,
fn_def.did.to_def_id(),
fn_def.to_def_id(),
fn_id,
thir,
expr,
@ -547,12 +528,12 @@ fn construct_fn<'tcx>(
fn construct_const<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
def: LocalDefId,
thir: &'a Thir<'tcx>,
expr: ExprId,
const_ty: Ty<'tcx>,
) -> Body<'tcx> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
// Figure out what primary body this item has.
let (span, const_ty_span) = match tcx.hir().get(hir_id) {
@ -568,10 +549,10 @@ fn construct_const<'a, 'tcx>(
..
}) => (*span, ty.span),
Node::AnonConst(_) => {
let span = tcx.def_span(def.did);
let span = tcx.def_span(def);
(span, span)
}
_ => span_bug!(tcx.def_span(def.did), "can't build MIR for {:?}", def.did),
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
};
let infcx = tcx.infer_ctxt().build();
@ -669,7 +650,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn new(
thir: &'a Thir<'tcx>,
infcx: InferCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
def: LocalDefId,
hir_id: hir::HirId,
span: Span,
arg_count: usize,
@ -688,20 +669,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
check_overflow |= tcx.sess.overflow_checks();
// Constants always need overflow checks.
check_overflow |= matches!(
tcx.hir().body_owner_kind(def.did),
tcx.hir().body_owner_kind(def),
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_)
);
let lint_level = LintLevel::Explicit(hir_id);
let param_env = tcx.param_env(def.did);
let param_env = tcx.param_env(def);
let mut builder = Builder {
thir,
tcx,
infcx,
region_scope_tree: tcx.region_scope_tree(def.did),
region_scope_tree: tcx.region_scope_tree(def),
param_env,
def,
def_id: def.did.to_def_id(),
def_id: def,
hir_id,
parent_module: tcx.parent_module(hir_id).to_def_id(),
check_overflow,
@ -741,7 +721,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
Body::new(
MirSource::item(self.def_id),
MirSource::item(self.def_id.to_def_id()),
self.cfg.basic_blocks,
self.source_scopes,
self.local_decls,
@ -779,7 +759,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = self.tcx;
self.upvars = tcx
.closure_captures(self.def.did)
.closure_captures(self.def_id)
.iter()
.zip(capture_tys)
.enumerate()

View file

@ -117,10 +117,10 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
}
/// Handle closures/generators/inline-consts, which is unsafecked with their parent body.
fn visit_inner_body(&mut self, def: ty::WithOptConstParam<LocalDefId>) {
fn visit_inner_body(&mut self, def: LocalDefId) {
if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) {
let inner_thir = &inner_thir.borrow();
let hir_context = self.tcx.hir().local_def_id_to_hir_id(def.did);
let hir_context = self.tcx.hir().local_def_id_to_hir_id(def);
let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
inner_visitor.visit_expr(&inner_thir[expr]);
// Unsafe blocks can be used in the inner body, make sure to take it into account
@ -396,18 +396,11 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
movability: _,
fake_reads: _,
}) => {
let closure_def = if let Some((did, const_param_id)) =
ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
{
ty::WithOptConstParam { did, const_param_did: Some(const_param_id) }
} else {
ty::WithOptConstParam::unknown(closure_id)
};
self.visit_inner_body(closure_def);
self.visit_inner_body(closure_id);
}
ExprKind::ConstBlock { did, substs: _ } => {
let def_id = did.expect_local();
self.visit_inner_body(ty::WithOptConstParam::unknown(def_id));
self.visit_inner_body(def_id);
}
ExprKind::Field { lhs, .. } => {
let lhs = &self.thir[lhs];
@ -706,14 +699,14 @@ impl UnsafeOpKind {
}
}
pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
// THIR unsafeck is gated under `-Z thir-unsafeck`
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
return;
}
// Closures and inline consts are handled by their owner, if it has a body
if tcx.is_typeck_child(def.did.to_def_id()) {
if tcx.is_typeck_child(def.to_def_id()) {
return;
}
@ -726,7 +719,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
return;
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
if fn_sig.header.unsafety == hir::Unsafety::Unsafe {
BodyUnsafety::Unsafe(fn_sig.span)
@ -734,7 +727,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
BodyUnsafety::Safe
}
});
let body_target_features = &tcx.body_codegen_attrs(def.did.to_def_id()).target_features;
let body_target_features = &tcx.body_codegen_attrs(def.to_def_id()).target_features;
let safety_context =
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
let mut visitor = UnsafetyVisitor {
@ -746,23 +739,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) {
body_target_features,
assignment_info: None,
in_union_destructure: false,
param_env: tcx.param_env(def.did),
param_env: tcx.param_env(def),
inside_adt: false,
};
visitor.visit_expr(&thir[expr]);
}
pub(crate) fn thir_check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.thir_check_unsafety_for_const_arg(def)
} else {
check_unsafety(tcx, ty::WithOptConstParam::unknown(def_id))
}
}
pub(crate) fn thir_check_unsafety_for_const_arg(
tcx: TyCtxt<'_>,
(did, param_did): (LocalDefId, DefId),
) {
check_unsafety(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
}

View file

@ -35,7 +35,6 @@ pub fn provide(providers: &mut Providers) {
providers.lit_to_mir_constant = build::lit_to_mir_constant;
providers.mir_built = build::mir_built;
providers.thir_check_unsafety = check_unsafety::thir_check_unsafety;
providers.thir_check_unsafety_for_const_arg = check_unsafety::thir_check_unsafety_for_const_arg;
providers.thir_body = thir::cx::thir_body;
providers.thir_tree = thir::print::thir_tree;
providers.thir_flat = thir::print::thir_flat;

View file

@ -20,25 +20,25 @@ use rustc_span::Span;
pub(crate) fn thir_body(
tcx: TyCtxt<'_>,
owner_def: ty::WithOptConstParam<LocalDefId>,
owner_def: LocalDefId,
) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
let hir = tcx.hir();
let body = hir.body(hir.body_owned_by(owner_def.did));
let body = hir.body(hir.body_owned_by(owner_def));
let mut cx = Cx::new(tcx, owner_def);
if let Some(reported) = cx.typeck_results.tainted_by_errors {
return Err(reported);
}
let expr = cx.mirror_expr(&body.value);
let owner_id = hir.local_def_id_to_hir_id(owner_def.did);
let owner_id = hir.local_def_id_to_hir_id(owner_def);
if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
let closure_env_param = cx.closure_env_param(owner_def.did, owner_id);
let closure_env_param = cx.closure_env_param(owner_def, owner_id);
let explicit_params = cx.explicit_params(owner_id, fn_decl, body);
cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect();
// The resume argument may be missing, in that case we need to provide it here.
// It will always be `()` in this case.
if tcx.def_kind(owner_def.did) == DefKind::Generator && body.params.is_empty() {
if tcx.def_kind(owner_def) == DefKind::Generator && body.params.is_empty() {
cx.thir.params.push(Param {
ty: tcx.mk_unit(),
pat: None,
@ -78,13 +78,12 @@ struct Cx<'tcx> {
}
impl<'tcx> Cx<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
let typeck_results = tcx.typeck_opt_const_arg(def);
let did = def.did;
fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Cx<'tcx> {
let typeck_results = tcx.typeck(def);
let hir = tcx.hir();
let hir_id = hir.local_def_id_to_hir_id(did);
let hir_id = hir.local_def_id_to_hir_id(def);
let body_type = if hir.body_owner_kind(did).is_fn_or_closure() {
let body_type = if hir.body_owner_kind(def).is_fn_or_closure() {
// fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced)
BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
@ -106,11 +105,11 @@ impl<'tcx> Cx<'tcx> {
Cx {
tcx,
thir: Thir::new(body_type),
param_env: tcx.param_env(def.did),
region_scope_tree: tcx.region_scope_tree(def.did),
param_env: tcx.param_env(def),
region_scope_tree: tcx.region_scope_tree(def),
typeck_results,
rvalue_scopes: &typeck_results.rvalue_scopes,
body_owner: did.to_def_id(),
body_owner: def.to_def_id(),
adjustment_span: None,
apply_adjustments: hir
.attrs(hir_id)

View file

@ -27,7 +27,7 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::Span;
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let Ok((thir, expr)) = tcx.thir_body(ty::WithOptConstParam::unknown(def_id)) else { return };
let Ok((thir, expr)) = tcx.thir_body(def_id) else { return };
let thir = thir.borrow();
let pattern_arena = TypedArena::default();
let mut visitor = MatchVisitor {

View file

@ -3,7 +3,7 @@ use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::LocalDefId;
use std::fmt::{self, Write};
pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(tcx, owner_def) {
Ok((thir, _)) => {
let thir = thir.steal();
@ -15,7 +15,7 @@ pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalD
}
}
pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(tcx, owner_def) {
Ok((thir, _)) => format!("{:#?}", thir.steal()),
Err(_) => "error".into(),

View file

@ -148,7 +148,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
if let Some(uv) = maybe_uneval {
if uv.promoted.is_none() {
let def_id = uv.def.def_id_for_type_of();
let def_id = uv.def;
if self.tcx.def_kind(def_id) == DefKind::InlineConst {
let local_def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
@ -375,22 +375,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
}
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
unsafety_check_result: |tcx, def_id| {
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.unsafety_check_result_for_const_arg(def)
} else {
unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
}
},
unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
unsafety_check_result(
tcx,
ty::WithOptConstParam { did, const_param_did: Some(param_did) },
)
},
..*providers
};
*providers = Providers { unsafety_check_result, ..*providers };
}
/// Context information for [`UnusedUnsafeVisitor`] traversal,
@ -492,10 +477,7 @@ fn check_unused_unsafe(
unused_unsafes
}
fn unsafety_check_result(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &UnsafetyCheckResult {
fn unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheckResult {
debug!("unsafety_violations({:?})", def);
// N.B., this borrow is valid because all the consumers of
@ -510,13 +492,13 @@ fn unsafety_check_result(
});
}
let param_env = tcx.param_env(def.did);
let param_env = tcx.param_env(def);
let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
let mut checker = UnsafetyChecker::new(body, def, tcx, param_env);
checker.visit_body(&body);
let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
.then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
let unused_unsafes = (!tcx.is_typeck_child(def.to_def_id()))
.then(|| check_unused_unsafe(tcx, def, &checker.used_unsafe_blocks));
tcx.arena.alloc(UnsafetyCheckResult {
violations: checker.violations,

View file

@ -164,7 +164,6 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
/// whether that means const mir or runtime mir. For `const fn` this opts for runtime
/// mir.
fn mir_body(tcx: TyCtxt<'_>, def_id: DefId) -> &mir::Body<'_> {
let id = ty::WithOptConstParam::unknown(def_id);
let def = ty::InstanceDef::Item(id);
let def = ty::InstanceDef::Item(def_id);
tcx.instance_mir(def)
}

View file

@ -48,7 +48,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
return false;
}
let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow();
let body = &*tcx.mir_built(local_def_id).borrow();
let body_ty = tcx.type_of(def_id).skip_binder();
let body_abi = match body_ty.kind() {

View file

@ -1399,7 +1399,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
) -> GeneratorLayout<'tcx> {
assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
let (body, _) = tcx.mir_promoted(ty::WithOptConstParam::unknown(def_id));
let (body, _) = tcx.mir_promoted(def_id);
let body = body.borrow();
let body = &*body;

View file

@ -148,8 +148,7 @@ pub(crate) fn mir_inliner_callees<'tcx>(
let guard;
let body = match (instance, instance.def_id().as_local()) {
(InstanceDef::Item(_), Some(def_id)) => {
let def = ty::WithOptConstParam::unknown(def_id);
steal = tcx.mir_promoted(def).0;
steal = tcx.mir_promoted(def_id).0;
guard = steal.borrow();
&*guard
}

View file

@ -23,7 +23,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::steal::Steal;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor as _;
@ -111,36 +111,17 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers {
mir_keys,
mir_const,
mir_const_qualif: |tcx, def_id| {
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.mir_const_qualif_const_arg(def)
} else {
mir_const_qualif(tcx, ty::WithOptConstParam::unknown(def_id))
}
},
mir_const_qualif_const_arg: |tcx, (did, param_did)| {
mir_const_qualif(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
},
mir_const_qualif,
mir_promoted,
mir_drops_elaborated_and_const_checked,
mir_for_ctfe,
mir_for_ctfe_of_const_arg,
mir_generator_witnesses: generator::mir_generator_witnesses,
optimized_mir,
is_mir_available,
is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable,
mir_inliner_callees: inline::cycle::mir_inliner_callees,
promoted_mir: |tcx, def_id| {
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.promoted_mir_of_const_arg(def)
} else {
promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id))
}
},
promoted_mir_of_const_arg: |tcx, (did, param_did)| {
promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
},
promoted_mir,
deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
..*providers
};
@ -234,8 +215,8 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
set
}
fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
let const_kind = tcx.hir().body_const_context(def.did);
fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
let const_kind = tcx.hir().body_const_context(def);
// No need to const-check a non-const `fn`.
if const_kind.is_none() {
@ -253,7 +234,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
return Default::default();
}
let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def.did) };
let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) };
let mut validator = check_consts::check::Checker::new(&ccx);
validator.check_body();
@ -266,22 +247,14 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
/// Make MIR ready for const evaluation. This is run on all MIR, not just on consts!
/// FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
/// We used to have this for pre-miri MIR based const eval.
fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<Body<'_>> {
if let Some(def) = def.try_upgrade(tcx) {
return tcx.mir_const(def);
}
fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
// Unsafety check uses the raw mir, so make sure it is run.
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
if let Some(param_did) = def.const_param_did {
tcx.ensure_with_value().unsafety_check_result_for_const_arg((def.did, param_did));
} else {
tcx.ensure_with_value().unsafety_check_result(def.did);
}
tcx.ensure_with_value().unsafety_check_result(def);
}
// has_ffi_unwind_calls query uses the raw mir, so make sure it is run.
tcx.ensure_with_value().has_ffi_unwind_calls(def.did);
tcx.ensure_with_value().has_ffi_unwind_calls(def);
let mut body = tcx.mir_built(def).steal();
@ -307,16 +280,12 @@ fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<
/// Compute the main MIR body and the list of MIR bodies of the promoteds.
fn mir_promoted(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
def: LocalDefId,
) -> (&Steal<Body<'_>>, &Steal<IndexVec<Promoted, Body<'_>>>) {
if let Some(def) = def.try_upgrade(tcx) {
return tcx.mir_promoted(def);
}
// Ensure that we compute the `mir_const_qualif` for constants at
// this point, before we steal the mir-const result.
// Also this means promotion can rely on all const checks having been done.
let const_qualifs = tcx.mir_const_qualif_opt_const_arg(def);
let const_qualifs = tcx.mir_const_qualif(def);
let mut body = tcx.mir_const(def).steal();
if let Some(error_reported) = const_qualifs.tainted_by_errors {
body.tainted_by_errors = Some(error_reported);
@ -344,38 +313,22 @@ fn mir_promoted(
/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &Body<'_> {
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.mir_for_ctfe_of_const_arg(def)
} else {
tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(def_id)))
}
tcx.arena.alloc(inner_mir_for_ctfe(tcx, def_id))
}
/// Same as `mir_for_ctfe`, but used to get the MIR of a const generic parameter.
/// The docs on `WithOptConstParam` explain this a bit more, but the TLDR is that
/// we'd get cycle errors with `mir_for_ctfe`, because typeck would need to typeck
/// the const parameter while type checking the main body, which in turn would try
/// to type check the main body again.
fn mir_for_ctfe_of_const_arg(tcx: TyCtxt<'_>, (did, param_did): (LocalDefId, DefId)) -> &Body<'_> {
tcx.arena.alloc(inner_mir_for_ctfe(
tcx,
ty::WithOptConstParam { did, const_param_did: Some(param_did) },
))
}
fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
// FIXME: don't duplicate this between the optimized_mir/mir_for_ctfe queries
if tcx.is_constructor(def.did.to_def_id()) {
if tcx.is_constructor(def.to_def_id()) {
// There's no reason to run all of the MIR passes on constructors when
// we can just output the MIR we want directly. This also saves const
// qualification and borrow checking the trouble of special casing
// constructors.
return shim::build_adt_ctor(tcx, def.did.to_def_id());
return shim::build_adt_ctor(tcx, def.to_def_id());
}
let context = tcx
.hir()
.body_const_context(def.did)
.body_const_context(def)
.expect("mir_for_ctfe should not be used for runtime functions");
let body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
@ -413,29 +366,19 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
/// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs
/// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
/// end up missing the source MIR due to stealing happening.
fn mir_drops_elaborated_and_const_checked(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &Steal<Body<'_>> {
if let Some(def) = def.try_upgrade(tcx) {
return tcx.mir_drops_elaborated_and_const_checked(def);
}
fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
if tcx.sess.opts.unstable_opts.drop_tracking_mir
&& let DefKind::Generator = tcx.def_kind(def.did)
&& let DefKind::Generator = tcx.def_kind(def)
{
tcx.ensure_with_value().mir_generator_witnesses(def.did);
tcx.ensure_with_value().mir_generator_witnesses(def);
}
let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
let mir_borrowck = tcx.mir_borrowck(def);
let is_fn_like = tcx.def_kind(def.did).is_fn_like();
let is_fn_like = tcx.def_kind(def).is_fn_like();
if is_fn_like {
let did = def.did.to_def_id();
let def = ty::WithOptConstParam::unknown(did);
// Do not compute the mir call graph without said call graph actually being used.
if inline::Inline.is_enabled(&tcx.sess) {
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def));
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id()));
}
}
@ -588,7 +531,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// Optimize the MIR and prepare it for codegen.
fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None);
tcx.arena.alloc(inner_optimized_mir(tcx, did))
}
@ -610,8 +552,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
}
debug!("about to call mir_drops_elaborated...");
let body =
tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
let body = tcx.mir_drops_elaborated_and_const_checked(did).steal();
let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
debug!("body: {:#?}", body);
run_optimization_passes(tcx, &mut body);
@ -621,15 +562,12 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
/// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for
/// constant evaluation once all substitutions become known.
fn promoted_mir(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &IndexVec<Promoted, Body<'_>> {
if tcx.is_constructor(def.did.to_def_id()) {
fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_>> {
if tcx.is_constructor(def.to_def_id()) {
return tcx.arena.alloc(IndexVec::new());
}
let tainted_by_errors = tcx.mir_borrowck_opt_const_arg(def).tainted_by_errors;
let tainted_by_errors = tcx.mir_borrowck(def).tainted_by_errors;
let mut promoted = tcx.mir_promoted(def).1.steal();
for body in &mut promoted {

View file

@ -267,7 +267,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
match mono_item {
MonoItem::Fn(instance) => {
let def_id = match instance.def {
ty::InstanceDef::Item(def) => def.did,
ty::InstanceDef::Item(def) => def,
ty::InstanceDef::VTableShim(..)
| ty::InstanceDef::ReifyShim(..)
| ty::InstanceDef::FnPtrShim(..)
@ -421,8 +421,7 @@ fn mono_item_visibility<'tcx>(
};
let def_id = match instance.def {
InstanceDef::Item(def) => def.did,
InstanceDef::DropGlue(def_id, Some(_)) => def_id,
InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
// We match the visibility of statics here
InstanceDef::ThreadLocalShim(def_id) => {

View file

@ -232,7 +232,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
/// a closure, generator or constant).
#[instrument(level = "debug", skip(self, def_id, substs))]
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
let instance = ty::InstanceDef::Item(def_id);
let unused = self.tcx.unused_generic_params(instance);
debug!(?self.unused_parameters, ?unused);
for (i, arg) in substs.iter().enumerate() {
@ -272,10 +272,10 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
// Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]`
if let Some(p) = promoted {
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self {
if self.def_id == def && !self.tcx.generics_of(def).has_self {
// If there is a promoted, don't look at the substs - since it will always contain
// the generic parameters, instead, traverse the promoted MIR.
let promoted = self.tcx.promoted_mir(def.did);
let promoted = self.tcx.promoted_mir(def);
self.visit_body(&promoted[p]);
}
}
@ -305,9 +305,9 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
ControlFlow::Continue(())
}
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
{
self.visit_child_body(def.did, substs);
self.visit_child_body(def, substs);
ControlFlow::Continue(())
}
_ => c.super_visit_with(self),

View file

@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_middle::ty::{TyCtxt, WithOptConstParam};
use rustc_middle::ty::TyCtxt;
use rustc_query_system::query::QueryCache;
use std::fmt::Debug;
use std::io::Write;
@ -151,37 +151,6 @@ impl SpecIntoSelfProfilingString for LocalDefId {
}
}
impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
fn spec_to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_>) -> StringId {
// We print `WithOptConstParam` values as tuples to make them shorter
// and more readable, without losing information:
//
// "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
// becomes "(foo::bar, foo::baz)" and
// "WithOptConstParam { did: foo::bar, const_param_did: None }"
// becomes "(foo::bar, _)".
let did = StringComponent::Ref(self.did.to_self_profile_string(builder));
let const_param_did = if let Some(const_param_did) = self.const_param_did {
let const_param_did = builder.def_id_to_string_id(const_param_did);
StringComponent::Ref(const_param_did)
} else {
StringComponent::Value("_")
};
let components = [
StringComponent::Value("("),
did,
StringComponent::Value(", "),
const_param_did,
StringComponent::Value(")"),
];
builder.profiler.alloc_string(&components[..])
}
}
impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
where
T0: SpecIntoSelfProfilingString,

View file

@ -410,10 +410,29 @@ where
// as its feeding query had. So if the fed query is red, so is its feeder, which will
// get evaluated first, and re-feed the query.
if let Some((cached_result, _)) = cache.lookup(&key) {
let Some(hasher) = query.hash_result() else {
panic!(
"fed query later has its value computed. The already cached value: {}",
"no_hash fed query later has its value computed.\n\
Remove `no_hash` modifier to allow recomputation.\n\
The already cached value: {}",
(query.format_value())(&cached_result)
);
};
let (old_hash, new_hash) = qcx.dep_context().with_stable_hashing_context(|mut hcx| {
(hasher(&mut hcx, &cached_result), hasher(&mut hcx, &result))
});
let formatter = query.format_value();
debug_assert_eq!(
old_hash,
new_hash,
"Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
computed={:#?}\nfed={:#?}",
query.dep_kind(),
key,
formatter(&result),
formatter(&cached_result),
);
}
}
job_owner.complete(cache, result, dep_node_index);

View file

@ -198,7 +198,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let identity_substs =
ty::InternalSubsts::identity_for_item(tcx, assoc_def.item.def_id);
let did = ty::WithOptConstParam::unknown(assoc_def.item.def_id);
let did = assoc_def.item.def_id;
let kind =
ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
ty.map_bound(|ty| tcx.mk_const(kind, ty).into())

View file

@ -796,10 +796,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
Ok(Some(valtree)) => Ok(selcx.tcx().mk_const(valtree, c.ty())),
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def.did;
let reported =
tcx.sess.emit_err(UnableToConstructConstantValue {
span: tcx.def_span(def_id),
span: tcx.def_span(unevaluated.def),
unevaluated: unevaluated,
});
Err(ErrorHandled::Reported(reported))

View file

@ -44,7 +44,7 @@ pub fn is_const_evaluatable<'tcx>(
let ct = tcx.expand_abstract_consts(unexpanded_ct);
let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
tcx.def_kind(uv.def.did) == DefKind::AnonConst
tcx.def_kind(uv.def) == DefKind::AnonConst
} else {
false
};
@ -119,7 +119,7 @@ pub fn is_const_evaluatable<'tcx>(
tcx.sess
.struct_span_fatal(
// Slightly better span than just using `span` alone
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def) } else { span },
"failed to evaluate generic const expression",
)
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")

View file

@ -1476,7 +1476,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
};
let mut err =
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(uv.def.did);
let const_span = self.tcx.def_span(uv.def);
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(&format!(
"try adding a `where` bound using this expression: `where [(); {}]:`",
@ -1771,7 +1771,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.tcx
.mk_const(
ty::UnevaluatedConst {
def: ty::WithOptConstParam::unknown(data.projection_ty.def_id),
def: data.projection_ty.def_id,
substs: data.projection_ty.substs,
},
ct.ty(),

View file

@ -540,8 +540,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
use ty::ConstKind::Unevaluated;
match (c1.kind(), c2.kind()) {
(Unevaluated(a), Unevaluated(b))
if a.def.did == b.def.did
&& tcx.def_kind(a.def.did) == DefKind::AssocConst =>
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
{
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)

View file

@ -2131,9 +2131,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let ty = tcx.type_of(assoc_ty.item.def_id);
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let identity_substs =
crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
let did = assoc_ty.item.def_id;
let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, did);
let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
ty.map_bound(|ty| tcx.mk_const(kind, ty).into())
} else {

View file

@ -896,8 +896,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
use ty::ConstKind::Unevaluated;
match (c1.kind(), c2.kind()) {
(Unevaluated(a), Unevaluated(b))
if a.def.did == b.def.did
&& tcx.def_kind(a.def.did) == DefKind::AssocConst =>
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
{
if let Ok(InferOk { obligations, value: () }) = self
.infcx

View file

@ -478,7 +478,7 @@ impl<'tcx> WfPredicates<'tcx> {
match ct.kind() {
ty::ConstKind::Unevaluated(uv) => {
if !ct.has_escaping_bound_vars() {
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
let obligations = self.nominal_obligations(uv.def, uv.substs);
self.out.extend(obligations);
let predicate =

View file

@ -132,7 +132,7 @@ fn recurse_build<'tcx>(
tcx.mk_const(val, node.ty)
}
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
let uneval = ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let uneval = ty::UnevaluatedConst::new(def_id, substs);
tcx.mk_const(uneval, node.ty)
}
ExprKind::ConstParam { param, .. } => tcx.mk_const(*param, node.ty),
@ -391,10 +391,13 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
/// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
pub fn thir_abstract_const(
tcx: TyCtxt<'_>,
def: ty::WithOptConstParam<LocalDefId>,
def: LocalDefId,
) -> Result<Option<ty::Const<'_>>, ErrorGuaranteed> {
if tcx.features().generic_const_exprs {
match tcx.def_kind(def.did) {
if !tcx.features().generic_const_exprs {
return Ok(None);
}
match tcx.def_kind(def) {
// FIXME(generic_const_exprs): We currently only do this for anonymous constants,
// meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
// we want to look into them or treat them as opaque projections.
@ -416,27 +419,8 @@ pub fn thir_abstract_const(
let root_span = body.exprs[body_id].span;
Some(recurse_build(tcx, body, body_id, root_span)).transpose()
} else {
Ok(None)
}
}
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
destructure_const,
thir_abstract_const: |tcx, def_id| {
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
tcx.thir_abstract_const_of_const_arg(def)
} else {
thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
}
},
thir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
thir_abstract_const(
tcx,
ty::WithOptConstParam { did, const_param_did: Some(param_did) },
)
},
..*providers
};
*providers = ty::query::Providers { destructure_const, thir_abstract_const, ..*providers };
}

View file

@ -1,5 +1,5 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::subst::SubstsRef;
@ -13,55 +13,27 @@ use crate::errors::UnexpectedFnPtrAssociatedItem;
fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (did, substs)) = key.into_parts();
if let Some(did) = did.as_local() {
if let Some(param_did) = tcx.opt_const_param_of(did) {
return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs)));
}
}
inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs)))
}
fn resolve_instance_of_const_arg<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (did, const_param_did, substs)) = key.into_parts();
inner_resolve_instance(
tcx,
param_env.and((
ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) },
substs,
)),
)
}
fn inner_resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
let (param_env, (def, substs)) = key.into_parts();
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
let result = if let Some(trait_def_id) = tcx.trait_of_item(def) {
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
resolve_associated_item(
tcx,
def.did,
def,
param_env,
trait_def_id,
tcx.normalize_erasing_regions(param_env, substs),
)
} else {
let ty = tcx.type_of(def.def_id_for_type_of());
let ty = tcx.type_of(def);
let item_type =
tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
let def = match *item_type.kind() {
ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
debug!(" => intrinsic");
ty::InstanceDef::Intrinsic(def.did)
ty::InstanceDef::Intrinsic(def)
}
ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => {
let ty = substs.type_at(0);
@ -206,15 +178,11 @@ fn resolve_associated_item<'tcx>(
Some(ty::Instance::new(leaf_def.item.def_id, substs))
}
traits::ImplSource::Generator(generator_data) => Some(Instance {
def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
generator_data.generator_def_id,
)),
def: ty::InstanceDef::Item(generator_data.generator_def_id),
substs: generator_data.substs,
}),
traits::ImplSource::Future(future_data) => Some(Instance {
def: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(
future_data.generator_def_id,
)),
def: ty::InstanceDef::Item(future_data.generator_def_id),
substs: future_data.substs,
}),
traits::ImplSource::Closure(closure_data) => {
@ -298,6 +266,5 @@ fn resolve_associated_item<'tcx>(
}
pub fn provide(providers: &mut ty::query::Providers) {
*providers =
ty::query::Providers { resolve_instance, resolve_instance_of_const_arg, ..*providers };
*providers = ty::query::Providers { resolve_instance, ..*providers };
}

View file

@ -243,9 +243,9 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => {
let s = if let Some(def) = def.as_local() {
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def))
} else {
inline::print_inlined_const(cx.tcx, def.did)
inline::print_inlined_const(cx.tcx, def)
};
s

View file

@ -196,11 +196,9 @@ fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<
fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
let substs = cx.typeck_results().node_substs(hir_id);
let result = cx.tcx.const_eval_resolve(
cx.param_env,
mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
);
let result = cx
.tcx
.const_eval_resolve(cx.param_env, mir::UnevaluatedConst::new(def_id, substs), None);
is_value_unfrozen_raw(cx, result, ty)
}

View file

@ -450,11 +450,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
let result = self
.lcx
.tcx
.const_eval_resolve(
self.param_env,
mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
)
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
.ok()
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
let result = miri_to_const(self.lcx.tcx, result);

View file

@ -0,0 +1,29 @@
// revisions: rpass1 rpass2 rpass3
// compile-flags: -Zincremental-ignore-spans
#![feature(generic_associated_types)]
// This test unsures that with_opt_const_param returns the
// def_id of the N param in the Foo::Assoc GAT.
trait Foo {
type Assoc<const N: usize>;
fn foo(
&self,
) -> Self::Assoc<{ if cfg!(rpass2) { 3 } else { 2 } }>;
}
impl Foo for () {
type Assoc<const N: usize> = [(); N];
fn foo(
&self,
) -> Self::Assoc<{ if cfg!(rpass2) { 3 } else { 2 } }> {
[(); { if cfg!(rpass2) { 3 } else { 2 } }]
}
}
fn main() {
assert_eq!(
().foo(),
[(); { if cfg!(rpass2) { 3 } else { 2 } }]
);
}

View file

@ -0,0 +1,68 @@
// revisions: rpass1 rpass2 rpass3
// compile-flags: -Zincremental-ignore-spans
enum Foo<const N: usize> {
Variant,
Variant2(),
Variant3 {},
}
impl Foo<1> {
fn foo<const N: usize>(&self) -> [(); N] { [(); N] }
}
impl Foo<2> {
fn foo<const N: u32>(self) -> usize { N as usize }
}
struct Bar<const N: usize>;
struct Bar2<const N: usize>();
struct Bar3<const N: usize> {}
#[cfg(rpass1)]
struct ChangingStruct<const N: usize>;
#[cfg(any(rpass2, rpass3))]
struct ChangingStruct<const N: u32>;
struct S;
impl S {
#[cfg(rpass1)]
fn changing_method<const N: usize>(self) {}
#[cfg(any(rpass2, rpass3))]
fn changing_method<const N: u32>(self) {}
}
// We want to verify that all goes well when the value of the const argument change.
// To avoid modifying `main`'s HIR, we use a separate constant, and use `{ FOO_ARG + 1 }`
// inside the body to keep having an `AnonConst` to compute.
const FOO_ARG: usize = if cfg!(rpass2) { 1 } else { 0 };
fn main() {
let foo = Foo::Variant::<{ FOO_ARG + 1 }>;
foo.foo::<{ if cfg!(rpass3) { 3 } else { 4 } }>();
let foo = Foo::Variant2::<{ FOO_ARG + 1 }>();
foo.foo::<{ if cfg!(rpass3) { 3 } else { 4 } }>();
let foo = Foo::Variant3::<{ FOO_ARG + 1 }> {};
foo.foo::<{ if cfg!(rpass3) { 3 } else { 4 } }>();
let foo = Foo::<{ FOO_ARG + 1 }>::Variant;
foo.foo::<{ if cfg!(rpass3) { 3 } else { 4 } }>();
let foo = Foo::<{ FOO_ARG + 1 }>::Variant2();
foo.foo::<{ if cfg!(rpass3) { 3 } else { 4 } }>();
let foo = Foo::<{ FOO_ARG + 1 }>::Variant3 {};
foo.foo::<{ if cfg!(rpass3) { 3 } else { 4 } }>();
let _ = Bar::<{ FOO_ARG + 1 }>;
let _ = Bar2::<{ FOO_ARG + 1 }>();
let _ = Bar3::<{ FOO_ARG + 1 }> {};
let _ = ChangingStruct::<{ 5 }>;
let _ = S.changing_method::<{ 5 }>();
}

View file

@ -2,7 +2,7 @@
| User Type Annotations
| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[22bb]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), substs: [] }) }], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/issue_99325.rs:+0:15: +0:15

View file

@ -20,13 +20,13 @@ extern crate rustc_session;
use rustc_borrowck::consumers::BodyWithBorrowckFacts;
use rustc_driver::Compilation;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_interface::interface::Compiler;
use rustc_interface::{Config, Queries};
use rustc_middle::ty::query::query_values::mir_borrowck;
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use std::cell::RefCell;
use std::collections::HashMap;
@ -127,10 +127,7 @@ thread_local! {
}
fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> {
let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(
tcx,
ty::WithOptConstParam::unknown(def_id),
);
let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id);
// SAFETY: The reader casts the 'static lifetime to 'tcx before using it.
let body_with_facts: BodyWithBorrowckFacts<'static> =
unsafe { std::mem::transmute(body_with_facts) };

View file

@ -11,15 +11,15 @@
11| 3| self.strength = new_strength;
12| 3| }
------------------
| <generics::Firework<i32>>::set_strength:
| 10| 1| fn set_strength(&mut self, new_strength: T) {
| 11| 1| self.strength = new_strength;
| 12| 1| }
------------------
| <generics::Firework<f64>>::set_strength:
| 10| 2| fn set_strength(&mut self, new_strength: T) {
| 11| 2| self.strength = new_strength;
| 12| 2| }
------------------
| <generics::Firework<i32>>::set_strength:
| 10| 1| fn set_strength(&mut self, new_strength: T) {
| 11| 1| self.strength = new_strength;
| 12| 1| }
------------------
13| |}
14| |

View file

@ -18,7 +18,7 @@ LL | async fn foo(x: u32) -> u32 {
#3 [mir_built] building MIR for `foo`
#4 [unsafety_check_result] unsafety-checking `foo`
#5 [mir_const] preparing `foo` for borrow checking
#6 [mir_promoted] processing MIR for `foo`
#6 [mir_promoted] promoting constants in MIR for `foo`
#7 [mir_borrowck] borrow-checking `foo`
#8 [type_of] computing type of `foo::{opaque#0}`
#9 [check_mod_item_types] checking item types in top-level module

View file

@ -9,7 +9,7 @@ note: ...which requires borrow-checking `cycle1`...
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing MIR for `cycle1`...
note: ...which requires promoting constants in MIR for `cycle1`...
--> $DIR/auto-trait-leak.rs:12:1
|
LL | fn cycle1() -> impl Clone {
@ -55,7 +55,7 @@ note: ...which requires borrow-checking `cycle2`...
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing MIR for `cycle2`...
note: ...which requires promoting constants in MIR for `cycle2`...
--> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {

View file

@ -1,4 +1,4 @@
error: internal compiler error: broken MIR in Item(WithOptConstParam { did: DefId(0:8 ~ storage_live[HASH]::multiple_storage), const_param_did: None }) (before pass CheckPackedRef) at bb0[1]:
error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH]::multiple_storage)) (before pass CheckPackedRef) at bb0[1]:
StorageLive(_1) which already has storage here
--> $DIR/storage-live.rs:22:13
|
@ -9,5 +9,5 @@ error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [mir_const] preparing `multiple_storage` for borrow checking
#1 [mir_promoted] processing MIR for `multiple_storage`
#1 [mir_promoted] promoting constants in MIR for `multiple_storage`
end of query stack

View file

@ -29,7 +29,7 @@ note: ...which requires borrow-checking `Alpha::V3::{constant#0}`...
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing MIR for `Alpha::V3::{constant#0}`...
note: ...which requires promoting constants in MIR for `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,