From fdbf109b635d8928b7b47570f2a8f00ec9d39d94 Mon Sep 17 00:00:00 2001 From: joboet Date: Sun, 26 Feb 2023 11:33:28 +0100 Subject: [PATCH 01/14] std: use random HashMap keys on Hermit --- library/std/src/sys/hermit/mod.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index d34a4cfedea78..d0e09890b8b6c 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -76,9 +76,24 @@ pub fn abort_internal() -> ! { } } -// FIXME: just a workaround to test the system pub fn hashmap_random_keys() -> (u64, u64) { - (1, 2) + let mut buf = [0; 16]; + let mut slice = &mut buf[..]; + while !slice.is_empty() { + let res = unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }; + if res < 0 { + panic!( + "random key generation failed: {}", + crate::io::Error::from_raw_os_error(-res as i32) + ); + } else { + slice = &mut slice[res as usize..]; + } + } + + let key1 = buf[..8].try_into().unwrap(); + let key2 = buf[8..].try_into().unwrap(); + (u64::from_ne_bytes(key1), u64::from_ne_bytes(key2)) } // This function is needed by the panic runtime. The symbol is named in From 8e56c2c5f1e8417ae7dcaf1fad1d72dd1ca964f5 Mon Sep 17 00:00:00 2001 From: Mu42 Date: Fri, 24 Mar 2023 14:24:25 +0800 Subject: [PATCH 02/14] Suggest ..= when someone tries to create an overflowing range --- compiler/rustc_lint/src/types.rs | 27 ++++++++++++++++++++------- tests/ui/lint/issue-109529.rs | 5 +++++ tests/ui/lint/issue-109529.stderr | 10 ++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 tests/ui/lint/issue-109529.rs create mode 100644 tests/ui/lint/issue-109529.stderr diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7ca50f5a2db70..db93f6d340200 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -136,6 +136,13 @@ fn lint_overflowing_range_endpoint<'tcx>( expr: &'tcx hir::Expr<'tcx>, ty: &str, ) -> bool { + let (expr, cast_ty) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id)) + && let ExprKind::Cast(_, ty) = par_expr.kind { + (par_expr, Some(ty)) + } else { + (expr, None) + }; + // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. let par_id = cx.tcx.hir().parent_id(expr.hir_id); @@ -157,13 +164,19 @@ fn lint_overflowing_range_endpoint<'tcx>( }; let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; - use rustc_ast::{LitIntType, LitKind}; - let suffix = match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(), - LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(), - LitKind::Int(_, LitIntType::Unsuffixed) => "", - _ => bug!(), + let suffix = if let Some(cast_ty) = cast_ty { + let Ok(ty) = cx.sess().source_map().span_to_snippet(cast_ty.span) else { return false }; + format!(" as {}", ty) + } else { + use rustc_ast::{LitIntType, LitKind}; + match lit.node { + LitKind::Int(_, LitIntType::Signed(s)) => s.name_str().to_owned(), + LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str().to_owned(), + LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), + _ => bug!(), + } }; + cx.emit_spanned_lint( OVERFLOWING_LITERALS, struct_expr.span, @@ -172,7 +185,7 @@ fn lint_overflowing_range_endpoint<'tcx>( suggestion: struct_expr.span, start, literal: lit_val - 1, - suffix, + suffix: &suffix, }, ); diff --git a/tests/ui/lint/issue-109529.rs b/tests/ui/lint/issue-109529.rs new file mode 100644 index 0000000000000..f6829d0c76a55 --- /dev/null +++ b/tests/ui/lint/issue-109529.rs @@ -0,0 +1,5 @@ +fn main() { + for i in 0..256 as u8 { //~ ERROR range endpoint is out of range + println!("{}", i); + } +} diff --git a/tests/ui/lint/issue-109529.stderr b/tests/ui/lint/issue-109529.stderr new file mode 100644 index 0000000000000..87c9119ee6f1c --- /dev/null +++ b/tests/ui/lint/issue-109529.stderr @@ -0,0 +1,10 @@ +error: range endpoint is out of range for `u8` + --> $DIR/issue-109529.rs:2:14 + | +LL | for i in 0..256 as u8 { + | ^^^^^^^^^^^^ help: use an inclusive range instead: `0..=255 as u8` + | + = note: `#[deny(overflowing_literals)]` on by default + +error: aborting due to previous error + From 6034b2fcb80915d35a871d438663758b4241a0fa Mon Sep 17 00:00:00 2001 From: Mu42 Date: Fri, 24 Mar 2023 20:09:02 +0800 Subject: [PATCH 03/14] Use independent suggestions --- compiler/rustc_lint/src/lints.rs | 7 ++++--- compiler/rustc_lint/src/types.rs | 33 +++++++++++++------------------ tests/ui/lint/issue-109529.rs | 2 +- tests/ui/lint/issue-109529.stderr | 12 +++++++++-- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 308c02929ca42..925e9654f931d 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1210,9 +1210,10 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, - #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")] - pub suggestion: Span, - pub start: String, + #[suggestion(code = "=", applicability = "machine-applicable")] + pub eq_suggestion: Span, + #[suggestion(code = "{literal}{suffix}", applicability = "machine-applicable")] + pub lit_suggestion: Span, pub literal: u128, pub suffix: &'a str, } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index db93f6d340200..1cc873c6de9c4 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -136,11 +136,12 @@ fn lint_overflowing_range_endpoint<'tcx>( expr: &'tcx hir::Expr<'tcx>, ty: &str, ) -> bool { - let (expr, cast_ty) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id)) - && let ExprKind::Cast(_, ty) = par_expr.kind { - (par_expr, Some(ty)) + // Look past casts to support cases like `0..256 as u8` + let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.hir().get(cx.tcx.hir().parent_id(expr.hir_id)) + && let ExprKind::Cast(_, _) = par_expr.kind { + (par_expr, expr.span) } else { - (expr, None) + (expr, expr.span) }; // We only want to handle exclusive (`..`) ranges, @@ -162,19 +163,13 @@ fn lint_overflowing_range_endpoint<'tcx>( if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) { return false; }; - let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; - let suffix = if let Some(cast_ty) = cast_ty { - let Ok(ty) = cx.sess().source_map().span_to_snippet(cast_ty.span) else { return false }; - format!(" as {}", ty) - } else { - use rustc_ast::{LitIntType, LitKind}; - match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => s.name_str().to_owned(), - LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str().to_owned(), - LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), - _ => bug!(), - } + use rustc_ast::{LitIntType, LitKind}; + let suffix = match lit.node { + LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(), + LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(), + LitKind::Int(_, LitIntType::Unsuffixed) => "", + _ => bug!(), }; cx.emit_spanned_lint( @@ -182,10 +177,10 @@ fn lint_overflowing_range_endpoint<'tcx>( struct_expr.span, RangeEndpointOutOfRange { ty, - suggestion: struct_expr.span, - start, + eq_suggestion: expr.span.shrink_to_lo(), + lit_suggestion: lit_span, literal: lit_val - 1, - suffix: &suffix, + suffix, }, ); diff --git a/tests/ui/lint/issue-109529.rs b/tests/ui/lint/issue-109529.rs index f6829d0c76a55..36c6d4fdfe3b4 100644 --- a/tests/ui/lint/issue-109529.rs +++ b/tests/ui/lint/issue-109529.rs @@ -1,5 +1,5 @@ fn main() { - for i in 0..256 as u8 { //~ ERROR range endpoint is out of range + for i in 0..(256 as u8) { //~ ERROR range endpoint is out of range println!("{}", i); } } diff --git a/tests/ui/lint/issue-109529.stderr b/tests/ui/lint/issue-109529.stderr index 87c9119ee6f1c..e9f6d546ac20b 100644 --- a/tests/ui/lint/issue-109529.stderr +++ b/tests/ui/lint/issue-109529.stderr @@ -1,10 +1,18 @@ error: range endpoint is out of range for `u8` --> $DIR/issue-109529.rs:2:14 | -LL | for i in 0..256 as u8 { - | ^^^^^^^^^^^^ help: use an inclusive range instead: `0..=255 as u8` +LL | for i in 0..(256 as u8) { + | ^^^^^^^^^^^^^^ | = note: `#[deny(overflowing_literals)]` on by default +help: use an inclusive range instead + | +LL | for i in 0..=(256 as u8) { + | + +help: use an inclusive range instead + | +LL | for i in 0..(255 as u8) { + | ~~~ error: aborting due to previous error From 7f89c7c32dcee0e01bb1eda00fbdb77a9ab5e281 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 23 Mar 2023 05:40:50 +0000 Subject: [PATCH 04/14] Make EvalCtxt's infcx private --- .../src/solve/canonical/mod.rs | 57 ++------- .../src/solve/eval_ctxt.rs | 112 +++++++++++++++++- .../rustc_trait_selection/src/solve/mod.rs | 24 ++-- .../src/solve/project_goals.rs | 16 ++- 4 files changed, 134 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs index efecaf33ef987..d393ab1ba4a85 100644 --- a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs @@ -8,17 +8,15 @@ /// section of the [rustc-dev-guide][c]. /// /// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html -use self::canonicalize::{CanonicalizeMode, Canonicalizer}; +pub use self::canonicalize::{CanonicalizeMode, Canonicalizer}; + use super::{CanonicalGoal, Certainty, EvalCtxt, Goal}; -use super::{CanonicalResponse, ExternalConstraints, QueryResult, Response}; -use rustc_infer::infer::canonical::query_response::make_query_region_constraints; +use super::{CanonicalResponse, QueryResult, Response}; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::ExternalConstraintsData; -use rustc_infer::traits::ObligationCause; use rustc_middle::ty::{self, GenericArgKind}; -use rustc_span::DUMMY_SP; use std::iter; use std::ops::Deref; @@ -32,12 +30,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, ) -> (Vec>, CanonicalGoal<'tcx>) { let mut orig_values = Default::default(); - let canonical_goal = Canonicalizer::canonicalize( - self.infcx, - CanonicalizeMode::Input, - &mut orig_values, - goal, - ); + let canonical_goal = self.canonicalize(CanonicalizeMode::Input, &mut orig_values, goal); (orig_values, canonical_goal) } @@ -58,8 +51,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let external_constraints = self.compute_external_query_constraints()?; let response = Response { var_values: self.var_values, external_constraints, certainty }; - let canonical = Canonicalizer::canonicalize( - self.infcx, + let canonical = self.canonicalize( CanonicalizeMode::Response { max_input_universe: self.max_input_universe }, &mut Default::default(), response, @@ -67,26 +59,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Ok(canonical) } - #[instrument(level = "debug", skip(self), ret)] - fn compute_external_query_constraints(&self) -> Result, NoSolution> { - // Cannot use `take_registered_region_obligations` as we may compute the response - // inside of a `probe` whenever we have multiple choices inside of the solver. - let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); - let region_constraints = self.infcx.with_region_constraints(|region_constraints| { - make_query_region_constraints( - self.tcx(), - region_obligations - .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), - region_constraints, - ) - }); - let opaque_types = self.infcx.clone_opaque_types_for_query_response(); - Ok(self - .tcx() - .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types })) - } - /// After calling a canonical query, we apply the constraints returned /// by the query using this function. /// @@ -126,10 +98,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. - let prev_universe = self.infcx.universe(); + let prev_universe = self.universe(); let universes_created_in_query = response.max_universe.index() + 1; for _ in 0..universes_created_in_query { - self.infcx.create_next_universe(); + self.create_next_universe(); } let var_values = response.value.var_values; @@ -172,7 +144,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // A variable from inside a binder of the query. While ideally these shouldn't // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. - self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| { + self.instantiate_canonical_var(info, |idx| { ty::UniverseIndex::from(prev_universe.index() + idx.index()) }) } else if info.is_existential() { @@ -186,7 +158,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if let Some(v) = opt_values[index] { v } else { - self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe) + self.instantiate_canonical_var(info, |_| prev_universe) } } else { // For placeholders which were already part of the input, we simply map this @@ -219,15 +191,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { fn register_region_constraints(&mut self, region_constraints: &QueryRegionConstraints<'tcx>) { for &(ty::OutlivesPredicate(lhs, rhs), _) in ®ion_constraints.outlives { match lhs.unpack() { - GenericArgKind::Lifetime(lhs) => self.infcx.region_outlives_predicate( - &ObligationCause::dummy(), - ty::Binder::dummy(ty::OutlivesPredicate(lhs, rhs)), - ), - GenericArgKind::Type(lhs) => self.infcx.register_region_obligation_with_cause( - lhs, - rhs, - &ObligationCause::dummy(), - ), + GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs), + GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs), GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"), } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index e47b5ae21b5af..92aff517fbb8b 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -1,14 +1,17 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; -use rustc_infer::infer::canonical::CanonicalVarValues; +use rustc_infer::infer::canonical::query_response::make_query_region_constraints; +use rustc_infer::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarValues}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt, }; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult}; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::traits::solve::{ + CanonicalGoal, Certainty, ExternalConstraints, ExternalConstraintsData, MaybeCause, QueryResult, +}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, @@ -16,13 +19,31 @@ use rustc_middle::ty::{ use rustc_span::DUMMY_SP; use std::ops::ControlFlow; +use crate::traits::specialization_graph; + +use super::canonical::{CanonicalizeMode, Canonicalizer}; use super::search_graph::{self, OverflowHandler}; use super::SolverMode; use super::{search_graph::SearchGraph, Goal}; pub struct EvalCtxt<'a, 'tcx> { - // FIXME: should be private. - pub(super) infcx: &'a InferCtxt<'tcx>, + /// The inference context that backs (mostly) inference and placeholder terms + /// instantiated while solving goals. + /// + /// NOTE: The `InferCtxt` that backs the `EvalCtxt` is intentionally private, + /// because the `InferCtxt` is much more general than `EvalCtxt`. Methods such + /// as `take_registered_region_obligations` can mess up query responses, + /// using `At::normalize` is totally wrong, calling `evaluate_root_goal` can + /// cause coinductive unsoundness, etc. + /// + /// Methods that are generally of use for trait solving are *intentionally* + /// re-declared through the `EvalCtxt` below, often with cleaner signatures + /// since we don't care about things like `ObligationCause`s and `Span`s here. + /// If some `InferCtxt` method is missing, please first think defensively about + /// the method's compatibility with this solver, or if an existing one does + /// the job already. + infcx: &'a InferCtxt<'tcx>, + pub(super) var_values: CanonicalVarValues<'tcx>, /// The highest universe index nameable by the caller. /// @@ -548,4 +569,87 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { pub(super) fn universe(&self) -> ty::UniverseIndex { self.infcx.universe() } + + pub(super) fn create_next_universe(&self) -> ty::UniverseIndex { + self.infcx.create_next_universe() + } + + pub(super) fn instantiate_canonical_var( + &self, + cv_info: CanonicalVarInfo<'tcx>, + universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, + ) -> ty::GenericArg<'tcx> { + self.infcx.instantiate_canonical_var(DUMMY_SP, cv_info, universe_map) + } + + pub(super) fn translate_substs( + &self, + param_env: ty::ParamEnv<'tcx>, + source_impl: DefId, + source_substs: ty::SubstsRef<'tcx>, + target_node: specialization_graph::Node, + ) -> ty::SubstsRef<'tcx> { + crate::traits::translate_substs( + self.infcx, + param_env, + source_impl, + source_substs, + target_node, + ) + } + + pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) { + self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy()); + } + + pub(super) fn register_region_outlives(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) { + // `b : a` ==> `a <= b` + // (inlined from `InferCtxt::region_outlives_predicate`) + self.infcx.sub_regions( + rustc_infer::infer::SubregionOrigin::RelateRegionParamBound(DUMMY_SP), + b, + a, + ); + } + + /// Computes the list of goals required for `arg` to be well-formed + pub(super) fn well_formed_goals( + &self, + param_env: ty::ParamEnv<'tcx>, + arg: ty::GenericArg<'tcx>, + ) -> Option>>> { + crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg) + .map(|obligations| obligations.into_iter().map(|obligation| obligation.into())) + } + + #[instrument(level = "debug", skip(self), ret)] + pub(super) fn compute_external_query_constraints( + &self, + ) -> Result, NoSolution> { + // Cannot use `take_registered_region_obligations` as we may compute the response + // inside of a `probe` whenever we have multiple choices inside of the solver. + let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); + let region_constraints = self.infcx.with_region_constraints(|region_constraints| { + make_query_region_constraints( + self.tcx(), + region_obligations + .iter() + .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), + region_constraints, + ) + }); + let opaque_types = self.infcx.clone_opaque_types_for_query_response(); + Ok(self + .tcx() + .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types })) + } + + pub(super) fn canonicalize>>( + &self, + canonicalize_mode: CanonicalizeMode, + variables: &mut Vec>, + value: T, + ) -> Canonical<'tcx, T> { + Canonicalizer::canonicalize(self.infcx, canonicalize_mode, variables, value) + } } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 6a64dfdedd42f..7c01d5d2bef92 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -15,16 +15,14 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ - CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, - Goal, QueryResult, Response, + CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, + Response, }; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate, }; -use crate::traits::ObligationCause; - mod assembly; mod canonical; mod eval_ctxt; @@ -68,7 +66,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>, ) -> QueryResult<'tcx> { let ty::OutlivesPredicate(ty, lt) = goal.predicate; - self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy()); + self.register_ty_outlives(ty, lt); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -77,10 +75,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { &mut self, goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>, ) -> QueryResult<'tcx> { - self.infcx.region_outlives_predicate( - &ObligationCause::dummy(), - ty::Binder::dummy(goal.predicate), - ); + let ty::OutlivesPredicate(a, b) = goal.predicate; + self.register_region_outlives(a, b); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -146,13 +142,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { &mut self, goal: Goal<'tcx, ty::GenericArg<'tcx>>, ) -> QueryResult<'tcx> { - match crate::traits::wf::unnormalized_obligations( - self.infcx, - goal.param_env, - goal.predicate, - ) { - Some(obligations) => { - self.add_goals(obligations.into_iter().map(|o| o.into())); + match self.well_formed_goals(goal.param_env, goal.predicate) { + Some(goals) => { + self.add_goals(goals); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } None => self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS), diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 525b3105538d0..4c61a2cb2cc78 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -1,4 +1,4 @@ -use crate::traits::{specialization_graph, translate_substs}; +use crate::traits::specialization_graph; use super::assembly; use super::trait_goals::structural_traits; @@ -7,7 +7,6 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; -use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::specialization_graph::LeafDef; use rustc_infer::traits::Reveal; @@ -168,7 +167,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { // return ambiguity this would otherwise be incomplete, resulting in // unsoundness during coherence (#105782). let Some(assoc_def) = fetch_eligible_assoc_item_def( - ecx.infcx, + ecx, goal.param_env, goal_trait_ref, goal.predicate.def_id(), @@ -199,8 +198,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { goal_trait_ref.def_id, impl_substs, ); - let substs = translate_substs( - ecx.infcx, + let substs = ecx.translate_substs( goal.param_env, impl_def_id, impl_substs_with_gat, @@ -500,15 +498,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { /// /// FIXME: We should merge these 3 implementations as it's likely that they otherwise /// diverge. -#[instrument(level = "debug", skip(infcx, param_env), ret)] +#[instrument(level = "debug", skip(ecx, param_env), ret)] fn fetch_eligible_assoc_item_def<'tcx>( - infcx: &InferCtxt<'tcx>, + ecx: &EvalCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, goal_trait_ref: ty::TraitRef<'tcx>, trait_assoc_def_id: DefId, impl_def_id: DefId, ) -> Result, NoSolution> { - let node_item = specialization_graph::assoc_def(infcx.tcx, impl_def_id, trait_assoc_def_id) + let node_item = specialization_graph::assoc_def(ecx.tcx(), impl_def_id, trait_assoc_def_id) .map_err(|ErrorGuaranteed { .. }| NoSolution)?; let eligible = if node_item.is_final() { @@ -520,7 +518,7 @@ fn fetch_eligible_assoc_item_def<'tcx>( // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. if param_env.reveal() == Reveal::All { - let poly_trait_ref = infcx.resolve_vars_if_possible(goal_trait_ref); + let poly_trait_ref = ecx.resolve_vars_if_possible(goal_trait_ref); !poly_trait_ref.still_further_specializable() } else { debug!(?node_item.item.def_id, "not eligible due to default"); From 910a5ad2dfbff6c29092b73e696349eb45eb1aa5 Mon Sep 17 00:00:00 2001 From: Mu001999 Date: Sat, 25 Mar 2023 01:00:49 +0800 Subject: [PATCH 05/14] Emits suggestions for expressions with parentheses or not separately --- compiler/rustc_lint/messages.ftl | 4 +++- compiler/rustc_lint/src/lints.rs | 33 +++++++++++++++++++++++++------ compiler/rustc_lint/src/types.rs | 28 ++++++++++++++++++-------- tests/ui/lint/issue-109529.rs | 5 ++--- tests/ui/lint/issue-109529.stderr | 21 ++++++++++++-------- 5 files changed, 65 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 68e62c9789aed..5b7e994e035f4 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -197,7 +197,9 @@ lint_drop_glue = types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` - .suggestion = use an inclusive range instead + +lint_range_use_inclusive_range = use an inclusive range instead + lint_overflowing_bin_hex = literal out of range for `{$ty}` .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 925e9654f931d..8ec4c2b3d463a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1210,12 +1210,33 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> { #[diag(lint_range_endpoint_out_of_range)] pub struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, - #[suggestion(code = "=", applicability = "machine-applicable")] - pub eq_suggestion: Span, - #[suggestion(code = "{literal}{suffix}", applicability = "machine-applicable")] - pub lit_suggestion: Span, - pub literal: u128, - pub suffix: &'a str, + #[subdiagnostic] + pub sub: UseInclusiveRange<'a>, +} + +#[derive(Subdiagnostic)] +pub enum UseInclusiveRange<'a> { + #[suggestion( + lint_range_use_inclusive_range, + code = "{start}..={literal}{suffix}", + applicability = "machine-applicable" + )] + WithoutParen { + #[primary_span] + sugg: Span, + start: String, + literal: u128, + suffix: &'a str, + }, + #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")] + WithParen { + #[suggestion_part(code = "=")] + eq_sugg: Span, + #[suggestion_part(code = "{literal}{suffix}")] + lit_sugg: Span, + literal: u128, + suffix: &'a str, + }, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 1cc873c6de9c4..f6bca7045c846 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -4,7 +4,8 @@ use crate::{ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, - OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag, + OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, + VariantSizeDifferencesDiag, }, }; use crate::{LateContext, LateLintPass, LintContext}; @@ -172,16 +173,27 @@ fn lint_overflowing_range_endpoint<'tcx>( _ => bug!(), }; + let sub_sugg = if expr.span.lo() == lit_span.lo() { + let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; + UseInclusiveRange::WithoutParen { + sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()), + start, + literal: lit_val - 1, + suffix, + } + } else { + UseInclusiveRange::WithParen { + eq_sugg: expr.span.shrink_to_lo(), + lit_sugg: lit_span, + literal: lit_val - 1, + suffix, + } + }; + cx.emit_spanned_lint( OVERFLOWING_LITERALS, struct_expr.span, - RangeEndpointOutOfRange { - ty, - eq_suggestion: expr.span.shrink_to_lo(), - lit_suggestion: lit_span, - literal: lit_val - 1, - suffix, - }, + RangeEndpointOutOfRange { ty, sub: sub_sugg }, ); // We've just emitted a lint, special cased for `(...)..MAX+1` ranges, diff --git a/tests/ui/lint/issue-109529.rs b/tests/ui/lint/issue-109529.rs index 36c6d4fdfe3b4..c9b4da4b26e75 100644 --- a/tests/ui/lint/issue-109529.rs +++ b/tests/ui/lint/issue-109529.rs @@ -1,5 +1,4 @@ fn main() { - for i in 0..(256 as u8) { //~ ERROR range endpoint is out of range - println!("{}", i); - } + for _ in 0..256 as u8 {} //~ ERROR range endpoint is out of range + for _ in 0..(256 as u8) {} //~ ERROR range endpoint is out of range } diff --git a/tests/ui/lint/issue-109529.stderr b/tests/ui/lint/issue-109529.stderr index e9f6d546ac20b..15b259ad55ee4 100644 --- a/tests/ui/lint/issue-109529.stderr +++ b/tests/ui/lint/issue-109529.stderr @@ -1,18 +1,23 @@ error: range endpoint is out of range for `u8` --> $DIR/issue-109529.rs:2:14 | -LL | for i in 0..(256 as u8) { - | ^^^^^^^^^^^^^^ +LL | for _ in 0..256 as u8 {} + | ------^^^^^^ + | | + | help: use an inclusive range instead: `0..=255` | = note: `#[deny(overflowing_literals)]` on by default -help: use an inclusive range instead + +error: range endpoint is out of range for `u8` + --> $DIR/issue-109529.rs:3:14 + | +LL | for _ in 0..(256 as u8) {} + | ^^^^^^^^^^^^^^ | -LL | for i in 0..=(256 as u8) { - | + help: use an inclusive range instead | -LL | for i in 0..(255 as u8) { - | ~~~ +LL | for _ in 0..=(255 as u8) {} + | + ~~~ -error: aborting due to previous error +error: aborting due to 2 previous errors From e34ad763639eda0e6174fc89ee31d808ec0d1536 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 28 Mar 2023 03:25:30 -0700 Subject: [PATCH 06/14] Remove ~const from alloc --- library/alloc/src/alloc.rs | 8 +------ library/alloc/src/borrow.rs | 5 ++-- library/alloc/src/boxed.rs | 44 +++++++++++++----------------------- library/alloc/tests/boxed.rs | 15 ------------ library/alloc/tests/lib.rs | 1 - 5 files changed, 19 insertions(+), 54 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 3a797bd5ecaa8..6f2ba957bcda0 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -14,8 +14,6 @@ use core::ptr::{self, NonNull}; #[doc(inline)] pub use core::alloc::*; -use core::marker::Destruct; - #[cfg(test)] mod tests; @@ -331,16 +329,12 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { #[cfg_attr(not(test), lang = "box_free")] #[inline] -#[rustc_const_unstable(feature = "const_box", issue = "92521")] // This signature has to be the same as `Box`, otherwise an ICE will happen. // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // well. // For example if `Box` is changed to `struct Box(Unique, A)`, // this function has to be changed to `fn box_free(Unique, A)` as well. -pub(crate) const unsafe fn box_free( - ptr: Unique, - alloc: A, -) { +pub(crate) unsafe fn box_free(ptr: Unique, alloc: A) { unsafe { let size = size_of_val(ptr.as_ref()); let align = min_align_of_val(ptr.as_ref()); diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 83a1385599bec..0c8c796ae9b81 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -328,10 +328,9 @@ impl Cow<'_, B> { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_deref", issue = "88955")] -impl const Deref for Cow<'_, B> +impl Deref for Cow<'_, B> where - B::Owned: ~const Borrow, + B::Owned: Borrow, { type Target = B; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 241b11c3f5f52..09041bb119bb7 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -159,7 +159,7 @@ use core::hash::{Hash, Hasher}; use core::iter::FromIterator; use core::iter::{FusedIterator, Iterator}; use core::marker::Tuple; -use core::marker::{Destruct, Unpin, Unsize}; +use core::marker::{Unpin, Unsize}; use core::mem; use core::ops::{ CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Generator, GeneratorState, Receiver, @@ -376,12 +376,11 @@ impl Box { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline] - pub const fn new_in(x: T, alloc: A) -> Self + pub fn new_in(x: T, alloc: A) -> Self where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let mut boxed = Self::new_uninit_in(alloc); unsafe { @@ -406,12 +405,10 @@ impl Box { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn try_new_in(x: T, alloc: A) -> Result + pub fn try_new_in(x: T, alloc: A) -> Result where - T: ~const Destruct, - A: ~const Allocator + ~const Destruct, + A: Allocator, { let mut boxed = Self::try_new_uninit_in(alloc)?; unsafe { @@ -441,13 +438,12 @@ impl Box { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[cfg(not(no_global_oom_handling))] #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] - pub const fn new_uninit_in(alloc: A) -> Box, A> + pub fn new_uninit_in(alloc: A) -> Box, A> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -482,10 +478,9 @@ impl Box { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] - pub const fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::>(); let ptr = alloc.allocate(layout)?.cast(); @@ -513,13 +508,12 @@ impl Box { /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] - pub const fn new_zeroed_in(alloc: A) -> Box, A> + pub fn new_zeroed_in(alloc: A) -> Box, A> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. @@ -554,10 +548,9 @@ impl Box { /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] - pub const fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> where - A: ~const Allocator + ~const Destruct, + A: Allocator, { let layout = Layout::new::>(); let ptr = alloc.allocate_zeroed(layout)?.cast(); @@ -573,12 +566,11 @@ impl Box { /// construct a (pinned) `Box` in a different way than with [`Box::new_in`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline(always)] - pub const fn pin_in(x: T, alloc: A) -> Pin + pub fn pin_in(x: T, alloc: A) -> Pin where - A: 'static + ~const Allocator + ~const Destruct, + A: 'static + Allocator, { Self::into_pin(Self::new_in(x, alloc)) } @@ -605,12 +597,8 @@ impl Box { /// assert_eq!(Box::into_inner(c), 5); /// ``` #[unstable(feature = "box_into_inner", issue = "80437")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn into_inner(boxed: Self) -> T - where - Self: ~const Destruct, - { + pub fn into_inner(boxed: Self) -> T { *boxed } } diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index af49826ff30a3..68ebd8e35ee3d 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -179,18 +179,3 @@ unsafe impl const Allocator for ConstAllocator { self } } - -#[test] -fn const_box() { - const VALUE: u32 = { - let mut boxed = Box::new_in(1u32, ConstAllocator); - assert!(*boxed == 1); - - *boxed = 42; - assert!(*boxed == 42); - - *Box::leak(boxed) - }; - - assert!(VALUE == 42); -} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 966cf57511630..c27ca642e9b1f 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -3,7 +3,6 @@ #![feature(assert_matches)] #![feature(btree_drain_filter)] #![feature(cow_is_borrowed)] -#![feature(const_box)] #![feature(const_convert)] #![feature(const_cow_is_borrowed)] #![feature(const_heap)] From dde26b31b6b625496e8dc0933e231c27f35b8933 Mon Sep 17 00:00:00 2001 From: Mu42 Date: Wed, 29 Mar 2023 09:56:28 +0800 Subject: [PATCH 07/14] add run-rustfix --- tests/ui/lint/issue-109529.fixed | 6 ++++++ tests/ui/lint/issue-109529.rs | 2 ++ tests/ui/lint/issue-109529.stderr | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lint/issue-109529.fixed diff --git a/tests/ui/lint/issue-109529.fixed b/tests/ui/lint/issue-109529.fixed new file mode 100644 index 0000000000000..5ad489073eead --- /dev/null +++ b/tests/ui/lint/issue-109529.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + for _ in 0..=255 as u8 {} //~ ERROR range endpoint is out of range + for _ in 0..=(255 as u8) {} //~ ERROR range endpoint is out of range +} diff --git a/tests/ui/lint/issue-109529.rs b/tests/ui/lint/issue-109529.rs index c9b4da4b26e75..383d7bc4cf31f 100644 --- a/tests/ui/lint/issue-109529.rs +++ b/tests/ui/lint/issue-109529.rs @@ -1,3 +1,5 @@ +// run-rustfix + fn main() { for _ in 0..256 as u8 {} //~ ERROR range endpoint is out of range for _ in 0..(256 as u8) {} //~ ERROR range endpoint is out of range diff --git a/tests/ui/lint/issue-109529.stderr b/tests/ui/lint/issue-109529.stderr index 15b259ad55ee4..9e857d1b0ab5d 100644 --- a/tests/ui/lint/issue-109529.stderr +++ b/tests/ui/lint/issue-109529.stderr @@ -1,5 +1,5 @@ error: range endpoint is out of range for `u8` - --> $DIR/issue-109529.rs:2:14 + --> $DIR/issue-109529.rs:4:14 | LL | for _ in 0..256 as u8 {} | ------^^^^^^ @@ -9,7 +9,7 @@ LL | for _ in 0..256 as u8 {} = note: `#[deny(overflowing_literals)]` on by default error: range endpoint is out of range for `u8` - --> $DIR/issue-109529.rs:3:14 + --> $DIR/issue-109529.rs:5:14 | LL | for _ in 0..(256 as u8) {} | ^^^^^^^^^^^^^^ From 5bbaeadc013cae79e440fb5d3da2175c83cb36e4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 28 Mar 2023 12:32:57 -0700 Subject: [PATCH 08/14] =?UTF-8?q?Move=20`mir::Field`=20=E2=86=92=20`abi::F?= =?UTF-8?q?ieldIdx`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first PR for https://github.com/rust-lang/compiler-team/issues/606 This is just the move-and-rename, because it's plenty big-and-bitrotty already. Future PRs will start using `FieldIdx` more broadly, and concomitantly removing `FieldIdx::new`s. --- compiler/rustc_abi/src/lib.rs | 26 +++++++++++++ .../rustc_borrowck/src/diagnostics/mod.rs | 10 ++--- .../src/diagnostics/mutability_errors.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 7 ++-- compiler/rustc_borrowck/src/path_utils.rs | 5 ++- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- .../rustc_codegen_cranelift/src/abi/mod.rs | 4 +- compiler/rustc_codegen_cranelift/src/base.rs | 2 +- .../src/discriminant.rs | 6 +-- .../src/intrinsics/llvm_x86.rs | 4 +- .../src/intrinsics/simd.rs | 2 +- compiler/rustc_codegen_cranelift/src/lib.rs | 2 +- .../rustc_codegen_cranelift/src/unsize.rs | 4 +- .../src/value_and_place.rs | 6 +-- .../rustc_codegen_cranelift/src/vtable.rs | 6 +-- .../src/debuginfo/metadata/enums/mod.rs | 8 ++-- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 8 ++-- compiler/rustc_middle/src/mir/mod.rs | 37 +++++++------------ compiler/rustc_middle/src/mir/query.rs | 12 +++--- compiler/rustc_middle/src/mir/syntax.rs | 14 +++++-- compiler/rustc_middle/src/mir/tcx.rs | 8 ++-- compiler/rustc_middle/src/query/keys.rs | 3 +- compiler/rustc_middle/src/thir.rs | 10 ++--- compiler/rustc_middle/src/ty/context.rs | 8 ++-- .../rustc_middle/src/ty/structural_impls.rs | 4 +- .../src/build/custom/parse/instruction.rs | 4 +- .../src/build/expr/as_place.rs | 4 +- .../src/build/expr/as_rvalue.rs | 5 ++- .../rustc_mir_build/src/build/expr/into.rs | 3 +- compiler/rustc_mir_build/src/build/mod.rs | 3 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 12 +++--- .../src/thir/pattern/const_to_pat.rs | 5 ++- .../src/thir/pattern/deconstruct_pat.rs | 12 +++--- .../rustc_mir_build/src/thir/pattern/mod.rs | 9 +++-- .../rustc_mir_dataflow/src/elaborate_drops.rs | 18 ++++----- .../rustc_mir_dataflow/src/value_analysis.rs | 6 +-- .../src/dataflow_const_prop.rs | 5 +-- .../src/elaborate_box_derefs.rs | 7 ++-- .../src/elaborate_drops.rs | 4 +- compiler/rustc_mir_transform/src/generator.rs | 13 ++++--- compiler/rustc_mir_transform/src/inline.rs | 4 +- .../rustc_mir_transform/src/instcombine.rs | 8 ++-- .../src/lower_intrinsics.rs | 4 +- .../src/remove_uninit_drops.rs | 7 ++-- compiler/rustc_mir_transform/src/shim.rs | 8 ++-- compiler/rustc_mir_transform/src/sroa.rs | 5 ++- 46 files changed, 192 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 6740001c38be1..428191bc8b934 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1057,6 +1057,32 @@ impl Scalar { } } +rustc_index::newtype_index! { + /// The *source-order* index of a field in a variant. + /// + /// This is how most code after type checking refers to fields, rather than + /// using names (as names have hygiene complications and more complex lookup). + /// + /// Particularly for `repr(Rust)` types, this may not be the same as *layout* order. + /// (It is for `repr(C)` `struct`s, however.) + /// + /// For example, in the following types, + /// ```rust + /// # enum Never {} + /// # #[repr(u16)] + /// enum Demo1 { + /// Variant0 { a: Never, b: i32 } = 100, + /// Variant1 { c: u8, d: u64 } = 10, + /// } + /// struct Demo2 { e: u8, f: u16, g: u8 } + /// ``` + /// `b` is `FieldIdx(1)` in `VariantIdx(0)`, + /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and + /// `f` is `FieldIdx(1)` in `VariantIdx(0)`. + #[derive(HashStable_Generic)] + pub struct FieldIdx {} +} + /// Describes how the fields of a type are located in memory. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 9f543b71c5fa4..5827fa81cffb5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -9,15 +9,15 @@ use rustc_hir::GeneratorKind; use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand, - Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, + AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place, + PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::def_id::LocalDefId; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause, @@ -302,7 +302,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn describe_field( &self, place: PlaceRef<'tcx>, - field: Field, + field: FieldIdx, including_tuple_field: IncludingTupleField, ) -> Option { let place_ty = match place { @@ -331,7 +331,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn describe_field_from_ty( &self, ty: Ty<'_>, - field: Field, + field: FieldIdx, variant_index: Option, including_tuple_field: IncludingTupleField, ) -> Option { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a8c216407f931..9d90400965040 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -12,6 +12,7 @@ use rustc_middle::{ use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, BytePos, Span}; +use rustc_target::abi::FieldIdx; use crate::diagnostics::BorrowedContentSource; use crate::MirBorrowckCtxt; @@ -1275,7 +1276,7 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool { fn get_mut_span_in_struct_field<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - field: mir::Field, + field: FieldIdx, ) -> Option { // Expect our local to be a reference to a struct of some kind. if let ty::Ref(_, ty, _) = ty.kind() diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b7ce3afce7bb2..2f64ccee686a8 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -33,12 +33,13 @@ use rustc_middle::mir::{ Place, PlaceElem, PlaceRef, VarDebugInfoContents, }; use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; -use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; +use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; +use rustc_target::abi::FieldIdx; use either::Either; use smallvec::SmallVec; @@ -597,7 +598,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> { used_mut: FxIndexSet, /// If the function we're checking is a closure, then we'll need to report back the list of /// mutable upvars that have been used. This field keeps track of them. - used_mut_upvars: SmallVec<[Field; 8]>, + used_mut_upvars: SmallVec<[FieldIdx; 8]>, /// Region inference context. This contains the results from region inference and lets us e.g. /// find out which CFG points are contained in each borrow region. regioncx: Rc>, @@ -2277,7 +2278,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. - fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option { + fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option { path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body()) } diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index f8a99a2699e6f..ea9f8683ca7bb 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -7,8 +7,9 @@ use crate::BorrowIndex; use crate::Upvar; use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::BorrowKind; -use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem}; +use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::TyCtxt; +use rustc_target::abi::FieldIdx; /// Returns `true` if the borrow represented by `kind` is /// allowed to be split into separate Reservation and @@ -148,7 +149,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>( upvars: &[Upvar<'tcx>], place_ref: PlaceRef<'tcx>, body: &Body<'tcx>, -) -> Option { +) -> Option { let mut place_ref = place_ref; let mut by_ref = false; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 4b27d24098517..04da6d6beff68 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -36,7 +36,7 @@ use rustc_middle::ty::{ }; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::FIRST_VARIANT; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; @@ -786,7 +786,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { &mut self, parent: &dyn fmt::Debug, base_ty: PlaceTy<'tcx>, - field: Field, + field: FieldIdx, location: Location, ) -> Result, FieldAccessError> { let tcx = self.tcx(); diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 3bc64c44524ed..91c085d3d6986 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -327,7 +327,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ ArgKind::Spread(params) => { for (i, param) in params.into_iter().enumerate() { if let Some(param) = param { - place.place_field(fx, mir::Field::new(i)).write_cvalue(fx, param); + place.place_field(fx, FieldIdx::new(i)).write_cvalue(fx, param); } } } @@ -460,7 +460,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.push(self_arg); for i in 0..tupled_arguments.len() { args.push(CallArgument { - value: pack_arg.value.value_field(fx, mir::Field::new(i)), + value: pack_arg.value.value_field(fx, FieldIdx::new(i)), is_owned: pack_arg.is_owned, }); } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 1825fb8cb2288..615ef58ff5829 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -797,7 +797,7 @@ fn codegen_stmt<'tcx>( let index = fx.bcx.ins().iconst(fx.pointer_type, field_index as i64); variant_dest.place_index(fx, index) } else { - variant_dest.place_field(fx, mir::Field::new(field_index)) + variant_dest.place_field(fx, FieldIdx::new(field_index)) }; to.write_cvalue(fx, operand); } diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index 3cbf313adf0df..f740945a03c31 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -26,7 +26,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>( tag_encoding: TagEncoding::Direct, variants: _, } => { - let ptr = place.place_field(fx, mir::Field::new(tag_field)); + let ptr = place.place_field(fx, FieldIdx::new(tag_field)); let to = layout.ty.discriminant_for_variant(fx.tcx, variant_index).unwrap().val; let to = if ptr.layout().abi.is_signed() { ty::ScalarInt::try_from_int( @@ -47,7 +47,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>( variants: _, } => { if variant_index != untagged_variant { - let niche = place.place_field(fx, mir::Field::new(tag_field)); + let niche = place.place_field(fx, FieldIdx::new(tag_field)); let niche_type = fx.clif_type(niche.layout().ty).unwrap(); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = (niche_value as u128).wrapping_add(niche_start); @@ -107,7 +107,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let cast_to = fx.clif_type(dest_layout.ty).unwrap(); // Read the tag/niche-encoded discriminant from memory. - let tag = value.value_field(fx, mir::Field::new(tag_field)); + let tag = value.value_field(fx, FieldIdx::new(tag_field)); let tag = tag.load_scalar(fx); // Decode the discriminant (specifically if it's niche-encoded). diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs index e5c4b244a1afd..0f32d1a25ffad 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -179,8 +179,8 @@ fn llvm_add_sub<'tcx>( // c + carry -> c + first intermediate carry or borrow respectively let int0 = crate::num::codegen_checked_int_binop(fx, bin_op, a, b); - let c = int0.value_field(fx, mir::Field::new(0)); - let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx); + let c = int0.value_field(fx, FieldIdx::new(0)); + let cb0 = int0.value_field(fx, FieldIdx::new(1)).load_scalar(fx); // c + carry -> c + second intermediate carry or borrow respectively let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 034b4e8072cc5..6f54a8d49c867 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -253,7 +253,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } ret.write_cvalue(fx, base); - let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap())); + let ret_lane = ret.place_field(fx, FieldIdx::new(idx.try_into().unwrap())); ret_lane.write_cvalue(fx, val); } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 1bd03403f244b..8cc7f6c34b021 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -86,7 +86,7 @@ mod prelude { self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeVisitableExt, UintTy, }; - pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx, FIRST_VARIANT}; + pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT}; pub(crate) use rustc_data_structures::fx::FxHashMap; diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 93eefd92342d8..ff0e12410e703 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -147,8 +147,8 @@ pub(crate) fn coerce_unsized_into<'tcx>( assert_eq!(def_a, def_b); for i in 0..def_a.variant(FIRST_VARIANT).fields.len() { - let src_f = src.value_field(fx, mir::Field::new(i)); - let dst_f = dst.place_field(fx, mir::Field::new(i)); + let src_f = src.value_field(fx, FieldIdx::new(i)); + let dst_f = dst.place_field(fx, FieldIdx::new(i)); if dst_f.layout().is_zst() { continue; diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 58e0a498292d4..ffe3ccb0eca04 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -10,7 +10,7 @@ fn codegen_field<'tcx>( base: Pointer, extra: Option, layout: TyAndLayout<'tcx>, - field: mir::Field, + field: FieldIdx, ) -> (Pointer, TyAndLayout<'tcx>) { let field_offset = layout.fields.offset(field.index()); let field_layout = layout.field(&*fx, field.index()); @@ -210,7 +210,7 @@ impl<'tcx> CValue<'tcx> { pub(crate) fn value_field( self, fx: &mut FunctionCx<'_, '_, 'tcx>, - field: mir::Field, + field: FieldIdx, ) -> CValue<'tcx> { let layout = self.1; match self.0 { @@ -687,7 +687,7 @@ impl<'tcx> CPlace<'tcx> { pub(crate) fn place_field( self, fx: &mut FunctionCx<'_, '_, 'tcx>, - field: mir::Field, + field: FieldIdx, ) -> CPlace<'tcx> { let layout = self.layout(); diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs index 94806e0d798ed..b309695c190f8 100644 --- a/compiler/rustc_codegen_cranelift/src/vtable.rs +++ b/compiler/rustc_codegen_cranelift/src/vtable.rs @@ -50,7 +50,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( if let Abi::Scalar(_) = arg.layout().abi { 'descend_newtypes: while !arg.layout().ty.is_unsafe_ptr() && !arg.layout().ty.is_ref() { for i in 0..arg.layout().fields.count() { - let field = arg.value_field(fx, mir::Field::new(i)); + let field = arg.value_field(fx, FieldIdx::new(i)); if !field.layout().is_zst() { // we found the one non-zero-sized field that is allowed // now find *its* non-zero-sized field, or stop if it's a @@ -68,9 +68,9 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( if ty.is_dyn_star() { let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty); let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout); - let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr(); + let ptr = dyn_star.place_field(fx, FieldIdx::new(0)).to_ptr(); let vtable = - dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx); + dyn_star.place_field(fx, FieldIdx::new(1)).to_cvalue(fx).load_scalar(fx); break 'block (ptr, vtable); } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 54e850f25996b..3e4765fba57d5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -6,7 +6,7 @@ use rustc_hir::def::CtorKind; use rustc_index::vec::IndexVec; use rustc_middle::{ bug, - mir::{Field, GeneratorLayout, GeneratorSavedLocal}, + mir::{GeneratorLayout, GeneratorSavedLocal}, ty::{ self, layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}, @@ -14,7 +14,9 @@ use rustc_middle::{ }, }; use rustc_span::Symbol; -use rustc_target::abi::{HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants}; +use rustc_target::abi::{ + FieldIdx, HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants, +}; use std::borrow::Cow; use crate::{ @@ -353,7 +355,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>( let state_specific_fields: SmallVec<_> = (0..variant_layout.fields.count()) .map(|field_index| { let generator_saved_local = generator_layout.variant_fields[variant_index] - [Field::from_usize(field_index)]; + [FieldIdx::from_usize(field_index)]; let field_name_maybe = state_specific_upvar_names[generator_saved_local]; let field_name = field_name_maybe .as_ref() diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index d15774696a52b..ff25d1e38236d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; -use rustc_target::abi::{Abi, Size, VariantIdx}; +use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -79,7 +79,7 @@ impl<'tcx, S: Copy, L: Copy> DebugScope { trait DebugInfoOffsetLocation<'tcx, Bx> { fn deref(&self, bx: &mut Bx) -> Self; fn layout(&self) -> TyAndLayout<'tcx>; - fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self; + fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self; fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self; } @@ -94,7 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx> self.layout } - fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self { + fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self { PlaceRef::project_field(*self, bx, field.index()) } @@ -116,7 +116,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx> *self } - fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self { + fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self { self.field(bx.cx(), field.index()) } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9c575f6eb9fd0..37356b53c0271 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -21,7 +21,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::{self, GeneratorKind, ImplicitSelfKind}; use rustc_hir::{self as hir, HirId}; use rustc_session::Session; -use rustc_target::abi::{Size, VariantIdx}; +use rustc_target::abi::{FieldIdx, Size, VariantIdx}; use polonius_engine::Atom; pub use rustc_ast::Mutability; @@ -1512,7 +1512,7 @@ impl ProjectionElem { } /// Returns `true` if this is a `Field` projection with the given index. - pub fn is_field_to(&self, f: Field) -> bool { + pub fn is_field_to(&self, f: FieldIdx) -> bool { matches!(*self, Self::Field(x, _) if x == f) } } @@ -1521,22 +1521,6 @@ impl ProjectionElem { /// need neither the `V` parameter for `Index` nor the `T` for `Field`. pub type ProjectionKind = ProjectionElem<(), ()>; -rustc_index::newtype_index! { - /// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG] - /// - /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually, - /// rustc can identify that a field projection refers to either two different regions of memory - /// or the same one between the base and the 'projection element'. - /// Read more about projections in the [rustc-dev-guide][mir-datatypes] - /// - /// [wrapper]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#newtype - /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg - /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types - #[derive(HashStable)] - #[debug_format = "field[{}]"] - pub struct Field {} -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct PlaceRef<'tcx> { pub local: Local, @@ -2685,12 +2669,17 @@ impl<'tcx> UserTypeProjections { self.map_projections(|pat_ty_proj| pat_ty_proj.deref()) } - pub fn leaf(self, field: Field) -> Self { + pub fn leaf(self, field: FieldIdx) -> Self { self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field)) } - pub fn variant(self, adt_def: AdtDef<'tcx>, variant_index: VariantIdx, field: Field) -> Self { - self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) + pub fn variant( + self, + adt_def: AdtDef<'tcx>, + variant_index: VariantIdx, + field_index: FieldIdx, + ) -> Self { + self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index)) } } @@ -2733,7 +2722,7 @@ impl UserTypeProjection { self } - pub(crate) fn leaf(mut self, field: Field) -> Self { + pub(crate) fn leaf(mut self, field: FieldIdx) -> Self { self.projs.push(ProjectionElem::Field(field, ())); self } @@ -2742,13 +2731,13 @@ impl UserTypeProjection { mut self, adt_def: AdtDef<'_>, variant_index: VariantIdx, - field: Field, + field_index: FieldIdx, ) -> Self { self.projs.push(ProjectionElem::Downcast( Some(adt_def.variant(variant_index).name), variant_index, )); - self.projs.push(ProjectionElem::Field(field, ())); + self.projs.push(ProjectionElem::Field(field_index, ())); self } } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 786c2e9cd943e..68561cf6dd775 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -10,12 +10,12 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::BitMatrix; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::Span; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use smallvec::SmallVec; use std::cell::Cell; use std::fmt::{self, Debug}; -use super::{Field, SourceInfo}; +use super::SourceInfo; #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] pub enum UnsafetyViolationKind { @@ -152,7 +152,7 @@ pub struct GeneratorLayout<'tcx> { /// Which of the above fields are in each variant. Note that one field may /// be stored in multiple variants. - pub variant_fields: IndexVec>, + pub variant_fields: IndexVec>, /// The source that led to each variant being created (usually, a yield or /// await). @@ -229,7 +229,7 @@ pub struct BorrowCheckResult<'tcx> { /// unerased regions. pub concrete_opaque_types: FxIndexMap>, pub closure_requirements: Option>, - pub used_mut_upvars: SmallVec<[Field; 8]>, + pub used_mut_upvars: SmallVec<[FieldIdx; 8]>, pub tainted_by_errors: Option, } @@ -353,7 +353,7 @@ pub enum ConstraintCategory<'tcx> { /// like `Foo { field: my_val }`) Usage, OpaqueType, - ClosureUpvar(Field), + ClosureUpvar(FieldIdx), /// A constraint from a user-written predicate /// with the provided span, written on the item @@ -375,7 +375,7 @@ pub enum ConstraintCategory<'tcx> { #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] pub enum ReturnConstraint { Normal, - ClosureUpvar(Field), + ClosureUpvar(FieldIdx), } /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index bbd913d071d48..8fb693055fa8a 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -3,7 +3,7 @@ //! This is in a dedicated file so that changes to this file can be reviewed more carefully. //! The intention is that this file only contains datatype declarations, no code. -use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection}; +use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection}; use crate::mir::coverage::{CodeRegion, CoverageKind}; use crate::traits::Reveal; @@ -16,7 +16,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir}; use rustc_hir::{self, GeneratorKind}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_span::def_id::LocalDefId; @@ -888,7 +888,15 @@ pub struct Place<'tcx> { #[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum ProjectionElem { Deref, - Field(Field, T), + + /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually, + /// rustc can identify that a field projection refers to either two different regions of memory + /// or the same one between the base and the 'projection element'. + /// Read more about projections in the [rustc-dev-guide][mir-datatypes] + /// + /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types + Field(FieldIdx, T), + /// Index into a slice/array. /// /// Note that this does not also dereference, and so it does not exactly correspond to slice diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 0aa2c500f51fb..6e23c82a37b99 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -6,7 +6,7 @@ use crate::mir::*; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct PlaceTy<'tcx> { @@ -33,7 +33,7 @@ impl<'tcx> PlaceTy<'tcx> { /// /// Note that the resulting type has not been normalized. #[instrument(level = "debug", skip(tcx), ret)] - pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> { + pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> { match self.ty.kind() { ty::Adt(adt_def, substs) => { let variant_def = match self.variant_index { @@ -61,14 +61,14 @@ impl<'tcx> PlaceTy<'tcx> { /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` /// projects `place_ty` onto `elem`, returning the appropriate /// `Ty` or downcast variant corresponding to that projection. - /// The `handle_field` callback must map a `Field` to its `Ty`, + /// The `handle_field` callback must map a `FieldIdx` to its `Ty`, /// (which should be trivial when `T` = `Ty`). pub fn projection_ty_core( self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem, - mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>, + mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>, ) -> PlaceTy<'tcx> where diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index ca65fbc2fd470..4a096a2c0e840 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -12,6 +12,7 @@ use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::abi::FieldIdx; /// Placeholder for `CrateNum`'s "local" counterpart #[derive(Copy, Clone, Debug)] @@ -332,7 +333,7 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { } } -impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) { +impl<'tcx> Key for (ty::Const<'tcx>, FieldIdx) { type CacheSelector = DefaultCacheSelector; fn default_span(&self, _: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3b11fab8cdf57..29e3055a4b860 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -17,14 +17,14 @@ use rustc_index::newtype_index; use rustc_index::vec::IndexVec; use rustc_middle::middle::region; use rustc_middle::mir::interpret::AllocId; -use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp}; +use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp}; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts}; use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span, Symbol, DUMMY_SP}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::asm::InlineAsmRegOrRegClass; use std::fmt; use std::ops::Index; @@ -366,7 +366,7 @@ pub enum ExprKind<'tcx> { /// Variant containing the field. variant_index: VariantIdx, /// This can be a named (`.foo`) or unnamed (`.0`) field. - name: Field, + name: FieldIdx, }, /// A *non-overloaded* indexing operation. Index { @@ -491,7 +491,7 @@ pub enum ExprKind<'tcx> { /// This is used in struct constructors. #[derive(Clone, Debug, HashStable)] pub struct FieldExpr { - pub name: Field, + pub name: FieldIdx, pub expr: ExprId, } @@ -570,7 +570,7 @@ pub enum BindingMode { #[derive(Clone, Debug, HashStable)] pub struct FieldPat<'tcx> { - pub field: Field, + pub field: FieldIdx, pub pattern: Box>, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a1c1acc4a2541..8d0aa622244cd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -12,9 +12,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::resolve_bound_vars; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstAllocation}; -use crate::mir::{ - Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted, -}; +use crate::mir::{Body, BorrowCheckResult, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::query::LocalCrate; use crate::thir::Thir; use crate::traits; @@ -65,7 +63,7 @@ use rustc_span::def_id::{DefPathHash, StableCrateId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; +use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; @@ -2125,7 +2123,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> { + pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> { self.mk_place_elem(place, PlaceElem::Field(f, ty)) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c6bb814679586..d4f058440b954 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -4,7 +4,7 @@ //! to help with the tedium. use crate::mir::interpret; -use crate::mir::{Field, ProjectionKind}; +use crate::mir::ProjectionKind; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -217,6 +217,7 @@ CloneLiftImpls! { // implementation and traversal implementations (the latter only for // TyCtxt<'_> interners). TrivialTypeTraversalAndLiftImpls! { + ::rustc_target::abi::FieldIdx, ::rustc_target::abi::VariantIdx, crate::middle::region::Scope, crate::ty::FloatTy, @@ -268,7 +269,6 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_span::Span, ::rustc_span::symbol::Ident, ::rustc_errors::ErrorGuaranteed, - Field, interpret::Scalar, rustc_target::abi::Size, ty::BoundVar, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index bf58b3090fb8e..77a5017b3630f 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -3,7 +3,7 @@ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::cast::mir_cast_kind; use rustc_middle::{mir::*, thir::*, ty}; use rustc_span::Span; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use crate::build::custom::ParseError; use crate::build::expr::as_constant::as_constant_inner; @@ -223,7 +223,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place", @call("mir_field", args) => { let (parent, ty) = self.parse_place_inner(args[0])?; - let field = Field::from_u32(self.parse_integer_literal(args[1])? as u32); + let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32); let field_ty = ty.field_ty(self.tcx, field); let proj = PlaceElem::Field(field, field_ty); let place = parent.project_deeper(&[proj], self.tcx); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index e112bf9829b68..0fc99e57d1229 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -13,7 +13,7 @@ use rustc_middle::thir::*; use rustc_middle::ty::AdtDef; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance}; use rustc_span::Span; -use rustc_target::abi::{VariantIdx, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use std::assert_matches::assert_matches; use std::iter; @@ -293,7 +293,7 @@ impl<'tcx> PlaceBuilder<'tcx> { &self.projection } - pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self { + pub(crate) fn field(self, f: FieldIdx, ty: Ty<'tcx>) -> Self { self.project(PlaceElem::Field(f, ty)) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 7fff801b1692d..d1878bf77ef1e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -17,6 +17,7 @@ use rustc_middle::thir::*; use rustc_middle::ty::cast::{mir_cast_kind, CastTy}; use rustc_middle::ty::{self, Ty, UpvarSubsts}; use rustc_span::Span; +use rustc_target::abi::FieldIdx; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns an rvalue suitable for use until the end of the current @@ -553,8 +554,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { result_value, Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))), ); - let val_fld = Field::new(0); - let of_fld = Field::new(1); + let val_fld = FieldIdx::new(0); + let of_fld = FieldIdx::new(1); let tcx = self.tcx; let val = tcx.mk_place_field(result_value, val_fld, ty); diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index ebe8ea25ad3af..b8260c719c89a 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -10,6 +10,7 @@ use rustc_index::vec::Idx; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::CanonicalUserTypeAnnotation; +use rustc_target::abi::FieldIdx; use std::iter; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -344,7 +345,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .collect(); let field_names: Vec<_> = - (0..adt_def.variant(variant_index).fields.len()).map(Field::new).collect(); + (0..adt_def.variant(variant_index).fields.len()).map(FieldIdx::new).collect(); let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base { let place_builder = diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 1923e10ddb586..e87e38fd04caf 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -25,6 +25,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_span::Symbol; +use rustc_target::abi::FieldIdx; use rustc_target::spec::abi::Abi; use super::lints; @@ -793,7 +794,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mutability = captured_place.mutability; let mut projs = closure_env_projs.clone(); - projs.push(ProjectionElem::Field(Field::new(i), ty)); + projs.push(ProjectionElem::Field(FieldIdx::new(i), ty)); match capture { ty::UpvarCapture::ByValue => {} ty::UpvarCapture::ByRef(..) => { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 04e9273fc46c9..2a0b5d0473313 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -10,7 +10,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; -use rustc_middle::mir::{self, BinOp, BorrowKind, Field, UnOp}; +use rustc_middle::mir::{self, BinOp, BorrowKind, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast, @@ -20,7 +20,7 @@ use rustc_middle::ty::{ self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType, }; use rustc_span::{sym, Span}; -use rustc_target::abi::FIRST_VARIANT; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; impl<'tcx> Cx<'tcx> { pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId { @@ -379,7 +379,7 @@ impl<'tcx> Cx<'tcx> { .iter() .enumerate() .map(|(idx, e)| FieldExpr { - name: Field::new(idx), + name: FieldIdx::new(idx), expr: self.mirror_expr(e), }) .collect(); @@ -733,7 +733,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Field(ref source, ..) => ExprKind::Field { lhs: self.mirror_expr(source), variant_index: FIRST_VARIANT, - name: Field::new(self.typeck_results.field_index(expr.hir_id)), + name: FieldIdx::new(self.typeck_results.field_index(expr.hir_id)), }, hir::ExprKind::Cast(ref source, ref cast_ty) => { // Check for a user-given type annotation on this `cast` @@ -1053,7 +1053,7 @@ impl<'tcx> Cx<'tcx> { HirProjectionKind::Field(field, variant_index) => ExprKind::Field { lhs: self.thir.exprs.push(captured_place_expr), variant_index, - name: Field::new(field as usize), + name: FieldIdx::new(field as usize), }, HirProjectionKind::Index | HirProjectionKind::Subslice => { // We don't capture these projections, so we can ignore them here @@ -1107,7 +1107,7 @@ impl<'tcx> Cx<'tcx> { fields .iter() .map(|field| FieldExpr { - name: Field::new(self.typeck_results.field_index(field.hir_id)), + name: FieldIdx::new(self.typeck_results.field_index(field.hir_id)), expr: self.mirror_expr(field.expr), }) .collect() diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 274c2f06137a3..2dbef740d1a6e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -2,11 +2,12 @@ use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::Obligation; -use rustc_middle::mir::{self, Field}; +use rustc_middle::mir; use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint; use rustc_span::Span; +use rustc_target::abi::FieldIdx; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause}; @@ -218,7 +219,7 @@ impl<'tcx> ConstToPat<'tcx> { ) -> Result>, FallbackToConstRef> { vals.enumerate() .map(|(idx, val)| { - let field = Field::new(idx); + let field = FieldIdx::new(idx); Ok(FieldPat { field, pattern: self.recur(val, false)? }) }) .collect() diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 8a7b1fce51db4..e619e095496bc 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -53,14 +53,14 @@ use smallvec::{smallvec, SmallVec}; use rustc_data_structures::captures::Captures; use rustc_hir::{HirId, RangeEnd}; use rustc_index::vec::Idx; -use rustc_middle::mir::{self, Field}; +use rustc_middle::mir; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; use rustc_middle::{middle::stability::EvalResult, mir::interpret::ConstValue}; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::{Integer, Size, VariantIdx, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx, FIRST_VARIANT}; use self::Constructor::*; use self::SliceKind::*; @@ -1126,7 +1126,7 @@ impl<'tcx> SplitWildcard<'tcx> { /// Note that the number of fields of a constructor may not match the fields declared in the /// original struct/variant. This happens if a private or `non_exhaustive` field is uninhabited, /// because the code mustn't observe that it is uninhabited. In that case that field is not -/// included in `fields`. For that reason, when you have a `mir::Field` you must use +/// included in `fields`. For that reason, when you have a `FieldIdx` you must use /// `index_with_declared_idx`. #[derive(Debug, Clone, Copy)] pub(super) struct Fields<'p, 'tcx> { @@ -1165,7 +1165,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { cx: &'a MatchCheckCtxt<'p, 'tcx>, ty: Ty<'tcx>, variant: &'a VariantDef, - ) -> impl Iterator)> + Captures<'a> + Captures<'p> { + ) -> impl Iterator)> + Captures<'a> + Captures<'p> { let ty::Adt(adt, substs) = ty.kind() else { bug!() }; // Whether we must not match the fields of this variant exhaustively. let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local(); @@ -1180,7 +1180,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { if is_uninhabited && (!is_visible || is_non_exhaustive) { None } else { - Some((Field::new(i), ty)) + Some((FieldIdx::new(i), ty)) } }) } @@ -1438,7 +1438,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { ty::Tuple(..) => PatKind::Leaf { subpatterns: subpatterns .enumerate() - .map(|(i, pattern)| FieldPat { field: Field::new(i), pattern }) + .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern }) .collect(), }, ty::Adt(adt_def, _) if adt_def.is_box() => { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f356c8a68380c..72b4041aa1b72 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -21,12 +21,13 @@ use rustc_middle::mir::interpret::{ ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar, }; use rustc_middle::mir::{self, UserTypeProjection}; -use rustc_middle::mir::{BorrowKind, Field, Mutability}; +use rustc_middle::mir::{BorrowKind, Mutability}; use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange}; use rustc_middle::ty::subst::{GenericArg, SubstsRef}; use rustc_middle::ty::CanonicalUserTypeAnnotation; use rustc_middle::ty::{self, AdtDef, ConstKind, Region, Ty, TyCtxt, UserType}; use rustc_span::{Span, Symbol}; +use rustc_target::abi::FieldIdx; use std::cmp::Ordering; @@ -356,7 +357,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let subpatterns = fields .iter() .map(|field| FieldPat { - field: Field::new(self.typeck_results.field_index(field.hir_id)), + field: FieldIdx::new(self.typeck_results.field_index(field.hir_id)), pattern: self.lower_pattern(&field.pat), }) .collect(); @@ -379,7 +380,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { pats.iter() .enumerate_and_adjust(expected_len, gap_pos) .map(|(i, subpattern)| FieldPat { - field: Field::new(i), + field: FieldIdx::new(i), pattern: self.lower_pattern(subpattern), }) .collect() @@ -723,7 +724,7 @@ macro_rules! ClonePatternFoldableImpls { } ClonePatternFoldableImpls! { <'tcx> - Span, Field, Mutability, Symbol, LocalVarId, usize, + Span, FieldIdx, Mutability, Symbol, LocalVarId, usize, Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>, SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>, UserTypeProjection, CanonicalUserTypeAnnotation<'tcx> diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index fe6728fc76e4c..37787d99c2d51 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -7,7 +7,7 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_target::abi::{VariantIdx, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use std::{fmt, iter}; /// The value of an inserted drop flag. @@ -129,7 +129,7 @@ pub trait DropElaborator<'a, 'tcx>: fmt::Debug { /// Returns the subpath of a field of `path` (or `None` if there is no dedicated subpath). /// /// If this returns `None`, `field` will not get a dedicated drop flag. - fn field_subpath(&self, path: Self::Path, field: Field) -> Option; + fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option; /// Returns the subpath of a dereference of `path` (or `None` if there is no dedicated subpath). /// @@ -269,7 +269,7 @@ where .iter() .enumerate() .map(|(i, f)| { - let field = Field::new(i); + let field = FieldIdx::new(i); let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); @@ -397,8 +397,8 @@ where .enumerate() .map(|(i, &ty)| { ( - self.tcx().mk_place_field(self.place, Field::new(i), ty), - self.elaborator.field_subpath(self.path, Field::new(i)), + self.tcx().mk_place_field(self.place, FieldIdx::new(i), ty), + self.elaborator.field_subpath(self.path, FieldIdx::new(i)), ) }) .collect(); @@ -416,9 +416,9 @@ where unique_ty.ty_adt_def().unwrap().non_enum_variant().fields[0].ty(self.tcx(), substs); let ptr_ty = self.tcx().mk_imm_ptr(substs[0].expect_ty()); - let unique_place = self.tcx().mk_place_field(self.place, Field::new(0), unique_ty); - let nonnull_place = self.tcx().mk_place_field(unique_place, Field::new(0), nonnull_ty); - let ptr_place = self.tcx().mk_place_field(nonnull_place, Field::new(0), ptr_ty); + let unique_place = self.tcx().mk_place_field(self.place, FieldIdx::new(0), unique_ty); + let nonnull_place = self.tcx().mk_place_field(unique_place, FieldIdx::new(0), nonnull_ty); + let ptr_place = self.tcx().mk_place_field(nonnull_place, FieldIdx::new(0), ptr_ty); let interior = self.tcx().mk_place_deref(ptr_place); let interior_path = self.elaborator.deref_subpath(self.path); @@ -899,7 +899,7 @@ where .iter() .enumerate() .map(|(i, f)| { - let field = Field::new(i); + let field = FieldIdx::new(i); let field_ty = f.ty(tcx, substs); Operand::Move(tcx.mk_place_field(self.place, field, field_ty)) }) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 7f560d6119428..63e553bec5329 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -40,7 +40,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use crate::lattice::{HasBottom, HasTop}; use crate::{ @@ -919,7 +919,7 @@ impl ValueOrPlace { /// Although only field projections are currently allowed, this could change in the future. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TrackElem { - Field(Field), + Field(FieldIdx), Variant(VariantIdx), Discriminant, } @@ -941,7 +941,7 @@ pub fn iter_fields<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - mut f: impl FnMut(Option, Field, Ty<'tcx>), + mut f: impl FnMut(Option, FieldIdx, Ty<'tcx>), ) { match ty.kind() { ty::Tuple(list) => { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index a7218a4f2500d..15f5df41153b2 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -13,8 +13,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace}; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::DUMMY_SP; -use rustc_target::abi::Align; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{Align, FieldIdx, VariantIdx}; use crate::MirPass; @@ -148,7 +147,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { for (field_index, operand) in operands.iter().enumerate() { if let Some(field) = self.map().apply( variant_target_idx, - TrackElem::Field(Field::from_usize(field_index)), + TrackElem::Field(FieldIdx::from_usize(field_index)), ) { let result = self.handle_operand(operand, state); state.insert_idx(field, result, self.map()); diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 954bb5aff8de6..58bc083280a30 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_target::abi::FieldIdx; /// Constructs the types used when accessing a Box's pointer pub fn build_ptr_tys<'tcx>( @@ -32,9 +33,9 @@ pub fn build_projection<'tcx>( ptr_ty: Ty<'tcx>, ) -> [PlaceElem<'tcx>; 3] { [ - PlaceElem::Field(Field::new(0), unique_ty), - PlaceElem::Field(Field::new(0), nonnull_ty), - PlaceElem::Field(Field::new(0), ptr_ty), + PlaceElem::Field(FieldIdx::new(0), unique_ty), + PlaceElem::Field(FieldIdx::new(0), nonnull_ty), + PlaceElem::Field(FieldIdx::new(0), ptr_ty), ] } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 3faccca823a57..a028d6356d50e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -15,7 +15,7 @@ use rustc_mir_dataflow::MoveDataParamEnv; use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits}; use rustc_mir_dataflow::{Analysis, ResultsCursor}; use rustc_span::{DesugaringKind, Span}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use std::fmt; /// During MIR building, Drop terminators are inserted in every place where a drop may occur. @@ -252,7 +252,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { } } - fn field_subpath(&self, path: Self::Path, field: Field) -> Option { + fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option { rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { ProjectionElem::Field(idx, _) => idx == field, _ => false, diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 8a6360114dc54..50538248d91ee 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -73,7 +73,7 @@ use rustc_mir_dataflow::{self, Analysis}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::sym; use rustc_span::Span; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::spec::PanicStrategy; use std::{iter, ops}; @@ -162,9 +162,10 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { place, Place { local: SELF_ARG, - projection: self - .tcx() - .mk_place_elems(&[ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]), + projection: self.tcx().mk_place_elems(&[ProjectionElem::Field( + FieldIdx::new(0), + self.ref_gen_ty, + )]), }, self.tcx, ); @@ -297,7 +298,7 @@ impl<'tcx> TransformVisitor<'tcx> { let self_place = Place::from(SELF_ARG); let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index); let mut projection = base.projection.to_vec(); - projection.push(ProjectionElem::Field(Field::new(idx), ty)); + projection.push(ProjectionElem::Field(FieldIdx::new(idx), ty)); Place { local: base.local, projection: self.tcx.mk_place_elems(&projection) } } @@ -967,7 +968,7 @@ fn compute_layout<'tcx>( // Build the generator variant field list. // Create a map from local indices to generator struct indices. - let mut variant_fields: IndexVec> = + let mut variant_fields: IndexVec> = iter::repeat(IndexVec::new()).take(RESERVED_VARIANTS).collect(); let mut remap = FxHashMap::default(); for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index b69186c9451e4..8574dee4ad08b 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span}; -use rustc_target::abi::FIRST_VARIANT; +use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use rustc_target::spec::abi::Abi; use crate::simplify::{remove_dead_blocks, CfgSimplifier}; @@ -700,7 +700,7 @@ impl<'tcx> Inliner<'tcx> { // The `tmp0`, `tmp1`, and `tmp2` in our example above. let tuple_tmp_args = tuple_tys.iter().enumerate().map(|(i, ty)| { // This is e.g., `tuple_tmp.0` in our example above. - let tuple_field = Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty)); + let tuple_field = Operand::Move(tcx.mk_place_field(tuple, FieldIdx::new(i), ty)); // Spill to a local to make e.g., `tmp0`. self.create_temp_if_necessary(tuple_field, callsite, caller_body) diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs index c9750e899a51e..3d06a0a495f79 100644 --- a/compiler/rustc_mir_transform/src/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -3,14 +3,14 @@ use crate::MirPass; use rustc_hir::Mutability; use rustc_middle::mir::{ - BinOp, Body, CastKind, Constant, ConstantKind, Field, LocalDecls, Operand, Place, - ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, SwitchTargets, Terminator, - TerminatorKind, UnOp, + BinOp, Body, CastKind, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, + Rvalue, SourceInfo, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, UnOp, }; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt}; use rustc_span::symbol::Symbol; +use rustc_target::abi::FieldIdx; pub struct InstCombine; @@ -187,7 +187,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> { for (i, field) in variant.fields.iter().enumerate() { let field_ty = field.ty(self.tcx, substs); if field_ty == *cast_ty { - let place = place.project_deeper(&[ProjectionElem::Field(Field::from_usize(i), *cast_ty)], self.tcx); + let place = place.project_deeper(&[ProjectionElem::Field(FieldIdx::from_usize(i), *cast_ty)], self.tcx); let operand = if operand.is_move() { Operand::Move(place) } else { Operand::Copy(place) }; *rvalue = Rvalue::Use(operand); return; diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 6a7ceb8fef73f..c136642dff277 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{FieldIdx, VariantIdx}; pub struct LowerIntrinsics; @@ -211,7 +211,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { Some(sym::Some), VariantIdx::from_u32(1), ), - PlaceElem::Field(Field::from_u32(0), *dest_ty), + PlaceElem::Field(FieldIdx::from_u32(0), *dest_ty), ], tcx, ), diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index e72729b152e69..1f9e521d315d8 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,10 +1,11 @@ use rustc_index::bit_set::ChunkedBitSet; -use rustc_middle::mir::{Body, Field, TerminatorKind}; +use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv}; +use rustc_target::abi::FieldIdx; use crate::MirPass; @@ -130,7 +131,7 @@ fn is_needs_drop_and_init<'tcx>( .fields .iter() .enumerate() - .map(|(f, field)| (Field::from_usize(f), field.ty(tcx, substs), mpi)) + .map(|(f, field)| (FieldIdx::from_usize(f), field.ty(tcx, substs), mpi)) .any(field_needs_drop_and_init) }) } @@ -138,7 +139,7 @@ fn is_needs_drop_and_init<'tcx>( ty::Tuple(fields) => fields .iter() .enumerate() - .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi)) + .map(|(f, f_ty)| (FieldIdx::from_usize(f), f_ty, mpi)) .any(field_needs_drop_and_init), _ => true, diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 06a6deeee43e4..c89c09248eed2 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::InternalSubsts; use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt}; -use rustc_target::abi::{VariantIdx, FIRST_VARIANT}; +use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_index::vec::{Idx, IndexVec}; @@ -308,7 +308,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {} - fn field_subpath(&self, _path: Self::Path, _field: Field) -> Option { + fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option { None } fn deref_subpath(&self, _path: Self::Path) -> Option { @@ -501,7 +501,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { // created by block 2*i. We store this block in `unwind` so that the next clone block // will unwind to it if cloning fails. - let field = Field::new(i); + let field = FieldIdx::new(i); let src_field = self.tcx.mk_place_field(src, field, ity); let dest_field = self.tcx.mk_place_field(dest, field, ity); @@ -724,7 +724,7 @@ fn build_call_shim<'tcx>( if let Some(untuple_args) = untuple_args { let tuple_arg = Local::new(1 + (sig.inputs().len() - 1)); args.extend(untuple_args.iter().enumerate().map(|(i, ity)| { - Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), Field::new(i), *ity)) + Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity)) })); } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index ca2221520c825..c798bd05345e2 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -6,6 +6,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; +use rustc_target::abi::FieldIdx; pub struct ScalarReplacementOfAggregates; @@ -115,7 +116,7 @@ fn escaping_locals(excluded: &BitSet, body: &Body<'_>) -> BitSet { struct ReplacementMap<'tcx> { /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage /// and deinit statement and debuginfo. - fragments: IndexVec, Local)>>>>, + fragments: IndexVec, Local)>>>>, } impl<'tcx> ReplacementMap<'tcx> { @@ -129,7 +130,7 @@ impl<'tcx> ReplacementMap<'tcx> { fn place_fragments( &self, place: Place<'tcx>, - ) -> Option, Local)> + '_> { + ) -> Option, Local)> + '_> { let local = place.as_local()?; let fields = self.fragments[local].as_ref()?; Some(fields.iter_enumerated().filter_map(|(field, &opt_ty_local)| { From f6bde0352b52eb3b31c78b7abd70c1be396ccb0f Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 29 Mar 2023 10:52:48 +0200 Subject: [PATCH 09/14] std: use `cvt` to handle errors from `read_entropy` on Hermit --- library/std/src/sys/hermit/mod.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index d0e09890b8b6c..111150b06e1b0 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -80,15 +80,9 @@ pub fn hashmap_random_keys() -> (u64, u64) { let mut buf = [0; 16]; let mut slice = &mut buf[..]; while !slice.is_empty() { - let res = unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }; - if res < 0 { - panic!( - "random key generation failed: {}", - crate::io::Error::from_raw_os_error(-res as i32) - ); - } else { - slice = &mut slice[res as usize..]; - } + let res = cvt(unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }) + .expect("failed to generate random hashmap keys"); + slice = &mut slice[res as usize..]; } let key1 = buf[..8].try_into().unwrap(); From 71ff7ef17c260e1b29b58cdf359b50799d9449da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Mar 2023 16:16:02 +0200 Subject: [PATCH 10/14] Don't strip crate module --- src/librustdoc/passes/strip_hidden.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 890b3e8d67f7a..a688aa14863a9 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -121,9 +121,14 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { // strip things like impl methods but when doing so // we must not add any items to the `retained` set. let old = mem::replace(&mut self.update_retained, false); - let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i)); + let ret = self.set_is_in_hidden_item_and_fold(true, i); self.update_retained = old; - Some(ret) + if ret.is_crate() { + // We don't strip the crate, even if it has `#[doc(hidden)]`. + Some(ret) + } else { + Some(strip_item(ret)) + } } _ => { let ret = self.set_is_in_hidden_item_and_fold(true, i); From cdc4fa45896c2b086646c8c9c91adb8d9dc5e45f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Mar 2023 16:16:19 +0200 Subject: [PATCH 11/14] Add regression test for #109695 --- tests/rustdoc/issue-109695-crate-doc-hidden.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/rustdoc/issue-109695-crate-doc-hidden.rs diff --git a/tests/rustdoc/issue-109695-crate-doc-hidden.rs b/tests/rustdoc/issue-109695-crate-doc-hidden.rs new file mode 100644 index 0000000000000..7a3e53a0d32eb --- /dev/null +++ b/tests/rustdoc/issue-109695-crate-doc-hidden.rs @@ -0,0 +1,8 @@ +// This test ensures that even if the crate module is `#[doc(hidden)]`, the file +// is generated. + +// @has 'foo/index.html' +// @has 'foo/all.html' + +#![crate_name = "foo"] +#![doc(hidden)] From d62238d6a8ed57fecddfa9b97fd79cb0ac814791 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 Mar 2023 19:41:15 +0000 Subject: [PATCH 12/14] Do not consider elaborated projection predicates for objects in new solver --- .../src/solve/assembly.rs | 19 ++++++++++++++++--- .../dont-elaborate-for-projections.rs | 12 ++++++++++++ .../ui/traits/new-solver/more-object-bound.rs | 2 +- .../new-solver/more-object-bound.stderr | 13 ++++++++----- 4 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 tests/ui/traits/new-solver/dont-elaborate-for-projections.rs diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 0f7a0eb337ba6..856b1c08b7237 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -6,6 +6,7 @@ use super::trait_goals::structural_traits::*; use super::{EvalCtxt, SolverMode}; use crate::traits::coherence; use itertools::Itertools; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::elaborate_predicates; @@ -489,9 +490,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }; let tcx = self.tcx(); - for assumption in - elaborate_predicates(tcx, bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty))) - { + let own_bounds: FxIndexSet<_> = + bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect(); + for assumption in elaborate_predicates(tcx, own_bounds.iter().copied()) { + // FIXME: Predicates are fully elaborated in the object type's existential bounds + // list. We want to only consider these pre-elaborated projections, and not other + // projection predicates that we reach by elaborating the principal trait ref, + // since that'll cause ambiguity. + // + // We can remove this when we have implemented intersections in responses. + if assumption.to_opt_poly_projection_pred().is_some() + && !own_bounds.contains(&assumption) + { + continue; + } + match G::consider_object_bound_candidate(self, goal, assumption) { Ok(result) => { candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) diff --git a/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs b/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs new file mode 100644 index 0000000000000..e608250063c0b --- /dev/null +++ b/tests/ui/traits/new-solver/dont-elaborate-for-projections.rs @@ -0,0 +1,12 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +trait Iter<'a, I: 'a>: Iterator {} + +fn needs_iter<'a, T: Iter<'a, I> + ?Sized, I: 'a>(_: &T) {} + +fn test(x: &dyn Iter<'_, ()>) { + needs_iter(x); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/more-object-bound.rs b/tests/ui/traits/new-solver/more-object-bound.rs index 712759ef0e612..bb730b18ef77b 100644 --- a/tests/ui/traits/new-solver/more-object-bound.rs +++ b/tests/ui/traits/new-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR type annotations needed: cannot satisfy `dyn Trait: Trait` + //~^ ERROR the trait bound `dyn Trait: Trait` is not satisfied } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr index 208fdecb08fc9..4554b8c7473cb 100644 --- a/tests/ui/traits/new-solver/more-object-bound.stderr +++ b/tests/ui/traits/new-solver/more-object-bound.stderr @@ -1,10 +1,9 @@ -error[E0283]: type annotations needed: cannot satisfy `dyn Trait: Trait` - --> $DIR/more-object-bound.rs:12:5 +error[E0277]: the trait bound `dyn Trait: Trait` is not satisfied + --> $DIR/more-object-bound.rs:12:17 | LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` | - = note: cannot satisfy `dyn Trait: Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 | @@ -13,7 +12,11 @@ LL | fn foo(x: T::A) -> B LL | where LL | T: Trait, | ^^^^^^^^^^^^ required by this bound in `foo` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn transmute(x: A) -> B where dyn Trait: Trait { + | ++++++++++++++++++++++++++++++++++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0277`. From a61616a016aadb41cb18cc898f1ce9ff70709607 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 Mar 2023 17:27:06 +0000 Subject: [PATCH 13/14] Move canonicalization code around --- .../src/solve/{canonical => }/canonicalize.rs | 0 .../src/solve/eval_ctxt.rs | 61 ++----------------- .../mod.rs => eval_ctxt/canonical.rs} | 53 +++++++++++----- .../rustc_trait_selection/src/solve/mod.rs | 5 +- 4 files changed, 47 insertions(+), 72 deletions(-) rename compiler/rustc_trait_selection/src/solve/{canonical => }/canonicalize.rs (100%) rename compiler/rustc_trait_selection/src/solve/{canonical/mod.rs => eval_ctxt/canonical.rs} (81%) diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs similarity index 100% rename from compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs rename to compiler/rustc_trait_selection/src/solve/canonicalize.rs diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 92aff517fbb8b..e64b4a7656f25 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -1,7 +1,6 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; -use rustc_infer::infer::canonical::query_response::make_query_region_constraints; -use rustc_infer::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarValues}; +use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt, @@ -9,9 +8,7 @@ use rustc_infer::infer::{ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use rustc_middle::traits::solve::{ - CanonicalGoal, Certainty, ExternalConstraints, ExternalConstraintsData, MaybeCause, QueryResult, -}; +use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, @@ -21,11 +18,12 @@ use std::ops::ControlFlow; use crate::traits::specialization_graph; -use super::canonical::{CanonicalizeMode, Canonicalizer}; use super::search_graph::{self, OverflowHandler}; use super::SolverMode; use super::{search_graph::SearchGraph, Goal}; +mod canonical; + pub struct EvalCtxt<'a, 'tcx> { /// The inference context that backs (mostly) inference and placeholder terms /// instantiated while solving goals. @@ -414,7 +412,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if let &ty::Infer(ty::TyVar(vid)) = ty.kind() { match self.infcx.probe_ty_var(vid) { Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"), - Err(universe) => universe == self.universe(), + Err(universe) => universe == self.infcx.universe(), } } else { false @@ -424,7 +422,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() { match self.infcx.probe_const_var(vid) { Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"), - Err(universe) => universe == self.universe(), + Err(universe) => universe == self.infcx.universe(), } } else { false @@ -566,22 +564,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.infcx.fresh_substs_for_item(DUMMY_SP, def_id) } - pub(super) fn universe(&self) -> ty::UniverseIndex { - self.infcx.universe() - } - - pub(super) fn create_next_universe(&self) -> ty::UniverseIndex { - self.infcx.create_next_universe() - } - - pub(super) fn instantiate_canonical_var( - &self, - cv_info: CanonicalVarInfo<'tcx>, - universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, - ) -> ty::GenericArg<'tcx> { - self.infcx.instantiate_canonical_var(DUMMY_SP, cv_info, universe_map) - } - pub(super) fn translate_substs( &self, param_env: ty::ParamEnv<'tcx>, @@ -621,35 +603,4 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg) .map(|obligations| obligations.into_iter().map(|obligation| obligation.into())) } - - #[instrument(level = "debug", skip(self), ret)] - pub(super) fn compute_external_query_constraints( - &self, - ) -> Result, NoSolution> { - // Cannot use `take_registered_region_obligations` as we may compute the response - // inside of a `probe` whenever we have multiple choices inside of the solver. - let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); - let region_constraints = self.infcx.with_region_constraints(|region_constraints| { - make_query_region_constraints( - self.tcx(), - region_obligations - .iter() - .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), - region_constraints, - ) - }); - let opaque_types = self.infcx.clone_opaque_types_for_query_response(); - Ok(self - .tcx() - .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types })) - } - - pub(super) fn canonicalize>>( - &self, - canonicalize_mode: CanonicalizeMode, - variables: &mut Vec>, - value: T, - ) -> Canonical<'tcx, T> { - Canonicalizer::canonicalize(self.infcx, canonicalize_mode, variables, value) - } } diff --git a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs similarity index 81% rename from compiler/rustc_trait_selection/src/solve/canonical/mod.rs rename to compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index d393ab1ba4a85..ee90488730a64 100644 --- a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -8,20 +8,19 @@ /// section of the [rustc-dev-guide][c]. /// /// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html -pub use self::canonicalize::{CanonicalizeMode, Canonicalizer}; - use super::{CanonicalGoal, Certainty, EvalCtxt, Goal}; -use super::{CanonicalResponse, QueryResult, Response}; +use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer}; +use crate::solve::{CanonicalResponse, QueryResult, Response}; +use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; -use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::ExternalConstraintsData; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData}; use rustc_middle::ty::{self, GenericArgKind}; +use rustc_span::DUMMY_SP; use std::iter; use std::ops::Deref; -mod canonicalize; - impl<'tcx> EvalCtxt<'_, 'tcx> { /// Canonicalizes the goal remembering the original values /// for each bound variable. @@ -30,7 +29,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, ) -> (Vec>, CanonicalGoal<'tcx>) { let mut orig_values = Default::default(); - let canonical_goal = self.canonicalize(CanonicalizeMode::Input, &mut orig_values, goal); + let canonical_goal = Canonicalizer::canonicalize( + self.infcx, + CanonicalizeMode::Input, + &mut orig_values, + goal, + ); (orig_values, canonical_goal) } @@ -41,7 +45,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { /// - `external_constraints`: additional constraints which aren't expressable /// using simple unification of inference variables. #[instrument(level = "debug", skip(self))] - pub(super) fn evaluate_added_goals_and_make_canonical_response( + pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response( &mut self, certainty: Certainty, ) -> QueryResult<'tcx> { @@ -51,7 +55,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let external_constraints = self.compute_external_query_constraints()?; let response = Response { var_values: self.var_values, external_constraints, certainty }; - let canonical = self.canonicalize( + let canonical = Canonicalizer::canonicalize( + self.infcx, CanonicalizeMode::Response { max_input_universe: self.max_input_universe }, &mut Default::default(), response, @@ -59,6 +64,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Ok(canonical) } + #[instrument(level = "debug", skip(self), ret)] + fn compute_external_query_constraints(&self) -> Result, NoSolution> { + // Cannot use `take_registered_region_obligations` as we may compute the response + // inside of a `probe` whenever we have multiple choices inside of the solver. + let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned(); + let region_constraints = self.infcx.with_region_constraints(|region_constraints| { + make_query_region_constraints( + self.tcx(), + region_obligations + .iter() + .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())), + region_constraints, + ) + }); + let opaque_types = self.infcx.clone_opaque_types_for_query_response(); + Ok(self + .tcx() + .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types })) + } + /// After calling a canonical query, we apply the constraints returned /// by the query using this function. /// @@ -98,10 +123,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the // caller. - let prev_universe = self.universe(); + let prev_universe = self.infcx.universe(); let universes_created_in_query = response.max_universe.index() + 1; for _ in 0..universes_created_in_query { - self.create_next_universe(); + self.infcx.create_next_universe(); } let var_values = response.value.var_values; @@ -144,7 +169,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // A variable from inside a binder of the query. While ideally these shouldn't // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. - self.instantiate_canonical_var(info, |idx| { + self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| { ty::UniverseIndex::from(prev_universe.index() + idx.index()) }) } else if info.is_existential() { @@ -158,7 +183,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if let Some(v) = opt_values[index] { v } else { - self.instantiate_canonical_var(info, |_| prev_universe) + self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe) } } else { // For placeholders which were already part of the input, we simply map this diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 7c01d5d2bef92..1925043e5fdcc 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -15,8 +15,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ - CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, - Response, + CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, Response, }; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ @@ -24,7 +23,7 @@ use rustc_middle::ty::{ }; mod assembly; -mod canonical; +mod canonicalize; mod eval_ctxt; mod fulfill; mod project_goals; From 979c265a5d54a3a267563153859f2921db717b1d Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 29 Mar 2023 16:00:48 +0100 Subject: [PATCH 14/14] Check for escape sequences in Fluent resources --- compiler/rustc_codegen_llvm/messages.ftl | 3 ++- compiler/rustc_const_eval/messages.ftl | 16 +++++++++--- compiler/rustc_incremental/messages.ftl | 2 +- compiler/rustc_lint/messages.ftl | 2 +- .../rustc_macros/src/diagnostics/fluent.rs | 12 +++++++++ .../fluent-messages/invalid-escape.ftl | 1 + tests/ui-fulldeps/fluent-messages/test.rs | 9 +++++++ tests/ui-fulldeps/fluent-messages/test.stderr | 26 ++++++++++++++++++- .../existing_doc_keyword.stderr | 2 +- 9 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 tests/ui-fulldeps/fluent-messages/invalid-escape.ftl diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index e5df417370bb9..b6d7484bccefd 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -27,7 +27,8 @@ codegen_llvm_error_calling_dlltool = Error calling dlltool: {$error} codegen_llvm_dlltool_fail_import_library = - Dlltool could not create import library: {$stdout}\n{$stderr} + Dlltool could not create import library: {$stdout} + {$stderr} codegen_llvm_target_feature_disable_or_enable = the target features {$features} must all be either enabled or disabled together diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 33bb116d6fa23..f6751df443f7a 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -39,17 +39,25 @@ const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn const_eval_unallowed_mutable_refs = mutable references are not allowed in the final value of {$kind}s .teach_note = - References in statics and constants may only refer to immutable values.\n\n + References in statics and constants may only refer to immutable values. + + Statics are shared everywhere, and if they refer to mutable data one might violate memory - safety since holding multiple mutable references to shared data is not allowed.\n\n + safety since holding multiple mutable references to shared data is not allowed. + + If you really want global mutable state, try using static mut or a global UnsafeCell. const_eval_unallowed_mutable_refs_raw = raw mutable references are not allowed in the final value of {$kind}s .teach_note = - References in statics and constants may only refer to immutable values.\n\n + References in statics and constants may only refer to immutable values. + + Statics are shared everywhere, and if they refer to mutable data one might violate memory - safety since holding multiple mutable references to shared data is not allowed.\n\n + safety since holding multiple mutable references to shared data is not allowed. + + If you really want global mutable state, try using static mut or a global UnsafeCell. const_eval_non_const_fmt_macro_call = diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index 4852ee0d9595c..b760620e3d48b 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -24,7 +24,7 @@ incremental_field_associated_value_expected = associated value expected for `{$n incremental_no_field = no field `{$name}` incremental_assertion_auto = - `except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\" + `except` specified DepNodes that can not be affected for "{$name}": "{$e}" incremental_undefined_clean_dirty_assertions_item = clean/dirty auto-assertions not yet defined for Node::Item.node={$kind} diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 68e62c9789aed..02af8ca54e402 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -91,7 +91,7 @@ lint_ty_qualified = usage of qualified `ty::{$ty}` lint_lintpass_by_hand = implementing `LintPass` by hand .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead -lint_non_existant_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = \"...\")]` +lint_non_existant_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]` .help = only existing keywords are allowed in core/std lint_diag_out_of_impl = diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 38c0f4895db06..3b2f5cfdc7316 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -111,6 +111,18 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok .emit(); return failed(&crate_name); } + let mut bad = false; + for esc in ["\\n", "\\\"", "\\'"] { + for _ in resource_contents.matches(esc) { + bad = true; + Diagnostic::spanned(resource_span, Level::Error, format!("invalid escape `{esc}` in Fluent resource")) + .note("Fluent does not interpret these escape sequences ()") + .emit(); + } + } + if bad { + return failed(&crate_name); + } let resource = match FluentResource::try_new(resource_contents) { Ok(resource) => resource, diff --git a/tests/ui-fulldeps/fluent-messages/invalid-escape.ftl b/tests/ui-fulldeps/fluent-messages/invalid-escape.ftl new file mode 100644 index 0000000000000..e28852ea0050e --- /dev/null +++ b/tests/ui-fulldeps/fluent-messages/invalid-escape.ftl @@ -0,0 +1 @@ +no_crate_bad_escape = don't use \n, \', or \" diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs index 66575eb8e30cf..1ee7227a8e992 100644 --- a/tests/ui-fulldeps/fluent-messages/test.rs +++ b/tests/ui-fulldeps/fluent-messages/test.rs @@ -92,3 +92,12 @@ mod missing_message_ref { fluent_messages! { "./missing-message-ref.ftl" } //~^ ERROR referenced message `message` does not exist } + +mod bad_escape { + use super::fluent_messages; + + fluent_messages! { "./invalid-escape.ftl" } + //~^ ERROR invalid escape `\n` + //~| ERROR invalid escape `\"` + //~| ERROR invalid escape `\'` +} diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr index c7961ed22f2b4..8a6a4a91cc201 100644 --- a/tests/ui-fulldeps/fluent-messages/test.stderr +++ b/tests/ui-fulldeps/fluent-messages/test.stderr @@ -83,5 +83,29 @@ LL | fluent_messages! { "./missing-message-ref.ftl" } | = help: you may have meant to use a variable reference (`{$message}`) -error: aborting due to 10 previous errors +error: invalid escape `\n` in Fluent resource + --> $DIR/test.rs:99:24 + | +LL | fluent_messages! { "./invalid-escape.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: os-specific message + +error: invalid escape `\"` in Fluent resource + --> $DIR/test.rs:99:24 + | +LL | fluent_messages! { "./invalid-escape.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: os-specific message + +error: invalid escape `\'` in Fluent resource + --> $DIR/test.rs:99:24 + | +LL | fluent_messages! { "./invalid-escape.ftl" } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: os-specific message + +error: aborting due to 13 previous errors diff --git a/tests/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/tests/ui-fulldeps/internal-lints/existing_doc_keyword.stderr index 4e296fff6d0ba..5110b9be08a53 100644 --- a/tests/ui-fulldeps/internal-lints/existing_doc_keyword.stderr +++ b/tests/ui-fulldeps/internal-lints/existing_doc_keyword.stderr @@ -1,4 +1,4 @@ -error: found non-existing keyword `tadam` used in `#[doc(keyword = \"...\")]` +error: found non-existing keyword `tadam` used in `#[doc(keyword = "...")]` --> $DIR/existing_doc_keyword.rs:10:1 | LL | #[doc(keyword = "tadam")]