From 25700232f7edad5a73b92bc7a315356837a58ced Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Wed, 17 May 2023 14:43:57 +0000 Subject: [PATCH 01/15] Create definitions for promoted constants. --- compiler/rustc_borrowck/src/consumers.rs | 6 +- compiler/rustc_borrowck/src/lib.rs | 65 +------ compiler/rustc_borrowck/src/nll.rs | 11 +- compiler/rustc_borrowck/src/renumber.rs | 21 +-- compiler/rustc_borrowck/src/type_check/mod.rs | 147 +++------------- .../rustc_borrowck/src/universal_regions.rs | 74 +++++--- .../src/const_eval/eval_queries.rs | 62 ++++--- .../src/const_eval/machine.rs | 2 +- .../src/interpret/eval_context.rs | 9 +- .../src/interpret/intrinsics.rs | 2 +- .../rustc_const_eval/src/interpret/operand.rs | 4 +- .../src/transform/check_consts/qualifs.rs | 10 +- .../src/transform/promote_consts.rs | 160 ++++++++++-------- compiler/rustc_hir/src/def.rs | 6 + compiler/rustc_hir/src/definitions.rs | 5 +- .../src/collect/generics_of.rs | 38 +++-- .../src/collect/predicates_of.rs | 9 +- .../rustc_hir_analysis/src/collect/type_of.rs | 9 +- .../rustc_hir_analysis/src/outlives/mod.rs | 4 +- .../src/rmeta/decoder/cstore_impl.rs | 1 - compiler/rustc_metadata/src/rmeta/encoder.rs | 15 +- compiler/rustc_metadata/src/rmeta/mod.rs | 1 - compiler/rustc_metadata/src/rmeta/table.rs | 1 + compiler/rustc_middle/src/arena.rs | 11 +- compiler/rustc_middle/src/hir/map/mod.rs | 8 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- .../rustc_middle/src/mir/interpret/mod.rs | 11 +- .../rustc_middle/src/mir/interpret/queries.rs | 14 +- compiler/rustc_middle/src/mir/mod.rs | 13 +- compiler/rustc_middle/src/mir/pretty.rs | 48 ++---- compiler/rustc_middle/src/query/mod.rs | 18 +- .../rustc_middle/src/query/on_disk_cache.rs | 5 +- compiler/rustc_middle/src/ty/consts/kind.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 16 +- compiler/rustc_middle/src/ty/mod.rs | 8 +- compiler/rustc_middle/src/ty/print/mod.rs | 2 + compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 2 +- .../src/build/expr/as_constant.rs | 5 +- .../rustc_mir_transform/src/check_unsafety.rs | 13 +- .../rustc_mir_transform/src/const_prop.rs | 5 - .../src/const_prop_lint.rs | 5 - .../rustc_mir_transform/src/coverage/mod.rs | 3 +- compiler/rustc_mir_transform/src/inline.rs | 4 +- compiler/rustc_mir_transform/src/lib.rs | 28 ++- .../rustc_monomorphize/src/polymorphize.rs | 25 +-- compiler/rustc_privacy/src/lib.rs | 1 + .../rustc_resolve/src/build_reduced_graph.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + .../src/typeid/typeid_itanium_cxx_abi.rs | 1 + compiler/rustc_symbol_mangling/src/v0.rs | 1 + compiler/rustc_ty_utils/src/implied_bounds.rs | 1 + compiler/rustc_ty_utils/src/opaque_types.rs | 1 + compiler/rustc_ty_utils/src/ty.rs | 4 + src/librustdoc/formats/item_type.rs | 1 + .../passes/collect_intra_doc_links.rs | 1 + src/tools/miri/src/helpers.rs | 4 +- src/tools/miri/src/shims/foreign_items.rs | 4 +- src/tools/miri/src/shims/mod.rs | 2 +- ...ransmutes.adt_transmutes.InstSimplify.diff | 2 +- ...#0}.SimplifyCfg-elaborate-drops.after.mir} | 4 +- ...motion_extern_static.BAR.PromoteTemps.diff | 2 +- ...#0}.SimplifyCfg-elaborate-drops.after.mir} | 4 +- ...motion_extern_static.FOO.PromoteTemps.diff | 2 +- .../mir-opt/const_promotion_extern_static.rs | 4 +- ...e_oob_for_slices.main.ConstProp.64bit.diff | 2 +- ..._prop_fails_gracefully.main.ConstProp.diff | 2 +- .../const_prop/ref_deref.main.ConstProp.diff | 2 +- .../ref_deref_project.main.ConstProp.diff | 2 +- .../slice_len.main.ConstProp.64bit.diff | 2 +- .../derefer_complex_case.main.Derefer.diff | 2 +- .../inline/inline_retag.bar.Inline.after.mir | 4 +- .../inline/issue_106141.outer.Inline.diff | 2 +- ...trinsics.discriminant.LowerIntrinsics.diff | 6 +- ...e_prop.debuginfo.ReferencePropagation.diff | 6 +- ...asts.SimplifyCfg-elaborate-drops.after.mir | 2 +- ...main.SimplifyCfg-elaborate-drops.after.mir | 2 +- ...mes.foo.ScalarReplacementOfAggregates.diff | 2 +- .../defaults-cyclic-fail.stderr | 2 +- tests/ui/borrowck/issue-81899.rs | 2 +- tests/ui/borrowck/issue-81899.stderr | 4 +- .../borrowck/issue-88434-minimal-example.rs | 2 +- .../issue-88434-minimal-example.stderr | 4 +- ...ssue-88434-removal-index-should-be-less.rs | 2 +- ...-88434-removal-index-should-be-less.stderr | 4 +- .../consts/const-eval/raw-bytes.64bit.stderr | 12 +- tests/ui/consts/const-eval/ub-ref-ptr.rs | 4 +- tests/ui/consts/const-eval/ub-ref-ptr.stderr | 4 +- tests/ui/consts/const-eval/ub-wide-ptr.stderr | 12 +- tests/ui/consts/invalid-union.64bit.stderr | 10 +- tests/ui/consts/invalid-union.rs | 4 +- tests/ui/limits/issue-55878.stderr | 2 +- ...ram-closure-approximate-lower-bound.stderr | 8 + .../promoted-annotation.stderr | 2 +- .../polymorphization/promoted-function-1.rs | 1 + .../promoted-function-1.stderr | 11 +- tests/ui/polymorphization/unsized_cast.rs | 5 +- tests/ui/polymorphization/unsized_cast.stderr | 39 ++++- tests/ui/query-system/query_depth.rs | 2 +- tests/ui/query-system/query_depth.stderr | 7 +- tests/ui/rfcs/rfc1623-2.rs | 4 +- 101 files changed, 531 insertions(+), 605 deletions(-) rename tests/mir-opt/{const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir => const_promotion_extern_static.BAR-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir} (93%) rename tests/mir-opt/{const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir => const_promotion_extern_static.FOO-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir} (92%) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 3451b7db8caae..7e5e149792bdf 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -3,7 +3,6 @@ //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; -use rustc_index::IndexSlice; use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; @@ -29,9 +28,8 @@ pub use super::{ /// /// * Polonius is highly unstable, so expect regular changes in its signature or other details. pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> { - let (input_body, promoted) = tcx.mir_promoted(def); + let (input_body, _) = tcx.mir_promoted(def); 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() + *super::do_mir_borrowck(&infcx, input_body, true).1.unwrap() } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index eb25d454339b5..5cc07a154e627 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -24,17 +24,11 @@ use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::ChunkedBitSet; -use rustc_index::{IndexSlice, IndexVec}; +use rustc_index::IndexVec; use rustc_infer::infer::{ DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, }; -use rustc_middle::mir::{ - traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand, - Place, PlaceElem, PlaceRef, VarDebugInfoContents, -}; -use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; -use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; -use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; +use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt}; use rustc_session::lint::builtin::UNUSED_MUT; @@ -123,7 +117,7 @@ pub fn provide(providers: &mut Providers) { } fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { - let (input_body, promoted) = tcx.mir_promoted(def); + let (input_body, _) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); if input_body.borrow().should_skip() { @@ -138,13 +132,11 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { return tcx.arena.alloc(result); } - let hir_owner = tcx.hir().local_def_id_to_hir_id(def).owner; - + let typeck_root = tcx.typeck_root_def_id(def.to_def_id()).expect_local(); let infcx = - tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); + tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(typeck_root)).build(); let input_body: &Body<'_> = &input_body.borrow(); - let promoted: &IndexSlice<_, _> = &promoted.borrow(); - let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0; + let opt_closure_req = do_mir_borrowck(&infcx, input_body, false).0; debug!("mir_borrowck done"); tcx.arena.alloc(opt_closure_req) @@ -155,11 +147,10 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { /// 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.def_id()), level = "debug")] +#[instrument(skip(infcx, input_body), 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.def_id().expect_local(); @@ -212,9 +203,7 @@ fn do_mir_borrowck<'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body_owned = input_body.clone(); - let mut promoted = input_promoted.to_owned(); - let free_regions = - nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted); + let free_regions = nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned); let body = &body_owned; // no further changes let location_table_owned = LocationTable::new(body); @@ -225,9 +214,6 @@ fn do_mir_borrowck<'tcx>( Ok((_, move_data)) => (move_data, Vec::new()), Err((move_data, move_errors)) => (move_data, move_errors), }; - let promoted_errors = promoted - .iter_enumerated() - .map(|(idx, body)| (idx, MoveData::gather_moves(&body, tcx, param_env))); let mdpe = MoveDataParamEnv { move_data, param_env }; @@ -255,7 +241,6 @@ fn do_mir_borrowck<'tcx>( &infcx, free_regions, body, - &promoted, location_table, param_env, &mut flow_inits, @@ -311,39 +296,6 @@ fn do_mir_borrowck<'tcx>( true }; - for (idx, move_data_results) in promoted_errors { - let promoted_body = &promoted[idx]; - - if let Err((move_data, move_errors)) = move_data_results { - let mut promoted_mbcx = MirBorrowckCtxt { - infcx: &infcx, - param_env, - body: promoted_body, - move_data: &move_data, - location_table, // no need to create a real one for the promoted, it is not used - movable_generator, - fn_self_span_reported: Default::default(), - locals_are_invalidated_at_exit, - access_place_error_reported: Default::default(), - reservation_error_reported: Default::default(), - uninitialized_error_reported: Default::default(), - regioncx: regioncx.clone(), - used_mut: Default::default(), - used_mut_upvars: SmallVec::new(), - borrow_set: Rc::clone(&borrow_set), - dominators: Default::default(), - upvars: Vec::new(), - local_names: IndexVec::from_elem(None, &promoted_body.local_decls), - region_names: RefCell::default(), - next_region_name: RefCell::new(1), - polonius_output: None, - errors, - }; - promoted_mbcx.report_move_errors(move_errors); - errors = promoted_mbcx.errors; - }; - } - let mut mbcx = MirBorrowckCtxt { infcx: &infcx, param_env, @@ -737,7 +689,6 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx } TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { self.consume_operand(loc, (cond, span), flow_state); - use rustc_middle::mir::AssertKind; if let AssertKind::BoundsCheck { len, index } = &**msg { self.consume_operand(loc, (len, span), flow_state); self.consume_operand(loc, (index, span), flow_state); diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index b6ccf924a5c88..aa97e1fb6f4e3 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -4,11 +4,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::LocalDefId; -use rustc_index::IndexSlice; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ - Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, - START_BLOCK, + Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, START_BLOCK, }; use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_span::symbol::sym; @@ -54,12 +52,11 @@ pub(crate) struct NllOutput<'tcx> { /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal /// regions (e.g., region parameters) declared on the function. That set will need to be given to /// `compute_regions`. -#[instrument(skip(infcx, param_env, body, promoted), level = "debug")] +#[instrument(skip(infcx, param_env, body), level = "debug")] pub(crate) fn replace_regions_in_mir<'tcx>( infcx: &BorrowckInferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, - promoted: &mut IndexSlice<Promoted, Body<'tcx>>, ) -> UniversalRegions<'tcx> { let def = body.source.def_id().expect_local(); @@ -69,7 +66,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>( let universal_regions = UniversalRegions::new(infcx, def, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body, promoted); + renumber::renumber_mir(infcx, body); dump_mir(infcx.tcx, false, "renumber", &0, body, |_, _| Ok(())); @@ -158,7 +155,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( infcx: &BorrowckInferCtxt<'_, 'tcx>, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, - promoted: &IndexSlice<Promoted, Body<'tcx>>, location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>, @@ -180,7 +176,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>( infcx, param_env, body, - promoted, &universal_regions, location_table, borrow_set, diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 4389d2b60bc55..b5f1a182f005a 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,32 +1,21 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] + use crate::BorrowckInferCtxt; -use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::Constant; -use rustc_middle::mir::{Body, Location, Promoted}; +use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. -#[instrument(skip(infcx, body, promoted), level = "debug")] -pub fn renumber_mir<'tcx>( - infcx: &BorrowckInferCtxt<'_, 'tcx>, - body: &mut Body<'tcx>, - promoted: &mut IndexSlice<Promoted, Body<'tcx>>, -) { +#[instrument(skip(infcx, body), level = "debug")] +pub fn renumber_mir<'tcx>(infcx: &BorrowckInferCtxt<'_, 'tcx>, body: &mut Body<'tcx>) { debug!(?body.arg_count); - - let mut renumberer = RegionRenumberer { infcx }; - - for body in promoted.iter_mut() { - renumberer.visit_body(body); - } - - renumberer.visit_body(body); + RegionRenumberer { infcx }.visit_body(body); } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fa4bc926f2739..11e09ac20e019 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -3,7 +3,7 @@ //! This pass type-checks the MIR to ensure it is not broken. use std::rc::Rc; -use std::{fmt, iter, mem}; +use std::{fmt, iter}; use either::Either; @@ -113,7 +113,6 @@ mod relate_tys; /// - `infcx` -- inference context to use /// - `param_env` -- parameter environment to use for trait solving /// - `body` -- MIR body to type-check -/// - `promoted` -- map of promoted constants within `body` /// - `universal_regions` -- the universal regions from `body`s function signature /// - `location_table` -- MIR location map of `body` /// - `borrow_set` -- information about borrows occurring in `body` @@ -125,7 +124,6 @@ pub(crate) fn type_check<'mir, 'tcx>( infcx: &BorrowckInferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, - promoted: &IndexSlice<Promoted, Body<'tcx>>, universal_regions: &Rc<UniversalRegions<'tcx>>, location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, @@ -184,7 +182,7 @@ pub(crate) fn type_check<'mir, 'tcx>( ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, promoted); + let mut verifier = TypeVerifier::new(&mut checker); verifier.visit_body(&body); verifier.errors_reported }; @@ -292,7 +290,6 @@ enum FieldAccessError { /// is a problem. struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, - promoted: &'b IndexSlice<Promoted, Body<'tcx>>, last_span: Span, errors_reported: bool, } @@ -364,42 +361,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { }; if let Some(uv) = maybe_uneval { - if let Some(promoted) = uv.promoted { - let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, - promoted: &Body<'tcx>, - ty, - san_ty| { - if let Err(terr) = - verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring) - { - span_mirbug!( - verifier, - promoted, - "bad promoted type ({:?}: {:?}): {:?}", - ty, - san_ty, - terr - ); - }; - }; - - if !self.errors_reported { - let promoted_body = &self.promoted[promoted]; - self.sanitize_promoted(promoted_body, location); - - let promoted_ty = promoted_body.return_ty(); - check_err(self, promoted_body, ty, promoted_ty); - } - } else { - self.cx.ascribe_user_type( - constant.literal.ty(), - UserType::TypeOf( - uv.def, - UserSubsts { substs: uv.substs, user_self_ty: None }, - ), - locations.span(&self.cx.body), - ); - } + self.cx.ascribe_user_type( + constant.literal.ty(), + UserType::TypeOf(uv.def, UserSubsts { substs: uv.substs, user_self_ty: None }), + locations.span(&self.cx.body), + ); } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { let unnormalized_ty = tcx.type_of(static_def_id).subst_identity(); let normalized_ty = self.cx.normalize(unnormalized_ty, locations); @@ -491,11 +457,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { - fn new( - cx: &'a mut TypeChecker<'b, 'tcx>, - promoted: &'b IndexSlice<Promoted, Body<'tcx>>, - ) -> Self { - TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false } + fn new(cx: &'a mut TypeChecker<'b, 'tcx>) -> Self { + TypeVerifier { last_span: cx.body.span, cx, errors_reported: false } } fn body(&self) -> &Body<'tcx> { @@ -562,74 +525,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place_ty } - fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) { - // Determine the constraints from the promoted MIR by running the type - // checker on the promoted MIR, then transfer the constraints back to - // the main MIR, changing the locations to the provided location. - - let parent_body = mem::replace(&mut self.cx.body, promoted_body); - - // Use new sets of constraints and closure bounds so that we can - // modify their locations. - let all_facts = &mut None; - let mut constraints = Default::default(); - let mut liveness_constraints = - LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); - // Don't try to add borrow_region facts for the promoted MIR - - let mut swap_constraints = |this: &mut Self| { - mem::swap(this.cx.borrowck_context.all_facts, all_facts); - mem::swap( - &mut this.cx.borrowck_context.constraints.outlives_constraints, - &mut constraints, - ); - mem::swap( - &mut this.cx.borrowck_context.constraints.liveness_constraints, - &mut liveness_constraints, - ); - }; - - swap_constraints(self); - - self.visit_body(&promoted_body); - - if !self.errors_reported { - // if verifier failed, don't do further checks to avoid ICEs - self.cx.typeck_mir(promoted_body); - } - - self.cx.body = parent_body; - // Merge the outlives constraints back in, at the given location. - swap_constraints(self); - - let locations = location.to_locations(); - for constraint in constraints.outlives().iter() { - let mut constraint = *constraint; - constraint.locations = locations; - if let ConstraintCategory::Return(_) - | ConstraintCategory::UseAsConst - | ConstraintCategory::UseAsStatic = constraint.category - { - // "Returning" from a promoted is an assignment to a - // temporary from the user's point of view. - constraint.category = ConstraintCategory::Boring; - } - self.cx.borrowck_context.constraints.outlives_constraints.push(constraint) - } - for region in liveness_constraints.rows() { - // If the region is live at at least one location in the promoted MIR, - // then add a liveness constraint to the main MIR for this region - // at the location provided as an argument to this method - if liveness_constraints.get_elements(region).next().is_some() { - self.cx - .borrowck_context - .constraints - .liveness_constraints - .add_element(region, location); - } - } - } - #[instrument(skip(self), level = "debug")] fn sanitize_projection( &mut self, @@ -1767,19 +1662,15 @@ 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; - if tcx.def_kind(def_id) == DefKind::InlineConst { - let def_id = def_id.expect_local(); - let predicates = - self.prove_closure_bounds(tcx, def_id, uv.substs, location); - self.normalize_and_prove_instantiated_predicates( - def_id.to_def_id(), - predicates, - location.to_locations(), - ); - } + let tcx = self.tcx(); + if matches!(tcx.def_kind(uv.def), DefKind::InlineConst | DefKind::Promoted) { + let def_id = uv.def.expect_local(); + let predicates = self.prove_closure_bounds(tcx, def_id, uv.substs, location); + self.normalize_and_prove_instantiated_predicates( + def_id.to_def_id(), + predicates, + location.to_locations(), + ); } } } @@ -2628,7 +2519,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let parent_substs = match tcx.def_kind(def_id) { DefKind::Closure => substs.as_closure().parent_substs(), DefKind::Generator => substs.as_generator().parent_substs(), - DefKind::InlineConst => substs.as_inline_const().parent_substs(), + DefKind::InlineConst | DefKind::Promoted => substs.as_inline_const().parent_substs(), other => bug!("unexpected item {:?}", other), }; let parent_substs = tcx.mk_substs(parent_substs); diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 56f078f2da816..bf5ed61591f8d 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -16,11 +16,13 @@ use either::Either; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::BodyOwnerKind; use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_middle::mir::RETURN_PLACE; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; @@ -571,31 +573,53 @@ 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.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.to_def_id(), substs) - } else { - // FIXME this line creates a dependency between borrowck and typeck. - // - // This is required for `AscribeUserType` canonical query, which will call - // `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes - // into borrowck, which is ICE #78174. - // - // As a workaround, inline consts have an additional generic param (`ty` - // 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) - .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.to_def_id(), substs) + match tcx.def_kind(self.mir_def) { + DefKind::InlineConst => { + // FIXME this line creates a dependency between borrowck and typeck. + // + // This is required for `AscribeUserType` canonical query, which will call + // `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes + // into borrowck, which is ICE #78174. + // + // As a workaround, inline consts have an additional generic param (`ty` + // 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) + .node_type(tcx.local_def_id_to_hir_id(self.mir_def)); + let identity_substs = + InternalSubsts::identity_for_item(tcx, typeck_root_def_id); + 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.to_def_id(), substs) + } + DefKind::Promoted => { + let body = tcx.mir_for_promoted(self.mir_def).borrow(); + let ty = body.local_decls[RETURN_PLACE].ty; + let parent_def_id = tcx.parent(self.mir_def.to_def_id()); + let parent_substs = InternalSubsts::identity_for_item(tcx, parent_def_id); + let substs = InlineConstSubsts::new( + tcx, + InlineConstSubstsParts { parent_substs, ty }, + ) + .substs; + let substs = + self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs); + DefiningTy::InlineConst(self.mir_def.to_def_id(), substs) + } + _ => { + let identity_substs = + InternalSubsts::identity_for_item(tcx, self.mir_def.to_def_id()); + let substs = self + .infcx + .replace_free_regions_with_nll_infer_vars(FR, identity_substs); + DefiningTy::Const(self.mir_def.to_def_id(), substs) + } } } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 046d2052968a3..efc08c9b0eb23 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -35,16 +35,16 @@ fn eval_body_using_ecx<'mir, 'tcx>( debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); let tcx = *ecx.tcx; assert!( - cid.promoted.is_some() - || matches!( - ecx.tcx.def_kind(cid.instance.def_id()), - DefKind::Const - | DefKind::Static(_) - | DefKind::ConstParam - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::AssocConst - ), + matches!( + ecx.tcx.def_kind(cid.instance.def_id()), + DefKind::Const + | DefKind::Static(_) + | DefKind::ConstParam + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::AssocConst + | DefKind::Promoted + ), "Unexpected DefKind: {:?}", ecx.tcx.def_kind(cid.instance.def_id()) ); @@ -53,9 +53,8 @@ fn eval_body_using_ecx<'mir, 'tcx>( let ret = ecx.allocate(layout, MemoryKind::Stack)?; trace!( - "eval_body_using_ecx: pushing stack frame for global: {}{}", + "eval_body_using_ecx: pushing stack frame for global: {}", with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())), - cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p)) ); ecx.push_stack_frame( @@ -69,13 +68,10 @@ fn eval_body_using_ecx<'mir, 'tcx>( while ecx.step()? {} // Intern the result - let intern_kind = if cid.promoted.is_some() { - InternKind::Promoted - } else { - match tcx.static_mutability(cid.instance.def_id()) { - Some(m) => InternKind::Static(m), - None => InternKind::Constant, - } + let intern_kind = match tcx.def_kind(cid.instance.def_id()) { + DefKind::Promoted => InternKind::Promoted, + DefKind::Static(m) => InternKind::Static(m), + _ => InternKind::Constant, }; ecx.machine.check_alignment = CheckAlignment::No; // interning doesn't need to respect alignment intern_const_alloc_recursive(ecx, intern_kind, &ret)?; @@ -218,7 +214,7 @@ pub(crate) fn turn_into_const_value<'tcx>( which should have given a good error before ever invoking this function", ); assert!( - !is_static || cid.promoted.is_some(), + !is_static, "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead" ); @@ -297,17 +293,21 @@ pub fn eval_to_allocation_raw_provider<'tcx>( let cid = key.value; let def = cid.instance.def.def_id(); - let is_static = tcx.is_static(def); + let within_static = match tcx.def_kind(def) { + DefKind::Promoted => tcx.is_static(tcx.parent(def)), + DefKind::Static(_) => true, + _ => false, + }; let mut ecx = InterpCx::new( tcx, tcx.def_span(def), key.param_env, - // Statics (and promoteds inside statics) may access other statics, because unlike consts + // Statics may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. CompileTimeInterpreter::new( tcx.const_eval_limit(), - /*can_access_statics:*/ is_static, + /*can_access_statics:*/ within_static, if tcx.sess.opts.unstable_opts.extra_const_ub_checks { CheckAlignment::Error } else { @@ -316,11 +316,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>( ), ); - let res = ecx.load_mir(cid.instance.def, cid.promoted); + let res = ecx.load_mir(cid.instance.def); match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { Err(error) => { let err = ConstEvalErr::new(&ecx, error, None); - let msg = if is_static { + let msg = if within_static { Cow::from("could not evaluate static initializer") } else { // If the current item has generics, we'd like to enrich the message with the @@ -345,13 +345,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>( let mut ref_tracking = RefTracking::new(mplace); let mut inner = false; while let Some((mplace, path)) = ref_tracking.todo.pop() { - let mode = match tcx.static_mutability(cid.instance.def_id()) { - Some(_) if cid.promoted.is_some() => { - // Promoteds in statics are allowed to point to statics. - CtfeValidationMode::Const { inner, allow_static_ptrs: true } - } - Some(_) => CtfeValidationMode::Regular, // a `static` - None => CtfeValidationMode::Const { inner, allow_static_ptrs: false }, + let mode = if tcx.is_static(def) { + CtfeValidationMode::Regular // a `static` + } else { + // Promoteds in statics are allowed to point to statics. + CtfeValidationMode::Const { inner, allow_static_ptrs: within_static } }; ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?; inner = true; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 58b5755af07f2..ce6fc2eaa79ec 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -441,7 +441,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } // This is a const fn. Call it. - Ok(Some((ecx.load_mir(instance.def, None)?, instance))) + Ok(Some((ecx.load_mir(instance.def)?, instance))) } fn call_intrinsic( diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 040eba10eb4f7..4a8df9d4a5926 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -458,15 +458,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn load_mir( &self, instance: ty::InstanceDef<'tcx>, - promoted: Option<mir::Promoted>, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { - trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); - let body = if let Some(promoted) = promoted { - let def = instance.def_id(); - &self.tcx.promoted_mir(def)[promoted] - } else { - M::load_mir(self, instance)? - }; + let body = M::load_mir(self, instance)?; // do not continue if typeck errors occurred (can only occur in local crate) if let Some(err) = body.tainted_by_errors { throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err))); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index a77c699c22f7e..9933b249a5b0e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -163,7 +163,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | sym::type_id | sym::type_name | sym::variant_count => { - let gid = GlobalId { instance, promoted: None }; + let gid = GlobalId { instance }; let ty = match intrinsic_name { sym::pref_align_of | sym::variant_count => self.tcx.types.usize, sym::needs_drop => self.tcx.types.bool, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e30af165501e5..44bc4695eddf2 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -599,7 +599,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ty::ConstKind::Unevaluated(uv) => { let instance = self.resolve(uv.def, uv.substs)?; - let cid = GlobalId { instance, promoted: None }; + let cid = GlobalId { instance }; self.ctfe_query(span, |tcx| { tcx.eval_to_valtree(self.param_env.with_const().and(cid)) })? @@ -628,7 +628,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; - Ok(self.eval_global(GlobalId { instance, promoted: uv.promoted }, span)?.into()) + Ok(self.eval_global(GlobalId { instance }, span)?.into()) } } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1da20579021a1..177bdb3dfa80f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -3,9 +3,9 @@ //! See the `Qualif` trait for more info. use rustc_errors::ErrorGuaranteed; +use rustc_hir::def::DefKind; use rustc_hir::LangItem; use rustc_infer::infer::TyCtxtInferExt; -use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; use rustc_trait_selection::traits::{ @@ -357,14 +357,16 @@ where ConstantKind::Val(..) => None, }; - if let Some(mir::UnevaluatedConst { def, substs: _, promoted }) = uneval { + if let Some(UnevaluatedConst { def, substs: _ }) = uneval { + let is_promoted = cx.tcx.def_kind(def) == DefKind::Promoted; + // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible // only for `NeedsNonConstDrop` with precise drop checking. This is the only const // check performed after the promotion. Verify that with an assertion. - assert!(promoted.is_none() || Q::ALLOW_PROMOTED); + assert!(!is_promoted || Q::ALLOW_PROMOTED); // Don't peek inside trait associated constants. - if promoted.is_none() && cx.tcx.trait_of_item(def).is_none() { + if !is_promoted && cx.tcx.trait_of_item(def).is_none() { let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def); if !Q::in_qualifs(&qualifs) { diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 0e2d9ee8fb2fb..e7333ba8e98d0 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -13,16 +13,15 @@ //! move analysis runs after promotion on broken MIR. use rustc_hir as hir; -use rustc_middle::mir; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::traversal::ReversePostorderIter; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt}; +use rustc_span::def_id::LocalDefId; use rustc_span::Span; -use rustc_index::{Idx, IndexSlice, IndexVec}; - use std::cell::Cell; use std::{cmp, iter, mem}; @@ -36,11 +35,11 @@ use crate::transform::check_consts::{qualifs, ConstCx}; /// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each /// newly created `Constant`. #[derive(Default)] -pub struct PromoteTemps<'tcx> { - pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>, +pub struct PromoteTemps { + pub promoted_fragments: Cell<IndexVec<Promoted, LocalDefId>>, } -impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { +impl<'tcx> MirPass<'tcx> for PromoteTemps { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // @@ -49,9 +48,6 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { debug!("PromoteTemps: MIR had errors"); return; } - if body.source.promoted.is_some() { - return; - } let mut rpo = traversal::reverse_postorder(body); let ccx = ConstCx::new(tcx, body); @@ -828,75 +824,54 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> { - let def = self.source.source.def_id(); - let mut rvalue = { - let promoted = &mut self.promoted; - let promoted_id = Promoted::new(next_promoted_id); - let tcx = self.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)); - let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) }; - - Operand::Constant(Box::new(Constant { - span, - user_ty: None, - literal: ConstantKind::Unevaluated(uneval, ty), - })) - }; + fn promote_candidate(mut self, candidate: Candidate) -> LocalDefId { + let tcx = self.tcx; - let blocks = self.source.basic_blocks.as_mut(); - let local_decls = &mut self.source.local_decls; - let loc = candidate.location; - let statement = &mut blocks[loc.block].statements[loc.statement_index]; - let StatementKind::Assign(box (_, Rvalue::Ref(region, borrow_kind, place))) = &mut statement.kind else { - bug!() - }; + let blocks = self.source.basic_blocks.as_mut_preserves_cfg(); + let local_decls = &mut self.source.local_decls; + let loc = candidate.location; - // Use the underlying local for this (necessarily interior) borrow. - let ty = local_decls[place.local].ty; - let span = statement.source_info.span; + let statement = &mut blocks[loc.block].statements[loc.statement_index]; + let source_info = statement.source_info; + let span = source_info.span; + self.promoted.span = span; - let ref_ty = tcx.mk_ref( - tcx.lifetimes.re_erased, - ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() }, - ); + let StatementKind::Assign(box (_, Rvalue::Ref(region, borrow_kind, place))) = &mut statement.kind else { + bug!() + }; + *region = tcx.lifetimes.re_erased; - *region = tcx.lifetimes.re_erased; + // Use the underlying local for this (necessarily interior) borrow. + let ty = local_decls[place.local].ty; + let ref_ty = tcx.mk_ref( + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() }, + ); + self.promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ref_ty, span); + place.projection = { let mut projection = vec![PlaceElem::Deref]; projection.extend(place.projection); - place.projection = tcx.mk_place_elems(&projection); - - // Create a temp to hold the promoted reference. - // This is because `*r` requires `r` to be a local, - // otherwise we would use the `promoted` directly. - let mut promoted_ref = LocalDecl::new(ref_ty, span); - promoted_ref.source_info = statement.source_info; - let promoted_ref = local_decls.push(promoted_ref); - assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref); - - let promoted_ref_statement = Statement { - source_info: statement.source_info, - kind: StatementKind::Assign(Box::new(( - Place::from(promoted_ref), - Rvalue::Use(promoted_operand(ref_ty, span)), - ))), - }; - self.extra_statements.push((loc, promoted_ref_statement)); - - Rvalue::Ref( - tcx.lifetimes.re_erased, - *borrow_kind, - Place { - local: mem::replace(&mut place.local, promoted_ref), - projection: List::empty(), - }, - ) + tcx.mk_place_elems(&projection) }; + // Create a temp to hold the promoted reference. + // This is because `*r` requires `r` to be a local, + // otherwise we would use the `promoted` directly. + let mut promoted_ref = LocalDecl::new(ref_ty, span); + promoted_ref.source_info = source_info; + let promoted_ref = local_decls.push(promoted_ref); + assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref); + + let mut rvalue = Rvalue::Ref( + tcx.lifetimes.re_erased, + *borrow_kind, + Place { + local: mem::replace(&mut place.local, promoted_ref), + projection: List::empty(), + }, + ); + assert_eq!(self.new_block(), START_BLOCK); self.visit_rvalue( &mut rvalue, @@ -905,7 +880,45 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, rvalue, span); - self.promoted + + let source_def_id = self.source.source.def_id().expect_local(); + let feeder = + tcx.at(span).create_def(source_def_id, hir::definitions::DefPathData::Promoted); + feeder.opt_def_kind(Some(hir::def::DefKind::Promoted)); + feeder.opt_local_def_id_to_hir_id(None); + + let def_id = feeder.def_id(); + self.promoted.source = MirSource::item(def_id.to_def_id()); + let parent_substs = tcx.erase_regions(InternalSubsts::identity_for_item( + tcx, + tcx.typeck_root_def_id(source_def_id.to_def_id()), + )); + let substs = ty::InlineConstSubsts::new( + tcx, + ty::InlineConstSubstsParts { parent_substs, ty: ref_ty }, + ) + .substs; + let uneval = UnevaluatedConst { def: self.promoted.source.def_id(), substs }; + + feeder.mir_for_promoted(tcx.alloc_steal_mir(self.promoted)); + + let promoted_operand = { + Operand::Constant(Box::new(Constant { + span, + user_ty: None, + literal: ConstantKind::Unevaluated(uneval, ref_ty), + })) + }; + let promoted_ref_statement = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + Place::from(promoted_ref), + Rvalue::Use(promoted_operand), + ))), + }; + self.extra_statements.push((loc, promoted_ref_statement)); + + def_id } } @@ -927,7 +940,7 @@ pub fn promote_candidates<'tcx>( tcx: TyCtxt<'tcx>, mut temps: IndexVec<Local, TempState>, candidates: Vec<Candidate>, -) -> IndexVec<Promoted, Body<'tcx>> { +) -> IndexVec<Promoted, LocalDefId> { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); @@ -957,7 +970,7 @@ pub fn promote_candidates<'tcx>( IndexVec::new(), IndexVec::from_elem_n(scope, 1), initial_locals, - IndexVec::new(), + body.user_type_annotations.clone(), 0, vec![], body.span, @@ -975,8 +988,7 @@ pub fn promote_candidates<'tcx>( keep_original: false, }; - let mut promoted = promoter.promote_candidate(candidate, promotions.len()); - promoted.source.promoted = Some(promotions.next_index()); + let promoted = promoter.promote_candidate(candidate); promotions.push(promoted); } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 30bf8c2ad104b..001def88cb8de 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -121,6 +121,9 @@ pub enum DefKind { }, Closure, Generator, + + /// Promoted constant from a MIR body. + Promoted, } impl DefKind { @@ -167,6 +170,7 @@ impl DefKind { DefKind::Generator => "generator", DefKind::ExternCrate => "extern crate", DefKind::GlobalAsm => "global assembly block", + DefKind::Promoted => "promoted constant", } } @@ -227,6 +231,7 @@ impl DefKind { | DefKind::Use | DefKind::ForeignMod | DefKind::GlobalAsm + | DefKind::Promoted | DefKind::Impl { .. } | DefKind::ImplTraitPlaceholder => None, } @@ -271,6 +276,7 @@ impl DefKind { | DefKind::AnonConst | DefKind::InlineConst | DefKind::GlobalAsm + | DefKind::Promoted | DefKind::ExternCrate => false, } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 66b153d8931b0..6677f1678645c 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -278,6 +278,8 @@ pub enum DefPathData { Ctor, /// A constant expression (see `{ast,hir}::AnonConst`). AnonConst, + /// A constant promoted from a MIR body. + Promoted, /// An `impl Trait` type node. ImplTrait, /// `impl Trait` generated associated type node. @@ -405,7 +407,7 @@ impl DefPathData { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst - | ImplTrait | ImplTraitAssocTy => None, + | ImplTrait | ImplTraitAssocTy | Promoted => None, } } @@ -425,6 +427,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque }, + Promoted => DefPathDataName::Anon { namespace: sym::promoted }, } } } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index ed60998ec8dcf..2edc1c9d78630 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -14,6 +14,30 @@ use rustc_span::Span; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; + // provide junk type parameter defs for const blocks. + if let DefKind::Promoted | DefKind::InlineConst = tcx.def_kind(def_id) { + let def_id = def_id.to_def_id(); + let parent_def_id = tcx.typeck_root_def_id(def_id); + let parent_generics = tcx.generics_of(parent_def_id); + let params = vec![ty::GenericParamDef { + index: parent_generics.count() as u32, + name: Symbol::intern("<const_ty>"), + def_id, + pure_wrt_drop: false, + kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, + }]; + let param_def_id_to_index = + params.iter().map(|param| (param.def_id, param.index)).collect(); + return ty::Generics { + parent: Some(parent_def_id), + parent_count: parent_generics.count(), + params, + param_def_id_to_index, + has_self: parent_generics.has_self, + has_late_bound_regions: None, + }; + } + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let node = tcx.hir().get(hir_id); @@ -338,20 +362,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { })); } - // provide junk type parameter defs for const blocks. - if let Node::AnonConst(_) = node { - let parent_node = tcx.hir().get_parent(hir_id); - if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node { - params.push(ty::GenericParamDef { - index: next_index(), - name: Symbol::intern("<const_ty>"), - def_id: def_id.to_def_id(), - pure_wrt_drop: false, - kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, - }); - } - } - let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); ty::Generics { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index a33990813b820..d4b0d208c7580 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -62,7 +62,13 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let generics = tcx.generics_of(def_id); + let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(def_id) else { + return ty::GenericPredicates { + parent: generics.parent, + predicates: &[], + }; + }; let node = tcx.hir().get(hir_id); let mut is_trait = None; @@ -114,7 +120,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen _ => NO_GENERICS, }; - let generics = tcx.generics_of(def_id); let parent_count = generics.parent_count as u32; let has_own_self = generics.has_self && parent_count == 0; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index ca430a5e86324..0007054de175c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -1,5 +1,6 @@ use rustc_errors::{Applicability, StashKey}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; @@ -39,8 +40,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { 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() + bug!("InlineConst should have been handled by type_of") } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) @@ -333,6 +333,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty } } + if let DefKind::Promoted | DefKind::InlineConst = tcx.def_kind(def_id) { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + return ty::EarlyBinder(substs.as_inline_const().ty()); + } + use rustc_hir::*; let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index a8596c707f3a4..631ac3b837ea4 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -18,7 +18,9 @@ pub fn provide(providers: &mut Providers) { } fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] { - let id = tcx.hir().local_def_id_to_hir_id(item_def_id); + let Some(id) = tcx.opt_local_def_id_to_hir_id(item_def_id) else { + return &[]; + }; if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization() { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 364269095e011..b346be4d2f39f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -219,7 +219,6 @@ provide! { tcx, def_id, other, cdata, optimized_mir => { table } mir_for_ctfe => { table } mir_generator_witnesses => { table } - promoted_mir => { table } def_span => { table } def_ident_span => { table } lookup_stability => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 79eb48a1a3155..345022cc4a2c6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -829,6 +829,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::Macro(_) | DefKind::ExternCrate + | DefKind::Promoted | DefKind::Use | DefKind::AnonConst | DefKind::InlineConst @@ -876,6 +877,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::Promoted | DefKind::ImplTraitPlaceholder | DefKind::LifetimeParam | DefKind::GlobalAsm @@ -914,6 +916,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam + | DefKind::Promoted | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator => false, @@ -953,6 +956,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::Closure | DefKind::Generator + | DefKind::Promoted | DefKind::ExternCrate => false, } } @@ -990,6 +994,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator + | DefKind::Promoted | DefKind::ExternCrate => false, } } @@ -1015,6 +1020,7 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { | DefKind::InlineConst | DefKind::AssocConst | DefKind::Static(..) + | DefKind::Promoted | DefKind::Const => (true, false), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { @@ -1068,6 +1074,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool { | DefKind::GlobalAsm | DefKind::Closure | DefKind::Generator + | DefKind::Promoted | DefKind::ExternCrate => false, } } @@ -1097,6 +1104,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::Field | DefKind::TyParam | DefKind::Closure + | DefKind::Promoted | DefKind::Generator => true, DefKind::Mod | DefKind::ForeignMod @@ -1129,6 +1137,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Generator | DefKind::ConstParam | DefKind::AnonConst + | DefKind::Promoted | DefKind::InlineConst => true, DefKind::OpaqueTy => { @@ -1219,6 +1228,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm + | DefKind::Promoted | DefKind::ExternCrate => false, } } @@ -1542,7 +1552,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); + + for &def_id in tcx.promoted_mir(def_id) { + record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id)); + } let instance = ty::InstanceDef::Item(def_id.to_def_id()); let unused = tcx.unused_generic_params(instance); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 987a484049f6c..2e1729fa10dd7 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -393,7 +393,6 @@ define_tables! { optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>, mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>, mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>, - promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>, thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::Const<'static>>>>, impl_parent: Table<DefIndex, RawDefId>, impl_polarity: Table<DefIndex, ty::ImplPolarity>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index dda30bce2c057..bfee49e028332 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -150,6 +150,7 @@ fixed_size_enum! { ( Impl { of_trait: true } ) ( Closure ) ( Generator ) + ( Promoted ) ( Static(ast::Mutability::Not) ) ( Static(ast::Mutability::Mut) ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 6a1a2a061ddd6..85b7ab27151fb 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -19,14 +19,13 @@ macro_rules! arena_types { rustc_data_structures::steal::Steal< rustc_index::IndexVec< rustc_middle::mir::Promoted, - rustc_middle::mir::Body<'tcx> + rustc_span::def_id::LocalDefId, > >, - [decode] promoted: - rustc_index::IndexVec< - rustc_middle::mir::Promoted, - rustc_middle::mir::Body<'tcx> - >, + [decode] promoted: rustc_index::IndexVec< + rustc_middle::mir::Promoted, + rustc_span::def_id::LocalDefId, + >, [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5bf0938d51869..332072fad7edf 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -451,9 +451,11 @@ impl<'hir> Map<'hir> { /// Panics if `LocalDefId` does not have an associated body. pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind { match self.tcx.def_kind(def_id) { - DefKind::Const | DefKind::AssocConst | DefKind::InlineConst | DefKind::AnonConst => { - BodyOwnerKind::Const - } + DefKind::Const + | DefKind::AssocConst + | DefKind::InlineConst + | DefKind::AnonConst + | DefKind::Promoted => BodyOwnerKind::Const, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure | DefKind::Generator => BodyOwnerKind::Closure, DefKind::Static(mt) => BodyOwnerKind::Static(mt), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index ac0b2844177f3..a43471e728cde 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -160,7 +160,7 @@ pub fn provide(providers: &mut Providers) { }; providers.def_ident_span = |tcx, def_id| { let def_id = def_id; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.opt_local_def_id_to_hir_id(def_id)?; tcx.hir().opt_ident_span(hir_id) }; providers.fn_arg_names = |tcx, id| { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 3620385fab134..61faca85b71e9 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -112,7 +112,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; use rustc_target::abi::{AddressSpace, Endian, HasDataLayout}; -use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::subst::GenericArgKind; use crate::ty::{self, Instance, Ty, TyCtxt}; @@ -142,19 +141,11 @@ pub struct GlobalId<'tcx> { /// For a constant or static, the `Instance` of the item itself. /// For a promoted global, the `Instance` of the function they belong to. pub instance: ty::Instance<'tcx>, - - /// The index for promoted globals within their function's `mir::Body`. - pub promoted: Option<mir::Promoted>, } impl<'tcx> GlobalId<'tcx> { pub fn display(self, tcx: TyCtxt<'tcx>) -> String { - let instance_name = with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id())); - if let Some(promoted) = self.promoted { - format!("{}::{:?}", instance_name, promoted) - } else { - instance_name - } + with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id())) } } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index f53dc8cb0ec13..3faad36633481 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -22,7 +22,7 @@ impl<'tcx> TyCtxt<'tcx> { // encountered. let substs = InternalSubsts::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, substs); - let cid = GlobalId { instance, promoted: None }; + let cid = GlobalId { instance }; let param_env = self.param_env(def_id).with_reveal_all_normalized(self); self.const_eval_global_id(param_env, cid, None) } @@ -58,7 +58,7 @@ impl<'tcx> TyCtxt<'tcx> { ct.def, ct.substs, ) { Ok(Some(instance)) => { - let cid = GlobalId { instance, promoted: ct.promoted }; + let cid = GlobalId { instance }; self.const_eval_global_id(param_env, cid, span) } Ok(None) => Err(ErrorHandled::TooGeneric), @@ -85,7 +85,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::resolve(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { - let cid = GlobalId { instance, promoted: None }; + let cid = GlobalId { instance }; self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| { // We are emitting the lint here instead of in `is_const_evaluatable` // as we normalize obligations before checking them, and normalization @@ -121,7 +121,7 @@ impl<'tcx> TyCtxt<'tcx> { instance: ty::Instance<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { - self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span) + self.const_eval_global_id(param_env, GlobalId { instance }, span) } /// Evaluate a constant to a `ConstValue`. @@ -185,7 +185,7 @@ impl<'tcx> TyCtxtAt<'tcx> { trace!("eval_static_initializer: Need to compute {:?}", def_id); assert!(self.is_static(def_id)); let instance = ty::Instance::mono(*self, def_id); - let gid = GlobalId { instance, promoted: None }; + let gid = GlobalId { instance }; self.eval_to_allocation(gid, ty::ParamEnv::reveal_all()) } @@ -216,7 +216,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> { // encountered. let substs = InternalSubsts::identity_for_item(self.tcx, def_id); let instance = ty::Instance::new(def_id, substs); - let cid = GlobalId { instance, promoted: None }; + let cid = GlobalId { instance }; let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should @@ -230,7 +230,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> { trace!("eval_static_initializer: Need to compute {:?}", def_id); assert!(self.tcx.is_static(def_id)); let instance = ty::Instance::mono(self.tcx, def_id); - let gid = GlobalId { instance, promoted: None }; + let gid = GlobalId { instance }; let param_env = ty::ParamEnv::reveal_all().with_const(); trace!("eval_to_allocation: Need to compute {:?}", gid); self.eval_to_allocation_raw(param_env.and(gid)) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 1da94dd79179c..bc7ae02909010 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -184,18 +184,15 @@ impl RuntimePhase { #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub struct MirSource<'tcx> { pub instance: InstanceDef<'tcx>, - - /// If `Some`, this is a promoted rvalue within the parent function. - pub promoted: Option<Promoted>, } impl<'tcx> MirSource<'tcx> { pub fn item(def_id: DefId) -> Self { - MirSource { instance: InstanceDef::Item(def_id), promoted: None } + MirSource { instance: InstanceDef::Item(def_id) } } pub fn from_instance(instance: InstanceDef<'tcx>) -> Self { - MirSource { instance, promoted: None } + MirSource { instance } } #[inline] @@ -2500,7 +2497,7 @@ impl<'tcx> ConstantKind<'tcx> { ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) .substs; - let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None }; + let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs }; debug_assert!(!uneval.has_free_regions()); Self::Unevaluated(uneval, ty) @@ -2594,7 +2591,6 @@ impl<'tcx> ConstantKind<'tcx> { UnevaluatedConst { def: did, substs: InternalSubsts::identity_for_item(tcx, did), - promoted: None, }, ty, ) @@ -2620,7 +2616,6 @@ impl<'tcx> ConstantKind<'tcx> { pub struct UnevaluatedConst<'tcx> { pub def: DefId, pub substs: SubstsRef<'tcx>, - pub promoted: Option<Promoted>, } impl<'tcx> UnevaluatedConst<'tcx> { @@ -2635,7 +2630,7 @@ impl<'tcx> UnevaluatedConst<'tcx> { impl<'tcx> UnevaluatedConst<'tcx> { #[inline] pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> { - UnevaluatedConst { def, substs, promoted: Default::default() } + UnevaluatedConst { def, substs } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 62c3d8cf23913..dc618da0d7798 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -123,13 +123,7 @@ fn dump_matched_mir_node<'tcx, F>( // see notes on #41697 above let def_path = ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); - // ignore-tidy-odd-backticks the literal below is fine - write!(file, "// MIR for `{}", def_path)?; - match body.source.promoted { - None => write!(file, "`")?, - Some(promoted) => write!(file, "::{:?}`", promoted)?, - } - writeln!(file, " {} {}", disambiguator, pass_name)?; + writeln!(file, "// MIR for `{}` {} {}", def_path, disambiguator, pass_name)?; if let Some(ref layout) = body.generator_layout() { writeln!(file, "/* generator_layout = {:#?} */", layout)?; } @@ -168,11 +162,6 @@ fn dump_file_basename<'tcx>( body: &Body<'tcx>, ) -> String { let source = body.source; - let promotion_id = match source.promoted { - Some(id) => format!("-{:?}", id), - None => String::new(), - }; - let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number { String::new() } else { @@ -203,8 +192,8 @@ fn dump_file_basename<'tcx>( }; format!( - "{}.{}{}{}{}.{}.{}", - crate_name, item_name, shim_disambiguator, promotion_id, pass_num, pass_name, disambiguator, + "{}.{}{}{}.{}.{}", + crate_name, item_name, shim_disambiguator, pass_num, pass_name, disambiguator, ) } @@ -282,9 +271,12 @@ pub fn write_mir_pretty<'tcx>( 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)?; + if let Some(def_id) = def_id.as_local() { + for body in tcx.promoted_mir(def_id) { + writeln!(w)?; + let body = tcx.mir_for_ctfe(body.to_def_id()); + write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?; + } } Ok(()) }; @@ -474,12 +466,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { | ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal), }, ConstantKind::Unevaluated(uv, _) => { - format!( - "Unevaluated({}, {:?}, {:?})", - self.tcx.def_path_str(uv.def), - uv.substs, - uv.promoted, - ) + format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.substs,) } // To keep the diffs small, we render this like we render `ty::Const::Value`. // @@ -996,13 +983,12 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, _ => tcx.is_closure(def_id), }; - match (kind, body.source.promoted) { - (_, Some(i)) => write!(w, "{:?} in ", i)?, - (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, - (DefKind::Static(hir::Mutability::Not), _) => write!(w, "static ")?, - (DefKind::Static(hir::Mutability::Mut), _) => write!(w, "static mut ")?, - (_, _) if is_function => write!(w, "fn ")?, - (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item + match kind { + DefKind::Const | DefKind::AssocConst => write!(w, "const ")?, + DefKind::Static(hir::Mutability::Not) => write!(w, "static ")?, + DefKind::Static(hir::Mutability::Mut) => write!(w, "static mut ")?, + _ if is_function => write!(w, "fn ")?, + DefKind::AnonConst | DefKind::InlineConst | DefKind::Promoted => {} // things like anon const, not an item _ => bug!("Unexpected def kind {:?}", kind), } @@ -1011,7 +997,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res write!(w, "{}", tcx.def_path_str(def_id))? } - if body.source.promoted.is_none() && is_function { + if is_function { write!(w, "(")?; // fn argument types. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 12c94dc46760d..0f14d3aa73804 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -504,9 +504,12 @@ rustc_queries! { desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) } } - query mir_for_ctfe( - key: DefId - ) -> &'tcx mir::Body<'tcx> { + query mir_for_promoted(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> { + desc { |tcx| "caching mir of promoted constant `{}`", tcx.def_path_str(key.to_def_id()) } + feedable + } + + 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() } separate_provide_extern @@ -514,7 +517,7 @@ rustc_queries! { query mir_promoted(key: LocalDefId) -> ( &'tcx Steal<mir::Body<'tcx>>, - &'tcx Steal<IndexVec<mir::Promoted, mir::Body<'tcx>>> + &'tcx IndexVec<mir::Promoted, LocalDefId>, ) { no_hash desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) } @@ -569,10 +572,9 @@ rustc_queries! { /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because /// after inlining a body may refer to promoteds from other bodies. In that case you still /// need to use the `DefId` of the original body. - query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> { - desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern + query promoted_mir(key: LocalDefId) -> &'tcx IndexVec<mir::Promoted, LocalDefId> { + desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key.to_def_id()) } + cache_on_disk_if { true } } /// Erases regions from `ty` to yield a new type. diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 220118ae5ccb8..4f5cf4b20bfd9 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -782,10 +782,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> } } -impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> - for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> -{ - #[inline] +impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx IndexVec<mir::Promoted, LocalDefId> { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { RefDecodable::decode(d) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 1dd4f8a243741..aa8aae9a3b0d0 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -30,7 +30,7 @@ impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { impl<'tcx> UnevaluatedConst<'tcx> { #[inline] pub fn expand(self) -> mir::UnevaluatedConst<'tcx> { - mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None } + mir::UnevaluatedConst { def: self.def, substs: self.substs } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bbea3e1412b00..8478c6e0c19a0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind}; use crate::query::plumbing::QuerySystem; use crate::query::LocalCrate; use crate::query::Providers; @@ -559,7 +559,11 @@ impl<'tcx> TyCtxt<'tcx> { self.codegen_fn_attrs(def_id) } else if matches!( def_kind, - DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst + DefKind::AnonConst + | DefKind::AssocConst + | DefKind::Const + | DefKind::InlineConst + | DefKind::Promoted ) { CodegenFnAttrs::EMPTY } else { @@ -579,13 +583,6 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(Steal::new(mir)) } - pub fn alloc_steal_promoted( - self, - promoted: IndexVec<Promoted, Body<'tcx>>, - ) -> &'tcx Steal<IndexVec<Promoted, Body<'tcx>>> { - self.arena.alloc(Steal::new(promoted)) - } - pub fn mk_adt_def( self, did: DefId, @@ -2393,6 +2390,7 @@ impl<'tcx> TyCtxt<'tcx> { ) } + #[track_caller] pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId { self.opt_local_def_id_to_hir_id(local_def_id).unwrap() } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index be0d1e61a46b0..1374523930e64 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2304,7 +2304,13 @@ impl<'tcx> TyCtxt<'tcx> { let did: DefId = did.into(); let filter_fn = move |a: &&ast::Attribute| a.has_name(attr); if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + if let Some(hir_id) = self.opt_local_def_id_to_hir_id(did) { + self.hir().attrs(hir_id) + } else { + &[] + } + .iter() + .filter(filter_fn) } else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) { bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); } else { diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 64e7480e626d7..1fb0b2fa3e703 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -144,6 +144,8 @@ pub trait Printer<'tcx>: Sized { // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. DefPathData::AnonConst => {} + // Promoted do not have their own generics, so we don't print them. + DefPathData::Promoted => {} // If we have any generic arguments to print, we do that // on top of the same path, but without its own generics. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4491d78648f7a..dba9d19ec830b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1324,7 +1324,7 @@ pub trait PrettyPrinter<'tcx>: DefKind::Const | DefKind::AssocConst => { p!(print_value_path(def, substs)) } - DefKind::AnonConst => { + DefKind::AnonConst | DefKind::Promoted => { if def.is_local() && let span = self.tcx().def_span(def) && let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index eb903ebfd99fb..43dc76746f9e2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -533,7 +533,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_typeck_child(self, def_id: DefId) -> bool { matches!( self.def_kind(def_id), - DefKind::Closure | DefKind::Generator | DefKind::InlineConst + DefKind::Closure | DefKind::Generator | DefKind::InlineConst | DefKind::Promoted ) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 4d99ab4b0ec29..3ddc9b0bf4167 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -2,7 +2,6 @@ use crate::build::{parse_float_into_constval, Builder}; use rustc_ast as ast; -use rustc_middle::mir; use rustc_middle::mir::interpret::{ Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar, }; @@ -78,7 +77,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(def_id, substs); + let uneval = UnevaluatedConst::new(def_id, substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty, span, literal } @@ -90,7 +89,7 @@ pub fn as_constant_inner<'tcx>( Constant { user_ty: None, span, literal } } ExprKind::ConstBlock { did: def_id, substs } => { - let uneval = mir::UnevaluatedConst::new(def_id, substs); + let uneval = UnevaluatedConst::new(def_id, substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty: None, span, literal } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 069514d8a3bf3..ff4e48c431c83 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -148,14 +148,11 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { }; if let Some(uv) = maybe_uneval { - if uv.promoted.is_none() { - 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, .. } = - self.tcx.unsafety_check_result(local_def_id); - self.register_violations(violations, used_unsafe_blocks.items().copied()); - } + if self.tcx.def_kind(uv.def) == DefKind::InlineConst { + let local_def_id = uv.def.expect_local(); + let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = + self.tcx.unsafety_check_result(local_def_id); + self.register_violations(violations, used_unsafe_blocks.items().copied()); } } } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index a5d18fff89bd7..17ef17b02e39c 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -58,11 +58,6 @@ impl<'tcx> MirPass<'tcx> for ConstProp { #[instrument(skip(self, tcx), level = "debug")] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // will be evaluated by miri and produce its errors there - if body.source.promoted.is_some() { - return; - } - let def_id = body.source.def_id().expect_local(); let def_kind = tcx.def_kind(def_id); let is_fn_like = def_kind.is_fn_like(); diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index adb09c509d287..cffb6fd467943 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -38,11 +38,6 @@ pub struct ConstProp; impl<'tcx> MirLint<'tcx> for ConstProp { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { - // will be evaluated by miri and produce its errors there - if body.source.promoted.is_some() { - return; - } - let def_id = body.source.def_id().expect_local(); let is_fn_like = tcx.def_kind(def_id).is_fn_like(); let is_assoc_const = tcx.def_kind(def_id) == DefKind::AssocConst; diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 076e714d70370..7e4e1df3c86e0 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -16,6 +16,7 @@ use crate::MirPass; use rustc_data_structures::graph::WithNumNodes; use rustc_data_structures::sync::Lrc; +use rustc_hir::def::DefKind; use rustc_index::IndexVec; use rustc_middle::hir; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -57,7 +58,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { // If the InstrumentCoverage pass is called on promoted MIRs, skip them. // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601 - if mir_source.promoted.is_some() { + if let DefKind::Promoted = tcx.def_kind(mir_source.def_id()) { trace!( "InstrumentCoverage skipped for {:?} (already promoted for Miri evaluation)", mir_source.def_id() diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 12f955d46bd31..24e39655a4a68 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -76,9 +76,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() { return false; } - if body.source.promoted.is_some() { - return false; - } + // Avoid inlining into generators, since their `optimized_mir` is used for layout computation, // which can create a cycle, even when no attempt is made to inline the function in the other // direction. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 65864dc016f4f..5bbea37cd36a1 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -197,7 +197,7 @@ fn remap_mir_for_const_eval_select<'tcx>( } fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - tcx.mir_keys(()).contains(&def_id) + tcx.mir_keys(()).contains(&def_id) || tcx.def_kind(def_id) == DefKind::Promoted } /// Finds the full set of `DefId`s within the current crate that have @@ -292,7 +292,11 @@ fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> { fn mir_promoted( tcx: TyCtxt<'_>, def: LocalDefId, -) -> (&Steal<Body<'_>>, &Steal<IndexVec<Promoted, Body<'_>>>) { +) -> (&Steal<Body<'_>>, &IndexVec<Promoted, LocalDefId>) { + if tcx.def_kind(def) == DefKind::Promoted { + return (tcx.mir_for_promoted(def), tcx.arena.alloc(IndexVec::new())); + } + // 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. @@ -319,7 +323,7 @@ fn mir_promoted( ); let promoted = promote_pass.promoted_fragments.into_inner(); - (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) + (tcx.alloc_steal_mir(body), tcx.arena.alloc(promoted)) } /// Compute the MIR that is used during CTFE (and thus has no optimizations run on it) @@ -378,15 +382,13 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { /// 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: LocalDefId) -> &Steal<Body<'_>> { - if tcx.sess.opts.unstable_opts.drop_tracking_mir - && let DefKind::Generator = tcx.def_kind(def) - { + let def_kind = tcx.def_kind(def); + if tcx.sess.opts.unstable_opts.drop_tracking_mir && def_kind == DefKind::Generator { tcx.ensure_with_value().mir_generator_witnesses(def); } let mir_borrowck = tcx.mir_borrowck(def); - let is_fn_like = tcx.def_kind(def).is_fn_like(); - if is_fn_like { + if def_kind.is_fn_like() { // 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.to_def_id())); @@ -621,17 +623,11 @@ 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: LocalDefId) -> &IndexVec<Promoted, Body<'_>> { +fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, LocalDefId> { if tcx.is_constructor(def.to_def_id()) { return tcx.arena.alloc(IndexVec::new()); } tcx.ensure_with_value().mir_borrowck(def); - let mut promoted = tcx.mir_promoted(def).1.steal(); - - for body in &mut promoted { - run_analysis_to_runtime_passes(tcx, body); - } - - tcx.arena.alloc(promoted) + tcx.mir_promoted(def).1 } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 88a3e028527a3..1c66299813744 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -161,7 +161,6 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder | DefKind::Field @@ -175,6 +174,16 @@ fn mark_used_by_default_parameters<'tcx>( } } } + DefKind::InlineConst | DefKind::Promoted => { + for param in &generics.params { + debug!(?param, "(other)"); + if let ty::GenericParamDefKind::Lifetime = param.kind { + unused_parameters.mark_used(param.index); + } + } + // The last generic parameter is `<const_ty>`, which is a dummy for typeck purposes. + unused_parameters.mark_used((generics.count() - 1).try_into().unwrap()); + } } if let Some(parent) = generics.parent { @@ -268,18 +277,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { ConstantKind::Ty(c) => { c.visit_with(self); } - ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted }, ty) => { + ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs }, ty) => { // 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 && !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); - self.visit_body(&promoted[p]); - } + // `<Self as Foo<T>>::foo::{promoted#p}` + if let DefKind::Promoted = self.tcx.def_kind(def) { + self.visit_child_body(def, substs); } - Visitor::visit_ty(self, ty, TyContext::Location(location)); } ConstantKind::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)), diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 7b39cb0a06891..8d9803539627d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -692,6 +692,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::InlineConst | DefKind::Field | DefKind::GlobalAsm + | DefKind::Promoted | DefKind::Impl { .. } | DefKind::Closure | DefKind::Generator => (), diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2438b3a38ed4d..9f5143c84761e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -979,6 +979,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Closure + | DefKind::Promoted | DefKind::Impl { .. } | DefKind::Generator, _, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 874d578fe1db3..1ecbccef7c6fa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1145,6 +1145,7 @@ symbols! { proc_macro_path_invoc, profiler_builtins, profiler_runtime, + promoted, ptr, ptr_guaranteed_cmp, ptr_mask, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index c281aa7e83a85..663db908b9b45 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -372,6 +372,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { hir::definitions::DefPathData::ClosureExpr => "C", hir::definitions::DefPathData::Ctor => "c", hir::definitions::DefPathData::AnonConst => "k", + hir::definitions::DefPathData::Promoted => "p", hir::definitions::DefPathData::ImplTrait => "i", hir::definitions::DefPathData::CrateRoot | hir::definitions::DefPathData::Use diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 2235524129e62..14dff2cc1a72e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -777,6 +777,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { DefPathData::ClosureExpr => 'C', DefPathData::Ctor => 'c', DefPathData::AnonConst => 'k', + DefPathData::Promoted => 'p', DefPathData::ImplTrait => 'i', // These should never show up as `path_append` arguments. diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 081be065864c8..d43d30cad6f6f 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -68,6 +68,7 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> { | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm + | DefKind::Promoted | DefKind::Closure | DefKind::Generator => ty::List::empty(), } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4e91dd380e865..271b179de4d80 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -183,6 +183,7 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::Promoted | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 65dc3c39c6ae6..5fd11bcc97ad4 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -118,6 +118,10 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] { /// See `ParamEnv` struct definition for details. fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { + if let DefKind::Promoted = tcx.def_kind(def_id) { + return tcx.param_env(tcx.parent(def_id)); + } + // Compute the bounds on Self and the type parameters. let ty::InstantiatedPredicates { mut predicates, .. } = tcx.predicates_of(def_id).instantiate_identity(tcx); diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 452e14918faf7..21549e91d049f 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -135,6 +135,7 @@ impl From<DefKind> for ItemType { | DefKind::ForeignMod | DefKind::AnonConst | DefKind::InlineConst + | DefKind::Promoted | DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder | DefKind::Field diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9381b3e0567a5..d553323b8cc99 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1810,6 +1810,7 @@ fn resolution_failure( | LifetimeParam | Ctor(_, _) | AnonConst + | Promoted | InlineConst => { let note = assoc_item_not_allowed(res); if let Some(span) = sp { diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index a2b49e6f219d3..b33a173787e3b 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -160,7 +160,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> { let this = self.eval_context_ref(); let instance = this.resolve_path(path, Namespace::ValueNS); - let cid = GlobalId { instance, promoted: None }; + let cid = GlobalId { instance }; // We don't give a span -- this isn't actually used directly by the program anyway. let const_val = this .eval_global(cid, None) @@ -358,7 +358,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Push frame. - let mir = this.load_mir(f.def, None)?; + let mir = this.load_mir(f.def)?; let dest = match dest { Some(dest) => dest.clone(), None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?).into(), diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 44bca3796f9af..c8c0e413030cb 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -228,7 +228,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; match instance { None => Ok(None), // no symbol with this name - Some(instance) => Ok(Some((this.load_mir(instance.def, None)?, instance))), + Some(instance) => Ok(Some((this.load_mir(instance.def)?, instance))), } } @@ -283,7 +283,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); return Ok(Some(( - this.load_mir(panic_impl_instance.def, None)?, + this.load_mir(panic_impl_instance.def)?, panic_impl_instance, ))); } diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 918efda3777fa..55350823c881f 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -59,7 +59,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Otherwise, load the MIR. - Ok(Some((this.load_mir(instance.def, None)?, instance))) + Ok(Some((this.load_mir(instance.def)?, instance))) } /// Returns `true` if the computation was performed, and `false` if we should just evaluate diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff index 15117ea890e38..708a3cfa5c73d 100644 --- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff +++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff @@ -40,7 +40,7 @@ _2 = Option::<NonZeroU8>::Some(const _); // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58 // mir::Constant // + span: $DIR/combine_transmutes.rs:35:33: 35:57 - // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) } + // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, []) } _1 = move _2 as u8 (Transmute); // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:59 StorageDead(_2); // scope 0 at $DIR/combine_transmutes.rs:+1:58: +1:59 StorageLive(_3); // scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11 diff --git a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.BAR-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir similarity index 93% rename from tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir rename to tests/mir-opt/const_promotion_extern_static.BAR-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir index 028480bdc88b4..bff01eeba10a4 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.BAR-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir @@ -1,6 +1,6 @@ -// MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops +// MIR for `BAR::{promoted#0}` after SimplifyCfg-elaborate-drops -promoted[0] in BAR: &[&i32; 1] = { +BAR::{promoted#0}: &[&i32; 1] = { let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 let mut _1: [&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 let mut _2: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:34 diff --git a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index 2ef4378115fbe..0584e5d5a57b9 100644 --- a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -25,7 +25,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:35 - _2 = &_3; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 + // + span: $DIR/const_promotion_extern_static.rs:9:31: 9:44 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(BAR, [], Some(promoted[0])) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(BAR::{promoted#0}, [&[&i32; 1]]) } + _2 = &(*_6); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:44 - StorageDead(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:34: +0:35 diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir similarity index 92% rename from tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir rename to tests/mir-opt/const_promotion_extern_static.FOO-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir index 41657b53fc12c..cadb50a3fa8d2 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/const_promotion_extern_static.FOO-{promoted#0}.SimplifyCfg-elaborate-drops.after.mir @@ -1,6 +1,6 @@ -// MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops +// MIR for `FOO::{promoted#0}` after SimplifyCfg-elaborate-drops -promoted[0] in FOO: &[&i32; 1] = { +FOO::{promoted#0}: &[&i32; 1] = { let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 let mut _1: [&i32; 1]; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 let mut _2: &i32; // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45 diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index 25ba0face6bd8..466bb7b56f37f 100644 --- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -27,7 +27,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46 - _2 = &_3; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 + // + span: $DIR/const_promotion_extern_static.rs:13:31: 13:55 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(FOO, [], Some(promoted[0])) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(FOO::{promoted#0}, [&[&i32; 1]]) } + _2 = &(*_6); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55 - StorageDead(_4); // scope 0 at $DIR/const_promotion_extern_static.rs:+0:45: +0:46 diff --git a/tests/mir-opt/const_promotion_extern_static.rs b/tests/mir-opt/const_promotion_extern_static.rs index e4261cfe50447..9f6d349367537 100644 --- a/tests/mir-opt/const_promotion_extern_static.rs +++ b/tests/mir-opt/const_promotion_extern_static.rs @@ -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].SimplifyCfg-elaborate-drops.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].SimplifyCfg-elaborate-drops.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.built.after.mir diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index d72675c2d1157..484a357783c30 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -28,7 +28,7 @@ _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:9:25: 9:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(main::{promoted#0}, [&[i32; 3]]) } _3 = &(*_9); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index d75fae30b5386..57f3c8043f7ff 100644 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -19,7 +19,7 @@ _3 = const _; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 // mir::Constant // + span: $DIR/const_prop_fails_gracefully.rs:9:13: 9:16 - // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } + // + literal: Const { ty: &i32, val: Unevaluated(FOO, []) } _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39 StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:38: +2:39 diff --git a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff index 924a267f3d8ff..bd1ba3c7d6515 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -14,7 +14,7 @@ _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 // mir::Constant // + span: $DIR/ref_deref.rs:5:6: 5:10 - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(main::{promoted#0}, [&i32]) } _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11 diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index 59095b4483713..2d2f176784081 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -14,7 +14,7 @@ _4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 // mir::Constant // + span: $DIR/ref_deref_project.rs:5:6: 5:17 - // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &(i32, i32), val: Unevaluated(main::{promoted#0}, [&(i32, i32)]) } _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18 diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index 8bd2b48d6d6af..975f5e82b6d8c 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -21,7 +21,7 @@ _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant // + span: $DIR/slice_len.rs:8:6: 8:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(main::{promoted#0}, [&[u32; 3]]) } _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 diff --git a/tests/mir-opt/derefer_complex_case.main.Derefer.diff b/tests/mir-opt/derefer_complex_case.main.Derefer.diff index fa3eeedc40fff..3c7887ebb8d4f 100644 --- a/tests/mir-opt/derefer_complex_case.main.Derefer.diff +++ b/tests/mir-opt/derefer_complex_case.main.Derefer.diff @@ -31,7 +31,7 @@ _14 = const _; // scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 // mir::Constant // + span: $DIR/derefer_complex_case.rs:6:17: 6:26 - // + literal: Const { ty: &[i32; 2], val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &[i32; 2], val: Unevaluated(main::{promoted#0}, [&[i32; 2]]) } _2 = &(*_14); // scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 _1 = <&[i32; 2] as IntoIterator>::into_iter(move _2) -> bb1; // scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26 // mir::Constant diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir index 60149ff36064e..f9b19f86b2586 100644 --- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -35,7 +35,7 @@ fn bar() -> bool { _10 = const _; // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 // mir::Constant // + span: $DIR/inline_retag.rs:12:7: 12:9 - // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) } + // + literal: Const { ty: &i32, val: Unevaluated(bar::{promoted#1}, [&i32]) } Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 _4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 _3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 @@ -44,7 +44,7 @@ fn bar() -> bool { _9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 // mir::Constant // + span: $DIR/inline_retag.rs:12:11: 12:14 - // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(bar::{promoted#0}, [&i32]) } Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff index 3aebfb69e0ae1..ae3ad44284598 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff @@ -23,7 +23,7 @@ - // + span: $DIR/issue_106141.rs:3:5: 3:10 - // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) } + // + span: $DIR/issue_106141.rs:12:18: 12:25 -+ // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) } ++ // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner::{promoted#0}, [&[bool; 1]]) } + _0 = index() -> bb1; // scope 2 at $DIR/issue_106141.rs:13:17: 13:24 + // mir::Constant + // + span: $DIR/issue_106141.rs:13:17: 13:22 diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index 1f03b7b0baf4b..e7585dcea61a7 100644 --- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -47,7 +47,7 @@ _19 = const _; // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 // mir::Constant // + span: $DIR/lower_intrinsics.rs:83:42: 83:44 - // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) } + // + literal: Const { ty: &i32, val: Unevaluated(discriminant::{promoted#2}, [T, &i32]) } _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 - _5 = discriminant_value::<i32>(move _6) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 @@ -68,7 +68,7 @@ _18 = const _; // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 // mir::Constant // + span: $DIR/lower_intrinsics.rs:84:42: 84:45 - // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) } + // + literal: Const { ty: &(), val: Unevaluated(discriminant::{promoted#1}, [T, &()]) } _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 - _9 = discriminant_value::<()>(move _10) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 @@ -89,7 +89,7 @@ _17 = const _; // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 // mir::Constant // + span: $DIR/lower_intrinsics.rs:85:42: 85:47 - // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) } + // + literal: Const { ty: &E, val: Unevaluated(discriminant::{promoted#0}, [T, &E]) } _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 - _13 = discriminant_value::<E>(move _14) -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff index 07bd48fc84638..331cf065e9994 100644 --- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff @@ -67,7 +67,7 @@ _28 = const _; // scope 1 at $DIR/reference_prop.rs:+4:17: +4:24 // mir::Constant // + span: $DIR/reference_prop.rs:535:17: 535:24 - // + literal: Const { ty: &T, val: Unevaluated(debuginfo, [], Some(promoted[2])) } + // + literal: Const { ty: &T, val: Unevaluated(debuginfo::{promoted#2}, [&debuginfo::T]) } - _3 = &((*_28).0: u8); // scope 1 at $DIR/reference_prop.rs:+4:17: +4:24 - StorageLive(_5); // scope 2 at $DIR/reference_prop.rs:+7:9: +7:17 - _5 = &(*_1); // scope 2 at $DIR/reference_prop.rs:+7:20: +7:32 @@ -83,7 +83,7 @@ _27 = const _; // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31 // mir::Constant // + span: $DIR/reference_prop.rs:542:14: 542:31 - // + literal: Const { ty: &Option<i32>, val: Unevaluated(debuginfo, [], Some(promoted[1])) } + // + literal: Const { ty: &Option<i32>, val: Unevaluated(debuginfo::{promoted#1}, [&std::option::Option<i32>]) } - _9 = &(((*_27) as Some).0: i32); // scope 3 at $DIR/reference_prop.rs:+11:14: +11:31 - _6 = const (); // scope 4 at $DIR/reference_prop.rs:+11:36: +11:38 - StorageDead(_9); // scope 3 at $DIR/reference_prop.rs:+11:37: +11:38 @@ -109,7 +109,7 @@ _26 = const _; // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90 // mir::Constant // + span: $DIR/reference_prop.rs:547:83: 547:90 - // + literal: Const { ty: &[i32; 10], val: Unevaluated(debuginfo, [], Some(promoted[0])) } + // + literal: Const { ty: &[i32; 10], val: Unevaluated(debuginfo::{promoted#0}, [&[i32; 10]]) } _13 = &(*_26); // scope 5 at $DIR/reference_prop.rs:+16:83: +16:90 StorageLive(_15); // scope 5 at $DIR/reference_prop.rs:+16:91: +16:93 _15 = RangeFull; // scope 5 at $DIR/reference_prop.rs:+16:91: +16:93 diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 3b479710b4f2d..052910652f27a 100644 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -119,7 +119,7 @@ fn array_casts() -> () { _35 = const _; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) } + // + literal: Const { ty: &usize, val: Unevaluated(array_casts::{promoted#0}, [&usize]) } Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 4eef028e1ccb9..e2e85d3ecd750 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -142,7 +142,7 @@ fn main() -> () { _28 = const _; // scope 7 at $DIR/retag.rs:+18:21: +18:23 // mir::Constant // + span: $DIR/retag.rs:48:21: 48:23 - // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &i32, val: Unevaluated(main::{promoted#0}, [&i32]) } Retag(_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _23 = &(*_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _22 = &(*_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index 9bda5f575c99f..4415042f201cd 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -99,7 +99,7 @@ _26 = const _; // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 // mir::Constant // + span: $DIR/lifetimes.rs:27:19: 27:28 - // + literal: Const { ty: &[&str; 3], val: Unevaluated(foo, [T], Some(promoted[0])) } + // + literal: Const { ty: &[&str; 3], val: Unevaluated(foo::{promoted#0}, [T, &[&str; 3]]) } _14 = &(*_26); // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 _13 = &(*_14); // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 _12 = move _13 as &[&str] (Pointer(Unsize)); // scope 4 at $DIR/lifetimes.rs:+10:19: +10:28 diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr index a1483911b297d..706fafc5df3c1 100644 --- a/tests/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr @@ -10,7 +10,7 @@ note: ...which requires const-evaluating + checking `Tr::B`... LL | const B: u8 = Self::A; | ^^^^^^^ = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle -note: cycle used when const-evaluating + checking `main::promoted[1]` +note: cycle used when const-evaluating + checking `main::{promoted#1}` --> $DIR/defaults-cyclic-fail.rs:16:16 | LL | assert_eq!(<() as Tr>::A, 0); diff --git a/tests/ui/borrowck/issue-81899.rs b/tests/ui/borrowck/issue-81899.rs index 1f1af5c7e0502..e67559580d363 100644 --- a/tests/ui/borrowck/issue-81899.rs +++ b/tests/ui/borrowck/issue-81899.rs @@ -8,7 +8,7 @@ const fn f<F>(_: &[u8], _: F) -> &[u8] where F: FnMut(&u8), { - panic!() //~ ERROR evaluation of constant value failed + panic!() //~ ERROR evaluation of `_CONST::{promoted#0}` failed //~^ panic } diff --git a/tests/ui/borrowck/issue-81899.stderr b/tests/ui/borrowck/issue-81899.stderr index 1b03bc3af9c72..6f62395e4dbb5 100644 --- a/tests/ui/borrowck/issue-81899.stderr +++ b/tests/ui/borrowck/issue-81899.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of constant value failed +error[E0080]: evaluation of `_CONST::{promoted#0}` failed --> $DIR/issue-81899.rs:11:5 | LL | panic!() @@ -9,7 +9,7 @@ note: inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` | LL | panic!() | ^^^^^^^^ -note: inside `_CONST` +note: inside `_CONST::{promoted#0}` --> $DIR/issue-81899.rs:4:24 | LL | const _CONST: &[u8] = &f(&[], |_| {}); diff --git a/tests/ui/borrowck/issue-88434-minimal-example.rs b/tests/ui/borrowck/issue-88434-minimal-example.rs index b75abcb731e23..05cf90c5a751c 100644 --- a/tests/ui/borrowck/issue-88434-minimal-example.rs +++ b/tests/ui/borrowck/issue-88434-minimal-example.rs @@ -7,7 +7,7 @@ const fn f<F>(_: &F) where F: FnMut(&u8), { - panic!() //~ ERROR evaluation of constant value failed + panic!() //~ ERROR evaluation of `_CONST::{promoted#0}` failed //~^ panic } diff --git a/tests/ui/borrowck/issue-88434-minimal-example.stderr b/tests/ui/borrowck/issue-88434-minimal-example.stderr index a5a571c6d4df0..6f5f23a627591 100644 --- a/tests/ui/borrowck/issue-88434-minimal-example.stderr +++ b/tests/ui/borrowck/issue-88434-minimal-example.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of constant value failed +error[E0080]: evaluation of `_CONST::{promoted#0}` failed --> $DIR/issue-88434-minimal-example.rs:10:5 | LL | panic!() @@ -9,7 +9,7 @@ note: inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` | LL | panic!() | ^^^^^^^^ -note: inside `_CONST` +note: inside `_CONST::{promoted#0}` --> $DIR/issue-88434-minimal-example.rs:3:22 | LL | const _CONST: &() = &f(&|_| {}); diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs index f9134e669dcab..92856a1e72b31 100644 --- a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs @@ -7,7 +7,7 @@ const fn f<F>(_: &[u8], _: F) -> &[u8] where F: FnMut(&u8), { - panic!() //~ ERROR evaluation of constant value failed + panic!() //~ ERROR evaluation of `_CONST::{promoted#0}` failed //~^ panic } diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index 00023c459a8e7..a414339c9b7f2 100644 --- a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -1,4 +1,4 @@ -error[E0080]: evaluation of constant value failed +error[E0080]: evaluation of `_CONST::{promoted#0}` failed --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5 | LL | panic!() @@ -9,7 +9,7 @@ note: inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31 | LL | panic!() | ^^^^^^^^ -note: inside `_CONST` +note: inside `_CONST::{promoted#0}` --> $DIR/issue-88434-removal-index-should-be-less.rs:3:24 | LL | const _CONST: &[u8] = &f(&[], |_| {}); diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index a32d4863a38f0..906a4e3c1172a 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -330,10 +330,10 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:160:1 + --> $DIR/raw-bytes.rs:160:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: 8, align: 8) { @@ -347,10 +347,10 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:166:1 + --> $DIR/raw-bytes.rs:166:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: 8, align: 8) { @@ -364,10 +364,10 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:170:1 + --> $DIR/raw-bytes.rs:170:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: 8, align: 8) { diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs index a5d2ea0148659..b4914e670d994 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.rs +++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs @@ -34,10 +34,10 @@ const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; //~^ ERROR evaluation of constant value failed const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; -//~^ ERROR evaluation of constant value failed +//~^ ERROR evaluation of `REF_AS_USIZE_SLICE::{promoted#0}` failed const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR evaluation of `REF_AS_USIZE_BOX_SLICE::{promoted#0}` failed const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; //~^ ERROR it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr index 1d19dfff50b36..55737721a63f2 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -51,7 +51,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: evaluation of constant value failed +error[E0080]: evaluation of `REF_AS_USIZE_SLICE::{promoted#0}` failed --> $DIR/ub-ref-ptr.rs:36:39 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; @@ -66,7 +66,7 @@ note: erroneous constant used LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0080]: evaluation of constant value failed +error[E0080]: evaluation of `REF_AS_USIZE_BOX_SLICE::{promoted#0}` failed --> $DIR/ub-ref-ptr.rs:39:86 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index f38e7916b7553..25f340067129c 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -129,10 +129,10 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:85:1 + --> $DIR/ub-wide-ptr.rs:85:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -146,10 +146,10 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:92:1 + --> $DIR/ub-wide-ptr.rs:92:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -163,10 +163,10 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:96:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr index 07f36ee283264..d62c365ff74f6 100644 --- a/tests/ui/consts/invalid-union.64bit.stderr +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -1,8 +1,8 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-union.rs:41:1 + --> $DIR/invalid-union.rs:42:25 | -LL | fn main() { - | ^^^^^^^^^ constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const` +LL | let _: &'static _ = &C; + | ^^ constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const` | = 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 raw bytes of the constant (size: 8, align: 8) { @@ -10,13 +10,13 @@ LL | fn main() { } note: erroneous constant used - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:42:25 | LL | let _: &'static _ = &C; | ^^ note: erroneous constant used - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:42:25 | LL | let _: &'static _ = &C; | ^^ diff --git a/tests/ui/consts/invalid-union.rs b/tests/ui/consts/invalid-union.rs index 28706b4a923e7..de9d62eb07740 100644 --- a/tests/ui/consts/invalid-union.rs +++ b/tests/ui/consts/invalid-union.rs @@ -38,7 +38,7 @@ const C: S = { s }; -fn main() { //~ ERROR it is undefined behavior to use this value - // FIXME the span here is wrong, sould be pointing at the line below, not above. +fn main() { let _: &'static _ = &C; + //~^ ERROR it is undefined behavior to use this value } diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index 510b36edd8f47..d54c14cc5a90b 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -3,7 +3,7 @@ error[E0080]: values of the type `[u8; usize::MAX]` are too big for the current | note: inside `std::mem::size_of::<[u8; usize::MAX]>` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -note: inside `main` +note: inside `main::{promoted#0}` --> $DIR/issue-55878.rs:7:26 | LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 04616f9b7028b..80b8e812f6527 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -1,3 +1,11 @@ +note: no external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:23:26 + | +LL | let cell = Cell::new(&()); + | ^^^ + | + = note: defining inline constant type: generic<T>::{promoted#0} + note: external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:24:24 | diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr index 132a00ba41581..74ed89672e7ba 100644 --- a/tests/ui/nll/user-annotations/promoted-annotation.stderr +++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a>() { LL | let x = 0; | - binding `x` declared here LL | let f = &drop::<&'a i32>; - | ---------------- assignment requires that `x` is borrowed for `'a` + | ---------------- using this value as a constant requires that `x` is borrowed for `'a` LL | f(&x); | ^^ borrowed value does not live long enough LL | diff --git a/tests/ui/polymorphization/promoted-function-1.rs b/tests/ui/polymorphization/promoted-function-1.rs index 2cd02673442fe..8e9f4cdf3a165 100644 --- a/tests/ui/polymorphization/promoted-function-1.rs +++ b/tests/ui/polymorphization/promoted-function-1.rs @@ -9,4 +9,5 @@ fn foo<'a>(_: &'a ()) {} pub fn test<T>() { //~^ ERROR item has unused generic parameters foo(&()); + //~^ ERROR item has unused generic parameters } diff --git a/tests/ui/polymorphization/promoted-function-1.stderr b/tests/ui/polymorphization/promoted-function-1.stderr index fcbb86949232b..4ed36c86bf67f 100644 --- a/tests/ui/polymorphization/promoted-function-1.stderr +++ b/tests/ui/polymorphization/promoted-function-1.stderr @@ -1,8 +1,17 @@ +error: item has unused generic parameters + --> $DIR/promoted-function-1.rs:11:9 + | +LL | pub fn test<T>() { + | - generic parameter `T` is unused +LL | +LL | foo(&()); + | ^^^ + error: item has unused generic parameters --> $DIR/promoted-function-1.rs:9:8 | LL | pub fn test<T>() { | ^^^^ - generic parameter `T` is unused -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/polymorphization/unsized_cast.rs b/tests/ui/polymorphization/unsized_cast.rs index b803fec2ccfdb..fe89ce07480c8 100644 --- a/tests/ui/polymorphization/unsized_cast.rs +++ b/tests/ui/polymorphization/unsized_cast.rs @@ -10,7 +10,8 @@ fn foo<T: Default>() { let _: T = Default::default(); (|| Box::new(|| {}) as Box<dyn Fn()>)(); //~^ ERROR item has unused generic parameters - //~^^ ERROR item has unused generic parameters + //~| ERROR item has unused generic parameters + //~| ERROR item has unused generic parameters } #[rustc_polymorphize_error] @@ -18,9 +19,11 @@ fn foo2<T: Default>() { let _: T = Default::default(); (|| { //~^ ERROR item has unused generic parameters + //~| ERROR item has unused generic parameters let call: extern "rust-call" fn(_, _) = Fn::call; call(&|| {}, ()); //~^ ERROR item has unused generic parameters + //~| ERROR item has unused generic parameters })(); } diff --git a/tests/ui/polymorphization/unsized_cast.stderr b/tests/ui/polymorphization/unsized_cast.stderr index 27f88d2817464..757ee9f9857ff 100644 --- a/tests/ui/polymorphization/unsized_cast.stderr +++ b/tests/ui/polymorphization/unsized_cast.stderr @@ -17,7 +17,16 @@ LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); | ^^ error: item has unused generic parameters - --> $DIR/unsized_cast.rs:22:15 + --> $DIR/unsized_cast.rs:11:5 + | +LL | fn foo<T: Default>() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:24:15 | LL | fn foo2<T: Default>() { | - generic parameter `T` is unused @@ -26,7 +35,16 @@ LL | call(&|| {}, ()); | ^^ error: item has unused generic parameters - --> $DIR/unsized_cast.rs:19:6 + --> $DIR/unsized_cast.rs:24:14 + | +LL | fn foo2<T: Default>() { + | - generic parameter `T` is unused +... +LL | call(&|| {}, ()); + | ^^^^^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:20:6 | LL | fn foo2<T: Default>() { | - generic parameter `T` is unused @@ -34,5 +52,20 @@ LL | let _: T = Default::default(); LL | (|| { | ^^ -error: aborting due to 4 previous errors +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:20:5 + | +LL | fn foo2<T: Default>() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | / (|| { +LL | | +LL | | +LL | | let call: extern "rust-call" fn(_, _) = Fn::call; +... | +LL | | +LL | | })(); + | |______^ + +error: aborting due to 7 previous errors diff --git a/tests/ui/query-system/query_depth.rs b/tests/ui/query-system/query_depth.rs index e600c1c08e5cf..58032bb2281dc 100644 --- a/tests/ui/query-system/query_depth.rs +++ b/tests/ui/query-system/query_depth.rs @@ -26,6 +26,6 @@ type Byte = Option<Option<Option<Option< Option<Option<Option<Option< >>>> >>>>; fn main() { -//~^ ERROR: queries overflow the depth limit! println!("{}", std::mem::size_of::<Byte>()); + //~^ ERROR: queries overflow the depth limit! } diff --git a/tests/ui/query-system/query_depth.stderr b/tests/ui/query-system/query_depth.stderr index 43a18b4e07455..b3c346a40e413 100644 --- a/tests/ui/query-system/query_depth.stderr +++ b/tests/ui/query-system/query_depth.stderr @@ -1,11 +1,12 @@ error: queries overflow the depth limit! - --> $DIR/query_depth.rs:28:1 + --> $DIR/query_depth.rs:29:20 | -LL | fn main() { - | ^^^^^^^^^ +LL | println!("{}", std::mem::size_of::<Byte>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`) = note: query depth increased by 66 when computing layout of `core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<alloc::boxed::Box<alloc::string::String>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/rfcs/rfc1623-2.rs b/tests/ui/rfcs/rfc1623-2.rs index c0e13a5f5f031..ccd373475e915 100644 --- a/tests/ui/rfcs/rfc1623-2.rs +++ b/tests/ui/rfcs/rfc1623-2.rs @@ -50,9 +50,9 @@ static STATIC_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8] const CONST_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); // this should be the same as without elision -static STATIC_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = +static STATIC_NON_ELIDED_FN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); -const CONST_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = +const CONST_NON_ELIDED_FN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); // another function that elides, each to a different unbound lifetime From 6fc8881a25ab4fe29e9cb7f326299482d9221187 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 14:13:45 +0000 Subject: [PATCH 02/15] Do not check user type annotations for promoted. --- compiler/rustc_borrowck/src/type_check/mod.rs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 11e09ac20e019..44f3f838f58e5 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -948,6 +948,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// Equate the inferred type and the annotated type for user type annotations #[instrument(skip(self), level = "debug")] fn check_user_type_annotations(&mut self) { + // Promoted clone the `user_type_annotations` from their original body, because some + // statements may refer to them. However, we don't want to apply the other type annotations + // while checking the promoted: that would create spurious constraints that we won't be + // able to verify. Instead, the annotations are checked on-demand before relating to the + // actual type in MIR. + if let DefKind::Promoted = self.tcx().def_kind(self.body.source.def_id()) { + debug!("promoted: skipping user type annotations"); + return; + } + debug!(?self.user_type_annotations); for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; @@ -1012,12 +1022,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory<'tcx>, ) -> Fallible<()> { - let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; + let CanonicalUserTypeAnnotation { + span, + user_ty: ref canonical_user_ty, + inferred_ty: annotated_type, + } = self.user_type_annotations[user_ty.base]; trace!(?annotated_type); - let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); + + // We may have skipped checking the canonical annotation earlier, so do it now. + if let DefKind::Promoted = self.tcx().def_kind(self.body.source.def_id()) { + let annotation = + self.instantiate_canonical_with_fresh_inference_vars(span, canonical_user_ty); + self.ascribe_user_type(annotated_type, annotation, span); + } let tcx = self.infcx.tcx; + let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); for proj in &user_ty.projs { if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() { // There is nothing that we can compare here if we go through an opaque type. From c1a89fcd0648c643415ab80d159e3ee81975f4be Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 15:57:06 +0000 Subject: [PATCH 03/15] Select user type annotations instead of cloning them. --- compiler/rustc_borrowck/src/type_check/mod.rs | 25 +----------- .../src/transform/promote_consts.rs | 38 ++++++++++++++++++- compiler/rustc_middle/src/mir/visit.rs | 19 ++++++++-- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 44f3f838f58e5..11e09ac20e019 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -948,16 +948,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// Equate the inferred type and the annotated type for user type annotations #[instrument(skip(self), level = "debug")] fn check_user_type_annotations(&mut self) { - // Promoted clone the `user_type_annotations` from their original body, because some - // statements may refer to them. However, we don't want to apply the other type annotations - // while checking the promoted: that would create spurious constraints that we won't be - // able to verify. Instead, the annotations are checked on-demand before relating to the - // actual type in MIR. - if let DefKind::Promoted = self.tcx().def_kind(self.body.source.def_id()) { - debug!("promoted: skipping user type annotations"); - return; - } - debug!(?self.user_type_annotations); for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; @@ -1022,23 +1012,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory<'tcx>, ) -> Fallible<()> { - let CanonicalUserTypeAnnotation { - span, - user_ty: ref canonical_user_ty, - inferred_ty: annotated_type, - } = self.user_type_annotations[user_ty.base]; + let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; trace!(?annotated_type); - - // We may have skipped checking the canonical annotation earlier, so do it now. - if let DefKind::Promoted = self.tcx().def_kind(self.body.source.def_id()) { - let annotation = - self.instantiate_canonical_with_fresh_inference_vars(span, canonical_user_ty); - self.ascribe_user_type(annotated_type, annotation, span); - } + let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); let tcx = self.infcx.tcx; - let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); for proj in &user_ty.projs { if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() { // There is nothing that we can compare here if we go through an opaque type. diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index e7333ba8e98d0..7c2299061bbfb 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -12,13 +12,14 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. +use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::traversal::ReversePostorderIter; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt, UserTypeAnnotationIndex}; use rustc_span::def_id::LocalDefId; use rustc_span::Span; @@ -881,6 +882,22 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, rvalue, span); + // Copy user type annotations from the original body to the promoted. + // We don't want to keep all the original annotations, as they may create + // constants that borrowck will not be able to verify. However, we still + // need some of them to borrow-check the promoted itself. + // + // We don't remove the cloned annotations from the original body, as they + // are harmless there. + let mut annotation_renumber = + RenumberUserTypeAnnotations { tcx, mapping: FxIndexSet::default() }; + annotation_renumber.visit_body_preserves_cfg(&mut self.promoted); + self.promoted.user_type_annotations = annotation_renumber + .mapping + .iter() + .map(|&original_index| self.source.user_type_annotations[original_index].clone()) + .collect(); + let source_def_id = self.source.source.def_id().expect_local(); let feeder = tcx.at(span).create_def(source_def_id, hir::definitions::DefPathData::Promoted); @@ -935,6 +952,23 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { } } +/// Replaces type annotation indices. +struct RenumberUserTypeAnnotations<'tcx> { + tcx: TyCtxt<'tcx>, + mapping: FxIndexSet<UserTypeAnnotationIndex>, +} + +impl<'tcx> MutVisitor<'tcx> for RenumberUserTypeAnnotations<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_user_type_annotation_index(&mut self, annotation: &mut UserTypeAnnotationIndex) { + let (new_index, _) = self.mapping.insert_full(*annotation); + *annotation = UserTypeAnnotationIndex::from_usize(new_index); + } +} + pub fn promote_candidates<'tcx>( body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, @@ -970,7 +1004,7 @@ pub fn promote_candidates<'tcx>( IndexVec::new(), IndexVec::from_elem_n(scope, 1), initial_locals, - body.user_type_annotations.clone(), + IndexVec::new(), 0, vec![], body.span, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 596dd80bf4874..c47a8c8e26322 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -156,6 +156,12 @@ macro_rules! make_mir_visitor { self.super_ascribe_user_ty(place, variance, user_ty, location); } + fn visit_user_type_annotation_index( + &mut self, + _index: $(& $mutability)? UserTypeAnnotationIndex, + ) { + } + fn visit_coverage( &mut self, coverage: & $($mutability)? Coverage, @@ -724,10 +730,13 @@ macro_rules! make_mir_visitor { _adt_def, _variant_index, substs, - _user_substs, + user_substs, _active_field_index ) => { self.visit_substs(substs, location); + if let Some(user_substs) = user_substs { + self.visit_user_type_annotation_index($(& $mutability)? *user_substs); + } } AggregateKind::Closure( _, @@ -881,11 +890,14 @@ macro_rules! make_mir_visitor { ) { let Constant { span, - user_ty: _, // no visit method for this + user_ty, literal, } = constant; self.visit_span($(& $mutability)? *span); + if let Some(user_ty) = user_ty { + self.visit_user_type_annotation_index($(& $mutability)? *user_ty); + } match literal { ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location), ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), @@ -916,8 +928,9 @@ macro_rules! make_mir_visitor { fn super_user_type_projection( &mut self, - _ty: & $($mutability)? UserTypeProjection, + ty: & $($mutability)? UserTypeProjection, ) { + self.visit_user_type_annotation_index($(&$mutability)? ty.base); } fn super_user_type_annotation( From c15438ae43f10a88e0564e56f4b2aeedc5a4b530 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 14:07:41 +0000 Subject: [PATCH 04/15] Remove useless parameter. --- .../rustc_borrowck/src/region_infer/mod.rs | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8fbe814c85607..f6c286fdb8fcd 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -642,7 +642,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { polonius_output: Option<Rc<PoloniusOutput>>, ) -> (Option<ClosureRegionRequirements<'tcx>>, RegionErrors<'tcx>) { let mir_def_id = body.source.def_id(); - self.propagate_constraints(body); + self.propagate_constraints(); let mut errors_buffer = RegionErrors::new(infcx.tcx); @@ -653,13 +653,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // eagerly. let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests( - infcx, - param_env, - body, - outlives_requirements.as_mut(), - &mut errors_buffer, - ); + self.check_type_tests(infcx, param_env, outlives_requirements.as_mut(), &mut errors_buffer); // In Polonius mode, the errors about missing universal region relations are in the output // and need to be emitted or propagated. Otherwise, we need to check whether the @@ -695,8 +689,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be /// feasible, but we check this later. - #[instrument(skip(self, _body), level = "debug")] - fn propagate_constraints(&mut self, _body: &Body<'tcx>) { + #[instrument(skip(self), level = "debug")] + fn propagate_constraints(&mut self) { debug!("constraints={:#?}", { let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); @@ -908,7 +902,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - body: &Body<'tcx>, mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, errors_buffer: &mut RegionErrors<'tcx>, ) { @@ -937,7 +930,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { if self.try_promote_type_test( infcx, param_env, - body, type_test, propagated_outlives_requirements, ) { @@ -990,12 +982,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// The idea then is to lower the `T: 'X` constraint into multiple /// bounds -- e.g., if `'X` is the union of two free lifetimes, /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. - #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] + #[instrument( + level = "debug", + skip(self, infcx, param_env, propagated_outlives_requirements), + ret + )] fn try_promote_type_test( &self, infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - body: &Body<'tcx>, type_test: &TypeTest<'tcx>, propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>, ) -> bool { From cc58ae518e3a4ecd935a26ed571703442622033d Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 14:13:25 +0000 Subject: [PATCH 05/15] Print the def-id when finishing borrowck. --- compiler/rustc_borrowck/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5cc07a154e627..b5dc3cb067435 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -118,7 +118,7 @@ pub fn provide(providers: &mut Providers) { fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let (input_body, _) = tcx.mir_promoted(def); - debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); + debug!("run query mir_borrowck: {def:?}"); if input_body.borrow().should_skip() { debug!("Skipping borrowck because of injected body"); @@ -137,7 +137,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(typeck_root)).build(); let input_body: &Body<'_> = &input_body.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, false).0; - debug!("mir_borrowck done"); + debug!("mir_borrowck done: {def:?}"); tcx.arena.alloc(opt_closure_req) } From bfdeb2e25fcf83b694296a9a8b4ce429b78544f1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 14:16:19 +0000 Subject: [PATCH 06/15] Retire MirSource. --- .../src/transform/promote_consts.rs | 2 +- .../src/transform/validate.rs | 8 +++--- compiler/rustc_middle/src/mir/mod.rs | 28 ++----------------- compiler/rustc_middle/src/mir/pretty.rs | 4 +-- .../rustc_mir_build/src/build/custom/mod.rs | 4 +-- compiler/rustc_mir_build/src/build/mod.rs | 4 +-- .../src/check_packed_ref.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 18 +++++------- 8 files changed, 22 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 7c2299061bbfb..f7bb8eea26f1f 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -905,7 +905,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { feeder.opt_local_def_id_to_hir_id(None); let def_id = feeder.def_id(); - self.promoted.source = MirSource::item(def_id.to_def_id()); + self.promoted.source = ty::InstanceDef::Item(def_id.to_def_id()); let parent_substs = tcx.erase_regions(InternalSubsts::identity_for_item( tcx, tcx.typeck_root_def_id(source_def_id.to_def_id()), diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 3c350e25ba6ec..1d86673b60e10 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -42,7 +42,7 @@ impl<'tcx> MirPass<'tcx> for Validator { // terribly important that they pass the validator. However, I think other passes might // still see them, in which case they might be surprised. It would probably be better if we // didn't put this through the MIR pipeline at all. - if matches!(body.source.instance, InstanceDef::Intrinsic(..) | InstanceDef::Virtual(..)) { + if matches!(body.source, InstanceDef::Intrinsic(..) | InstanceDef::Virtual(..)) { return; } let def_id = body.source.def_id(); @@ -74,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for Validator { checker.check_cleanup_control_flow(); if let MirPhase::Runtime(_) = body.phase { - if let ty::InstanceDef::Item(_) = body.source.instance { + if let ty::InstanceDef::Item(_) = body.source { if body.has_free_regions() { checker.fail( Location::START, @@ -109,7 +109,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span, format!( "broken MIR in {:?} ({}) at {:?}:\n{}", - self.body.source.instance, + self.body.source, self.when, location, msg.as_ref() @@ -1104,7 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.body.span, format!( "broken MIR in {:?} ({}):\ninvalid source scope {:?}", - self.body.source.instance, self.when, scope, + self.body.source, self.when, scope, ), ); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index bc7ae02909010..0c97a9741b229 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -179,28 +179,6 @@ impl RuntimePhase { } } -/// Where a specific `mir::Body` comes from. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] -pub struct MirSource<'tcx> { - pub instance: InstanceDef<'tcx>, -} - -impl<'tcx> MirSource<'tcx> { - pub fn item(def_id: DefId) -> Self { - MirSource { instance: InstanceDef::Item(def_id) } - } - - pub fn from_instance(instance: InstanceDef<'tcx>) -> Self { - MirSource { instance } - } - - #[inline] - pub fn def_id(&self) -> DefId { - self.instance.def_id() - } -} - #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct GeneratorInfo<'tcx> { /// The yield type of the function, if it is a generator. @@ -234,7 +212,7 @@ pub struct Body<'tcx> { /// How many passses we have executed since starting the current phase. Used for debug output. pub pass_count: usize, - pub source: MirSource<'tcx>, + pub source: InstanceDef<'tcx>, /// A list of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. @@ -305,7 +283,7 @@ pub struct Body<'tcx> { impl<'tcx> Body<'tcx> { pub fn new( - source: MirSource<'tcx>, + source: InstanceDef<'tcx>, basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>, local_decls: IndexVec<Local, LocalDecl<'tcx>>, @@ -362,7 +340,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, pass_count: 0, - source: MirSource::item(CRATE_DEF_ID.to_def_id()), + source: InstanceDef::Item(CRATE_DEF_ID.to_def_id()), basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), generator: None, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index dc618da0d7798..252611602da6c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -176,7 +176,7 @@ fn dump_file_basename<'tcx>( let item_name = tcx.def_path(source.def_id()).to_filename_friendly_no_crate(); // All drop shims have the same DefId, so we have to add the type // to get unique file names. - let shim_disambiguator = match source.instance { + let shim_disambiguator = match source { ty::InstanceDef::DropGlue(_, Some(ty)) => { // Unfortunately, pretty-printed typed are not very filename-friendly. // We dome some filtering. @@ -976,7 +976,7 @@ fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Result<()> { use rustc_hir::def::DefKind; - trace!("write_mir_sig: {:?}", body.source.instance); + trace!("write_mir_sig: {:?}", body.source); let def_id = body.source.def_id(); let kind = tcx.def_kind(def_id); let is_function = match kind { diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 32c618828c9b2..b593f08fb7a54 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -25,7 +25,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::{ mir::*, thir::*, - ty::{ParamEnv, Ty, TyCtxt}, + ty::{InstanceDef, ParamEnv, Ty, TyCtxt}, }; use rustc_span::Span; @@ -45,7 +45,7 @@ pub(super) fn build_custom_mir<'tcx>( ) -> Body<'tcx> { let mut body = Body { basic_blocks: BasicBlocks::new(IndexVec::new()), - source: MirSource::item(did), + source: InstanceDef::Item(did), phase: MirPhase::Built, source_scopes: IndexVec::new(), generator: None, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 4e3e98b56e799..1451c78ff1eae 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -640,7 +640,7 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); let mut body = Body::new( - MirSource::item(def.to_def_id()), + ty::InstanceDef::Item(def.to_def_id()), cfg.basic_blocks, source_scopes, local_decls, @@ -730,7 +730,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Body::new( - MirSource::item(self.def_id.to_def_id()), + ty::InstanceDef::Item(self.def_id.to_def_id()), self.cfg.basic_blocks, self.source_scopes, self.local_decls, diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 2e6cf603d5968..e8ab1b7f75217 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -39,7 +39,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { if context.is_borrow() { if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - let def_id = self.body.source.instance.def_id(); + let def_id = self.body.source.def_id(); if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) && self.tcx.is_builtin_derived(impl_def_id) { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7c47d8814db83..1edbf95f3ec73 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -171,7 +171,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) block(&mut blocks, TerminatorKind::Goto { target: return_block }); block(&mut blocks, TerminatorKind::Return); - let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty)); + let source = ty::InstanceDef::DropGlue(def_id, ty); let mut body = new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); @@ -229,7 +229,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) } fn new_body<'tcx>( - source: MirSource<'tcx>, + source: ty::InstanceDef<'tcx>, basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, local_decls: IndexVec<Local, LocalDecl<'tcx>>, arg_count: usize, @@ -343,7 +343,7 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t }); new_body( - MirSource::from_instance(instance), + instance, blocks, IndexVec::from_raw(vec![LocalDecl::new(tcx.thread_local_ptr_ty(def_id), span)]), 0, @@ -407,10 +407,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { } fn into_mir(self) -> Body<'tcx> { - let source = MirSource::from_instance(ty::InstanceDef::CloneShim( - self.def_id, - self.sig.inputs_and_output[0], - )); + let source = ty::InstanceDef::CloneShim(self.def_id, self.sig.inputs_and_output[0]); new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span) } @@ -823,8 +820,7 @@ fn build_call_shim<'tcx>( block(&mut blocks, vec![], TerminatorKind::Resume, true); } - let mut body = - new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span); + let mut body = new_body(instance, blocks, local_decls, sig.inputs().len(), span); if let Abi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); @@ -890,7 +886,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { is_cleanup: false, }; - let source = MirSource::item(ctor_id); + let source = ty::InstanceDef::Item(ctor_id); let body = new_body( source, IndexVec::from_elem_n(start_block, 1), @@ -936,6 +932,6 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), is_cleanup: false, }; - let source = MirSource::from_instance(ty::InstanceDef::FnPtrAddrShim(def_id, self_ty)); + let source = ty::InstanceDef::FnPtrAddrShim(def_id, self_ty); new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) } From ece71786b0e3e1c17694a011da9c0bd0ae66f720 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 14:34:12 +0000 Subject: [PATCH 07/15] Retire GlobalId. --- .../src/const_eval/eval_queries.rs | 61 +++++++------------ .../rustc_const_eval/src/const_eval/mod.rs | 10 +-- .../src/interpret/eval_context.rs | 13 ++-- .../src/interpret/intrinsics.rs | 7 +-- .../rustc_const_eval/src/interpret/operand.rs | 11 ++-- .../rustc_middle/src/mir/interpret/mod.rs | 18 ------ .../rustc_middle/src/mir/interpret/queries.rs | 40 +++++------- compiler/rustc_middle/src/query/erase.rs | 1 - compiler/rustc_middle/src/query/keys.rs | 8 --- compiler/rustc_middle/src/query/mod.rs | 11 ++-- src/tools/miri/src/helpers.rs | 3 +- 11 files changed, 63 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index efc08c9b0eb23..72e516e705fe9 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -17,7 +17,7 @@ use rustc_target::abi::{self, Abi}; use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr}; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ - intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, + intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, }; @@ -29,14 +29,14 @@ const NOTE_ON_UNDEFINED_BEHAVIOR_ERROR: &str = "The rules on what exactly is und // Returns a pointer to where the result lives fn eval_body_using_ecx<'mir, 'tcx>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, - cid: GlobalId<'tcx>, + instance: ty::Instance<'tcx>, body: &'mir mir::Body<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); + debug!("eval_body_using_ecx: {:?}, {:?}", instance, ecx.param_env); let tcx = *ecx.tcx; assert!( matches!( - ecx.tcx.def_kind(cid.instance.def_id()), + ecx.tcx.def_kind(instance.def_id()), DefKind::Const | DefKind::Static(_) | DefKind::ConstParam @@ -46,29 +46,21 @@ fn eval_body_using_ecx<'mir, 'tcx>( | DefKind::Promoted ), "Unexpected DefKind: {:?}", - ecx.tcx.def_kind(cid.instance.def_id()) + ecx.tcx.def_kind(instance.def_id()) ); - let layout = ecx.layout_of(body.bound_return_ty().subst(tcx, cid.instance.substs))?; + let layout = ecx.layout_of(body.bound_return_ty().subst(tcx, instance.substs))?; assert!(layout.is_sized()); let ret = ecx.allocate(layout, MemoryKind::Stack)?; - trace!( - "eval_body_using_ecx: pushing stack frame for global: {}", - with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())), - ); + trace!("eval_body_using_ecx: pushing stack frame for global: {:?}", instance.def_id()); - ecx.push_stack_frame( - cid.instance, - body, - &ret.into(), - StackPopCleanup::Root { cleanup: false }, - )?; + ecx.push_stack_frame(instance, body, &ret.into(), StackPopCleanup::Root { cleanup: false })?; // The main interpreter loop. while ecx.step()? {} // Intern the result - let intern_kind = match tcx.def_kind(cid.instance.def_id()) { + let intern_kind = match tcx.def_kind(instance.def_id()) { DefKind::Promoted => InternKind::Promoted, DefKind::Static(m) => InternKind::Static(m), _ => InternKind::Constant, @@ -196,15 +188,15 @@ pub(super) fn op_to_const<'tcx>( pub(crate) fn turn_into_const_value<'tcx>( tcx: TyCtxt<'tcx>, constant: ConstAlloc<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::ParamEnvAnd<'tcx, ty::Instance<'tcx>>, ) -> ConstValue<'tcx> { - let cid = key.value; - let def_id = cid.instance.def.def_id(); + let instance = key.value; + let def_id = instance.def.def_id(); let is_static = tcx.is_static(def_id); // This is just accessing an already computed constant, so no need to check alignment here. let ecx = mk_eval_cx( tcx, - tcx.def_span(key.value.instance.def_id()), + tcx.def_span(def_id), key.param_env, /*can_access_statics:*/ is_static, ); @@ -225,7 +217,7 @@ pub(crate) fn turn_into_const_value<'tcx>( #[instrument(skip(tcx), level = "debug")] pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::ParamEnvAnd<'tcx, ty::Instance<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { assert!(key.param_env.is_const()); // see comment in eval_to_allocation_raw_provider for what we're doing here @@ -242,8 +234,8 @@ pub fn eval_to_const_value_raw_provider<'tcx>( // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. - if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, key.param_env); + if let ty::InstanceDef::Intrinsic(def_id) = key.value.def { + let ty = key.value.ty(tcx, key.param_env); let ty::FnDef(_, substs) = ty.kind() else { bug!("intrinsic with type {:?}", ty); }; @@ -260,7 +252,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( #[instrument(skip(tcx), level = "debug")] pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::ParamEnvAnd<'tcx, ty::Instance<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { assert!(key.param_env.is_const()); // Because the constant is computed twice (once per value of `Reveal`), we are at risk of @@ -281,18 +273,10 @@ pub fn eval_to_allocation_raw_provider<'tcx>( other => return other, } } - if cfg!(debug_assertions) { - // Make sure we format the instance even if we do not print it. - // This serves as a regression test against an ICE on printing. - // The next two lines concatenated contain some discussion: - // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ - // subject/anon_const_instance_printing/near/135980032 - let instance = with_no_trimmed_paths!(key.value.instance.to_string()); - trace!("const eval: {:?} ({})", key, instance); - } + trace!("const eval: {:?}", key); - let cid = key.value; - let def = cid.instance.def.def_id(); + let instance = key.value; + let def = instance.def.def_id(); let within_static = match tcx.def_kind(def) { DefKind::Promoted => tcx.is_static(tcx.parent(def)), DefKind::Static(_) => true, @@ -316,8 +300,8 @@ pub fn eval_to_allocation_raw_provider<'tcx>( ), ); - let res = ecx.load_mir(cid.instance.def); - match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { + let res = ecx.load_mir(instance.def); + match res.and_then(|body| eval_body_using_ecx(&mut ecx, instance, &body)) { Err(error) => { let err = ConstEvalErr::new(&ecx, error, None); let msg = if within_static { @@ -326,7 +310,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>( // If the current item has generics, we'd like to enrich the message with the // instance and its substs: to show the actual compile-time values, in addition to // the expression, leading to the const eval error. - let instance = &key.value.instance; if !instance.substs.is_empty() { let instance = with_no_trimmed_paths!(instance.to_string()); let msg = format!("evaluation of `{}` failed", instance); diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 05be45fef1391..13572ba859029 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -7,7 +7,7 @@ use crate::interpret::{ }; use rustc_hir::Mutability; use rustc_middle::mir; -use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; +use rustc_middle::mir::interpret::EvalToValTreeResult; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; @@ -51,9 +51,9 @@ pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeC pub(crate) fn eval_to_valtree<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - cid: GlobalId<'tcx>, + instance: ty::Instance<'tcx>, ) -> EvalToValTreeResult<'tcx> { - let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?; + let const_alloc = tcx.eval_to_allocation_raw(param_env.and(instance))?; // FIXME Need to provide a span to `eval_to_valtree` let ecx = mk_eval_cx( @@ -71,10 +71,10 @@ pub(crate) fn eval_to_valtree<'tcx>( match valtree_result { Ok(valtree) => Ok(Some(valtree)), Err(err) => { - let did = cid.instance.def_id(); - let global_const_id = cid.display(tcx); + let did = instance.def_id(); match err { ValTreeCreationError::NodesOverflow => { + let global_const_id = tcx.def_path_str(did); let msg = format!( "maximum number of nodes exceeded in constant {}", &global_const_id diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 4a8df9d4a5926..baefabe26db4e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -20,9 +20,9 @@ use rustc_span::Span; use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ - AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, - MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance, - Scalar, StackPopJump, + AllocId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, + Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance, Scalar, + StackPopJump, }; use crate::util; @@ -911,7 +911,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn eval_global( &self, - gid: GlobalId<'tcx>, + instance: ty::Instance<'tcx>, span: Option<Span>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics @@ -919,13 +919,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // `self.param_env`, that would mean we invoke the query to evaluate the static // with different parameter environments, thus causing the static to be evaluated // multiple times. - let param_env = if self.tcx.is_static(gid.instance.def_id()) { + let param_env = if self.tcx.is_static(instance.def_id()) { ty::ParamEnv::reveal_all() } else { self.param_env }; let param_env = param_env.with_const(); - let val = self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?; + let val = + self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(instance)))?; self.raw_const_to_mplace(val) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 9933b249a5b0e..c9ad3da00d279 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -5,9 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::{ self, - interpret::{ - Allocation, ConstAllocation, ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar, - }, + interpret::{Allocation, ConstAllocation, ConstValue, InterpResult, PointerArithmetic, Scalar}, BinOp, NonDivergingIntrinsic, }; use rustc_middle::ty; @@ -163,7 +161,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | sym::type_id | sym::type_name | sym::variant_count => { - let gid = GlobalId { instance }; let ty = match intrinsic_name { sym::pref_align_of | sym::variant_count => self.tcx.types.usize, sym::needs_drop => self.tcx.types.bool, @@ -172,7 +169,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => bug!(), }; let val = self.ctfe_query(None, |tcx| { - tcx.const_eval_global_id(self.param_env, gid, Some(tcx.span)) + tcx.const_eval_global_id(self.param_env, instance, Some(tcx.span)) })?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?; self.copy_op(&val, dest, /*allow_transmute*/ false)?; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 44bc4695eddf2..019a90b973225 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -12,9 +12,9 @@ use rustc_span::Span; use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size}; use super::{ - alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId, - InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Place, PlaceTy, Pointer, - Provenance, Scalar, + alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, InterpCx, + InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Place, PlaceTy, Pointer, Provenance, + Scalar, }; /// An `Immediate` represents a single immediate self-contained Rust value. @@ -599,9 +599,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ty::ConstKind::Unevaluated(uv) => { let instance = self.resolve(uv.def, uv.substs)?; - let cid = GlobalId { instance }; self.ctfe_query(span, |tcx| { - tcx.eval_to_valtree(self.param_env.with_const().and(cid)) + tcx.eval_to_valtree(self.param_env.with_const().and(instance)) })? .unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}")) } @@ -628,7 +627,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout), mir::ConstantKind::Unevaluated(uv, _) => { let instance = self.resolve(uv.def, uv.substs)?; - Ok(self.eval_global(GlobalId { instance }, span)?.into()) + Ok(self.eval_global(instance, span)?.into()) } } } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 61faca85b71e9..ebbd21469c057 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -108,7 +108,6 @@ use rustc_data_structures::tiny_list::TinyList; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; use rustc_target::abi::{AddressSpace, Endian, HasDataLayout}; @@ -132,23 +131,6 @@ pub use self::allocation::{ pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; -/// Uniquely identifies one of the following: -/// - A constant -/// - A static -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, Lift, TypeFoldable, TypeVisitable)] -pub struct GlobalId<'tcx> { - /// For a constant or static, the `Instance` of the item itself. - /// For a promoted global, the `Instance` of the function they belong to. - pub instance: ty::Instance<'tcx>, -} - -impl<'tcx> GlobalId<'tcx> { - pub fn display(self, tcx: TyCtxt<'tcx>) -> String { - with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id())) - } -} - /// Input argument for `tcx.lit_to_const`. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable)] pub struct LitToConstInput<'tcx> { diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 3faad36633481..8796fb2d6df92 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,4 +1,4 @@ -use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}; +use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult}; use crate::mir; use crate::query::{TyCtxtAt, TyCtxtEnsure}; @@ -22,9 +22,8 @@ impl<'tcx> TyCtxt<'tcx> { // encountered. let substs = InternalSubsts::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, substs); - let cid = GlobalId { instance }; let param_env = self.param_env(def_id).with_reveal_all_normalized(self); - self.const_eval_global_id(param_env, cid, None) + self.const_eval_global_id(param_env, instance, None) } /// Resolves and evaluates a constant. /// @@ -57,10 +56,7 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? ct.def, ct.substs, ) { - Ok(Some(instance)) => { - let cid = GlobalId { instance }; - self.const_eval_global_id(param_env, cid, span) - } + Ok(Some(instance)) => self.const_eval_global_id(param_env, instance, span), Ok(None) => Err(ErrorHandled::TooGeneric), Err(err) => Err(ErrorHandled::Reported(err.into())), } @@ -85,8 +81,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::resolve(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { - let cid = GlobalId { instance }; - self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| { + self.const_eval_global_id_for_typeck(param_env, instance, span).inspect(|_| { // We are emitting the lint here instead of in `is_const_evaluatable` // as we normalize obligations before checking them, and normalization // uses this function to evaluate this constant. @@ -121,7 +116,7 @@ impl<'tcx> TyCtxt<'tcx> { instance: ty::Instance<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { - self.const_eval_global_id(param_env, GlobalId { instance }, span) + self.const_eval_global_id(param_env, instance, span) } /// Evaluate a constant to a `ConstValue`. @@ -129,13 +124,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_global_id( self, param_env: ty::ParamEnv<'tcx>, - cid: GlobalId<'tcx>, + instance: ty::Instance<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { let param_env = param_env.with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.and(cid)); + let inputs = self.erase_regions(param_env.and(instance)); if let Some(span) = span { self.at(span).eval_to_const_value_raw(inputs) } else { @@ -148,14 +143,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_global_id_for_typeck( self, param_env: ty::ParamEnv<'tcx>, - cid: GlobalId<'tcx>, + instance: ty::Instance<'tcx>, span: Option<Span>, ) -> EvalToValTreeResult<'tcx> { let param_env = param_env.with_const(); debug!(?param_env); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.and(cid)); + let inputs = self.erase_regions(param_env.and(instance)); debug!(?inputs); if let Some(span) = span { self.at(span).eval_to_valtree(inputs) @@ -185,8 +180,7 @@ impl<'tcx> TyCtxtAt<'tcx> { trace!("eval_static_initializer: Need to compute {:?}", def_id); assert!(self.is_static(def_id)); let instance = ty::Instance::mono(*self, def_id); - let gid = GlobalId { instance }; - self.eval_to_allocation(gid, ty::ParamEnv::reveal_all()) + self.eval_to_allocation(instance, ty::ParamEnv::reveal_all()) } /// Evaluate anything constant-like, returning the allocation of the final memory. @@ -194,12 +188,12 @@ impl<'tcx> TyCtxtAt<'tcx> { /// The span is entirely ignored here, but still helpful for better query cycle errors. fn eval_to_allocation( self, - gid: GlobalId<'tcx>, + instance: ty::Instance<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result<mir::ConstAllocation<'tcx>, ErrorHandled> { let param_env = param_env.with_const(); - trace!("eval_to_allocation: Need to compute {:?}", gid); - let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; + trace!("eval_to_allocation: Need to compute {:?}", instance); + let raw_const = self.eval_to_allocation_raw(param_env.and(instance))?; Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) } } @@ -216,12 +210,11 @@ impl<'tcx> TyCtxtEnsure<'tcx> { // encountered. let substs = InternalSubsts::identity_for_item(self.tcx, def_id); let instance = ty::Instance::new(def_id, substs); - let cid = GlobalId { instance }; let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.tcx.erase_regions(param_env.and(cid)); + let inputs = self.tcx.erase_regions(param_env.and(instance)); self.eval_to_const_value_raw(inputs) } @@ -230,10 +223,9 @@ impl<'tcx> TyCtxtEnsure<'tcx> { trace!("eval_static_initializer: Need to compute {:?}", def_id); assert!(self.tcx.is_static(def_id)); let instance = ty::Instance::mono(self.tcx, def_id); - let gid = GlobalId { instance }; let param_env = ty::ParamEnv::reveal_all().with_const(); - trace!("eval_to_allocation: Need to compute {:?}", gid); - self.eval_to_allocation_raw(param_env.and(gid)) + trace!("eval_to_allocation: Need to compute {:?}", instance); + self.eval_to_allocation_raw(param_env.and(instance)) } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b45f7caaabe08..9c6339c667cb1 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -307,7 +307,6 @@ tcx_lifetime! { rustc_middle::mir::DestructuredConstant, rustc_middle::mir::interpret::ConstAlloc, rustc_middle::mir::interpret::ConstValue, - rustc_middle::mir::interpret::GlobalId, rustc_middle::mir::interpret::LitToConstInput, rustc_middle::traits::ChalkEnvironmentAndGoal, rustc_middle::traits::query::MethodAutoderefStepsResult, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index fa62b7f32b1a8..ea3af4e5d7cd0 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -87,14 +87,6 @@ impl<'tcx> Key for ty::Instance<'tcx> { } } -impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { - type CacheSelector = DefaultCacheSelector<Self>; - - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - self.instance.default_span(tcx) - } -} - impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) { type CacheSelector = DefaultCacheSelector<Self>; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0f14d3aa73804..c6d760af09104 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -18,7 +18,6 @@ use crate::middle::privacy::EffectiveVisibilities; use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; -use crate::mir::interpret::GlobalId; use crate::mir::interpret::{ ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, }; @@ -1028,11 +1027,11 @@ rustc_queries! { /// Evaluates a constant and returns the computed allocation. /// /// **Do not use this** directly, use the `tcx.eval_static_initializer` wrapper. - query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, ty::Instance<'tcx>>) -> EvalToAllocationRawResult<'tcx> { desc { |tcx| "const-evaluating + checking `{}`", - key.value.display(tcx) + tcx.def_path_str(key.value.def_id()), } cache_on_disk_if { true } } @@ -1043,11 +1042,11 @@ rustc_queries! { /// /// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`, /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. - query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, ty::Instance<'tcx>>) -> EvalToConstValueResult<'tcx> { desc { |tcx| "simplifying constant for the type system `{}`", - key.value.display(tcx) + tcx.def_path_str(key.value.def_id()), } cache_on_disk_if { true } } @@ -1055,7 +1054,7 @@ rustc_queries! { /// Evaluate a constant and convert it to a type level constant or /// return `None` if that is not possible. query eval_to_valtree( - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> + key: ty::ParamEnvAnd<'tcx, ty::Instance<'tcx>> ) -> EvalToValTreeResult<'tcx> { desc { "evaluating type-level constant" } } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b33a173787e3b..9952465e26f0e 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -160,10 +160,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> { let this = self.eval_context_ref(); let instance = this.resolve_path(path, Namespace::ValueNS); - let cid = GlobalId { instance }; // We don't give a span -- this isn't actually used directly by the program anyway. let const_val = this - .eval_global(cid, None) + .eval_global(instance, None) .unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err}")); this.read_scalar(&const_val.into()) .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err}")) From 1c8e593020f7d50736ec7c0037a38e6a1bd2b690 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 17:14:50 +0000 Subject: [PATCH 08/15] Use the same path for Promoted and InlineConst DefiningTy. --- .../rustc_borrowck/src/universal_regions.rs | 37 ++++--------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index bf5ed61591f8d..25880b2cf5ed4 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -546,7 +546,6 @@ 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.to_def_id()); match tcx.hir().body_owner_kind(self.mir_def) { BodyOwnerKind::Closure | BodyOwnerKind::Fn => { @@ -574,35 +573,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { BodyOwnerKind::Const | BodyOwnerKind::Static(..) => { match tcx.def_kind(self.mir_def) { - DefKind::InlineConst => { - // FIXME this line creates a dependency between borrowck and typeck. - // - // This is required for `AscribeUserType` canonical query, which will call - // `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes - // into borrowck, which is ICE #78174. - // - // As a workaround, inline consts have an additional generic param (`ty` - // 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) - .node_type(tcx.local_def_id_to_hir_id(self.mir_def)); - let identity_substs = - InternalSubsts::identity_for_item(tcx, typeck_root_def_id); - 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.to_def_id(), substs) - } - DefKind::Promoted => { - let body = tcx.mir_for_promoted(self.mir_def).borrow(); + DefKind::InlineConst | DefKind::Promoted => { + // Fetch the actual type from MIR, as `type_of` returns something useless + // like `<const_ty>`. + let body = tcx.mir_promoted(self.mir_def).0.borrow(); let ty = body.local_decls[RETURN_PLACE].ty; - let parent_def_id = tcx.parent(self.mir_def.to_def_id()); - let parent_substs = InternalSubsts::identity_for_item(tcx, parent_def_id); + + let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id()); + let parent_substs = + InternalSubsts::identity_for_item(tcx, typeck_root_def_id); let substs = InlineConstSubsts::new( tcx, InlineConstSubstsParts { parent_substs, ty }, From cc4f8b0fa8a42cf71e76b51bed292b5761bfb2e7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Thu, 18 May 2023 18:56:18 +0000 Subject: [PATCH 09/15] Bless 32bit tests. --- ...p_unsafe_oob_for_slices.main.ConstProp.32bit.diff | 2 +- .../const_prop/slice_len.main.ConstProp.32bit.diff | 2 +- tests/ui/consts/const-eval/raw-bytes.32bit.stderr | 12 ++++++------ tests/ui/consts/invalid-union.32bit.stderr | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index d72675c2d1157..484a357783c30 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -28,7 +28,7 @@ _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:9:25: 9:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(main::{promoted#0}, [&[i32; 3]]) } _3 = &(*_9); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index 8bd2b48d6d6af..975f5e82b6d8c 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -21,7 +21,7 @@ _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant // + span: $DIR/slice_len.rs:8:6: 8:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(main::{promoted#0}, [&[u32; 3]]) } _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index a93b561e5be27..b0f251d8b8b69 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -330,10 +330,10 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:160:1 + --> $DIR/raw-bytes.rs:160:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: 4, align: 4) { @@ -347,10 +347,10 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:166:1 + --> $DIR/raw-bytes.rs:166:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: 4, align: 4) { @@ -364,10 +364,10 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:170:1 + --> $DIR/raw-bytes.rs:170:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean | = 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 raw bytes of the constant (size: 4, align: 4) { diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr index 0dd18a55786ad..37f8aae5eca5c 100644 --- a/tests/ui/consts/invalid-union.32bit.stderr +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -1,8 +1,8 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-union.rs:41:1 + --> $DIR/invalid-union.rs:42:25 | -LL | fn main() { - | ^^^^^^^^^ constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const` +LL | let _: &'static _ = &C; + | ^^ constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const` | = 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 raw bytes of the constant (size: 4, align: 4) { @@ -10,13 +10,13 @@ LL | fn main() { } note: erroneous constant used - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:42:25 | LL | let _: &'static _ = &C; | ^^ note: erroneous constant used - --> $DIR/invalid-union.rs:43:25 + --> $DIR/invalid-union.rs:42:25 | LL | let _: &'static _ = &C; | ^^ From 87a9d98fb6607229ff4f0f4c0f99e9ce880c57b6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Fri, 19 May 2023 08:26:31 +0000 Subject: [PATCH 10/15] Only consider places with the same local in each_borrow_involving_path. --- compiler/rustc_borrowck/src/invalidation.rs | 3 +-- compiler/rustc_borrowck/src/lib.rs | 17 ++++++++++------- compiler/rustc_borrowck/src/path_utils.rs | 14 +++++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 863c92acdf4dc..d21eb7728bc70 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -351,7 +351,6 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { let tcx = self.tcx; let body = self.body; let borrow_set = self.borrow_set; - let indices = self.borrow_set.indices(); each_borrow_involving_path( self, tcx, @@ -359,7 +358,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { location, (sd, place), borrow_set, - indices, + |_| true, |this, borrow_index, borrow| { match (rw, borrow.kind) { // Obviously an activation is compatible with its own diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index eb25d454339b5..01f978a488bc2 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -23,7 +23,7 @@ use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, Subdiagnost use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_index::bit_set::ChunkedBitSet; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{ DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, @@ -41,7 +41,6 @@ use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use rustc_target::abi::FieldIdx; -use either::Either; use smallvec::SmallVec; use std::cell::OnceCell; use std::cell::RefCell; @@ -1049,12 +1048,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let borrow_set = self.borrow_set.clone(); // Use polonius output if it has been enabled. - let polonius_output = self.polonius_output.clone(); - let borrows_in_scope = if let Some(polonius) = &polonius_output { + let mut polonius_output; + let borrows_in_scope = if let Some(polonius) = &self.polonius_output { let location = self.location_table.start_index(location); - Either::Left(polonius.errors_at(location).iter().copied()) + polonius_output = BitSet::new_empty(borrow_set.len()); + for &idx in polonius.errors_at(location) { + polonius_output.insert(idx); + } + &polonius_output } else { - Either::Right(flow_state.borrows.iter()) + &flow_state.borrows }; each_borrow_involving_path( @@ -1064,7 +1067,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location, (sd, place_span.0), &borrow_set, - borrows_in_scope, + |borrow_index| borrows_in_scope.contains(borrow_index), |this, borrow_index, borrow| match (rw, borrow.kind) { // Obviously an activation is compatible with its own // reservation (or even prior activating uses of same diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index ea9f8683ca7bb..ed93a560981e4 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -33,20 +33,24 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( _location: Location, access_place: (AccessDepth, Place<'tcx>), borrow_set: &BorrowSet<'tcx>, - candidates: I, + is_candidate: I, mut op: F, ) where F: FnMut(&mut S, BorrowIndex, &BorrowData<'tcx>) -> Control, - I: Iterator<Item = BorrowIndex>, + I: Fn(BorrowIndex) -> bool, { let (access, place) = access_place; - // FIXME: analogous code in check_loans first maps `place` to - // its base_path. + // The number of candidates can be large, but borrows for different locals cannot conflict with + // each other, so we restrict the working set a priori. + let Some(borrows_for_place_base) = borrow_set.local_map.get(&place.local) else { return }; // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. - for i in candidates { + for &i in borrows_for_place_base { + if !is_candidate(i) { + continue; + } let borrowed = &borrow_set[i]; if places_conflict::borrow_conflicts_with_place( From ce8a9c9dde1e6d64bb6858903dcd411612fd5d2e Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Fri, 19 May 2023 08:28:21 +0000 Subject: [PATCH 11/15] Extract the local != local case in borrow_conflicts_with_place. --- .../rustc_borrowck/src/places_conflict.rs | 131 ++++++++---------- 1 file changed, 56 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 918fb2d69237e..3a2a11d43323b 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -1,3 +1,45 @@ +//! The borrowck rules for proving disjointness are applied from the "root" of the +//! borrow forwards, iterating over "similar" projections in lockstep until +//! we can prove overlap one way or another. Essentially, we treat `Overlap` as +//! a monoid and report a conflict if the product ends up not being `Disjoint`. +//! +//! At each step, if we didn't run out of borrow or place, we know that our elements +//! have the same type, and that they only overlap if they are the identical. +//! +//! For example, if we are comparing these: +//! BORROW: (*x1[2].y).z.a +//! ACCESS: (*x1[i].y).w.b +//! +//! Then our steps are: +//! x1 | x1 -- places are the same +//! x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) +//! x1[2].y | x1[i].y -- equal or disjoint +//! *x1[2].y | *x1[i].y -- equal or disjoint +//! (*x1[2].y).z | (*x1[i].y).w -- we are disjoint and don't need to check more! +//! +//! Because `zip` does potentially bad things to the iterator inside, this loop +//! also handles the case where the access might be a *prefix* of the borrow, e.g. +//! +//! BORROW: (*x1[2].y).z.a +//! ACCESS: x1[i].y +//! +//! Then our steps are: +//! x1 | x1 -- places are the same +//! x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) +//! x1[2].y | x1[i].y -- equal or disjoint +//! +//! -- here we run out of access - the borrow can access a part of it. If this +//! is a full deep access, then we *know* the borrow conflicts with it. However, +//! if the access is shallow, then we can proceed: +//! +//! x1[2].y | (*x1[i].y) -- a deref! the access can't get past this, so we +//! are disjoint +//! +//! Our invariant is, that at each step of the iteration: +//! - If we didn't run out of access to match, our borrow and access are comparable +//! and either equal or disjoint. +//! - If we did run out of access, the borrow can access a part of it. + #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] use crate::ArtificialField; @@ -46,7 +88,7 @@ pub(crate) fn places_conflict<'tcx>( /// access depth. The `bias` parameter is used to determine how the unknowable (comparing runtime /// array indices, for example) should be interpreted - this depends on what the caller wants in /// order to make the conservative choice and preserve soundness. -#[instrument(level = "debug", skip(tcx, body))] +#[inline] pub(super) fn borrow_conflicts_with_place<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -56,15 +98,24 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( access: AccessDepth, bias: PlaceConflictBias, ) -> bool { + let borrow_local = borrow_place.local; + let access_local = access_place.local; + + if borrow_local != access_local { + // We have proven the borrow disjoint - further projections will remain disjoint. + return false; + } + // This Local/Local case is handled by the more general code below, but // it's so common that it's a speed win to check for it first. - if let Some(l1) = borrow_place.as_local() && let Some(l2) = access_place.as_local() { - return l1 == l2; + if borrow_place.projection.is_empty() && access_place.projection.is_empty() { + return true; } place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias) } +#[instrument(level = "debug", skip(tcx, body))] fn place_components_conflict<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -74,65 +125,10 @@ fn place_components_conflict<'tcx>( access: AccessDepth, bias: PlaceConflictBias, ) -> bool { - // The borrowck rules for proving disjointness are applied from the "root" of the - // borrow forwards, iterating over "similar" projections in lockstep until - // we can prove overlap one way or another. Essentially, we treat `Overlap` as - // a monoid and report a conflict if the product ends up not being `Disjoint`. - // - // At each step, if we didn't run out of borrow or place, we know that our elements - // have the same type, and that they only overlap if they are the identical. - // - // For example, if we are comparing these: - // BORROW: (*x1[2].y).z.a - // ACCESS: (*x1[i].y).w.b - // - // Then our steps are: - // x1 | x1 -- places are the same - // x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) - // x1[2].y | x1[i].y -- equal or disjoint - // *x1[2].y | *x1[i].y -- equal or disjoint - // (*x1[2].y).z | (*x1[i].y).w -- we are disjoint and don't need to check more! - // - // Because `zip` does potentially bad things to the iterator inside, this loop - // also handles the case where the access might be a *prefix* of the borrow, e.g. - // - // BORROW: (*x1[2].y).z.a - // ACCESS: x1[i].y - // - // Then our steps are: - // x1 | x1 -- places are the same - // x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) - // x1[2].y | x1[i].y -- equal or disjoint - // - // -- here we run out of access - the borrow can access a part of it. If this - // is a full deep access, then we *know* the borrow conflicts with it. However, - // if the access is shallow, then we can proceed: - // - // x1[2].y | (*x1[i].y) -- a deref! the access can't get past this, so we - // are disjoint - // - // Our invariant is, that at each step of the iteration: - // - If we didn't run out of access to match, our borrow and access are comparable - // and either equal or disjoint. - // - If we did run out of access, the borrow can access a part of it. - let borrow_local = borrow_place.local; let access_local = access_place.local; - - match place_base_conflict(borrow_local, access_local) { - Overlap::Arbitrary => { - bug!("Two base can't return Arbitrary"); - } - Overlap::EqualOrDisjoint => { - // This is the recursive case - proceed to the next element. - } - Overlap::Disjoint => { - // We have proven the borrow disjoint - further - // projections will remain disjoint. - debug!("borrow_conflicts_with_place: disjoint"); - return false; - } - } + // borrow_conflicts_with_place should have checked that. + assert_eq!(borrow_local, access_local); // loop invariant: borrow_c is always either equal to access_c or disjoint from it. for (i, (borrow_c, &access_c)) in @@ -287,21 +283,6 @@ fn place_components_conflict<'tcx>( } } -// Given that the bases of `elem1` and `elem2` are always either equal -// or disjoint (and have the same type!), return the overlap situation -// between `elem1` and `elem2`. -fn place_base_conflict(l1: Local, l2: Local) -> Overlap { - if l1 == l2 { - // the same local - base case, equal - debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL"); - Overlap::EqualOrDisjoint - } else { - // different locals - base case, disjoint - debug!("place_element_conflict: DISJOINT-LOCAL"); - Overlap::Disjoint - } -} - // Given that the bases of `elem1` and `elem2` are always either equal // or disjoint (and have the same type!), return the overlap situation // between `elem1` and `elem2`. From 85fe5a0746e68a24de1fbf9974dde144825ceb1c Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Fri, 19 May 2023 08:28:45 +0000 Subject: [PATCH 12/15] Mark sccs_info as noinline. --- compiler/rustc_borrowck/src/region_infer/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8fbe814c85607..2ec68ece5bcdb 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -246,9 +246,10 @@ pub enum ExtraConstraintInfo { } #[instrument(skip(infcx, sccs), level = "debug")] +#[inline(never)] // This is a debugging tool, we need to discard it from profiles. fn sccs_info<'cx, 'tcx>( infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>, - sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>, + sccs: &Sccs<RegionVid, ConstraintSccIndex>, ) { use crate::renumber::RegionCtxt; @@ -348,7 +349,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static)); if cfg!(debug_assertions) { - sccs_info(_infcx, constraint_sccs.clone()); + sccs_info(_infcx, &*constraint_sccs); } let mut scc_values = From b49aba8b46850c85cd0dcbafc35e8a5bcbd5382b Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Fri, 19 May 2023 08:59:49 +0000 Subject: [PATCH 13/15] Prevent rustdoc from finding links. --- compiler/rustc_borrowck/src/places_conflict.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 3a2a11d43323b..8784999f3a9a1 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -7,33 +7,43 @@ //! have the same type, and that they only overlap if they are the identical. //! //! For example, if we are comparing these: +//! ```text //! BORROW: (*x1[2].y).z.a //! ACCESS: (*x1[i].y).w.b +//! ``` //! //! Then our steps are: +//! ```text //! x1 | x1 -- places are the same //! x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) //! x1[2].y | x1[i].y -- equal or disjoint //! *x1[2].y | *x1[i].y -- equal or disjoint //! (*x1[2].y).z | (*x1[i].y).w -- we are disjoint and don't need to check more! +//! ``` //! //! Because `zip` does potentially bad things to the iterator inside, this loop //! also handles the case where the access might be a *prefix* of the borrow, e.g. //! +//! ```text //! BORROW: (*x1[2].y).z.a //! ACCESS: x1[i].y +//! ``` //! //! Then our steps are: +//! ```text //! x1 | x1 -- places are the same //! x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) //! x1[2].y | x1[i].y -- equal or disjoint +//! ``` //! //! -- here we run out of access - the borrow can access a part of it. If this //! is a full deep access, then we *know* the borrow conflicts with it. However, //! if the access is shallow, then we can proceed: //! +//! ```text //! x1[2].y | (*x1[i].y) -- a deref! the access can't get past this, so we //! are disjoint +//! ``` //! //! Our invariant is, that at each step of the iteration: //! - If we didn't run out of access to match, our borrow and access are comparable From 4dd91c007f3d1a23265c4173d7cd62b3f97369c3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Fri, 19 May 2023 12:56:09 +0000 Subject: [PATCH 14/15] Simplify pre-order algorithm. --- compiler/rustc_borrowck/src/dataflow.rs | 94 +++++++++++-------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 68ef790ac26f8..37af4b06ad56c 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -125,15 +125,9 @@ pub struct Borrows<'a, 'tcx> { borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, } -struct StackEntry { - bb: mir::BasicBlock, - lo: usize, - hi: usize, -} - struct OutOfScopePrecomputer<'a, 'tcx> { visited: BitSet<mir::BasicBlock>, - visit_stack: Vec<StackEntry>, + visit_stack: Vec<mir::BasicBlock>, body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>, borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, @@ -158,29 +152,50 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> { borrow_region: RegionVid, first_location: Location, ) { - // We visit one BB at a time. The complication is that we may start in the - // middle of the first BB visited (the one containing `first_location`), in which - // case we may have to later on process the first part of that BB if there - // is a path back to its start. - - // For visited BBs, we record the index of the first statement processed. - // (In fully processed BBs this index is 0.) Note also that we add BBs to - // `visited` once they are added to `stack`, before they are actually - // processed, because this avoids the need to look them up again on - // completion. - self.visited.insert(first_location.block); - let first_block = first_location.block; - let mut first_lo = first_location.statement_index; - let first_hi = self.body[first_block].statements.len(); + let first_bb_data = &self.body.basic_blocks[first_block]; + + // This is the first block, we only want to visit it from the creation of the borrow at + // `first_location`. + let first_lo = first_location.statement_index; + let first_hi = first_bb_data.statements.len(); + + if let Some(kill_stmt) = self.regioncx.first_non_contained_inclusive( + borrow_region, + first_block, + first_lo, + first_hi, + ) { + let kill_location = Location { block: first_block, statement_index: kill_stmt }; + // If region does not contain a point at the location, then add to list and skip + // successor locations. + debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location); + self.borrows_out_of_scope_at_location + .entry(kill_location) + .or_default() + .push(borrow_index); + + // The borrow is already dead, there is no need to visit other blocks. + return; + } - self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi }); + // The borrow is not dead. Add successor BBs to the work list, if necessary. + for succ_bb in first_bb_data.terminator().successors() { + if self.visited.insert(succ_bb) { + self.visit_stack.push(succ_bb); + } + } - 'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() { + // We may end up visiting `first_block` again. This is not an issue: we know at this point + // that it does not kill the borrow in the `first_lo..=first_hi` range, so checking the + // `0..first_lo` range and the `0..first_hi` range give the same result. + while let Some(block) = self.visit_stack.pop() { + let bb_data = &self.body[block]; + let num_stmts = bb_data.statements.len(); if let Some(kill_stmt) = - self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi) + self.regioncx.first_non_contained_inclusive(borrow_region, block, 0, num_stmts) { - let kill_location = Location { block: bb, statement_index: kill_stmt }; + let kill_location = Location { block, statement_index: kill_stmt }; // If region does not contain a point at the location, then add to list and skip // successor locations. debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location); @@ -188,38 +203,15 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> { .entry(kill_location) .or_default() .push(borrow_index); - continue 'preorder; - } - // If we process the first part of the first basic block (i.e. we encounter that block - // for the second time), we no longer have to visit its successors again. - if bb == first_block && hi != first_hi { + // We killed the borrow, so we do not visit this block's successors. continue; } // Add successor BBs to the work list, if necessary. - let bb_data = &self.body[bb]; - debug_assert!(hi == bb_data.statements.len()); for succ_bb in bb_data.terminator().successors() { - if !self.visited.insert(succ_bb) { - if succ_bb == first_block && first_lo > 0 { - // `succ_bb` has been seen before. If it wasn't - // fully processed, add its first part to `stack` - // for processing. - self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 }); - - // And update this entry with 0, to represent the - // whole BB being processed. - first_lo = 0; - } - } else { - // succ_bb hasn't been seen before. Add it to - // `stack` for processing. - self.visit_stack.push(StackEntry { - bb: succ_bb, - lo: 0, - hi: self.body[succ_bb].statements.len(), - }); + if self.visited.insert(succ_bb) { + self.visit_stack.push(succ_bb); } } } From d07bb8ef9eb6722fb6597b5de01dfabbc227e3ed Mon Sep 17 00:00:00 2001 From: Camille GILLOT <gillot.camille@gmail.com> Date: Sat, 20 May 2023 08:03:58 +0000 Subject: [PATCH 15/15] Hash mir_promoted. --- compiler/rustc_middle/src/query/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c6d760af09104..348bf564d250b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -518,7 +518,6 @@ rustc_queries! { &'tcx Steal<mir::Body<'tcx>>, &'tcx IndexVec<mir::Promoted, LocalDefId>, ) { - no_hash desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) } }