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_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index 9e7ff620fea43..13f364f3d8258 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -26,8 +26,8 @@ pub(crate) mod managarm_mlibc; pub(crate) mod motor; pub(crate) mod msvc; pub(crate) mod netbsd; -pub(crate) mod nto_qnx; pub(crate) mod openbsd; +pub(crate) mod qnx_sdp; pub(crate) mod redox; pub(crate) mod solaris; pub(crate) mod solid; diff --git a/compiler/rustc_target/src/spec/base/nto_qnx.rs b/compiler/rustc_target/src/spec/base/qnx_sdp.rs similarity index 100% rename from compiler/rustc_target/src/spec/base/nto_qnx.rs rename to compiler/rustc_target/src/spec/base/qnx_sdp.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 628b35e27da70..78f4690443525 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1791,10 +1791,10 @@ supported_targets! { ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700), ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710), ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock), - ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800), + ("aarch64-unknown-qnx", aarch64_unknown_qnx), ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock), - ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800), + ("x86_64-pc-qnx", x86_64_pc_qnx), ("i686-pc-nto-qnx700", i686_pc_nto_qnx700), ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos), @@ -2001,6 +2001,7 @@ crate::target_spec_enum! { OpenBsd = "openbsd", Psp = "psp", Psx = "psx", + Qnx = "qnx", Qurt = "qurt", Redox = "redox", Rtems = "rtems", @@ -2041,7 +2042,6 @@ crate::target_spec_enum! { Nto70 = "nto70", Nto71 = "nto71", Nto71IoSock = "nto71_iosock", - Nto80 = "nto80", Ohos = "ohos", Relibc = "relibc", Sgx = "sgx", diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs index e1f29f832f0b5..db8905dba6cc3 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -1,11 +1,12 @@ -use crate::spec::base::nto_qnx; +use crate::spec::base::qnx_sdp; use crate::spec::{Env, Target}; pub(crate) fn target() -> Target { - let mut target = nto_qnx::aarch64(); - target.metadata.description = Some("ARM64 QNX Neutrino 7.0 RTOS".into()); + let mut target = qnx_sdp::aarch64(); + target.metadata.description = Some("ARM64 QNX SDP 7.0".into()); target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::Aarch64); + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::Default, qnx_sdp::Arch::Aarch64); + // for QNX SDP 7.x, we keep target_os = "nto" for backwards compatibility, and use target_env to specify which version target.options.env = Env::Nto70; target } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs index 1baa56630d3a9..3a76a0e34d699 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs @@ -1,12 +1,12 @@ -use crate::spec::base::nto_qnx; +use crate::spec::base::qnx_sdp; use crate::spec::{Env, Target}; pub(crate) fn target() -> Target { - let mut target = nto_qnx::aarch64(); - target.metadata.description = - Some("ARM64 QNX Neutrino 7.1 RTOS with io-pkt network stack".into()); + let mut target = qnx_sdp::aarch64(); + target.metadata.description = Some("ARM64 QNX SDP 7.1 with io-pkt network stack".into()); target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::Aarch64); + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::Default, qnx_sdp::Arch::Aarch64); + // for QNX SDP 7.x, we keep target_os = "nto" for backwards compatibility, and use target_env to specify which version target.options.env = Env::Nto71; target } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs index 80ae93247a3f0..e612105201ff0 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs @@ -1,12 +1,12 @@ -use crate::spec::base::nto_qnx; +use crate::spec::base::qnx_sdp; use crate::spec::{Env, Target}; pub(crate) fn target() -> Target { - let mut target = nto_qnx::aarch64(); - target.metadata.description = - Some("ARM64 QNX Neutrino 7.1 RTOS with io-sock network stack".into()); + let mut target = qnx_sdp::aarch64(); + target.metadata.description = Some("ARM64 QNX SDP 7.1 with io-sock network stack".into()); target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::IoSock, nto_qnx::Arch::Aarch64); + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::IoSock, qnx_sdp::Arch::Aarch64); + // for QNX SDP 7.x, we keep target_os = "nto" for backwards compatibility, and use target_env to specify which version target.options.env = Env::Nto71IoSock; target } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx800.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx800.rs deleted file mode 100644 index 5d265087c4a21..0000000000000 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx800.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::spec::base::nto_qnx; -use crate::spec::{Env, Target}; - -pub(crate) fn target() -> Target { - let mut target = nto_qnx::aarch64(); - target.metadata.description = Some("ARM64 QNX Neutrino 8.0 RTOS".into()); - target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::Aarch64); - target.options.env = Env::Nto80; - target -} diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_qnx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_qnx.rs new file mode 100644 index 0000000000000..cbd2f4224185d --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_qnx.rs @@ -0,0 +1,12 @@ +use crate::spec::base::qnx_sdp; +use crate::spec::{Os, Target}; + +pub(crate) fn target() -> Target { + let mut target = qnx_sdp::aarch64(); + target.metadata.description = Some("ARM64 QNX SDP 8.0+".into()); + target.options.pre_link_args = + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::Default, qnx_sdp::Arch::Aarch64); + // for QNX SDP 8.0, we have target_os = "qnx" and no target_env + target.options.os = Os::Qnx; + target +} diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs index 7184a54961e20..c8def7e5bc423 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_nto_qnx700.rs @@ -1,9 +1,9 @@ -use crate::spec::base::nto_qnx; +use crate::spec::base::qnx_sdp; use crate::spec::{Arch, Env, RustcAbi, StackProbeType, Target, TargetOptions, base}; pub(crate) fn target() -> Target { - let mut meta = nto_qnx::meta(); - meta.description = Some("32-bit x86 QNX Neutrino 7.0 RTOS".into()); + let mut meta = qnx_sdp::meta(); + meta.description = Some("32-bit x86 QNX SDP 7.0".into()); meta.std = Some(false); Target { llvm_target: "i586-pc-unknown".into(), @@ -17,14 +17,15 @@ pub(crate) fn target() -> Target { rustc_abi: Some(RustcAbi::X86Sse2), cpu: "pentium4".into(), max_atomic_width: Some(64), - pre_link_args: nto_qnx::pre_link_args( - nto_qnx::ApiVariant::Default, - nto_qnx::Arch::I586, + pre_link_args: qnx_sdp::pre_link_args( + qnx_sdp::ApiVariant::Default, + qnx_sdp::Arch::I586, ), + // for QNX SDP 7.x, we keep target_os = "nto" for backwards compatibility, and use target_env to specify which version env: Env::Nto70, vendor: "pc".into(), stack_probes: StackProbeType::Inline, - ..base::nto_qnx::opts() + ..base::qnx_sdp::opts() }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 9160015485097..6d814725d16ed 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -1,12 +1,12 @@ -use crate::spec::base::nto_qnx; +use crate::spec::base::qnx_sdp; use crate::spec::{Env, Target}; pub(crate) fn target() -> Target { - let mut target = nto_qnx::x86_64(); - target.metadata.description = - Some("x86 64-bit QNX Neutrino 7.1 RTOS with io-pkt network stack".into()); + let mut target = qnx_sdp::x86_64(); + target.metadata.description = Some("x86 64-bit QNX SDP 7.1 with io-pkt network stack".into()); target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::X86_64); + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::Default, qnx_sdp::Arch::X86_64); + // for QNX SDP 7.x, we keep target_os = "nto" for backwards compatibility, and use target_env to specify which version target.options.env = Env::Nto71; target } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs index 1e97ae6b7a08e..33789b61a18b1 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs @@ -1,12 +1,12 @@ -use crate::spec::base::nto_qnx; +use crate::spec::base::qnx_sdp; use crate::spec::{Env, Target}; pub(crate) fn target() -> Target { - let mut target = nto_qnx::x86_64(); - target.metadata.description = - Some("x86 64-bit QNX Neutrino 7.1 RTOS with io-sock network stack".into()); + let mut target = qnx_sdp::x86_64(); + target.metadata.description = Some("x86 64-bit QNX SDP 7.1 with io-sock network stack".into()); target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::IoSock, nto_qnx::Arch::X86_64); + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::IoSock, qnx_sdp::Arch::X86_64); + // for QNX SDP 7.x, we keep target_os = "nto" for backwards compatibility, and use target_env to specify which version target.options.env = Env::Nto71IoSock; target } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx800.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx800.rs deleted file mode 100644 index bd98df621db16..0000000000000 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx800.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::spec::base::nto_qnx; -use crate::spec::{Env, Target}; - -pub(crate) fn target() -> Target { - let mut target = nto_qnx::x86_64(); - target.metadata.description = Some("x86 64-bit QNX Neutrino 8.0 RTOS".into()); - target.options.pre_link_args = - nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::X86_64); - target.options.env = Env::Nto80; - target -} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_qnx.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_qnx.rs new file mode 100644 index 0000000000000..59eff3dbeb5d4 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_qnx.rs @@ -0,0 +1,12 @@ +use crate::spec::base::qnx_sdp; +use crate::spec::{Os, Target}; + +pub(crate) fn target() -> Target { + let mut target = qnx_sdp::x86_64(); + target.metadata.description = Some("x86 64-bit QNX SDP 8.0+".into()); + target.options.pre_link_args = + qnx_sdp::pre_link_args(qnx_sdp::ApiVariant::Default, qnx_sdp::Arch::X86_64); + // for QNX SDP 8.0, we have target_os = "qnx" and no target_env + target.options.os = Os::Qnx; + target +} 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/library/std/build.rs b/library/std/build.rs index 5f2e441bf7d83..98856b58d890f 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -48,6 +48,7 @@ fn main() { || target_os == "vita" || target_os == "aix" || target_os == "nto" + || target_os == "qnx" || target_os == "xous" || target_os == "hurd" || target_os == "uefi" diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 1cbabf572367e..fa5dfd8b76ec1 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -1096,6 +1096,7 @@ pub mod consts { /// * `"netbsd"` /// * `"nto"` /// * `"openbsd"` + /// * `"qnx"` /// * `"redox"` /// * `"solaris"` /// * `"solid_asp3"` diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 88f6af0e33df7..cada78a0d55ad 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -733,7 +733,13 @@ fn debug() { // no longer has rounding errors. // VxWorks ignores SO_SNDTIMEO. #[cfg_attr( - any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"), + any( + target_os = "netbsd", + target_os = "openbsd", + target_os = "vxworks", + target_os = "nto", + target_os = "qnx" + ), ignore )] #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index 9e9d3bf77e50b..eeb6afdb072eb 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -188,7 +188,13 @@ fn debug() { // no longer has rounding errors. // VxWorks ignores SO_SNDTIMEO. #[cfg_attr( - any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"), + any( + target_os = "netbsd", + target_os = "openbsd", + target_os = "vxworks", + target_os = "nto", + target_os = "qnx" + ), ignore )] #[cfg_attr(target_os = "wasi", ignore)] // timeout not supported diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 44ddb55c920f4..a7ffd87d84d93 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -121,7 +121,7 @@ pub mod macos; pub mod motor; #[cfg(target_os = "netbsd")] pub mod netbsd; -#[cfg(target_os = "nto")] +#[cfg(any(target_os = "nto", target_os = "qnx"))] pub mod nto; #[cfg(target_os = "nuttx")] pub mod nuttx; diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index e3f15a00a0944..25aa3bf7893f4 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -69,7 +69,7 @@ mod platform { pub use crate::os::linux::*; #[cfg(target_os = "netbsd")] pub use crate::os::netbsd::*; - #[cfg(target_os = "nto")] + #[cfg(any(target_os = "nto", target_os = "qnx"))] pub use crate::os::nto::*; #[cfg(target_os = "nuttx")] pub use crate::os::nuttx::*; diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 6876446c25c5d..e7bcd70140d67 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -9,6 +9,7 @@ target_os = "illumos", target_os = "haiku", target_os = "nto", + target_os = "qnx", target_os = "cygwin" ))] use libc::MSG_NOSIGNAL; @@ -36,6 +37,7 @@ use crate::{fmt, io}; target_os = "illumos", target_os = "haiku", target_os = "nto", + target_os = "qnx", target_os = "cygwin" )))] const MSG_NOSIGNAL: core::ffi::c_int = 0x0; diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index a44b23a77d2d4..137088dd832f7 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -20,6 +20,7 @@ mod tests; target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_os = "qnx", target_vendor = "apple", target_os = "cygwin" ))] @@ -44,6 +45,7 @@ pub use self::stream::*; target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_os = "qnx", target_vendor = "apple", target_os = "cygwin", ))] diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index a4218bd4da62c..4dfa06d74ce7e 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -6,7 +6,7 @@ cfg_select! { target_os = "openbsd", target_os = "netbsd", target_os = "solaris", target_os = "illumos", target_os = "haiku", target_os = "nto", - target_os = "cygwin", + target_os = "qnx", target_os = "cygwin", ) => { use libc::MSG_NOSIGNAL; } @@ -26,6 +26,7 @@ use super::{SocketAncillary, recv_vectored_with_ancillary_from, send_vectored_wi target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_os = "qnx", target_vendor = "apple", target_os = "cygwin" ))] diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index d88c97113efeb..f703fc6d54c02 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -176,7 +176,7 @@ fn long_path() { } #[test] -#[cfg(not(target_os = "nto"))] +#[cfg(not(any(target_os = "nto", target_os = "qnx")))] #[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets #[cfg_attr(target_os = "cygwin", ignore)] // Cygwin connect needs handshake #[cfg_attr(target_os = "vxworks", ignore = "Unix sockets are not implemented in VxWorks")] diff --git a/library/std/src/os/unix/net/ucred.rs b/library/std/src/os/unix/net/ucred.rs index 1395d2ef4be3c..36b67cb1163d8 100644 --- a/library/std/src/os/unix/net/ucred.rs +++ b/library/std/src/os/unix/net/ucred.rs @@ -30,7 +30,8 @@ pub(super) use self::impl_apple::peer_cred; target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "nto" + target_os = "nto", + target_os = "qnx" ))] pub(super) use self::impl_bsd::peer_cred; #[cfg(any(target_os = "android", target_os = "linux", target_os = "cygwin"))] @@ -79,6 +80,7 @@ mod impl_linux { target_os = "openbsd", target_os = "netbsd", target_os = "nto", + target_os = "qnx", ))] mod impl_bsd { use super::UCred; diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 8a7b94d914ab0..3b3a5794ac4f1 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -16,7 +16,7 @@ cfg_select! { type UserId = u16; type GroupId = u16; } - target_os = "nto" => { + any(target_os = "nto", target_os = "qnx") => { // Both IDs are signed, see `sys/target_nto.h` of the QNX Neutrino SDP. // Only positive values should be used, see e.g. // https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html diff --git a/library/std/src/sys/args/unix.rs b/library/std/src/sys/args/unix.rs index 7a592c2b079dd..197931d8cc8d2 100644 --- a/library/std/src/sys/args/unix.rs +++ b/library/std/src/sys/args/unix.rs @@ -81,6 +81,7 @@ pub fn args() -> Args { target_os = "horizon", target_os = "aix", target_os = "nto", + target_os = "qnx", target_os = "hurd", target_os = "rtems", target_os = "nuttx", diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs index 573f540483b1a..b14160cf4ad32 100644 --- a/library/std/src/sys/env_consts.rs +++ b/library/std/src/sys/env_consts.rs @@ -224,6 +224,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "qnx")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "qnx"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "nuttx")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index edb2ffc49995e..392e33a77dc50 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -76,6 +76,7 @@ const fn max_iov() -> usize { target_os = "emscripten", target_os = "linux", target_os = "nto", + target_os = "qnx", ))] const fn max_iov() -> usize { libc::UIO_MAXIOV as usize @@ -91,6 +92,7 @@ const fn max_iov() -> usize { target_os = "netbsd", target_os = "nuttx", target_os = "nto", + target_os = "qnx", target_os = "openbsd", target_os = "horizon", target_os = "vita", @@ -561,6 +563,7 @@ impl FileDesc { target_os = "redox", target_os = "vxworks", target_os = "nto", + target_os = "qnx", target_os = "wasi", )))] pub fn set_cloexec(&self) -> io::Result<()> { @@ -585,6 +588,7 @@ impl FileDesc { target_os = "redox", target_os = "vxworks", target_os = "nto", + target_os = "qnx", target_os = "wasi", ))] pub fn set_cloexec(&self) -> io::Result<()> { diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 3152a22534f6c..8fee56348c071 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -28,6 +28,7 @@ use libc::fstatat64; target_os = "fuchsia", target_os = "illumos", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -45,6 +46,7 @@ use libc::readdir as readdir64; target_os = "l4re", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -282,6 +284,7 @@ cfg_select! { target_os = "horizon", target_os = "vita", target_os = "nto", + target_os = "qnx", target_os = "vxworks", ) => { pub use crate::sys::fs::common::Dir; @@ -410,6 +413,7 @@ fn get_path_from_fd(fd: c_int) -> Option { target_os = "illumos", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -436,6 +440,7 @@ pub struct DirEntry { target_os = "illumos", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -448,6 +453,7 @@ struct dirent64_min { target_os = "illumos", target_os = "aix", target_os = "nto", + target_os = "qnx", target_os = "vita", )))] d_type: u8, @@ -462,6 +468,7 @@ struct dirent64_min { target_os = "illumos", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -611,7 +618,13 @@ impl FileAttr { } } -#[cfg(not(any(target_os = "netbsd", target_os = "nto", target_os = "aix", target_os = "wasi")))] +#[cfg(not(any( + target_os = "netbsd", + target_os = "nto", + target_os = "qnx", + target_os = "aix", + target_os = "wasi" +)))] impl FileAttr { #[cfg(not(any( target_os = "vxworks", @@ -736,7 +749,7 @@ impl FileAttr { } } -#[cfg(any(target_os = "nto", target_os = "wasi"))] +#[cfg(any(target_os = "nto", target_os = "qnx", target_os = "wasi"))] impl FileAttr { pub fn modified(&self) -> io::Result { SystemTime::new(self.stat.st_mtim.tv_sec, self.stat.st_mtim.tv_nsec.into()) @@ -854,6 +867,7 @@ impl Iterator for ReadDir { target_os = "illumos", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -927,6 +941,7 @@ impl Iterator for ReadDir { target_os = "illumos", target_os = "aix", target_os = "nto", + target_os = "qnx", )))] d_type: (*entry_ptr).d_type as u8, }; @@ -952,6 +967,7 @@ impl Iterator for ReadDir { target_os = "illumos", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "solaris", target_os = "vita", @@ -1015,6 +1031,7 @@ impl Drop for DirStream { miri, target_os = "redox", target_os = "nto", + target_os = "qnx", target_os = "vita", target_os = "hurd", target_os = "espidf", @@ -1103,6 +1120,7 @@ impl DirEntry { target_os = "vxworks", target_os = "aix", target_os = "nto", + target_os = "qnx", target_os = "vita", ))] pub fn file_type(&self) -> io::Result { @@ -1116,6 +1134,7 @@ impl DirEntry { target_os = "vxworks", target_os = "aix", target_os = "nto", + target_os = "qnx", target_os = "vita", )))] pub fn file_type(&self) -> io::Result { @@ -1146,6 +1165,7 @@ impl DirEntry { target_os = "l4re", target_os = "linux", target_os = "nto", + target_os = "qnx", target_os = "redox", target_os = "rtems", target_os = "solaris", @@ -1205,6 +1225,7 @@ impl DirEntry { target_os = "redox", target_os = "aix", target_os = "nto", + target_os = "qnx", target_os = "vita", target_os = "hurd", target_os = "wasi", @@ -1222,6 +1243,7 @@ impl DirEntry { target_os = "redox", target_os = "aix", target_os = "nto", + target_os = "qnx", target_os = "vita", target_os = "hurd", target_os = "wasi", @@ -1419,6 +1441,7 @@ impl File { target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_os = "qnx", target_os = "hurd", ))] unsafe fn os_datasync(fd: c_int) -> c_int { @@ -1433,6 +1456,7 @@ impl File { target_os = "netbsd", target_os = "openbsd", target_os = "nto", + target_os = "qnx", target_os = "hurd", target_vendor = "apple", )))] @@ -2405,6 +2429,7 @@ pub use remove_dir_impl::remove_dir_all; target_os = "horizon", target_os = "vita", target_os = "nto", + target_os = "qnx", target_os = "vxworks", miri ))] @@ -2419,6 +2444,7 @@ mod remove_dir_impl { target_os = "horizon", target_os = "vita", target_os = "nto", + target_os = "qnx", target_os = "vxworks", miri )))] diff --git a/library/std/src/sys/io/error/unix.rs b/library/std/src/sys/io/error/unix.rs index 56295578bf7d9..85e3c09782ae2 100644 --- a/library/std/src/sys/io/error/unix.rs +++ b/library/std/src/sys/io/error/unix.rs @@ -27,6 +27,7 @@ unsafe extern "C" { )] #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] + #[cfg_attr(target_os = "qnx", link_name = "__get_errno_ptr")] #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] #[cfg_attr(target_os = "aix", link_name = "_Errno")] diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index 55c928dc6c5fc..66aa2a804db22 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -46,6 +46,7 @@ cfg_select! { target_os = "haiku", target_os = "l4re", target_os = "nto", + target_os = "qnx", target_os = "nuttx", target_vendor = "apple", ) => { @@ -65,7 +66,8 @@ cfg_select! { target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "solaris", target_os = "illumos", - target_os = "haiku", target_os = "nto", + target_os = "haiku", + target_os = "nto", target_os = "qnx", target_os = "cygwin", ) => { use libc::MSG_NOSIGNAL; @@ -80,7 +82,7 @@ cfg_select! { target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "solaris", target_os = "illumos", - target_os = "nto", + target_os = "nto", target_os = "qnx", ) => { use crate::ffi::c_uchar; type IpV4MultiCastType = c_uchar; diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index 3336dc4cf9233..41850574c96fa 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -76,6 +76,7 @@ impl Socket { target_os = "openbsd", target_os = "cygwin", target_os = "nto", + target_os = "qnx", target_os = "solaris", ) => { // On platforms that support it we pass the SOCK_CLOEXEC @@ -124,6 +125,7 @@ impl Socket { target_os = "openbsd", target_os = "cygwin", target_os = "nto", + target_os = "qnx", ) => { // Like above, set cloexec atomically cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?; diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs index 73768860723d0..51162296ea3fc 100644 --- a/library/std/src/sys/pal/unix/sync/condvar.rs +++ b/library/std/src/sys/pal/unix/sync/condvar.rs @@ -1,9 +1,9 @@ use super::Mutex; use crate::cell::UnsafeCell; use crate::pin::Pin; -#[cfg(not(target_os = "nto"))] +#[cfg(not(any(target_os = "nto", target_os = "qnx")))] use crate::sys::pal::time::TIMESPEC_MAX; -#[cfg(target_os = "nto")] +#[cfg(any(target_os = "nto", target_os = "qnx"))] use crate::sys::pal::time::TIMESPEC_MAX_CAPPED; use crate::time::Duration; @@ -69,10 +69,10 @@ impl Condvar { let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur); - #[cfg(not(target_os = "nto"))] + #[cfg(not(any(target_os = "nto", target_os = "qnx")))] let timeout = timeout.and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); - #[cfg(target_os = "nto")] + #[cfg(any(target_os = "nto", target_os = "qnx"))] let timeout = timeout.and_then(|t| t.to_timespec_capped()).unwrap_or(TIMESPEC_MAX_CAPPED); let r = unsafe { libc::pthread_cond_timedwait(self.raw(), mutex, &timeout) }; diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index 26fb6d3d7cf2d..26296b5d169a1 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -16,7 +16,7 @@ pub const TIMESPEC_MAX: libc::timespec = { // This additional constant is only used when calling // `libc::pthread_cond_timedwait`. -#[cfg(target_os = "nto")] +#[cfg(any(target_os = "nto", target_os = "qnx"))] pub(in crate::sys) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec { tv_sec: (u64::MAX / NSEC_PER_SEC) as i64, tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64, diff --git a/library/std/src/sys/paths/unix.rs b/library/std/src/sys/paths/unix.rs index e0b1aafda6eb0..36879b7b9bce3 100644 --- a/library/std/src/sys/paths/unix.rs +++ b/library/std/src/sys/paths/unix.rs @@ -269,7 +269,7 @@ pub fn current_exe() -> io::Result { } } -#[cfg(target_os = "nto")] +#[cfg(any(target_os = "nto", target_os = "qnx"))] pub fn current_exe() -> io::Result { let mut e = crate::fs::read("/proc/self/exefile")?; // Current versions of QNX Neutrino provide a null-terminated path. diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index b6ccc6b698fda..55906ed2854f2 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -20,7 +20,7 @@ use crate::sys::process::PidFd; use crate::{fmt, mem, sys}; cfg_select! { - target_os = "nto" => { + any(target_os = "nto", target_os = "qnx") => { use crate::thread; use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; use crate::time::Duration; @@ -183,7 +183,12 @@ impl Command { // Attempts to fork the process. If successful, returns Ok((0, -1)) // in the child, and Ok((child_pid, -1)) in the parent. - #[cfg(not(any(target_os = "watchos", target_os = "tvos", target_os = "nto")))] + #[cfg(not(any( + target_os = "watchos", + target_os = "tvos", + target_os = "nto", + target_os = "qnx" + )))] unsafe fn do_fork(&mut self) -> Result { cvt(libc::fork()) } @@ -192,7 +197,7 @@ impl Command { // or closed a file descriptor while the fork() was occurring". // Documentation says "... or try calling fork() again". This is what we do here. // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html - #[cfg(target_os = "nto")] + #[cfg(any(target_os = "nto", target_os = "qnx"))] unsafe fn do_fork(&mut self) -> Result { use crate::sys::io::errno; @@ -424,6 +429,7 @@ impl Command { all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), target_os = "nto", + target_os = "qnx", target_vendor = "apple", target_os = "cygwin", )))] @@ -443,6 +449,7 @@ impl Command { all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), target_os = "nto", + target_os = "qnx", target_vendor = "apple", target_os = "cygwin", ))] @@ -550,7 +557,7 @@ impl Command { // or closed a file descriptor while the posix_spawn() was occurring". // Documentation says "... or try calling posix_spawn() again". This is what we do here. // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html - #[cfg(target_os = "nto")] + #[cfg(any(target_os = "nto", target_os = "qnx"))] unsafe fn retrying_libc_posix_spawnp( pid: *mut pid_t, file: *const c_char, @@ -763,9 +770,9 @@ impl Command { let _env_lock = sys::env::env_read_lock(); let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::env::environ() as *const _); - #[cfg(not(target_os = "nto"))] + #[cfg(not(any(target_os = "nto", target_os = "qnx")))] let spawn_fn = libc::posix_spawnp; - #[cfg(target_os = "nto")] + #[cfg(any(target_os = "nto", target_os = "qnx"))] let spawn_fn = retrying_libc_posix_spawnp; #[cfg(target_os = "linux")] @@ -822,7 +829,7 @@ impl Command { envp as *const _, ); - #[cfg(target_os = "nto")] + #[cfg(any(target_os = "nto", target_os = "qnx"))] let spawn_res = spawn_res?; cvt_nz(spawn_res)?; @@ -1202,7 +1209,12 @@ fn signal_string(signal: i32) -> &'static str { ) ))] libc::SIGSTKFLT => " (SIGSTKFLT)", - #[cfg(any(target_os = "linux", target_os = "nto", target_os = "cygwin"))] + #[cfg(any( + target_os = "linux", + target_os = "nto", + target_os = "qnx", + target_os = "cygwin" + ))] libc::SIGPWR => " (SIGPWR)", #[cfg(any( target_os = "freebsd", @@ -1210,6 +1222,7 @@ fn signal_string(signal: i32) -> &'static str { target_os = "openbsd", target_os = "dragonfly", target_os = "nto", + target_os = "qnx", target_vendor = "apple", target_os = "cygwin", ))] diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index 12346ef5a2edd..e5a66dc463c6b 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -54,6 +54,7 @@ cfg_select! { target_os = "hurd", target_os = "l4re", target_os = "nto", + target_os = "qnx", ) => { mod unix_legacy; pub use unix_legacy::fill_bytes; diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index dd7b7940de510..e52ffff165beb 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -12,7 +12,12 @@ use crate::mem::{self, DropGuard, ManuallyDrop}; use crate::num::NonZero; #[cfg(all(target_os = "linux", target_env = "gnu"))] use crate::sys::weak::dlsym; -#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))] +#[cfg(any( + target_os = "solaris", + target_os = "illumos", + target_os = "nto", + target_os = "qnx", +))] use crate::sys::weak::weak; use crate::thread::ThreadInit; use crate::time::Duration; diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 4e380d8894781..cb4a3593c51d6 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -193,7 +193,7 @@ unsafe extern "C" {} #[link(name = "unwind")] unsafe extern "C" {} -#[cfg(target_os = "nto")] +#[cfg(any(target_os = "nto", target_os = "qnx"))] cfg_select! { target_env = "nto70" => { #[link(name = "gcc")] 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/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 6ebfa4da4906a..99d9c8a04c5c1 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -39,6 +39,8 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined "powerpc64-unknown-linux-gnuelfv2", "aarch64-unknown-linux-pauthtest", // Stage 0 compiler is not guaranteed to see the target yet. + "aarch64-unknown-qnx", + "x86_64-pc-qnx", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 5cbdaf21de755..1bdbae13bdaec 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -278,7 +278,7 @@ target | std | host | notes [`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | [`aarch64-unknown-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with new network stack (io-sock) | -[`aarch64-unknown-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 8.0 RTOS | +[`aarch64-unknown-qnx`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX SDP 8.0+ | [`aarch64-unknown-nuttx`](platform-support/nuttx.md) | ✓ | | ARM64 with NuttX [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD [`aarch64-unknown-redox`](platform-support/redox.md) | ✓ | | ARM64 Redox OS @@ -451,7 +451,7 @@ target | std | host | notes [`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ✓ | | 64-bit x86 Cygwin | [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | [`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) | -[`x86_64-pc-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 8.0 RTOS | +[`x86_64-pc-qnx`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX SDP 8.0+ | [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.5 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 9f8960899c169..b3ab1c7c4485b 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -1,15 +1,22 @@ -# nto-qnx +# QNX **Tier: 3** -The [QNX®][qnx.com] Neutrino (nto) Real-time operating system. Known as QNX OS -from version 8 onwards. +Support for the [QNX®][qnx.com] [QNX Software Development Platform (SDP)], version 7.0, 7.1 and 8.0. -This support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit] -and [QNX][qnx.com]. +[QNX Software Development Platform (SDP)]: https://qnx.software/en/software/products-and-solutions/qnx-software-development-platform -[qnx.com]: https://blackberry.qnx.com -[Elektrobit]: https://www.elektrobit.com +The [QNX Software Development Platform (SDP)] is a development environment that +you download and install on a host computer. It includes a C toolchain for your +host, an IDE, and various board support packages for different target platforms. +You can then use QNX SDP to build a custom run-time environment which you deploy +onto an embedded device. That run-time environment will include a microkernel, +whatever services you have selected, and perhaps one or more applications +written in Rust. + +In QNX SDP 7.x the run-time environment is based on QNX Neutrino RTOS 7.x, while +in QNX SDP 8.0 the run-time environment is based on QNX OS 8.0. The name change +reflects architectural changes in the RTOS, but both use a microkernel design. ## Target maintainers @@ -20,107 +27,52 @@ and [QNX][qnx.com]. ## Requirements -Currently, the following QNX versions and compilation targets are supported: +The following QNX SDP versions and compilation targets are supported: | Target Tuple | QNX Version | Target Architecture | Full support | `no_std` support | | ----------------------------------- | ----------------------------- | ------------------- | :----------: | :--------------: | -| `aarch64-unknown-nto-qnx800` | QNX OS 8.0 | AArch64 | ? | ✓ | -| `x86_64-pc-nto-qnx800` | QNX OS 8.0 | x86_64 | ? | ✓ | -| `aarch64-unknown-nto-qnx710` | QNX Neutrino 7.1 with io-pkt | AArch64 | ✓ | ✓ | -| `x86_64-pc-nto-qnx710` | QNX Neutrino 7.1 with io-pkt | x86_64 | ✓ | ✓ | -| `aarch64-unknown-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | AArch64 | ? | ✓ | -| `x86_64-pc-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | x86_64 | ? | ✓ | -| `aarch64-unknown-nto-qnx700` | QNX Neutrino 7.0 | AArch64 | ? | ✓ | -| `i686-pc-nto-qnx700` | QNX Neutrino 7.0 | x86 | | ✓ | - -On QNX Neutrino 7.0 and 7.1, `io-pkt` is used as network stack by default. -QNX Neutrino 7.1 includes the optional network stack `io-sock`. -QNX OS 8.0 always uses `io-sock`. QNX OS 8.0 support is currently work in progress. - -Adding other architectures that are supported by QNX is possible. - -In the table above, 'full support' indicates support for building Rust applications with the full standard library. A '?' means that support is in-progress. -'`no_std` support' is for building `#![no_std]` applications where only `core` and `alloc` are available. - -For building or using the Rust toolchain for QNX, the -[QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform) -must be installed and initialized. -Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be installed as part of the SDP, see also installation instruction provided with the SDP). -Afterwards [`qcc`](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html) (QNX C/C++ compiler) -should be available (in the `$PATH` variable). -`qcc` will be called e.g. for linking executables. - -When linking `no_std` applications, they must link against `libc.so` (see example). This is -required because applications always link against the `crt` library and `crt` depends on `libc.so`. -This is done automatically when using the standard library. - -### Disabling RELocation Read-Only (RELRO) - -While not recommended by default, some QNX kernel setups may require the `RELRO` to be disabled with `-C relro_level=off`, e.g. by adding it to the `.cargo/config.toml` file: - -```toml -[target.aarch64-unknown-nto-qnx700] -rustflags = ["-C", "relro_level=off"] -``` - -If your QNX kernel does not allow it, and `relro` is not disabled, running compiled binary would fail with `syntax error: ... unexpected` or similar. This is due to kernel trying to interpret compiled binary with `/bin/sh`, and obviously failing. To verify that this is really the case, run your binary with the `DL_DEBUG=all` env var, and look for this output. If you see it, you should disable `relro` as described above. - -```text -Resolution scope for Executable->/bin/sh: - Executable->/bin/sh - libc.so.4->/usr/lib/ldqnx-64.so.2 -``` - -### Small example application - -Small `no_std` example is shown below. Applications using the standard library work as well. - -```rust,ignore (platform-specific) -#![no_std] -#![no_main] -#![feature(lang_items)] - -// We must always link against libc, even if no external functions are used -// "extern C" - Block can be empty but must be present -#[link(name = "c")] -extern "C" { - pub fn printf(format: *const core::ffi::c_char, ...) -> core::ffi::c_int; -} - -#[no_mangle] -pub extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { - const HELLO: &'static str = "Hello World, the answer is %d\n\0"; - unsafe { - printf(HELLO.as_ptr() as *const _, 42); - } - 0 -} - -use core::panic::PanicInfo; - -#[panic_handler] -fn panic(_panic: &PanicInfo<'_>) -> ! { - loop {} -} - -#[lang = "eh_personality"] -#[no_mangle] -pub extern "C" fn rust_eh_personality() {} -``` - -The QNX support in Rust has been tested with QNX Neutrino 7.0 and 7.1. Support for QNX OS 8.0 is a work in progress. - -There are no further known requirements. +| `aarch64-unknown-qnx` | QNX SDP 8.0+ | AArch64 | ? | ✓ | +| `x86_64-pc-qnx` | QNX SDP 8.0+ | x86_64 | ? | ✓ | +| `aarch64-unknown-nto-qnx710_iosock` | QNX SDP 7.1 with io-sock | AArch64 | ? | ✓ | +| `x86_64-pc-nto-qnx710_iosock` | QNX SDP 7.1 with io-sock | x86_64 | ? | ✓ | +| `aarch64-unknown-nto-qnx710` | QNX SDP 7.1 with io-pkt | AArch64 | ✓ | ✓ | +| `x86_64-pc-nto-qnx710` | QNX SDP 7.1 with io-pkt | x86_64 | ✓ | ✓ | +| `aarch64-unknown-nto-qnx700` | QNX SDP 7.0 | AArch64 | ? | ✓ | +| `i686-pc-nto-qnx700` | QNX SDP 7.0 | x86 | - | ✓ | + +* QNX SDP 7.0 only offers the `io-pkt` network stack +* QNX SDP 7.1 uses the `io-pkt` network stack by default, but also includes the optional `io-sock` network stack +* QNX SDP 8.0 only offers the `io-sock` network stack + +In the table above, 'full support' indicates support for building Rust +applications with the full standard library. A '?' means that support is +in-progress. `no_std` support is for building `#![no_std]` applications where +only `core` and `alloc` are available. + +For building or using the Rust toolchain for QNX, the relevant version of the +[QNX Software Development Platform (SDP)] must be installed and initialized. +Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be +installed as part of the SDP, so see the installation instruction provided with +the SDP). Afterwards [`qcc`] (the QNX C/C++ compiler) should be available in +your system PATH because it will be called during Rust compilation (e.g. for +linking executables). + +[`qcc`]: https://www.qnx.com/developers/docs/latest/com.qnx.doc.neutrino.utilities/topic/q/qcc.html + +When linking `no_std` applications, they must link against `libc.so` (see +example). This is required because applications always link against the `crt` +library and `crt` depends on `libc.so`. This is done automatically when using +the standard library. ## Conditional compilation -For conditional compilation, following QNX specific attributes are defined: +For conditional compilation, the following QNX specific attributes are defined: - `target_os` = `"nto"` -- `target_env` = `"nto71"` (for QNX Neutrino 7.1 with "classic" network stack "io_pkt") -- `target_env` = `"nto71_iosock"` (for QNX Neutrino 7.1 with network stack "io_sock") -- `target_env` = `"nto70"` (for QNX Neutrino 7.0) -- `target_env` = `"nto80"` (for QNX OS 8.0) + - `target_env` = `"nto70"` (for QNX SDP 7.0) + - `target_env` = `"nto71"` (for QNX SDP 7.1 with "classic" network stack "io_pkt") + - `target_env` = `"nto71_iosock"` (for QNX SDP 7.1 with "new" network stack "io_sock") +- `target_os` = `"qnx"` (for QNX SDP 8.0 or higher) ## Building the target @@ -176,18 +128,37 @@ For conditional compilation, following QNX specific attributes are defined: rustc library/core library/alloc library/std ``` +## Building Rust programs + +Rust does not ship pre-compiled artifacts for this target. To compile for this +target, you must either build Rust with the target enabled (see "Building the +target" above), or build your own copy of `core` by using `build-std` or +similar. + +Compiled executables can run directly on QNX, either by including them in the +disk image, or copying them over the network to a running system. + +Compiling C code requires the same environment variables to be set as compiling +the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. +To ensure compatibility, do not specify any further arguments that for example +change calling conventions or memory layout. + ## Running the Rust test suite -The test suites of the Rust compiler and standard library can be executed much like other Rust targets. -The environment for testing should match the one used during compiler compilation (refer to `build_env` and `qcc`/`PATH` above) with the -addition of the TEST_DEVICE_ADDR environment variable. -The TEST_DEVICE_ADDR variable controls the remote runner and should point to the target, despite localhost being shown in the following example. -Note that some tests are failing which is why they are currently excluded by the target maintainers which can be seen in the following example. +The test suites of the Rust compiler and standard library can be executed much +like other Rust targets. The environment for testing should match the one used +during compiler compilation (refer to `build_env` and `qcc`/`PATH` above) with +the addition of the `TEST_DEVICE_ADDR` environment variable. The +`TEST_DEVICE_ADDR` variable controls the remote runner and should point to a +target running the `remote-test-server` executable. + +Note that some tests are failing which is why they are currently excluded by the +target maintainers which can be seen in the following example. To run all tests on a x86_64 QNX Neutrino 7.1 target: ```bash -export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel +export TEST_DEVICE_ADDR="1.2.3.4:12345" # must address the test target, can be a SSH tunnel export build_env= # Disable tests that only work on the host or don't make sense for this target. @@ -210,16 +181,6 @@ env $build_env \ --target x86_64-pc-nto-qnx710 ``` -## Building Rust programs - -Rust does not yet ship pre-compiled artifacts for this target. -To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), -or build your own copy of `core` by using `build-std` or similar. - -## Testing - -Compiled executables can run directly on QNX. - ### Rust std library test suite The target needs sufficient resources to execute all tests. The commands below assume that a QEMU image @@ -279,8 +240,26 @@ is used. 64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms ``` -## Cross-compilation toolchains and C code +## Disabling RELocation Read-Only (RELRO) + +While not recommended by default, some QNX kernel setups may require the `RELRO` +to be disabled with `-C relro_level=off`, e.g. by adding it to the +`.cargo/config.toml` file: -Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), -to ensure `qcc` is used with proper arguments. -To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout. +```toml +[target.aarch64-unknown-nto-qnx700] +rustflags = ["-C", "relro_level=off"] +``` + +If your QNX kernel does not allow it, and `relro` is not disabled, running the +compiled binary would fail with `syntax error: ... unexpected` or similar. This +is due to kernel trying to interpret the compiled binary with `/bin/sh`, and +obviously failing. To verify that this is really the case, run your binary with +the `DL_DEBUG=all` env var, and look for this output. If you see it, you should +disable `relro` as described above. + +```text +Resolution scope for Executable->/bin/sh: + Executable->/bin/sh + libc.so.4->/usr/lib/ldqnx-64.so.2 +``` diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 2950e3b563c1c..74a04b4451040 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -638,11 +638,12 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> { Motor => "Motor OS", NetBsd => "NetBSD", None => "bare-metal", - Nto => "QNX Neutrino", + Nto => "QNX SDP 7.x", NuttX => "NuttX", OpenBsd => "OpenBSD", Psp => "Play Station Portable", Psx => "Play Station 1", + Qnx => "QNX SDP 8.0+", Qurt => "QuRT", Redox => "Redox OS", Rtems => "RTEMS OS", @@ -718,10 +719,9 @@ fn human_readable_target_env(env: Symbol) -> Option<&'static str> { Msvc => "MSVC", Musl => "musl", Newlib => "Newlib", - Nto70 => "Neutrino 7.0", - Nto71 => "Neutrino 7.1", - Nto71IoSock => "Neutrino 7.1 with io-sock", - Nto80 => "Neutrino 8.0", + Nto70 => "QNX SDP 7.0", + Nto71 => "QNX SDP 7.1", + Nto71IoSock => "QNX SDP 7.1 with io-sock", Ohos => "OpenHarmony", P1 => "WASIp1", P2 => "WASIp2", 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)?; diff --git a/src/tools/miri/tests/pass-dep/shims/gettid.rs b/src/tools/miri/tests/pass-dep/shims/gettid.rs index 9b186699ce275..05885ac277f76 100644 --- a/src/tools/miri/tests/pass-dep/shims/gettid.rs +++ b/src/tools/miri/tests/pass-dep/shims/gettid.rs @@ -9,7 +9,7 @@ fn gettid() -> u64 { any(target_os = "android", target_os = "linux") => { gettid_linux_like() } - target_os = "nto" => { + any(target_os = "nto", target_os = "qnx") => { unsafe { libc::gettid() as u64 } } target_os = "openbsd" => { diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 7fe8b1a260612..92977143e1f7a 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -88,9 +88,9 @@ //@ revisions: aarch64_unknown_nto_qnx710_iosock //@ [aarch64_unknown_nto_qnx710_iosock] compile-flags: --target aarch64-unknown-nto-qnx710_iosock //@ [aarch64_unknown_nto_qnx710_iosock] needs-llvm-components: aarch64 -//@ revisions: aarch64_unknown_nto_qnx800 -//@ [aarch64_unknown_nto_qnx800] compile-flags: --target aarch64-unknown-nto-qnx800 -//@ [aarch64_unknown_nto_qnx800] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_qnx +//@ [aarch64_unknown_qnx] compile-flags: --target aarch64-unknown-qnx +//@ [aarch64_unknown_qnx] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_openbsd //@ [aarch64_unknown_openbsd] compile-flags: --target aarch64-unknown-openbsd //@ [aarch64_unknown_openbsd] needs-llvm-components: aarch64 @@ -685,9 +685,9 @@ //@ revisions: x86_64_pc_nto_qnx710_iosock //@ [x86_64_pc_nto_qnx710_iosock] compile-flags: --target x86_64-pc-nto-qnx710_iosock //@ [x86_64_pc_nto_qnx710_iosock] needs-llvm-components: x86 -//@ revisions: x86_64_pc_nto_qnx800 -//@ [x86_64_pc_nto_qnx800] compile-flags: --target x86_64-pc-nto-qnx800 -//@ [x86_64_pc_nto_qnx800] needs-llvm-components: x86 +//@ revisions: x86_64_pc_qnx +//@ [x86_64_pc_qnx] compile-flags: --target x86_64-pc-qnx +//@ [x86_64_pc_qnx] needs-llvm-components: x86 //@ revisions: x86_64_pc_solaris //@ [x86_64_pc_solaris] compile-flags: --target x86_64-pc-solaris //@ [x86_64_pc_solaris] needs-llvm-components: x86 diff --git a/tests/rustdoc-html/doc-cfg/all-targets.rs b/tests/rustdoc-html/doc-cfg/all-targets.rs index 605a27a7d8927..d5a8be83bc1d3 100644 --- a/tests/rustdoc-html/doc-cfg/all-targets.rs +++ b/tests/rustdoc-html/doc-cfg/all-targets.rs @@ -3,9 +3,9 @@ //@ has all_targets/fn.foo.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ // 'Available on target_env=fake_env or Catalyst or GNU or Managarm C Library \ -// or MSVC or musl or Neutrino 7.0 or Neutrino 7.1 or Neutrino 7.1 with io-sock \ -// or Neutrino 8.0 or Newlib or OpenHarmony or relibc or SGX or Simulator or \ -// uClibc or V5 or WASIp1 or WASIp2 or WASIp3 only.' +// or MSVC or musl or Newlib or OpenHarmony or QNX SDP 7.0 or QNX SDP 7.1 or \ +// QNX SDP 7.1 with io-sock or relibc or SGX or Simulator or uClibc or V5 or WASIp1 \ +// or WASIp2 or WASIp3 only.' #[doc(cfg(any( target_env = "gnu", target_env = "macabi", @@ -16,7 +16,6 @@ target_env = "nto70", target_env = "nto71", target_env = "nto71_iosock", - target_env = "nto80", target_env = "ohos", target_env = "relibc", target_env = "sgx", @@ -81,7 +80,7 @@ pub fn bar() {} // and HelenOS and Hermit and Horizon and illumos and iOS and L4Re and Linux \ // and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and NuttX \ // and OpenBSD and Play Station 1 and Play Station Portable and Play Station Vita \ -// and QNX Neutrino and QuRT and Redox OS and RTEMS OS and Solaris and \ +// and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS and RTEMS OS and Solaris and \ // SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI and VEXos and visionOS \ // and VxWorks and WASI and watchOS and Windows and Xous and zero knowledge \ // Virtual Machine only.' @@ -112,6 +111,7 @@ pub fn bar() {} target_os = "netbsd", target_os = "none", target_os = "nto", + target_os = "qnx", target_os = "nuttx", target_os = "openbsd", target_os = "psp", diff --git a/tests/rustdoc-html/doc-cfg/sort.rs b/tests/rustdoc-html/doc-cfg/sort.rs index 3aa79b7836271..2c54e86be67c7 100644 --- a/tests/rustdoc-html/doc-cfg/sort.rs +++ b/tests/rustdoc-html/doc-cfg/sort.rs @@ -9,7 +9,7 @@ // Tests that OS targets are sorted alphabetically. //@ has 'foo/fn.foo.html' //@ has - '//*[@class="stab portability"]' 'Available on Android or Apple or Cygwin \ -// or DragonFly BSD or FreeBSD or Linux or NetBSD or OpenBSD or QNX Neutrino only.' +// or DragonFly BSD or FreeBSD or Linux or NetBSD or OpenBSD only.' #[doc(cfg(any( target_os = "android", target_os = "linux", @@ -17,7 +17,6 @@ target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "nto", target_vendor = "apple", target_os = "cygwin" )))] @@ -27,7 +26,7 @@ pub fn foo() {} // Tests that targets are sorted alphabetically just like explicit `doc(cfg)`. //@ has 'foo/fn.bar.html' //@ has - '//*[@class="stab portability"]' 'Available on Android or Apple or Cygwin \ -// or DragonFly BSD or FreeBSD or Linux or NetBSD or OpenBSD or QNX Neutrino only.' +// or DragonFly BSD or FreeBSD or Linux or NetBSD or OpenBSD only.' #[cfg(any( target_os = "android", target_os = "linux", @@ -35,7 +34,6 @@ pub fn foo() {} target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "nto", target_vendor = "apple", target_os = "cygwin" ))] diff --git a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs index f93a2aae5a1e9..6ea36dee947c1 100644 --- a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs +++ b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs @@ -18,6 +18,7 @@ target_os = "linux", target_os = "netbsd", target_os = "nto", + target_os = "qnx", target_os = "openbsd", target_os = "fuchsia", target_os = "managarm", diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index 242883995488e..9bf3cef403159 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, and `solid_asp3` and 14 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, and `solaris` and 15 more = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index ebcb439b73498..5c797783e48b8 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `gnu`, `macabi`, `mlibc`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `p3`, `relibc`, `sgx`, `sim`, `uclibc`, and `v5` + = note: expected values for `target_env` are: ``, `gnu`, `macabi`, `mlibc`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `ohos`, `p1`, `p2`, `p3`, `relibc`, `sgx`, `sim`, `uclibc`, and `v5` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -210,7 +210,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -283,7 +283,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 29 warnings emitted diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 242eea1f8407d..d14bdf35e81f3 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -16,6 +16,7 @@ target_os = "solaris", target_os = "vxworks", target_os = "nto", + target_os = "qnx", target_vendor = "apple", ))] mod m { diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs index 574d79ee1ddaf..b8eb2a9688b4d 100644 --- a/tests/ui/process/process-sigpipe.rs +++ b/tests/ui/process/process-sigpipe.rs @@ -31,9 +31,9 @@ fn main() { thread::sleep_ms(5000); process::exit(1); }); - // QNX Neutrino does not have `yes`. Therefore, use `while-echo` for `nto` + // QNX does not have `yes`. Therefore, use `while-echo` for `nto` // and `yes` for other platforms. - let command = if cfg!(target_os = "nto") { + let command = if cfg!(any(target_os = "nto", target_os = "qnx")) { "while echo y ; do : ; done | head" } else { "yes | head" diff --git a/tests/ui/structs/rec-align-u64.rs b/tests/ui/structs/rec-align-u64.rs index e49726c7d438f..a3d835799ad62 100644 --- a/tests/ui/structs/rec-align-u64.rs +++ b/tests/ui/structs/rec-align-u64.rs @@ -36,6 +36,7 @@ struct Outer { target_os = "solaris", target_os = "vxworks", target_os = "nto", + target_os = "qnx", target_vendor = "apple", ))] mod m {