diff --git a/Cargo.lock b/Cargo.lock index a3e77a97e04c5..6c14a9f26e175 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1556,16 +1556,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - [[package]] name = "generate-copyright" version = "0.1.0" @@ -1791,14 +1781,12 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.29.1" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8" dependencies = [ "log", - "mac", "markup5ever", - "match_token", ] [[package]] @@ -2424,35 +2412,15 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - [[package]] name = "markup5ever" -version = "0.14.1" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de" dependencies = [ "log", - "phf 0.11.3", - "phf_codegen", - "string_cache", - "string_cache_codegen", "tendril", -] - -[[package]] -name = "match_token" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "web_atoms", ] [[package]] @@ -2986,56 +2954,57 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" dependencies = [ - "phf_shared 0.11.3", + "phf_shared 0.12.1", ] [[package]] name = "phf" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_shared 0.12.1", + "phf_shared 0.13.1", + "serde", ] [[package]] name = "phf_codegen" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ "phf_generator", - "phf_shared 0.11.3", + "phf_shared 0.13.1", ] [[package]] name = "phf_generator" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", + "fastrand", + "phf_shared 0.13.1", ] [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" dependencies = [ "siphasher", ] [[package]] name = "phf_shared" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ "siphasher", ] @@ -5425,25 +5394,24 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "string_cache" -version = "0.8.9" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared 0.11.3", + "phf_shared 0.13.1", "precomputed-hash", - "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ "phf_generator", - "phf_shared 0.11.3", + "phf_shared 0.13.1", "proc-macro2", "quote", ] @@ -5533,12 +5501,11 @@ dependencies = [ [[package]] name = "tendril" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" dependencies = [ - "futf", - "mac", + "new_debug_unreachable", "utf-8", ] @@ -6503,6 +6470,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web_atoms" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" +dependencies = [ + "phf 0.13.1", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + [[package]] name = "winapi-util" version = "0.1.11" diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 7b68fbc9e77b0..003e811dc7855 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -477,12 +477,14 @@ impl LayoutCalculator { Ok(Some((repr, _))) => match repr { // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt BackendRepr::Scalar(_) | BackendRepr::ScalarPair(_, _) - if repr.scalar_align(dl).unwrap() != align => + if repr.scalar_platform_align(dl).unwrap() != align => { BackendRepr::Memory { sized: true } } // Vectors require at least element alignment, else disable the opt - BackendRepr::SimdVector { element, count: _ } if element.align(dl).abi > align => { + BackendRepr::SimdVector { element, count: _ } + if element.default_align(dl).abi > align => + { BackendRepr::Memory { sized: true } } // the alignment tests passed and we can use this @@ -986,7 +988,8 @@ impl LayoutCalculator { // roundtripping pointers through ptrtoint/inttoptr. (p @ Primitive::Pointer(_), i @ Primitive::Int(..)) | (i @ Primitive::Int(..), p @ Primitive::Pointer(_)) - if p.size(dl) == i.size(dl) && p.align(dl) == i.align(dl) => + if p.size(dl) == i.size(dl) + && p.default_align(dl) == i.default_align(dl) => { p } diff --git a/compiler/rustc_abi/src/layout/simple.rs b/compiler/rustc_abi/src/layout/simple.rs index b103e1e97bd96..5fd504def384a 100644 --- a/compiler/rustc_abi/src/layout/simple.rs +++ b/compiler/rustc_abi/src/layout/simple.rs @@ -49,7 +49,7 @@ impl LayoutData { pub fn scalar(cx: &C, scalar: Scalar) -> Self { let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); let size = scalar.size(cx); - let align = scalar.align(cx); + let align = scalar.default_align(cx); let range = scalar.valid_range(cx); @@ -90,8 +90,8 @@ impl LayoutData { pub fn scalar_pair(cx: &C, a: Scalar, b: Scalar) -> Self { let dl = cx.data_layout(); - let b_align = b.align(dl).abi; - let align = a.align(dl).abi.max(b_align).max(dl.aggregate_align); + let b_align = b.default_align(dl).abi; + let align = a.default_align(dl).abi.max(b_align).max(dl.aggregate_align); let b_offset = a.size(dl).align_to(b_align); let size = (b_offset + b.size(dl)).align_to(align); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index a5a4411146c44..e86c7f15e9679 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1404,7 +1404,11 @@ impl Primitive { } } - pub fn align(self, cx: &C) -> AbiAlign { + /// The *platform-specific* ABI alignment of this primitive. + /// + /// This is the type alignment for the corresponding built-in. + /// In other contexts it might have different alignment. + pub fn default_align(self, cx: &C) -> AbiAlign { use Primitive::*; let dl = cx.data_layout(); @@ -1579,8 +1583,12 @@ impl Scalar { } } - pub fn align(self, cx: &impl HasDataLayout) -> AbiAlign { - self.primitive().align(cx) + /// The *platform-specific* ABI alignment of this scalar. + /// + /// This is the type alignment for the corresponding built-in. + /// This is *not* necessarily the correct alignment for a type that has this `BackendRepr::Scalar`! + pub fn default_align(self, cx: &impl HasDataLayout) -> AbiAlign { + self.primitive().default_align(cx) } pub fn size(self, cx: &impl HasDataLayout) -> Size { @@ -1792,6 +1800,14 @@ impl IntoDiagArg for NumScalableVectors { #[cfg_attr(feature = "nightly", derive(StableHash))] pub enum BackendRepr { Scalar(Scalar), + /// The data contained in this type can be entirely represented by two scalars. + /// The two scalars are listed in *memory* order, so the first is at offset zero + /// and the second at a non-zero offset. + /// These need not be `FieldIdx(0)` and `FieldIdx(1)`. + /// + /// As of June 2026 the offset to the second scalar is the size of the first + /// scalar rounded up to the platform alignment of the second scalar. + /// That may soon change, however; see MCP#1007. ScalarPair(Scalar, Scalar), SimdScalableVector { element: Scalar, @@ -1857,10 +1873,16 @@ impl BackendRepr { /// The psABI alignment for a `Scalar` or `ScalarPair` /// /// `None` for other variants. - pub fn scalar_align(&self, cx: &C) -> Option { + /// + /// It's unclear whether this is a meaningful operation, and MCP#1007 proposes changes. + /// You should generally be using the alignment of the place or the type, + /// not calculating something from the `Scalar`s. + pub fn scalar_platform_align(&self, cx: &C) -> Option { match *self { - BackendRepr::Scalar(s) => Some(s.align(cx).abi), - BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi), + BackendRepr::Scalar(s) => Some(s.default_align(cx).abi), + BackendRepr::ScalarPair(s1, s2) => { + Some(s1.default_align(cx).max(s2.default_align(cx)).abi) + } // The align of a Vector can vary in surprising ways BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } @@ -1877,9 +1899,9 @@ impl BackendRepr { BackendRepr::Scalar(s) => Some(s.size(cx)), // May have some padding between the pair. BackendRepr::ScalarPair(s1, s2) => { - let field2_offset = s1.size(cx).align_to(s2.align(cx).abi); + let field2_offset = s1.size(cx).align_to(s2.default_align(cx).abi); let size = (field2_offset + s2.size(cx)).align_to( - self.scalar_align(cx) + self.scalar_platform_align(cx) // We absolutely must have an answer here or everything is FUBAR. .unwrap(), ); diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index a2a2cac3faaa8..995a70f24240b 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -56,7 +56,7 @@ fn codegen_field<'tcx>( } fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 { - let b_offset = a_scalar.size(&tcx).align_to(b_scalar.align(&tcx).abi); + let b_offset = a_scalar.size(&tcx).align_to(b_scalar.default_align(&tcx).abi); Offset32::new(b_offset.bytes().try_into().unwrap()) } diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 6cbc0054cc015..f9358872299b7 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1065,7 +1065,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }, ) } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr { - let b_offset = a.size(self).align_to(b.align(self).abi); + let b_offset = a.size(self).align_to(b.default_align(self).abi); let mut load = |i, scalar: &abi::Scalar, align| { let ptr = if i == 0 { diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 5b198eeaf0182..9807a84c0788d 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -325,7 +325,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { return cx.type_i1(); } - let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) }; + let offset = + if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.default_align(cx).abi) }; self.scalar_gcc_type_at(cx, scalar, offset) } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 58a62145d576e..804547745c5d5 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -794,7 +794,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { }); OperandValue::Immediate(llval) } else if let abi::BackendRepr::ScalarPair(a, b) = place.layout.backend_repr { - let b_offset = a.size(self).align_to(b.align(self).abi); + let b_offset = a.size(self).align_to(b.default_align(self).abi); let mut load = |i, scalar: abi::Scalar, layout, align, offset| { let llptr = if i == 0 { diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index c87ea83eacf62..a47b3443ea664 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -227,7 +227,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { b @ abi::Scalar::Initialized { .. }, ) => { let (a_size, b_size) = (a.size(bx), b.size(bx)); - let b_offset = (offset + a_size).align_to(b.align(bx).abi); + let b_offset = (offset + a_size).align_to(b.default_align(bx).abi); assert!(b_offset.bytes() > 0); let a_val = read_scalar( offset, @@ -388,7 +388,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { assert_eq!(field.size, a.size(bx.cx())); (Some(a), a_llval) } else { - assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi)); + assert_eq!(offset, a.size(bx.cx()).align_to(b.default_align(bx.cx()).abi)); assert_eq!(field.size, b.size(bx.cx())); (Some(b), b_llval) } @@ -962,7 +962,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { let BackendRepr::ScalarPair(a_scalar, b_scalar) = dest.layout.backend_repr else { bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout); }; - let b_offset = a_scalar.size(bx).align_to(b_scalar.align(bx).abi); + let b_offset = a_scalar.size(bx).align_to(b_scalar.default_align(bx).abi); let val = bx.from_immediate(a); let align = dest.val.align; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 7b2983620d420..1f67b896fc8ec 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -419,7 +419,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { Immediate::from(if offset.bytes() == 0 { a_val } else { - assert_eq!(offset, a.size(cx).align_to(b.align(cx).abi)); + assert_eq!(offset, a.size(cx).align_to(b.default_align(cx).abi)); b_val }) } @@ -614,7 +614,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`, // which `ptr.offset(b_offset)` cannot possibly fail to satisfy. let (a_size, b_size) = (a.size(self), b.size(self)); - let b_offset = a_size.align_to(b.align(self).abi); + let b_offset = a_size.align_to(b.default_align(self).abi); assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields let a_val = alloc.read_scalar( alloc_range(Size::ZERO, a_size), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index b4e6a6b99b7a8..d6d73b2d8da81 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -733,7 +733,7 @@ where ) }; let a_size = a_val.size(); - let b_offset = a_size.align_to(b.align(&tcx).abi); + let b_offset = a_size.align_to(b.default_align(&tcx).abi); assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index b30d2bd135546..2db4502ecc6b6 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -742,7 +742,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { a1.size(&self.ecx) == a2.size(&self.ecx) && b1.size(&self.ecx) == b2.size(&self.ecx) // The alignment of the second component determines its offset, so that also needs to match. - && b1.align(&self.ecx) == b2.align(&self.ecx) + && b1.default_align(&self.ecx) == b2.default_align(&self.ecx) // None of the inputs may be a pointer. && !matches!(a1.primitive(), Primitive::Pointer(..)) && !matches!(b1.primitive(), Primitive::Pointer(..)) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index fe573025c87f4..5e1d202f8f994 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -8,7 +8,7 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::region_constraint::RegionConstraint; use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::solver_relating::RelateExt; -use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind}; +use rustc_type_ir::search_graph::{CandidateHeadUsages, IncreaseDepthForNested, PathKind}; use rustc_type_ir::solve::{ AccessedOpaques, ExternalRegionConstraints, FetchEligibleAssocItemResponse, MaybeInfo, NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunCondition, @@ -484,7 +484,7 @@ where stalled_on: Option>, ) -> Result, NoSolutionOrRerunNonErased> { let (normalization_nested_goals, goal_evaluation) = - self.evaluate_goal_raw(source, goal, stalled_on)?; + self.evaluate_goal_raw(source, goal, stalled_on, IncreaseDepthForNested::Yes)?; assert!(normalization_nested_goals.is_empty()); Ok(goal_evaluation) } @@ -576,6 +576,7 @@ where source: GoalSource, goal: Goal, stalled_on: Option>, + increase_depth_for_nested: IncreaseDepthForNested, ) -> Result<(NestedNormalizationGoals, GoalEvaluation), NoSolutionOrRerunNonErased> { if let RerunStalled::WontMakeProgress(stalled_certainty) = self.rerunning_stalled_goal_may_make_progress(stalled_on.as_ref()) @@ -591,7 +592,7 @@ where )); } - self.evaluate_goal_cold(source, goal) + self.evaluate_goal_cold(source, goal, increase_depth_for_nested) } #[cold] @@ -600,6 +601,7 @@ where &mut self, source: GoalSource, goal: Goal, + increase_depth_for_nested: IncreaseDepthForNested, ) -> Result<(NestedNormalizationGoals, GoalEvaluation), NoSolutionOrRerunNonErased> { // We only care about one entry per `OpaqueTypeKey` here, // so we only canonicalize the lookup table and ignore @@ -663,6 +665,7 @@ where self.cx(), canonical_goal, step_kind, + increase_depth_for_nested, &mut inspect::ProofTreeBuilder::new_noop(), ); @@ -702,6 +705,7 @@ where self.cx(), canonical_goal, step_kind, + increase_depth_for_nested, &mut inspect::ProofTreeBuilder::new_noop(), ); assert!( diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs index e084ae077b561..21cfa0561dd8b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs @@ -3,6 +3,7 @@ mod free_alias; mod inherent; mod opaque_types; +use rustc_type_ir::search_graph::IncreaseDepthForNested; use rustc_type_ir::solve::QueryResultOrRerunNonErased; use rustc_type_ir::{self as ty, Interner, ProjectionPredicate}; use tracing::{instrument, trace}; @@ -67,7 +68,19 @@ where let ( NestedNormalizationGoals(nested_goals), GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ }, - ) = self.evaluate_goal_raw(GoalSource::TypeRelating, normalizes_to, None)?; + ) = self.evaluate_goal_raw( + GoalSource::TypeRelating, + normalizes_to, + None, + // We don't increase depth for nested goals for this `NormalizesTo` goal, as + // evaluating `NormalizesTo` is an extra step only exists in the new solver + // that behaves like a function call rather than an independent nested goal + // evaluation, so increasing the depth may end up regressions which hit the + // recursion limits for crates compiled well with the old solver. Furthermore, + // those nested goals from `NormalizesTo` will be evaluated again as the + // caller's nested goals with increased depths anyway. + IncreaseDepthForNested::No, + )?; trace!(?nested_goals); diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 30d16b5c7b1c9..4bc88cc4f9705 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -399,7 +399,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { BackendRepr::Scalar(scalar) => PassMode::Direct(scalar_attrs(scalar, Size::ZERO)), BackendRepr::ScalarPair(a, b) => PassMode::Pair( scalar_attrs(a, Size::ZERO), - scalar_attrs(b, a.size(cx).align_to(b.align(cx).abi)), + scalar_attrs(b, a.size(cx).align_to(b.default_align(cx).abi)), ), BackendRepr::SimdVector { .. } => PassMode::Direct(ArgAttributes::new()), BackendRepr::Memory { .. } => Self::indirect_pass_mode(&layout), diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 8c07a7ec3d2de..decf1ffb5570d 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -84,7 +84,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { // Verify the ABI-mandated alignment and size for scalars. - let align = layout.backend_repr.scalar_align(cx); + let align = layout.backend_repr.scalar_platform_align(cx); let size = layout.backend_repr.scalar_size(cx); if let Some(align) = align { assert_eq!( @@ -208,9 +208,9 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou }; // The fields should be at the right offset, and match the `scalar` layout. let size1 = scalar1.size(cx); - let align1 = scalar1.align(cx).abi; + let align1 = scalar1.default_align(cx).abi; let size2 = scalar2.size(cx); - let align2 = scalar2.align(cx).abi; + let align2 = scalar2.default_align(cx).abi; assert_eq!( offset1, Size::ZERO, @@ -251,7 +251,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou BackendRepr::SimdVector { element, count } => { let align = layout.align.abi; let size = layout.size; - let element_align = element.align(cx).abi; + let element_align = element.default_align(cx).abi; let element_size = element.size(cx); // Currently, vectors must always be aligned to at least their elements: assert!(align >= element_align); @@ -321,7 +321,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou } // The top-level ABI and the ABI of the variants should be coherent. let scalar_coherent = |s1: Scalar, s2: Scalar| { - s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx) + s1.size(cx) == s2.size(cx) && s1.default_align(cx) == s2.default_align(cx) }; let abi_coherent = match (layout.backend_repr, variant.backend_repr) { (BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => scalar_coherent(s1, s2), diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 3a962b3832aa3..a42ed8795e127 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -263,6 +263,12 @@ impl CandidateHeadUsages { } #[derive(Debug, Clone, Copy)] +pub enum IncreaseDepthForNested { + Yes, + No, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] struct AvailableDepth(usize); impl AvailableDepth { /// Returns the remaining depth allowed for nested goals. @@ -276,6 +282,13 @@ impl AvailableDepth { stack: &Stack, ) -> Option { if let Some(last) = stack.last() { + match last.increase_depth_for_nested { + IncreaseDepthForNested::Yes => {} + IncreaseDepthForNested::No => { + return Some(last.available_depth); + } + } + if last.available_depth.0 == 0 { return None; } @@ -566,7 +579,7 @@ impl EvaluationResult { encountered_overflow, // Unlike `encountered_overflow`, we share `heads`, `required_depth`, // and `nested_goals` between evaluations. - required_depth: final_entry.required_depth, + required_depth: final_entry.required_depth(), heads: final_entry.heads, nested_goals: final_entry.nested_goals, // We only care about the final result. @@ -597,7 +610,7 @@ pub struct SearchGraph, X: Cx = ::Cx> { /// don't need to track the nested goals used while computing a provisional /// cache entry. enum UpdateParentGoalCtxt<'a, X: Cx> { - Ordinary(&'a NestedGoals), + Ordinary { nested_goals: &'a NestedGoals, min_reachable_available_depth: AvailableDepth }, CycleOnStack(X::Input), ProvisionalCacheHit, } @@ -619,13 +632,11 @@ impl, X: Cx> SearchGraph { fn update_parent_goal( stack: &mut Stack, step_kind_from_parent: PathKind, - required_depth_for_nested: usize, heads: impl Iterator, encountered_overflow: bool, context: UpdateParentGoalCtxt<'_, X>, ) { if let Some((parent_index, parent)) = stack.last_mut_with_index() { - parent.required_depth = parent.required_depth.max(required_depth_for_nested + 1); parent.encountered_overflow |= encountered_overflow; for (head_index, head) in heads { @@ -650,7 +661,9 @@ impl, X: Cx> SearchGraph { } } let parent_depends_on_cycle = match context { - UpdateParentGoalCtxt::Ordinary(nested_goals) => { + UpdateParentGoalCtxt::Ordinary { nested_goals, min_reachable_available_depth } => { + parent.min_reached_available_depth = + parent.min_reached_available_depth.min(min_reachable_available_depth); parent.nested_goals.extend_from_child(step_kind_from_parent, nested_goals); !nested_goals.is_empty() } @@ -739,8 +752,9 @@ impl, X: Cx> SearchGraph { input, step_kind_from_parent, available_depth, + min_reached_available_depth: available_depth, provisional_result: None, - required_depth: 0, + increase_depth_for_nested: IncreaseDepthForNested::Yes, heads: Default::default(), encountered_overflow: false, usages: None, @@ -761,6 +775,7 @@ impl, X: Cx> SearchGraph { cx: X, input: X::Input, step_kind_from_parent: PathKind, + increase_depth_for_nested: IncreaseDepthForNested, inspect: &mut D::ProofTreeBuilder, ) -> X::Result { let Some(available_depth) = @@ -816,7 +831,8 @@ impl, X: Cx> SearchGraph { step_kind_from_parent, available_depth, provisional_result: None, - required_depth: 0, + min_reached_available_depth: available_depth, + increase_depth_for_nested, heads: Default::default(), encountered_overflow: false, usages: None, @@ -838,10 +854,14 @@ impl, X: Cx> SearchGraph { Self::update_parent_goal( &mut self.stack, step_kind_from_parent, - evaluation_result.required_depth, evaluation_result.heads.iter(), evaluation_result.encountered_overflow, - UpdateParentGoalCtxt::Ordinary(&evaluation_result.nested_goals), + UpdateParentGoalCtxt::Ordinary { + nested_goals: &evaluation_result.nested_goals, + min_reachable_available_depth: AvailableDepth( + available_depth.0 - evaluation_result.required_depth, + ), + }, ); let result = evaluation_result.result; @@ -1116,7 +1136,6 @@ impl, X: Cx> SearchGraph { Self::update_parent_goal( &mut self.stack, step_kind_from_parent, - 0, heads.iter(), encountered_overflow, UpdateParentGoalCtxt::ProvisionalCacheHit, @@ -1239,10 +1258,14 @@ impl, X: Cx> SearchGraph { Self::update_parent_goal( &mut self.stack, step_kind_from_parent, - required_depth, heads, encountered_overflow, - UpdateParentGoalCtxt::Ordinary(nested_goals), + UpdateParentGoalCtxt::Ordinary { + nested_goals, + min_reachable_available_depth: AvailableDepth( + available_depth.0 - required_depth, + ), + }, ); debug!(?required_depth, "global cache hit"); @@ -1271,7 +1294,6 @@ impl, X: Cx> SearchGraph { Self::update_parent_goal( &mut self.stack, step_kind_from_parent, - 0, iter::once((head_index, head)), false, UpdateParentGoalCtxt::CycleOnStack(input), @@ -1407,7 +1429,8 @@ impl, X: Cx> SearchGraph { provisional_result: Some(result), // We can keep these goals from previous iterations as they are only // ever read after finalizing this evaluation. - required_depth: stack_entry.required_depth, + min_reached_available_depth: stack_entry.min_reached_available_depth, + increase_depth_for_nested: stack_entry.increase_depth_for_nested, heads: stack_entry.heads, nested_goals: stack_entry.nested_goals, // We reset these two fields when rerunning this goal. We could diff --git a/compiler/rustc_type_ir/src/search_graph/stack.rs b/compiler/rustc_type_ir/src/search_graph/stack.rs index 8348666be412d..776ab28f9fcdc 100644 --- a/compiler/rustc_type_ir/src/search_graph/stack.rs +++ b/compiler/rustc_type_ir/src/search_graph/stack.rs @@ -4,7 +4,8 @@ use derive_where::derive_where; use rustc_index::IndexVec; use crate::search_graph::{ - AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, NestedGoals, PathKind, + AvailableDepth, CandidateHeadUsages, Cx, CycleHeads, HeadUsages, IncreaseDepthForNested, + NestedGoals, PathKind, }; rustc_index::newtype_index! { @@ -28,8 +29,20 @@ pub(super) struct StackEntry { /// The available depth of a given goal, immutable. pub available_depth: AvailableDepth, - /// The maximum depth required while evaluating this goal. - pub required_depth: usize, + /// The minimum available depth encountered while evaluating this goal's nested goals. + /// If there's no nested goal, this is equal to the `available_depth`. + pub min_reached_available_depth: AvailableDepth, + + /// Whether evaluating nested goals of a given goal should increase the depth. + /// + /// Normally, it should be `Yes`, but among rustc's predicate goals, `normalizes-to` + /// goals are exceptions. They act like functions that used for normalizing associated + /// terms while evaluating projection goals and since their expected terms are always fully + /// unconstrained intentionally, they often return ambiguous nested goals to the caller's + /// context. As these nested goals are evaluated again in the caller's context, we don't + /// want to increase depths when they are evaluated as nested goals for `normalizes-to` + /// goals, otherwise we will encounter recursion limit overflows more often. + pub increase_depth_for_nested: IncreaseDepthForNested, /// Starts out as `None` and gets set when rerunning this /// goal in case we encounter a cycle. @@ -57,6 +70,12 @@ pub(super) struct StackEntry { pub nested_goals: NestedGoals, } +impl StackEntry { + pub(super) fn required_depth(&self) -> usize { + self.available_depth.0 - self.min_reached_available_depth.0 + } +} + /// The stack of goals currently being computed. /// /// An element is *deeper* in the stack if its index is *lower*. diff --git a/library/core/src/num/imp/overflow_panic.rs b/library/core/src/num/imp/overflow_panic.rs index f62d09ea041ab..fd5b88ad324c6 100644 --- a/library/core/src/num/imp/overflow_panic.rs +++ b/library/core/src/num/imp/overflow_panic.rs @@ -20,12 +20,6 @@ pub(in crate::num) const fn mul() -> ! { panic!("attempt to multiply with overflow") } -#[cold] -#[track_caller] -pub(in crate::num) const fn div() -> ! { - panic!("attempt to divide with overflow") -} - #[cold] #[track_caller] pub(in crate::num) const fn rem() -> ! { diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 090fea81891ad..8a374f015a958 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -983,9 +983,12 @@ macro_rules! int_impl { /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where - /// [`MIN`](Self::MIN) is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// [`MIN`](Self::MIN) is the negative minimal value for the type); the result of this is `-MIN`, a positive value /// that is too large to represent in the type. /// + /// Note that this is equivalent to normal division: `MIN / -1` will also panic both in + /// debug and release builds. + /// /// # Examples /// /// ``` @@ -1010,8 +1013,8 @@ macro_rules! int_impl { #[inline] #[track_caller] pub const fn strict_div(self, rhs: Self) -> Self { - let (a, b) = self.overflowing_div(rhs); - if b { imp::overflow_panic::div() } else { a } + // Normal division already checks for "div-by-minus-1". + self / rhs } /// Checked Euclidean division. Computes `self.div_euclid(rhs)`, @@ -1050,9 +1053,12 @@ macro_rules! int_impl { /// This function will always panic on overflow, regardless of whether overflow checks are enabled. /// /// The only case where such an overflow can occur is when one divides `MIN / -1` on a signed type (where - /// [`MIN`](Self::MIN) is the negative minimal value for the type); this is equivalent to `-MIN`, a positive value + /// [`MIN`](Self::MIN) is the negative minimal value for the type); the result of this is `-MIN`, a positive value /// that is too large to represent in the type. /// + /// Note that this is equivalent to `div_euclid`: `MIN.div_euclid(-1)` will also panic both + /// in debug and release builds. + /// /// # Examples /// /// ``` @@ -1077,8 +1083,8 @@ macro_rules! int_impl { #[inline] #[track_caller] pub const fn strict_div_euclid(self, rhs: Self) -> Self { - let (a, b) = self.overflowing_div_euclid(rhs); - if b { imp::overflow_panic::div() } else { a } + // Normal `div_euclid` already checks for "div-by-minus-1". + self.div_euclid(rhs) } /// Checked integer division without remainder. Computes `self / rhs`, diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index c281aa94f64e6..89046c0eee779 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -11,6 +11,7 @@ use serde::Deserialize; use super::flags::Flags; use super::toml::change_id::ChangeIdWrapper; +use super::toml::rust::parse_codegen_backends; use super::{Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS}; use crate::ChangeId; use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order}; @@ -206,6 +207,15 @@ fn rust_optimize() { assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string())); } +#[test] +#[should_panic(expected = "Duplicate value 'llvm' for 'rust.codegen-backends'")] +fn rejects_duplicate_codegen_backends() { + parse_codegen_backends( + vec!["llvm", "llvm", "cranelift"].into_iter().map(str::to_owned).collect(), + "rust", + ); +} + #[test] #[should_panic] fn invalid_rust_optimize() { diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index a872671343405..d2d629e969f6c 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs @@ -422,23 +422,33 @@ pub(crate) fn parse_codegen_backends( Please, use '{stripped}' instead." ) } - if !BUILTIN_CODEGEN_BACKENDS.contains(&backend.as_str()) { + let backend = match backend.as_str() { + "llvm" => CodegenBackendKind::Llvm, + "cranelift" => CodegenBackendKind::Cranelift, + "gcc" => CodegenBackendKind::Gcc, + backend => CodegenBackendKind::Custom(backend.to_string()), + }; + + if found_backends.contains(&backend) { + panic!( + "Duplicate value '{}' for '{section}.codegen-backends'. \ + Each codegen backend should only be specified once.", + backend.name() + ); + } + + if !BUILTIN_CODEGEN_BACKENDS.contains(&backend.name()) { if CiEnv::is_rust_lang_managed_ci_job() { - eprintln!("Unknown codegen backend {backend}"); + eprintln!("Unknown codegen backend {}", backend.name()); exit!(1); } println!( - "HELP: '{backend}' for '{section}.codegen-backends' might fail. \ - List of known codegen backends: {BUILTIN_CODEGEN_BACKENDS:?}" + "HELP: '{}' for '{section}.codegen-backends' might fail. \ + List of known codegen backends: {BUILTIN_CODEGEN_BACKENDS:?}", + backend.name() ); } - let backend = match backend.as_str() { - "llvm" => CodegenBackendKind::Llvm, - "cranelift" => CodegenBackendKind::Cranelift, - "gcc" => CodegenBackendKind::Gcc, - backend => CodegenBackendKind::Custom(backend.to_string()), - }; found_backends.push(backend); } if found_backends.is_empty() { diff --git a/src/tools/linkchecker/Cargo.toml b/src/tools/linkchecker/Cargo.toml index f0886e31b243f..0950122a1710f 100644 --- a/src/tools/linkchecker/Cargo.toml +++ b/src/tools/linkchecker/Cargo.toml @@ -9,5 +9,5 @@ path = "main.rs" [dependencies] regex = "1" -html5ever = "0.29.0" +html5ever = "0.39.0" urlencoding = "2.1.3" diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index 27571a9eb7c87..5014541faeb01 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -321,7 +321,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { imm.layout ) }; - a.size(this).align_to(b.align(this).abi).bytes_usize() + a.size(this).align_to(b.default_align(this).abi).bytes_usize() }; write_scalar(this, sc_first, 0)?;