mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-25 05:14:27 +00:00
Auto merge of #78407 - oli-obk:ub_checkable_ctfe, r=RalfJung,pnkfelix
Make CTFE able to check for UB... ... by not doing any optimizations on the `const fn` MIR used in CTFE. This means we duplicate all `const fn`'s MIR now, once for CTFE, once for runtime. This PR is for checking the perf effect, so we have some data when talking about https://github.com/rust-lang/const-eval/blob/master/rfcs/0000-const-ub.md To do this, we now have two queries for obtaining mir: `optimized_mir` and `mir_for_ctfe`. It is now illegal to invoke `optimized_mir` to obtain the MIR of a const/static item's initializer, an array length, an inline const expression or an enum discriminant initializer. For `const fn`, both `optimized_mir` and `mir_for_ctfe` work, the former returning the MIR that LLVM should use if the function is called at runtime. Similarly it is illegal to invoke `mir_for_ctfe` on regular functions. This is all checked via appropriate assertions and I don't think it is easy to get wrong, as there should be no `mir_for_ctfe` calls outside the const evaluator or metadata encoding. Almost all rustc devs should keep using `optimized_mir` (or `instance_mir` for that matter).
This commit is contained in:
commit
704e47f78b
@ -1160,6 +1160,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ctfe_mir_available(&self, id: DefIndex) -> bool {
|
||||
self.root.tables.mir_for_ctfe.get(self, id).is_some()
|
||||
}
|
||||
|
||||
fn is_item_mir_available(&self, id: DefIndex) -> bool {
|
||||
self.root.tables.mir.get(self, id).is_some()
|
||||
}
|
||||
@ -1183,6 +1187,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
.decode((self, tcx))
|
||||
}
|
||||
|
||||
fn get_mir_for_ctfe(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
|
||||
self.root
|
||||
.tables
|
||||
.mir_for_ctfe
|
||||
.get(self, id)
|
||||
.unwrap_or_else(|| {
|
||||
bug!("get_mir_for_ctfe: missing MIR for `{:?}`", self.local_def_id(id))
|
||||
})
|
||||
.decode((self, tcx))
|
||||
}
|
||||
|
||||
fn get_mir_abstract_const(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -115,6 +115,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
})
|
||||
}
|
||||
optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
|
||||
mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) }
|
||||
promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
|
||||
mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
|
||||
unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
|
||||
@ -145,6 +146,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
impl_parent => { cdata.get_parent_impl(def_id.index) }
|
||||
trait_of_item => { cdata.get_trait_of_item(def_id.index) }
|
||||
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
|
||||
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
|
||||
|
||||
dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
|
||||
is_panic_runtime => { cdata.root.panic_runtime }
|
||||
|
@ -758,8 +758,6 @@ impl EncodeContext<'a, 'tcx> {
|
||||
self.encode_generics(def_id);
|
||||
self.encode_explicit_predicates(def_id);
|
||||
self.encode_inferred_outlives(def_id);
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
|
||||
fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) {
|
||||
@ -789,6 +787,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
self.encode_generics(def_id);
|
||||
self.encode_explicit_predicates(def_id);
|
||||
self.encode_inferred_outlives(def_id);
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
@ -897,6 +896,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
self.encode_explicit_predicates(def_id);
|
||||
self.encode_inferred_outlives(def_id);
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
|
||||
@ -1015,8 +1015,21 @@ impl EncodeContext<'a, 'tcx> {
|
||||
self.encode_inferred_outlives(def_id);
|
||||
|
||||
// This should be kept in sync with `PrefetchVisitor.visit_trait_item`.
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
match trait_item.kind {
|
||||
ty::AssocKind::Type => {}
|
||||
ty::AssocKind::Const => {
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata_output_only(&self) -> bool {
|
||||
@ -1089,8 +1102,8 @@ impl EncodeContext<'a, 'tcx> {
|
||||
|
||||
// The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`.
|
||||
|
||||
let mir = match ast_item.kind {
|
||||
hir::ImplItemKind::Const(..) => true,
|
||||
let (mir, mir_const) = match ast_item.kind {
|
||||
hir::ImplItemKind::Const(..) => (false, true),
|
||||
hir::ImplItemKind::Fn(ref sig, _) => {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let needs_inline = (generics.requires_monomorphization(self.tcx)
|
||||
@ -1098,14 +1111,19 @@ impl EncodeContext<'a, 'tcx> {
|
||||
&& !self.metadata_output_only();
|
||||
let is_const_fn = sig.header.constness == hir::Constness::Const;
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
needs_inline || is_const_fn || always_encode_mir
|
||||
(needs_inline || always_encode_mir, is_const_fn)
|
||||
}
|
||||
hir::ImplItemKind::TyAlias(..) => false,
|
||||
hir::ImplItemKind::TyAlias(..) => (false, false),
|
||||
};
|
||||
if mir {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
}
|
||||
if mir || mir_const {
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
if mir_const {
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> {
|
||||
@ -1116,28 +1134,34 @@ impl EncodeContext<'a, 'tcx> {
|
||||
self.lazy(param_names.iter())
|
||||
}
|
||||
|
||||
fn encode_mir_for_ctfe(&mut self, def_id: LocalDefId) {
|
||||
debug!("EntryBuilder::encode_mir_for_ctfe({:?})", def_id);
|
||||
record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
|
||||
|
||||
let unused = self.tcx.unused_generic_params(def_id);
|
||||
if !unused.is_empty() {
|
||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
||||
}
|
||||
|
||||
let abstract_const = self.tcx.mir_abstract_const(def_id);
|
||||
if let Ok(Some(abstract_const)) = abstract_const {
|
||||
record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
|
||||
debug!("EntryBuilder::encode_mir({:?})", def_id);
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
|
||||
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
|
||||
debug!("EntryBuilder::encode_optimized_mir({:?})", def_id);
|
||||
record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
|
||||
|
||||
let unused = self.tcx.unused_generic_params(def_id);
|
||||
if !unused.is_empty() {
|
||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
||||
}
|
||||
|
||||
let abstract_const = self.tcx.mir_abstract_const(def_id);
|
||||
if let Ok(Some(abstract_const)) = abstract_const {
|
||||
record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
|
||||
}
|
||||
let unused = self.tcx.unused_generic_params(def_id);
|
||||
if !unused.is_empty() {
|
||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_promoted_mir(&mut self, def_id: LocalDefId) {
|
||||
debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
|
||||
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
|
||||
}
|
||||
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
|
||||
}
|
||||
|
||||
// Encodes the inherent implementations of a structure, enumeration, or trait.
|
||||
@ -1406,22 +1430,31 @@ impl EncodeContext<'a, 'tcx> {
|
||||
|
||||
// The following part should be kept in sync with `PrefetchVisitor.visit_item`.
|
||||
|
||||
let mir = match item.kind {
|
||||
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true,
|
||||
let (mir, const_mir) = match item.kind {
|
||||
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true),
|
||||
hir::ItemKind::Fn(ref sig, ..) => {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let needs_inline = (generics.requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id).requests_inline())
|
||||
&& !self.metadata_output_only();
|
||||
|
||||
let is_const_fn = sig.header.constness == hir::Constness::Const;
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
needs_inline || sig.header.constness == hir::Constness::Const || always_encode_mir
|
||||
let mir = needs_inline || always_encode_mir;
|
||||
// We don't need the optimized MIR for const fns.
|
||||
(mir, is_const_fn)
|
||||
}
|
||||
_ => false,
|
||||
_ => (false, false),
|
||||
};
|
||||
if mir {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
}
|
||||
if mir || const_mir {
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
if const_mir {
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize the text of exported macros
|
||||
@ -1486,7 +1519,7 @@ impl EncodeContext<'a, 'tcx> {
|
||||
self.encode_generics(def_id.to_def_id());
|
||||
self.encode_explicit_predicates(def_id.to_def_id());
|
||||
self.encode_inferred_outlives(def_id.to_def_id());
|
||||
self.encode_optimized_mir(def_id);
|
||||
self.encode_mir_for_ctfe(def_id);
|
||||
self.encode_promoted_mir(def_id);
|
||||
}
|
||||
|
||||
@ -1951,6 +1984,12 @@ struct PrefetchVisitor<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> PrefetchVisitor<'tcx> {
|
||||
fn prefetch_ctfe_mir(&self, def_id: LocalDefId) {
|
||||
if self.mir_keys.contains(&def_id) {
|
||||
self.tcx.ensure().mir_for_ctfe(def_id);
|
||||
self.tcx.ensure().promoted_mir(def_id);
|
||||
}
|
||||
}
|
||||
fn prefetch_mir(&self, def_id: LocalDefId) {
|
||||
if self.mir_keys.contains(&def_id) {
|
||||
self.tcx.ensure().optimized_mir(def_id);
|
||||
@ -1965,16 +2004,19 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
match item.kind {
|
||||
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
|
||||
self.prefetch_mir(tcx.hir().local_def_id(item.hir_id))
|
||||
self.prefetch_ctfe_mir(tcx.hir().local_def_id(item.hir_id))
|
||||
}
|
||||
hir::ItemKind::Fn(ref sig, ..) => {
|
||||
let def_id = tcx.hir().local_def_id(item.hir_id);
|
||||
let generics = tcx.generics_of(def_id.to_def_id());
|
||||
let needs_inline = generics.requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
|
||||
if needs_inline || sig.header.constness == hir::Constness::Const {
|
||||
if needs_inline {
|
||||
self.prefetch_mir(def_id)
|
||||
}
|
||||
if sig.header.constness == hir::Constness::Const {
|
||||
self.prefetch_ctfe_mir(def_id);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@ -1982,7 +2024,16 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
|
||||
|
||||
fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) {
|
||||
// This should be kept in sync with `encode_info_for_trait_item`.
|
||||
self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id));
|
||||
let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
|
||||
match trait_item.kind {
|
||||
hir::TraitItemKind::Type(..) => {}
|
||||
hir::TraitItemKind::Const(..) => {
|
||||
self.prefetch_ctfe_mir(def_id);
|
||||
}
|
||||
hir::TraitItemKind::Fn(..) => {
|
||||
self.prefetch_mir(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
|
||||
@ -1990,7 +2041,7 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => {
|
||||
self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id))
|
||||
self.prefetch_ctfe_mir(tcx.hir().local_def_id(impl_item.hir_id))
|
||||
}
|
||||
hir::ImplItemKind::Fn(ref sig, _) => {
|
||||
let def_id = tcx.hir().local_def_id(impl_item.hir_id);
|
||||
@ -1998,9 +2049,12 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
|
||||
let needs_inline = generics.requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
|
||||
let is_const_fn = sig.header.constness == hir::Constness::Const;
|
||||
if needs_inline || is_const_fn {
|
||||
if needs_inline {
|
||||
self.prefetch_mir(def_id)
|
||||
}
|
||||
if is_const_fn {
|
||||
self.prefetch_ctfe_mir(def_id);
|
||||
}
|
||||
}
|
||||
hir::ImplItemKind::TyAlias(..) => (),
|
||||
}
|
||||
|
@ -302,6 +302,7 @@ define_tables! {
|
||||
// As an optimization, a missing entry indicates an empty `&[]`.
|
||||
explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
|
||||
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
|
||||
mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
|
||||
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
|
||||
mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
|
||||
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
|
||||
|
@ -439,17 +439,26 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn optimized_mir_opt_const_arg(
|
||||
pub fn optimized_mir_or_const_arg_mir(
|
||||
self,
|
||||
def: ty::WithOptConstParam<DefId>,
|
||||
) -> &'tcx Body<'tcx> {
|
||||
if let Some((did, param_did)) = def.as_const_arg() {
|
||||
self.optimized_mir_of_const_arg((did, param_did))
|
||||
self.mir_for_ctfe_of_const_arg((did, param_did))
|
||||
} else {
|
||||
self.optimized_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)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mir_abstract_const_opt_const_arg(
|
||||
self,
|
||||
|
@ -312,6 +312,20 @@ rustc_queries! {
|
||||
desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) }
|
||||
}
|
||||
|
||||
query mir_for_ctfe(
|
||||
key: DefId
|
||||
) -> &'tcx mir::Body<'tcx> {
|
||||
desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
|
||||
desc {
|
||||
|tcx| "MIR for CTFE of the const argument `{}`",
|
||||
tcx.def_path_str(key.0.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
query mir_promoted(key: ty::WithOptConstParam<LocalDefId>) ->
|
||||
(
|
||||
&'tcx Steal<mir::Body<'tcx>>,
|
||||
@ -331,12 +345,6 @@ rustc_queries! {
|
||||
desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) }
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
query optimized_mir_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
|
||||
desc {
|
||||
|tcx| "optimizing MIR for the const argument `{}`",
|
||||
tcx.def_path_str(key.0.to_def_id())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
|
||||
/// MIR pass (assuming the -Zinstrument-coverage option is enabled).
|
||||
@ -927,6 +935,9 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
Codegen {
|
||||
query is_ctfe_mir_available(key: DefId) -> bool {
|
||||
desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
query is_mir_available(key: DefId) -> bool {
|
||||
desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
@ -3010,7 +3010,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
|
||||
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
||||
match instance {
|
||||
ty::InstanceDef::Item(def) => self.optimized_mir_opt_const_arg(def),
|
||||
ty::InstanceDef::Item(def) => match self.def_kind(def.did) {
|
||||
DefKind::Const
|
||||
| DefKind::Static
|
||||
| DefKind::AssocConst
|
||||
| DefKind::Ctor(..)
|
||||
| DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(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.
|
||||
_ => self.optimized_mir_or_const_arg_mir(def),
|
||||
},
|
||||
ty::InstanceDef::VtableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::Intrinsic(..)
|
||||
|
@ -201,6 +201,22 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
|
||||
type MemoryExtra = MemoryExtra;
|
||||
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
) -> 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 {
|
||||
throw_unsup!(NoMirFor(def.did))
|
||||
}
|
||||
}
|
||||
_ => Ok(ecx.tcx.instance_mir(instance)),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
|
@ -477,16 +477,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
if let Some(promoted) = promoted {
|
||||
return Ok(&self.tcx.promoted_mir_opt_const_arg(def)[promoted]);
|
||||
}
|
||||
match instance {
|
||||
ty::InstanceDef::Item(def) => {
|
||||
if self.tcx.is_mir_available(def.did) {
|
||||
Ok(self.tcx.optimized_mir_opt_const_arg(def))
|
||||
} else {
|
||||
throw_unsup!(NoMirFor(def.did))
|
||||
}
|
||||
}
|
||||
_ => Ok(self.tcx.instance_mir(instance)),
|
||||
}
|
||||
M::load_mir(self, instance)
|
||||
}
|
||||
|
||||
/// Call this on things you got out of the MIR (so it is as generic as the current
|
||||
|
@ -132,6 +132,16 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
/// Whether to enforce the validity invariant
|
||||
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
|
||||
/// Entry point for obtaining the MIR of anything that should get evaluated.
|
||||
/// So not just functions and shims, but also const/static initializers, anonymous
|
||||
/// constants, ...
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> {
|
||||
Ok(ecx.tcx.instance_mir(instance))
|
||||
}
|
||||
|
||||
/// Entry point to all function calls.
|
||||
///
|
||||
/// Returns either the mir to use for the call, or `None` if execution should
|
||||
|
@ -5,7 +5,7 @@
|
||||
//! generic parameters are unused (and eventually, in what ways generic parameters are used - only
|
||||
//! for their size, offset of a field, etc.).
|
||||
|
||||
use rustc_hir::{def::DefKind, def_id::DefId};
|
||||
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
|
||||
use rustc_index::bit_set::FiniteBitSet;
|
||||
use rustc_middle::mir::{
|
||||
visit::{TyContext, Visitor},
|
||||
@ -54,9 +54,17 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
}
|
||||
|
||||
// Exit early when there is no MIR available.
|
||||
if !tcx.is_mir_available(def_id) {
|
||||
debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
|
||||
return FiniteBitSet::new_empty();
|
||||
let context = tcx.hir().body_const_context(def_id.expect_local());
|
||||
match context {
|
||||
Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
|
||||
debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
|
||||
return FiniteBitSet::new_empty();
|
||||
}
|
||||
Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
|
||||
debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id);
|
||||
return FiniteBitSet::new_empty();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Create a bitset with N rightmost ones for each parameter.
|
||||
@ -69,7 +77,12 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);
|
||||
|
||||
// Visit MIR and accumululate used generic parameters.
|
||||
let body = tcx.optimized_mir(def_id);
|
||||
let body = match context {
|
||||
// Const functions are actually called and should thus be considered for polymorphization
|
||||
// via their runtime MIR
|
||||
Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id),
|
||||
Some(_) => tcx.mir_for_ctfe(def_id),
|
||||
};
|
||||
let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
|
||||
vis.visit_body(body);
|
||||
debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
|
||||
|
@ -185,6 +185,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
||||
|
||||
type MemoryExtra = ();
|
||||
|
||||
fn load_mir(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_instance: ty::InstanceDef<'tcx>,
|
||||
) -> InterpResult<'tcx, &'tcx Body<'tcx>> {
|
||||
throw_machine_stop_str!("calling functions isn't supported in ConstProp")
|
||||
}
|
||||
|
||||
fn find_mir_or_eval_fn(
|
||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
_instance: ty::Instance<'tcx>,
|
||||
|
@ -4,7 +4,7 @@ use rustc_middle::mir::coverage::*;
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{self, Coverage, CoverageInfo, Location};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
/// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each
|
||||
@ -112,7 +112,7 @@ impl Visitor<'_> for CoverageVisitor {
|
||||
}
|
||||
|
||||
fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo {
|
||||
let mir_body = tcx.optimized_mir(def_id);
|
||||
let mir_body = mir_body(tcx, def_id);
|
||||
|
||||
let mut coverage_visitor = CoverageVisitor {
|
||||
// num_counters always has at least the `ZERO` counter.
|
||||
@ -129,8 +129,7 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo
|
||||
}
|
||||
|
||||
fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> {
|
||||
let mir_body = tcx.optimized_mir(def_id);
|
||||
for bb_data in mir_body.basic_blocks().iter() {
|
||||
for bb_data in mir_body(tcx, def_id).basic_blocks().iter() {
|
||||
for statement in bb_data.statements.iter() {
|
||||
if let StatementKind::Coverage(box ref coverage) = statement.kind {
|
||||
if let Some(code_region) = coverage.code_region.as_ref() {
|
||||
@ -142,9 +141,17 @@ fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> {
|
||||
None
|
||||
}
|
||||
|
||||
/// This function ensures we obtain the correct MIR for the given item irrespective of
|
||||
/// whether that means const mir or runtime mir. For `const fn` this opts for runtime
|
||||
/// mir.
|
||||
fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> {
|
||||
let id = ty::WithOptConstParam::unknown(def_id);
|
||||
let def = ty::InstanceDef::Item(id);
|
||||
tcx.instance_mir(def)
|
||||
}
|
||||
|
||||
fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> {
|
||||
let mir_body: &'tcx mir::Body<'tcx> = tcx.optimized_mir(def_id);
|
||||
mir_body
|
||||
mir_body(tcx, def_id)
|
||||
.basic_blocks()
|
||||
.iter()
|
||||
.map(|data| {
|
||||
|
@ -71,9 +71,11 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||
},
|
||||
mir_promoted,
|
||||
mir_drops_elaborated_and_const_checked,
|
||||
mir_for_ctfe,
|
||||
mir_for_ctfe_of_const_arg,
|
||||
optimized_mir,
|
||||
optimized_mir_of_const_arg,
|
||||
is_mir_available,
|
||||
is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
|
||||
promoted_mir: |tcx, def_id| {
|
||||
let def_id = def_id.expect_local();
|
||||
if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
|
||||
@ -278,6 +280,7 @@ fn mir_const<'tcx>(
|
||||
tcx.alloc_steal_mir(body)
|
||||
}
|
||||
|
||||
/// Compute the main MIR body and the list of MIR bodies of the promoteds.
|
||||
fn mir_promoted(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def: ty::WithOptConstParam<LocalDefId>,
|
||||
@ -319,6 +322,87 @@ fn mir_promoted(
|
||||
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
|
||||
}
|
||||
|
||||
/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
|
||||
fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
|
||||
let did = def_id.expect_local();
|
||||
if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
|
||||
tcx.mir_for_ctfe_of_const_arg(def)
|
||||
} else {
|
||||
tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(did)))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
(did, param_did): (LocalDefId, DefId),
|
||||
) -> &'tcx Body<'tcx> {
|
||||
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<'_> {
|
||||
// FIXME: don't duplicate this between the optimized_mir/mir_for_ctfe queries
|
||||
if tcx.is_constructor(def.did.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());
|
||||
}
|
||||
|
||||
let context = tcx
|
||||
.hir()
|
||||
.body_const_context(def.did)
|
||||
.expect("mir_for_ctfe should not be used for runtime functions");
|
||||
|
||||
let mut body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
|
||||
|
||||
match context {
|
||||
// Do not const prop functions, either they get executed at runtime or exported to metadata,
|
||||
// so we run const prop on them, or they don't, in which case we const evaluate some control
|
||||
// flow paths of the function and any errors in those paths will get emitted as const eval
|
||||
// errors.
|
||||
hir::ConstContext::ConstFn => {}
|
||||
// Static items always get evaluated, so we can just let const eval see if any erroneous
|
||||
// control flow paths get executed.
|
||||
hir::ConstContext::Static(_) => {}
|
||||
// Associated constants get const prop run so we detect common failure situations in the
|
||||
// crate that defined the constant.
|
||||
// Technically we want to not run on regular const items, but oli-obk doesn't know how to
|
||||
// conveniently detect that at this point without looking at the HIR.
|
||||
hir::ConstContext::Const => {
|
||||
#[rustfmt::skip]
|
||||
let optimizations: &[&dyn MirPass<'_>] = &[
|
||||
&const_prop::ConstProp,
|
||||
];
|
||||
|
||||
#[rustfmt::skip]
|
||||
run_passes(
|
||||
tcx,
|
||||
&mut body,
|
||||
MirPhase::Optimization,
|
||||
&[
|
||||
optimizations,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
|
||||
|
||||
body
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def: ty::WithOptConstParam<LocalDefId>,
|
||||
@ -456,35 +540,32 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
);
|
||||
}
|
||||
|
||||
/// Optimize the MIR and prepare it for codegen.
|
||||
fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {
|
||||
let did = did.expect_local();
|
||||
if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
|
||||
tcx.optimized_mir_of_const_arg(def)
|
||||
} else {
|
||||
tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did)))
|
||||
}
|
||||
assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None);
|
||||
tcx.arena.alloc(inner_optimized_mir(tcx, did))
|
||||
}
|
||||
|
||||
fn optimized_mir_of_const_arg<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
(did, param_did): (LocalDefId, DefId),
|
||||
) -> &'tcx Body<'tcx> {
|
||||
tcx.arena.alloc(inner_optimized_mir(
|
||||
tcx,
|
||||
ty::WithOptConstParam { did, const_param_did: Some(param_did) },
|
||||
))
|
||||
}
|
||||
|
||||
fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
|
||||
if tcx.is_constructor(def.did.to_def_id()) {
|
||||
fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
|
||||
if tcx.is_constructor(did.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, did.to_def_id());
|
||||
}
|
||||
|
||||
let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
|
||||
match tcx.hir().body_const_context(did) {
|
||||
// Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked`
|
||||
// which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it
|
||||
// computes and caches its result.
|
||||
Some(hir::ConstContext::ConstFn) => tcx.ensure().mir_for_ctfe(did),
|
||||
None => {}
|
||||
Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
|
||||
}
|
||||
let mut body =
|
||||
tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
|
||||
run_optimization_passes(tcx, &mut body);
|
||||
|
||||
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
|
||||
@ -492,6 +573,8 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<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>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def: ty::WithOptConstParam<LocalDefId>,
|
||||
@ -510,7 +593,6 @@ fn promoted_mir<'tcx>(
|
||||
|
||||
for body in &mut promoted {
|
||||
run_post_borrowck_cleanup_passes(tcx, body);
|
||||
run_optimization_passes(tcx, body);
|
||||
}
|
||||
|
||||
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
|
||||
|
@ -273,8 +273,6 @@ pub fn write_mir_pretty<'tcx>(
|
||||
|
||||
let mut first = true;
|
||||
for def_id in dump_mir_def_ids(tcx, single) {
|
||||
let body = &tcx.optimized_mir(def_id);
|
||||
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
@ -282,11 +280,28 @@ pub fn write_mir_pretty<'tcx>(
|
||||
writeln!(w)?;
|
||||
}
|
||||
|
||||
write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
|
||||
|
||||
for body in tcx.promoted_mir(def_id) {
|
||||
writeln!(w)?;
|
||||
let render_body = |w: &mut dyn Write, body| -> io::Result<()> {
|
||||
write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
|
||||
|
||||
for body in tcx.promoted_mir(def_id) {
|
||||
writeln!(w)?;
|
||||
write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?;
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
match tcx.hir().body_const_context(def_id.expect_local()) {
|
||||
None => render_body(w, tcx.optimized_mir(def_id))?,
|
||||
// For `const fn` we want to render the optimized MIR. If you want the mir used in
|
||||
// ctfe, you can dump the MIR after the `Deaggregator` optimization pass.
|
||||
Some(rustc_hir::ConstContext::ConstFn) => {
|
||||
render_body(w, tcx.optimized_mir(def_id))?;
|
||||
writeln!(w)?;
|
||||
writeln!(w, "// MIR FOR CTFE")?;
|
||||
// Do not use `render_body`, as that would render the promoteds again, but these
|
||||
// are shared between mir_for_ctfe and optimized_mir
|
||||
write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?;
|
||||
}
|
||||
Some(_) => render_body(w, tcx.mir_for_ctfe(def_id))?,
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -152,7 +152,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
if concrete.is_ok() && substs.has_param_types_or_consts() {
|
||||
match infcx.tcx.def_kind(def.did) {
|
||||
DefKind::AnonConst => {
|
||||
let mir_body = infcx.tcx.optimized_mir_opt_const_arg(def);
|
||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
|
||||
|
||||
if mir_body.is_polymorphic {
|
||||
future_compat_lint();
|
||||
|
@ -5,11 +5,11 @@ extern "C" {
|
||||
static Y: i32 = 42;
|
||||
|
||||
// EMIT_MIR const_promotion_extern_static.BAR.PromoteTemps.diff
|
||||
// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir
|
||||
// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir
|
||||
static mut BAR: *const &i32 = [&Y].as_ptr();
|
||||
|
||||
// EMIT_MIR const_promotion_extern_static.FOO.PromoteTemps.diff
|
||||
// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir
|
||||
// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
|
||||
static mut FOO: *const &i32 = [unsafe { &X }].as_ptr();
|
||||
|
||||
// EMIT_MIR const_promotion_extern_static.BOP.mir_map.0.mir
|
||||
|
@ -24,42 +24,42 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 8, align: 4) {
|
||||
╾─alloc14─╼ 03 00 00 00 │ ╾──╼....
|
||||
╾─alloc17─╼ 03 00 00 00 │ ╾──╼....
|
||||
}
|
||||
|
||||
alloc14 (size: 48, align: 4) {
|
||||
alloc17 (size: 48, align: 4) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼....
|
||||
0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc7──╼ 02 00 00 00 │ ....░░░░╾──╼....
|
||||
0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ....*...╾──╼....
|
||||
0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
|
||||
0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
|
||||
}
|
||||
|
||||
alloc4 (size: 0, align: 4) {}
|
||||
|
||||
alloc7 (size: 16, align: 4) {
|
||||
╾─alloc6──╼ 03 00 00 00 ╾─alloc8──╼ 03 00 00 00 │ ╾──╼....╾──╼....
|
||||
alloc8 (size: 16, align: 4) {
|
||||
╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼....
|
||||
}
|
||||
|
||||
alloc6 (size: 3, align: 1) {
|
||||
alloc7 (size: 3, align: 1) {
|
||||
66 6f 6f │ foo
|
||||
}
|
||||
|
||||
alloc8 (size: 3, align: 1) {
|
||||
alloc9 (size: 3, align: 1) {
|
||||
62 61 72 │ bar
|
||||
}
|
||||
|
||||
alloc11 (size: 24, align: 4) {
|
||||
0x00 │ ╾─alloc10─╼ 03 00 00 00 ╾─alloc12─╼ 03 00 00 00 │ ╾──╼....╾──╼....
|
||||
0x10 │ ╾─alloc13─╼ 04 00 00 00 │ ╾──╼....
|
||||
}
|
||||
|
||||
alloc10 (size: 3, align: 1) {
|
||||
6d 65 68 │ meh
|
||||
alloc13 (size: 24, align: 4) {
|
||||
0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼....
|
||||
0x10 │ ╾─alloc15─╼ 04 00 00 00 │ ╾──╼....
|
||||
}
|
||||
|
||||
alloc12 (size: 3, align: 1) {
|
||||
6d 65 68 │ meh
|
||||
}
|
||||
|
||||
alloc14 (size: 3, align: 1) {
|
||||
6d 6f 70 │ mop
|
||||
}
|
||||
|
||||
alloc13 (size: 4, align: 1) {
|
||||
alloc15 (size: 4, align: 1) {
|
||||
6d c3 b6 70 │ m..p
|
||||
}
|
||||
|
@ -24,46 +24,46 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 16, align: 8) {
|
||||
╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
||||
alloc14 (size: 72, align: 8) {
|
||||
alloc17 (size: 72, align: 8) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
|
||||
0x20 │ ╾───────alloc7────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc11───────╼ │ ....*...╾──────╼
|
||||
0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
|
||||
0x40 │ 03 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
alloc4 (size: 0, align: 8) {}
|
||||
|
||||
alloc7 (size: 32, align: 8) {
|
||||
0x00 │ ╾───────alloc6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x10 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
alloc8 (size: 32, align: 8) {
|
||||
0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
||||
alloc6 (size: 3, align: 1) {
|
||||
alloc7 (size: 3, align: 1) {
|
||||
66 6f 6f │ foo
|
||||
}
|
||||
|
||||
alloc8 (size: 3, align: 1) {
|
||||
alloc9 (size: 3, align: 1) {
|
||||
62 61 72 │ bar
|
||||
}
|
||||
|
||||
alloc11 (size: 48, align: 8) {
|
||||
0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x10 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x20 │ ╾───────alloc13───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
||||
alloc10 (size: 3, align: 1) {
|
||||
6d 65 68 │ meh
|
||||
alloc13 (size: 48, align: 8) {
|
||||
0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
||||
alloc12 (size: 3, align: 1) {
|
||||
6d 65 68 │ meh
|
||||
}
|
||||
|
||||
alloc14 (size: 3, align: 1) {
|
||||
6d 6f 70 │ mop
|
||||
}
|
||||
|
||||
alloc13 (size: 4, align: 1) {
|
||||
alloc15 (size: 4, align: 1) {
|
||||
6d c3 b6 70 │ m..p
|
||||
}
|
||||
|
@ -24,41 +24,41 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 8, align: 4) {
|
||||
╾─alloc20─╼ 03 00 00 00 │ ╾──╼....
|
||||
╾─alloc27─╼ 03 00 00 00 │ ╾──╼....
|
||||
}
|
||||
|
||||
alloc20 (size: 48, align: 4) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼....
|
||||
0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 02 00 00 00 │ ....░░░░╾──╼....
|
||||
0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼....
|
||||
alloc27 (size: 48, align: 4) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 00 00 00 00 │ ....░░░░╾──╼....
|
||||
0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc17─╼ 02 00 00 00 │ ....░░░░╾──╼....
|
||||
0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc25─╼ 03 00 00 00 │ ....*...╾──╼....
|
||||
}
|
||||
|
||||
alloc8 (size: 0, align: 4) {}
|
||||
alloc12 (size: 0, align: 4) {}
|
||||
|
||||
alloc12 (size: 8, align: 4) {
|
||||
╾─alloc10─╼ ╾─alloc11─╼ │ ╾──╼╾──╼
|
||||
alloc17 (size: 8, align: 4) {
|
||||
╾─alloc15─╼ ╾─alloc16─╼ │ ╾──╼╾──╼
|
||||
}
|
||||
|
||||
alloc10 (size: 1, align: 1) {
|
||||
alloc15 (size: 1, align: 1) {
|
||||
05 │ .
|
||||
}
|
||||
|
||||
alloc11 (size: 1, align: 1) {
|
||||
alloc16 (size: 1, align: 1) {
|
||||
06 │ .
|
||||
}
|
||||
|
||||
alloc19 (size: 12, align: 4) {
|
||||
╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼ │ ╾──╼╾──╼╾──╼
|
||||
alloc25 (size: 12, align: 4) {
|
||||
╾─a21+0x3─╼ ╾─alloc22─╼ ╾─a24+0x2─╼ │ ╾──╼╾──╼╾──╼
|
||||
}
|
||||
|
||||
alloc15 (size: 4, align: 1) {
|
||||
alloc21 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
||||
alloc16 (size: 1, align: 1) {
|
||||
alloc22 (size: 1, align: 1) {
|
||||
2a │ *
|
||||
}
|
||||
|
||||
alloc18 (size: 4, align: 1) {
|
||||
alloc24 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
@ -24,44 +24,44 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 16, align: 8) {
|
||||
╾───────alloc20───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
╾───────alloc27───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
||||
alloc20 (size: 72, align: 8) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼
|
||||
alloc27 (size: 72, align: 8) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc12───────╼ │ ....░░░░╾──────╼
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
|
||||
0x20 │ ╾───────alloc12───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼
|
||||
0x20 │ ╾───────alloc17───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc25───────╼ │ ....*...╾──────╼
|
||||
0x40 │ 03 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
alloc8 (size: 0, align: 8) {}
|
||||
alloc12 (size: 0, align: 8) {}
|
||||
|
||||
alloc12 (size: 16, align: 8) {
|
||||
╾───────alloc10───────╼ ╾───────alloc11───────╼ │ ╾──────╼╾──────╼
|
||||
alloc17 (size: 16, align: 8) {
|
||||
╾───────alloc15───────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
|
||||
}
|
||||
|
||||
alloc10 (size: 1, align: 1) {
|
||||
alloc15 (size: 1, align: 1) {
|
||||
05 │ .
|
||||
}
|
||||
|
||||
alloc11 (size: 1, align: 1) {
|
||||
alloc16 (size: 1, align: 1) {
|
||||
06 │ .
|
||||
}
|
||||
|
||||
alloc19 (size: 24, align: 8) {
|
||||
0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
|
||||
0x10 │ ╾─────alloc18+0x2─────╼ │ ╾──────╼
|
||||
alloc25 (size: 24, align: 8) {
|
||||
0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc22───────╼ │ ╾──────╼╾──────╼
|
||||
0x10 │ ╾─────alloc24+0x2─────╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
alloc15 (size: 4, align: 1) {
|
||||
alloc21 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
||||
alloc16 (size: 1, align: 1) {
|
||||
alloc22 (size: 1, align: 1) {
|
||||
2a │ *
|
||||
}
|
||||
|
||||
alloc18 (size: 4, align: 1) {
|
||||
alloc24 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
@ -24,30 +24,30 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 4, align: 4) {
|
||||
╾─alloc9──╼ │ ╾──╼
|
||||
╾─alloc10─╼ │ ╾──╼
|
||||
}
|
||||
|
||||
alloc9 (size: 168, align: 1) {
|
||||
alloc10 (size: 168, align: 1) {
|
||||
0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5──╼ │ ............╾──╼
|
||||
0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc6──╼ 00 00 │ ..........╾──╼..
|
||||
0x90 │ ╾─a7+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
|
||||
0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc7──╼ 00 00 │ ..........╾──╼..
|
||||
0x90 │ ╾─a8+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
|
||||
0xa0 │ 00 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
alloc4 (size: 4, align: 4) {
|
||||
alloc5 (size: 4, align: 4) {
|
||||
2a 00 00 00 │ *...
|
||||
}
|
||||
|
||||
alloc6 (fn: main)
|
||||
alloc7 (fn: main)
|
||||
|
||||
alloc7 (size: 100, align: 1) {
|
||||
alloc8 (size: 100, align: 1) {
|
||||
0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
|
@ -24,12 +24,12 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 8, align: 8) {
|
||||
╾───────alloc9────────╼ │ ╾──────╼
|
||||
╾───────alloc10───────╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
alloc9 (size: 180, align: 1) {
|
||||
alloc10 (size: 180, align: 1) {
|
||||
0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾───
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc5── │ ............╾───
|
||||
0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............
|
||||
0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
@ -37,18 +37,18 @@ alloc9 (size: 180, align: 1) {
|
||||
0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─
|
||||
0x90 │ ─────alloc6─────╼ 00 00 ╾─────alloc7+0x63─────╼ │ ─────╼..╾──────╼
|
||||
0x90 │ ─────alloc7─────╼ 00 00 ╾─────alloc8+0x63─────╼ │ ─────╼..╾──────╼
|
||||
0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0xb0 │ 00 00 00 00 │ ....
|
||||
}
|
||||
|
||||
alloc4 (size: 4, align: 4) {
|
||||
alloc5 (size: 4, align: 4) {
|
||||
2a 00 00 00 │ *...
|
||||
}
|
||||
|
||||
alloc6 (fn: main)
|
||||
alloc7 (fn: main)
|
||||
|
||||
alloc7 (size: 100, align: 1) {
|
||||
alloc8 (size: 100, align: 1) {
|
||||
0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
|
@ -1,4 +1,4 @@
|
||||
// MIR for `BAR::promoted[0]` after ConstProp
|
||||
// MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops
|
||||
|
||||
promoted[0] in BAR: &[&i32; 1] = {
|
||||
let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
|
||||
@ -14,7 +14,7 @@ promoted[0] in BAR: &[&i32; 1] = {
|
||||
// mir::Constant
|
||||
// + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34
|
||||
// + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) }
|
||||
_2 = _3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
|
||||
_2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34
|
||||
_1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
|
||||
_0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
|
||||
return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
|
@ -1,4 +1,4 @@
|
||||
// MIR for `FOO::promoted[0]` after ConstProp
|
||||
// MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops
|
||||
|
||||
promoted[0] in FOO: &[&i32; 1] = {
|
||||
let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
|
10
src/test/run-make/const_fn_mir/Makefile
Normal file
10
src/test/run-make/const_fn_mir/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir
|
||||
|
||||
ifdef RUSTC_BLESS_TEST
|
||||
cp "$(TMPDIR)"/dump.mir dump.mir
|
||||
else
|
||||
$(DIFF) dump.mir "$(TMPDIR)"/dump.mir
|
||||
endif
|
45
src/test/run-make/const_fn_mir/dump.mir
Normal file
45
src/test/run-make/const_fn_mir/dump.mir
Normal file
@ -0,0 +1,45 @@
|
||||
// WARNING: This output format is intended for human consumers only
|
||||
// and is subject to change without notice. Knock yourself out.
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at main.rs:8:11: 8:11
|
||||
let _1: i32; // in scope 0 at main.rs:9:5: 9:10
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at main.rs:9:5: 9:10
|
||||
_1 = foo() -> bb1; // scope 0 at main.rs:9:5: 9:10
|
||||
// mir::Constant
|
||||
// + span: main.rs:9:5: 9:8
|
||||
// + literal: Const { ty: fn() -> i32 {foo}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_1); // scope 0 at main.rs:9:10: 9:11
|
||||
_0 = const (); // scope 0 at main.rs:8:11: 10:2
|
||||
return; // scope 0 at main.rs:10:2: 10:2
|
||||
}
|
||||
}
|
||||
|
||||
fn foo() -> i32 {
|
||||
let mut _0: i32; // return place in scope 0 at main.rs:4:19: 4:22
|
||||
|
||||
bb0: {
|
||||
_0 = const 11_i32; // scope 0 at main.rs:5:5: 5:10
|
||||
return; // scope 0 at main.rs:6:2: 6:2
|
||||
}
|
||||
}
|
||||
|
||||
// MIR FOR CTFE
|
||||
fn foo() -> i32 {
|
||||
let mut _0: i32; // return place in scope 0 at main.rs:4:19: 4:22
|
||||
let mut _1: (i32, bool); // in scope 0 at main.rs:5:5: 5:10
|
||||
|
||||
bb0: {
|
||||
_1 = CheckedAdd(const 5_i32, const 6_i32); // scope 0 at main.rs:5:5: 5:10
|
||||
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; // scope 0 at main.rs:5:5: 5:10
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = move (_1.0: i32); // scope 0 at main.rs:5:5: 5:10
|
||||
return; // scope 0 at main.rs:6:2: 6:2
|
||||
}
|
||||
}
|
10
src/test/run-make/const_fn_mir/main.rs
Normal file
10
src/test/run-make/const_fn_mir/main.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// emit-mir
|
||||
// check-pass
|
||||
|
||||
const fn foo() -> i32 {
|
||||
5 + 6
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
}
|
@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a
|
||||
|
|
||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
||||
note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` for CTFE...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
||||
|
|
||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||
|
@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `FooDefault::BAR`...
|
||||
|
|
||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires optimizing MIR for `FooDefault::BAR`...
|
||||
note: ...which requires caching mir of `FooDefault::BAR` for CTFE...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
||||
|
|
||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||
|
@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a
|
||||
|
|
||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
||||
note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` for CTFE...
|
||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
||||
|
|
||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||
|
@ -1,6 +1,8 @@
|
||||
// check-pass
|
||||
|
||||
// compile-flags: --crate-type lib
|
||||
// need to emit MIR, because const prop (which emits `unconditional_panic`) only runs if
|
||||
// the `optimized_mir` query is run, which it isn't in check-only mode.
|
||||
// compile-flags: --crate-type lib --emit=mir,link
|
||||
|
||||
#![warn(unconditional_panic)]
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
warning: this operation will panic at runtime
|
||||
--> $DIR/ice-assert-fail-div-by-zero.rs:11:5
|
||||
--> $DIR/ice-assert-fail-div-by-zero.rs:13:5
|
||||
|
|
||||
LL | f.0 / 0;
|
||||
| ^^^^^^^ attempt to divide `_` by zero
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/ice-assert-fail-div-by-zero.rs:5:9
|
||||
--> $DIR/ice-assert-fail-div-by-zero.rs:7:9
|
||||
|
|
||||
LL | #![warn(unconditional_panic)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -4,7 +4,7 @@ error: any use of this value will cause an error
|
||||
LL | const X: u64 = *wat(42);
|
||||
| ---------------^^^^^^^^-
|
||||
| |
|
||||
| pointer to alloc2 was dereferenced after this allocation got freed
|
||||
| pointer to alloc1 was dereferenced after this allocation got freed
|
||||
|
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
|
@ -7,13 +7,13 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/ub-nonnull.rs:18:29
|
||||
--> $DIR/ub-nonnull.rs:18:30
|
||||
|
|
||||
LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
|
||||
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
|
||||
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
|
||||
LL | | let out_of_bounds_ptr = &ptr[255];
|
||||
| | ^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
|
||||
| | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
|
||||
LL | | mem::transmute(out_of_bounds_ptr)
|
||||
LL | | } };
|
||||
| |____-
|
||||
|
@ -95,22 +95,26 @@ const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||
|
||||
// # trait object
|
||||
// bad trait object
|
||||
#[warn(const_err)]
|
||||
const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^ WARN any use of this value will cause an error [const_err]
|
||||
// bad trait object
|
||||
#[warn(const_err)]
|
||||
const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^ WARN any use of this value will cause an error [const_err]
|
||||
// bad trait object
|
||||
#[warn(const_err)]
|
||||
const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^ WARN any use of this value will cause an error [const_err]
|
||||
const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
#[warn(const_err)]
|
||||
const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: &dyn Trait = unsafe { mem::transmute((&92u8, &[&42u8; 8])) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^ WARN any use of this value will cause an error [const_err]
|
||||
|
||||
// bad data *inside* the trait object
|
||||
const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
|
||||
|
@ -134,32 +134,50 @@ LL | | };
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:98:1
|
||||
warning: any use of this value will cause an error
|
||||
--> $DIR/ub-wide-ptr.rs:99:55
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
|
||||
| ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
note: the lint level is defined here
|
||||
--> $DIR/ub-wide-ptr.rs:98:8
|
||||
|
|
||||
LL | #[warn(const_err)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:101:1
|
||||
warning: any use of this value will cause an error
|
||||
--> $DIR/ub-wide-ptr.rs:103:55
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
|
||||
| ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
note: the lint level is defined here
|
||||
--> $DIR/ub-wide-ptr.rs:102:8
|
||||
|
|
||||
LL | #[warn(const_err)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:104:1
|
||||
warning: any use of this value will cause an error
|
||||
--> $DIR/ub-wide-ptr.rs:107:51
|
||||
|
|
||||
LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
|
||||
| --------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| unable to turn bytes into a pointer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
note: the lint level is defined here
|
||||
--> $DIR/ub-wide-ptr.rs:106:8
|
||||
|
|
||||
LL | #[warn(const_err)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:106:1
|
||||
--> $DIR/ub-wide-ptr.rs:109:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
|
||||
@ -167,7 +185,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:108:1
|
||||
--> $DIR/ub-wide-ptr.rs:111:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -175,23 +193,29 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:110:1
|
||||
--> $DIR/ub-wide-ptr.rs:113:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:112:1
|
||||
warning: any use of this value will cause an error
|
||||
--> $DIR/ub-wide-ptr.rs:116:63
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: &dyn Trait = unsafe { mem::transmute((&92u8, &[&42u8; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
| --------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
note: the lint level is defined here
|
||||
--> $DIR/ub-wide-ptr.rs:115:8
|
||||
|
|
||||
LL | #[warn(const_err)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:116:1
|
||||
--> $DIR/ub-wide-ptr.rs:120:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.<dyn-downcast>, but expected a boolean
|
||||
@ -199,7 +223,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:120:1
|
||||
--> $DIR/ub-wide-ptr.rs:124:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
|
||||
@ -207,7 +231,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:122:1
|
||||
--> $DIR/ub-wide-ptr.rs:126:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
|
||||
@ -215,17 +239,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:128:5
|
||||
--> $DIR/ub-wide-ptr.rs:132:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inbounds test failed: 0x0 is not a valid pointer
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:132:5
|
||||
--> $DIR/ub-wide-ptr.rs:136:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 24 previous errors; 4 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -35,11 +35,11 @@ LL | U8_MUT => true,
|
||||
| ^^^^^^
|
||||
|
||||
warning: any use of this value will cause an error
|
||||
--> $DIR/const_refers_to_static_cross_crate.rs:26:14
|
||||
--> $DIR/const_refers_to_static_cross_crate.rs:26:15
|
||||
|
|
||||
LL | / const U8_MUT2: &u8 = {
|
||||
LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
|
||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
|
||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
|
@ -66,6 +66,7 @@ const _: *const u8 =
|
||||
//~^ NOTE
|
||||
unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
|
||||
//~^ ERROR any use of this value will cause an error
|
||||
//~| NOTE
|
||||
|
||||
const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
|
||||
//~^ ERROR any use of this value will cause an error
|
||||
|
@ -16,19 +16,17 @@ LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/ptr_comparisons.rs:67:14
|
||||
--> $DIR/ptr_comparisons.rs:67:35
|
||||
|
|
||||
LL | / const _: *const u8 =
|
||||
LL | |
|
||||
LL | | unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
|
||||
| |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
|
||||
| |
|
||||
| memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
| |___________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
|
||||
| |
|
||||
| memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/ptr_comparisons.rs:70:27
|
||||
--> $DIR/ptr_comparisons.rs:71:27
|
||||
|
|
||||
LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
|
||||
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
@ -36,7 +34,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) +
|
||||
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/ptr_comparisons.rs:75:27
|
||||
--> $DIR/ptr_comparisons.rs:76:27
|
||||
|
|
||||
LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
|
||||
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
|
Loading…
Reference in New Issue
Block a user