diff options
154 files changed, 2203 insertions, 412 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c17dfd8c8e..44f789c592b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -322,7 +322,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-latest + os: macos-12-xl - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" @@ -333,7 +333,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: dist-x86_64-apple-alt env: SCRIPT: "./x.py dist bootstrap --include-default-paths" @@ -344,7 +344,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps" @@ -355,7 +355,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" @@ -366,7 +366,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: dist-aarch64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" @@ -381,7 +381,7 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-latest + os: macos-12-xl - name: x86_64-msvc-1 env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/Cargo.lock b/Cargo.lock index 917aa5a73a0..5530541cdd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2319,9 +2319,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" dependencies = [ "rustc-std-workspace-core", ] diff --git a/compiler/rustc_ast_lowering/locales/en-US.ftl b/compiler/rustc_ast_lowering/locales/en-US.ftl index a2837deafde..3ccd84398ec 100644 --- a/compiler/rustc_ast_lowering/locales/en-US.ftl +++ b/compiler/rustc_ast_lowering/locales/en-US.ftl @@ -22,9 +22,6 @@ ast_lowering_misplaced_impl_trait = ast_lowering_misplaced_assoc_ty_binding = associated type bounds are only allowed in where clauses and function signatures, not in {$position} -ast_lowering_rustc_box_attribute_error = - #[rustc_box] requires precisely one argument and no other attributes are allowed - ast_lowering_underscore_expr_lhs_assign = in expressions, `_` can only be used on the left-hand side of an assignment .label = `_` not allowed here diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index def74c2adee..5e6b6050bc0 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -88,13 +88,6 @@ pub struct MisplacedAssocTyBinding<'a> { } #[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_rustc_box_attribute_error)] -pub struct RustcBoxAttributeError { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_underscore_expr_lhs_assign)] pub struct UnderscoreExprLhsAssign { #[primary_span] diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d4fafe38638..ffb30b1b391 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2,7 +2,7 @@ use super::errors::{ AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt, GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure, - RustcBoxAttributeError, UnderscoreExprLhsAssign, + UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; @@ -83,15 +83,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), ExprKind::Call(f, args) => { - if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) { - if let [inner] = &args[..] && e.attrs.len() == 1 { - let kind = hir::ExprKind::Box(self.lower_expr(&inner)); - return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; - } else { - let guar = self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span }); - hir::ExprKind::Err(guar) - } - } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { + if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) } else { let f = self.lower_expr(f); diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 6aa900f0201..f011cb754cb 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -53,7 +53,7 @@ pub fn expand_env<'cx>( tts: TokenStream, ) -> Box<dyn base::MacResult + 'cx> { let mut exprs = match get_exprs_from_tts(cx, tts) { - Some(exprs) if exprs.is_empty() => { + Some(exprs) if exprs.is_empty() || exprs.len() > 2 => { cx.span_err(sp, "env! takes 1 or 2 arguments"); return DummyResult::any(sp); } @@ -64,28 +64,48 @@ pub fn expand_env<'cx>( let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else { return DummyResult::any(sp); }; - let msg = match exprs.next() { - None => Symbol::intern(&format!("environment variable `{}` not defined", var)), + + let custom_msg = match exprs.next() { + None => None, Some(second) => match expr_to_string(cx, second, "expected string literal") { None => return DummyResult::any(sp), - Some((s, _style)) => s, + Some((s, _style)) => Some(s), }, }; - if exprs.next().is_some() { - cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::any(sp); - } - let sp = cx.with_def_site_ctxt(sp); let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern); cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { - cx.span_err(sp, msg.as_str()); + let (msg, help) = match custom_msg { + None => ( + format!("environment variable `{var}` not defined at compile time"), + Some(help_for_missing_env_var(var.as_str())), + ), + Some(s) => (s.to_string(), None), + }; + let mut diag = cx.struct_span_err(sp, &msg); + if let Some(help) = help { + diag.help(help); + } + diag.emit(); return DummyResult::any(sp); } Some(value) => cx.expr_str(sp, value), }; MacEager::expr(e) } + +fn help_for_missing_env_var(var: &str) -> String { + if var.starts_with("CARGO_") + || var.starts_with("DEP_") + || matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET") + { + format!( + "Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead" + ) + } else { + format!("Use `std::env::var(\"{var}\")` to read the variable at run time") + } +} diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 3619cb48d64..7d5c0048626 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -224,23 +224,34 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).skip_binder().unsafety() == hir::Unsafety::Normal { - // The `#[target_feature]` attribute is allowed on - // WebAssembly targets on all functions, including safe - // ones. Other targets have conditions on the usage of - // `#[target_feature]` because on most targets - // execution of instructions that are not supported is - // considered undefined behavior. For WebAssembly which is a - // 100% safe target at execution time it's not possible to - // execute undefined instructions, and even if a future - // feature was added in some form for this it would be a - // deterministic trap. There is no undefined behavior when - // executing WebAssembly so `#[target_feature]` is allowed - // on safe functions (but again, only for WebAssembly) - // - // Note that this is also allowed if `actually_rustdoc` so - // if a target is documenting some wasm-specific code then - // it's not spuriously denied. - if !(tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc) { + if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { + // The `#[target_feature]` attribute is allowed on + // WebAssembly targets on all functions, including safe + // ones. Other targets require that `#[target_feature]` is + // only applied to unsafe functions (pending the + // `target_feature_11` feature) because on most targets + // execution of instructions that are not supported is + // considered undefined behavior. For WebAssembly which is a + // 100% safe target at execution time it's not possible to + // execute undefined instructions, and even if a future + // feature was added in some form for this it would be a + // deterministic trap. There is no undefined behavior when + // executing WebAssembly so `#[target_feature]` is allowed + // on safe functions (but again, only for WebAssembly) + // + // Note that this is also allowed if `actually_rustdoc` so + // if a target is documenting some wasm-specific code then + // it's not spuriously denied. + } else if !tcx.features().target_feature_11 { + let mut err = feature_err( + &tcx.sess.parse_sess, + sym::target_feature_11, + attr.span, + "`#[target_feature(..)]` can only be applied to `unsafe` functions", + ); + err.span_label(tcx.def_span(did), "not an `unsafe` function"); + err.emit(); + } else { check_target_feature_trait_unsafe(tcx, did, attr.span); } } @@ -467,7 +478,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { }); // #73631: closures inherit `#[target_feature]` annotations - if tcx.is_closure(did.to_def_id()) { + if tcx.features().target_feature_11 && tcx.is_closure(did.to_def_id()) { let owner_id = tcx.parent(did.to_def_id()); if tcx.def_kind(owner_id).has_codegen_attrs() { codegen_fn_attrs diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 450488315ef..92fa59aec6e 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -16,8 +16,8 @@ use rustc_target::spec::abi::Abi as CallAbi; use crate::const_eval::CheckAlignment; use super::{ - AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, - MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, + AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, + InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; /// Data returned by Machine::stack_pop, @@ -105,10 +105,16 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Extra data stored in every allocation. type AllocExtra: Debug + Clone + 'static; + /// Type for the bytes of the allocation. + type Bytes: AllocBytes + 'static; + /// Memory's allocation map type MemoryMap: AllocMap< AllocId, - (MemoryKind<Self::MemoryKind>, Allocation<Self::Provenance, Self::AllocExtra>), + ( + MemoryKind<Self::MemoryKind>, + Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>, + ), > + Default + Clone; @@ -338,7 +344,7 @@ pub trait Machine<'mir, 'tcx>: Sized { id: AllocId, alloc: Cow<'b, Allocation>, kind: Option<MemoryKind<Self::MemoryKind>>, - ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>; + ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>; fn eval_inline_asm( _ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -459,6 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type AllocExtra = (); type FrameExtra = (); + type Bytes = Box<[u8]>; #[inline(always)] fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index f4e03ad8c59..a3764a7d142 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -21,8 +21,9 @@ use rustc_target::abi::{Align, HasDataLayout, Size}; use crate::const_eval::CheckAlignment; use super::{ - alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, - InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, + alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, + GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, + Scalar, }; #[derive(Debug, PartialEq, Copy, Clone)] @@ -114,16 +115,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// A reference to some allocation that was already bounds-checked for the given region /// and had the on-access machine hooks run. #[derive(Copy, Clone)] -pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra> { - alloc: &'a Allocation<Prov, Extra>, +pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> { + alloc: &'a Allocation<Prov, Extra, Bytes>, range: AllocRange, tcx: TyCtxt<'tcx>, alloc_id: AllocId, } /// A reference to some allocation that was already bounds-checked for the given region /// and had the on-access machine hooks run. -pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra> { - alloc: &'a mut Allocation<Prov, Extra>, +pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> { + alloc: &'a mut Allocation<Prov, Extra, Bytes>, range: AllocRange, tcx: TyCtxt<'tcx>, alloc_id: AllocId, @@ -483,7 +484,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, id: AllocId, is_write: bool, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra>>> { + ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra, M::Bytes>>> { let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) { Some(GlobalAlloc::Memory(mem)) => { // Memory of a constant or promoted or anonymous memory referenced by a static. @@ -526,6 +527,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } + /// Get the base address for the bytes in an `Allocation` specified by the + /// `AllocID` passed in; error if no such allocation exists. + /// + /// It is up to the caller to take sufficient care when using this address: + /// there could be provenance or uninit memory in there, and other memory + /// accesses could invalidate the exposed pointer. + pub fn alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, *const u8> { + let alloc = self.get_alloc_raw(id)?; + Ok(alloc.base_addr()) + } + /// Gives raw access to the `Allocation`, without bounds or alignment checks. /// The caller is responsible for calling the access hooks! /// @@ -533,7 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn get_alloc_raw( &self, id: AllocId, - ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra>> { + ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> { // The error type of the inner closure here is somewhat funny. We have two // ways of "erroring": An actual error, or because we got a reference from // `get_global_alloc` that we can actually use directly without inserting anything anywhere. @@ -569,7 +581,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer<Option<M::Provenance>>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> { + ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>> + { let ptr_and_alloc = self.check_and_deref_ptr( ptr, size, @@ -612,7 +625,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn get_alloc_raw_mut( &mut self, id: AllocId, - ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra>, &mut M)> { + ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> { // We have "NLL problem case #3" here, which cannot be worked around without loss of // efficiency even for the common case where the key is in the map. // <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions> @@ -641,7 +654,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer<Option<M::Provenance>>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra>>> { + ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>> + { let parts = self.get_ptr_access(ptr, size, align)?; if let Some((alloc_id, offset, prov)) = parts { let tcx = *self.tcx; @@ -840,11 +854,11 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Cannot be a closure because it is generic in `Prov`, `Extra`. - fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>( + fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'tcx>, allocs_to_print: &mut VecDeque<AllocId>, - alloc: &Allocation<Prov, Extra>, + alloc: &Allocation<Prov, Extra, Bytes>, ) -> std::fmt::Result { for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id()) { @@ -912,7 +926,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, } /// Reading and writing. -impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> + AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> +{ /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> { let range = self.range.subrange(range); @@ -937,7 +953,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> { } } -impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 244fa8030af..3c463500a60 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -353,7 +353,8 @@ where pub(super) fn get_place_alloc( &self, place: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra>>> { + ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>> + { assert!(place.layout.is_sized()); assert!(!place.meta.has_meta()); let size = place.layout.size; @@ -364,7 +365,8 @@ where pub(super) fn get_place_alloc_mut( &mut self, place: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra>>> { + ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>> + { assert!(place.layout.is_sized()); assert!(!place.meta.has_meta()); let size = place.layout.size; diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 761f1ebdbac..e7b2df34ccc 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -314,8 +314,6 @@ declare_features! ( (accepted, struct_variant, "1.0.0", None, None), /// Allows `#[target_feature(...)]`. (accepted, target_feature, "1.27.0", None, None), - /// Allows the use of `#[target_feature]` on safe functions. - (accepted, target_feature_11, "CURRENT_RUSTC_VERSION", Some(69098), None), /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). (accepted, termination_trait, "1.26.0", Some(43301), None), /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index adc06d9aa10..a01914f969e 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -510,6 +510,8 @@ declare_features! ( (active, strict_provenance, "1.61.0", Some(95228), None), /// Allows string patterns to dereference values to match them. (active, string_deref_patterns, "1.67.0", Some(87121), None), + /// Allows the use of `#[target_feature]` on safe functions. + (active, target_feature_11, "1.45.0", Some(69098), None), /// Allows using `#[thread_local]` on `static` items. (active, thread_local, "1.0.0", Some(29594), None), /// Allows defining `trait X = A + B;` alias items. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 25c467bfd2b..f5ce02c9e61 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2399,8 +2399,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infcx .can_eq( ty::ParamEnv::empty(), - tcx.erase_regions(impl_.self_ty()), - tcx.erase_regions(qself_ty), + impl_.self_ty(), + // Must fold past escaping bound vars too, + // since we have those at this point in astconv. + tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased), ) }) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index d64492e503d..b09886fe3a9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -714,12 +714,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.parent(expr_ctor_def_id) } hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { - // If this is a variant, its parent is the type definition. - if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { + // For a typical enum like + // `enum Blah<T> { Variant(T) }` + // we get the following resolutions: + // - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0}) + // - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant) + // - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah) + + // Therefore, we need to go up once to obtain the variant and up twice to obtain the type. + // Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions + // together; this resolution is handled automatically by `qpath_res`. + + // FIXME: Deal with type aliases? + if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) { + // The constructor definition refers to the "constructor" of the variant: + // For example, `Some(5)` triggers this case. + self.tcx.parent(expr_ctor_def_id) + } else { // FIXME: Deal with type aliases? return Err(expr); } - expr_ctor_def_id } _ => { return Err(expr); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 47a4d4e72df..60d56263d2e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -333,6 +333,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty.prefix_string(self.tcx), ty_str_reported, ); + if tcx.sess.source_map().is_multiline(sugg_span) { + err.span_label(sugg_span.with_hi(span.lo()), ""); + } let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 { short_ty_str } else { diff --git a/compiler/rustc_infer/locales/en-US.ftl b/compiler/rustc_infer/locales/en-US.ftl index c5b2b6c2d73..9794c0ac9df 100644 --- a/compiler/rustc_infer/locales/en-US.ftl +++ b/compiler/rustc_infer/locales/en-US.ftl @@ -345,3 +345,6 @@ infer_prlf_defined_without_sub = the lifetime defined here... infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds + .label = opaque type defined here diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 7dccd0bb930..6bbd3fd3e6e 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1147,3 +1147,13 @@ pub enum PlaceholderRelationLfNotSatisfied { note: (), }, } + +#[derive(Diagnostic)] +#[diag(infer_opaque_captures_lifetime, code = "E0700")] +pub struct OpaqueCapturesLifetime<'tcx> { + #[primary_span] + pub span: Span, + #[label] + pub opaque_ty_span: Span, + pub opaque_ty: Ty<'tcx>, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 79efc1ce7bf..2acbd513852 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError; use super::region_constraints::GenericKind; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; +use crate::errors; use crate::infer; use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::ExpectedFound; @@ -281,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( span: Span, hidden_ty: Ty<'tcx>, hidden_region: ty::Region<'tcx>, - opaque_ty: ty::OpaqueTypeKey<'tcx>, + opaque_ty_key: ty::OpaqueTypeKey<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs); - let mut err = struct_span_err!( - tcx.sess, + let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime { span, - E0700, - "hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds", - ); + opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs), + opaque_ty_span: tcx.def_span(opaque_ty_key.def_id), + }); // Explain the region we are capturing. match *hidden_region { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 221105ac48f..48375ed301d 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -8,7 +8,8 @@ mod tests; use std::borrow::Cow; use std::fmt; use std::hash; -use std::ops::Range; +use std::hash::Hash; +use std::ops::{Deref, DerefMut, Range}; use std::ptr; use either::{Left, Right}; @@ -29,6 +30,39 @@ use provenance_map::*; pub use init_mask::{InitChunk, InitChunkIter}; +/// Functionality required for the bytes of an `Allocation`. +pub trait AllocBytes: + Clone + fmt::Debug + Eq + PartialEq + Hash + Deref<Target = [u8]> + DerefMut<Target = [u8]> +{ + /// Adjust the bytes to the specified alignment -- by default, this is a no-op. + fn adjust_to_align(self, _align: Align) -> Self; + + /// Create an `AllocBytes` from a slice of `u8`. + fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self; + + /// Create a zeroed `AllocBytes` of the specified size and alignment; + /// call the callback error handler if there is an error in allocating the memory. + fn zeroed(size: Size, _align: Align) -> Option<Self>; +} + +// Default `bytes` for `Allocation` is a `Box<[u8]>`. +impl AllocBytes for Box<[u8]> { + fn adjust_to_align(self, _align: Align) -> Self { + self + } + + fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self { + Box::<[u8]>::from(slice.into()) + } + + fn zeroed(size: Size, _align: Align) -> Option<Self> { + let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?; + // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> + let bytes = unsafe { bytes.assume_init() }; + Some(bytes) + } +} + /// This type represents an Allocation in the Miri/CTFE core engine. /// /// Its public API is rather low-level, working directly with allocation offsets and a custom error @@ -38,10 +72,10 @@ pub use init_mask::{InitChunk, InitChunkIter}; // hashed. (see the `Hash` impl below for more details), so the impl is not derived. #[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)] #[derive(HashStable)] -pub struct Allocation<Prov: Provenance = AllocId, Extra = ()> { +pub struct Allocation<Prov: Provenance = AllocId, Extra = (), Bytes = Box<[u8]>> { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. - bytes: Box<[u8]>, + bytes: Bytes, /// Maps from byte addresses to extra provenance data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting @@ -220,14 +254,27 @@ impl AllocRange { } // The constructors are all without extra; the extra gets added by a machine hook later. -impl<Prov: Provenance> Allocation<Prov> { +impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> { + /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support + pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self { + let size = Size::from_bytes(bytes.len()); + Self { + bytes, + provenance: ProvenanceMap::new(), + init_mask: InitMask::new(size, true), + align, + mutability, + extra: (), + } + } + /// Creates an allocation initialized by the given bytes pub fn from_bytes<'a>( slice: impl Into<Cow<'a, [u8]>>, align: Align, mutability: Mutability, ) -> Self { - let bytes = Box::<[u8]>::from(slice.into()); + let bytes = Bytes::from_bytes(slice, align); let size = Size::from_bytes(bytes.len()); Self { bytes, @@ -248,7 +295,7 @@ impl<Prov: Provenance> Allocation<Prov> { /// /// If `panic_on_fail` is true, this will never return `Err`. pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> { - let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| { + let bytes = Bytes::zeroed(size, align).ok_or_else(|| { // This results in an error that can happen non-deterministically, since the memory // available to the compiler can change between runs. Normally queries are always // deterministic. However, we can be non-deterministic here because all uses of const @@ -262,8 +309,7 @@ impl<Prov: Provenance> Allocation<Prov> { }); InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) })?; - // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> - let bytes = unsafe { bytes.assume_init() }; + Ok(Allocation { bytes, provenance: ProvenanceMap::new(), @@ -275,7 +321,7 @@ impl<Prov: Provenance> Allocation<Prov> { } } -impl Allocation { +impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> { /// Adjust allocation from the ones in tcx to a custom Machine instance /// with a different Provenance and Extra type. pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>( @@ -283,9 +329,11 @@ impl Allocation { cx: &impl HasDataLayout, extra: Extra, mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>, - ) -> Result<Allocation<Prov, Extra>, Err> { - // Compute new pointer provenance, which also adjusts the bytes. - let mut bytes = self.bytes; + ) -> Result<Allocation<Prov, Extra, Bytes>, Err> { + // Compute new pointer provenance, which also adjusts the bytes, and realign the pointer if + // necessary. + let mut bytes = self.bytes.adjust_to_align(self.align); + let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; @@ -311,7 +359,7 @@ impl Allocation { } /// Raw accessors. Provide access to otherwise private bytes. -impl<Prov: Provenance, Extra> Allocation<Prov, Extra> { +impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> { pub fn len(&self) -> usize { self.bytes.len() } @@ -340,7 +388,11 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> { } /// Byte accessors. -impl<Prov: Provenance, Extra> Allocation<Prov, Extra> { +impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> { + pub fn base_addr(&self) -> *const u8 { + self.bytes.as_ptr() + } + /// This is the entirely abstraction-violating way to just grab the raw bytes without /// caring about provenance or initialization. /// @@ -412,7 +464,7 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> { } /// Reading and writing. -impl<Prov: Provenance, Extra> Allocation<Prov, Extra> { +impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> { /// Sets the init bit for the given range. fn mark_init(&mut self, range: AllocRange, is_init: bool) { if range.size.bytes() == 0 { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index b0975616b61..1766d7a6698 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -127,8 +127,8 @@ pub use self::error::{ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar}; pub use self::allocation::{ - alloc_range, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk, - InitChunkIter, + alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, + InitChunk, InitChunkIter, }; pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 16daf63b82d..d8829e3e782 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{ - alloc_range, read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc, - Pointer, Provenance, + alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue, + GlobalAlloc, Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -787,21 +787,21 @@ pub fn write_allocations<'tcx>( /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` /// This also prints provenance adequately. -pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra>( +pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( tcx: TyCtxt<'tcx>, - alloc: &'a Allocation<Prov, Extra>, -) -> RenderAllocation<'a, 'tcx, Prov, Extra> { + alloc: &'a Allocation<Prov, Extra, Bytes>, +) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> { RenderAllocation { tcx, alloc } } #[doc(hidden)] -pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra> { +pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> { tcx: TyCtxt<'tcx>, - alloc: &'a Allocation<Prov, Extra>, + alloc: &'a Allocation<Prov, Extra, Bytes>, } -impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display - for RenderAllocation<'a, 'tcx, Prov, Extra> +impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display + for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> { fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; @@ -845,9 +845,9 @@ fn write_allocation_newline( /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there /// is only one line). Note that your prefix should contain a trailing space as the lines are /// printed directly after it. -fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>( +fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( tcx: TyCtxt<'tcx>, - alloc: &Allocation<Prov, Extra>, + alloc: &Allocation<Prov, Extra, Bytes>, w: &mut dyn std::fmt::Write, prefix: &str, ) -> std::fmt::Result { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 2b3601bec7b..3b11fab8cdf 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -237,6 +237,9 @@ pub struct LocalVarId(pub hir::HirId); /// A THIR expression. #[derive(Clone, Debug, HashStable)] pub struct Expr<'tcx> { + /// kind of expression + pub kind: ExprKind<'tcx>, + /// The type of this expression pub ty: Ty<'tcx>, @@ -246,9 +249,6 @@ pub struct Expr<'tcx> { /// span of the expression in the source pub span: Span, - - /// kind of expression - pub kind: ExprKind<'tcx>, } #[derive(Clone, Debug, HashStable)] diff --git a/compiler/rustc_mir_build/locales/en-US.ftl b/compiler/rustc_mir_build/locales/en-US.ftl index f9bda721df3..93e7fb330e0 100644 --- a/compiler/rustc_mir_build/locales/en-US.ftl +++ b/compiler/rustc_mir_build/locales/en-US.ftl @@ -374,3 +374,9 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co } matched mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + + +mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly + .attributes = no other attributes may be applied + .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call + .missing_box = `#[rustc_box]` requires the `owned_box` lang item diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c1f6b8b59ce..dc4d2276e4a 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -888,3 +888,22 @@ pub enum MiscPatternSuggestion { start_span: Span, }, } + +#[derive(Diagnostic)] +#[diag(mir_build_rustc_box_attribute_error)] +pub struct RustcBoxAttributeError { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub reason: RustcBoxAttrReason, +} + +#[derive(Subdiagnostic)] +pub enum RustcBoxAttrReason { + #[note(mir_build_attributes)] + Attributes, + #[note(mir_build_not_box)] + NotBoxNew, + #[note(mir_build_missing_box)] + MissingBox, +} diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index d510a5fc76f..a937ec24741 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1,3 +1,4 @@ +use crate::errors; use crate::thir::cx::region::Scope; use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; @@ -18,7 +19,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{ self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType, }; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::abi::VariantIdx; impl<'tcx> Cx<'tcx> { @@ -262,6 +263,7 @@ impl<'tcx> Cx<'tcx> { } } + #[instrument(level = "debug", skip(self), ret)] fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let tcx = self.tcx; let expr_ty = self.typeck_results().expr_ty(expr); @@ -322,6 +324,34 @@ impl<'tcx> Cx<'tcx> { fn_span: expr.span, } } else { + let attrs = tcx.hir().attrs(expr.hir_id); + if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_box) { + if attrs.len() != 1 { + tcx.sess.emit_err(errors::RustcBoxAttributeError { + span: attrs[0].span, + reason: errors::RustcBoxAttrReason::Attributes, + }); + } else if let Some(box_item) = tcx.lang_items().owned_box() { + if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) = fun.kind + && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind + && path.res.opt_def_id().map_or(false, |did| did == box_item) + && fn_path.ident.name == sym::new + && let [value] = args + { + return Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: ExprKind::Box { value: self.mirror_expr(value) } } + } else { + tcx.sess.emit_err(errors::RustcBoxAttributeError { + span: expr.span, + reason: errors::RustcBoxAttrReason::NotBoxNew + }); + } + } else { + tcx.sess.emit_err(errors::RustcBoxAttributeError { + span: attrs[0].span, + reason: errors::RustcBoxAttrReason::MissingBox, + }); + } + } let adt_data = if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind { // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index efbbfe6c24b..0648784b265 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -53,9 +53,37 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { ) } } - hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), - ), + hir::ItemKind::Impl(ref impl_) => { + if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty { + // We collect RPITITs for each trait method's return type, on the impl side too and + // create a corresponding associated item using + // associated_items_for_impl_trait_in_trait query. + tcx.arena.alloc_from_iter( + impl_ + .items + .iter() + .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()) + .chain(impl_.of_trait.iter().flat_map(|_| { + impl_ + .items + .iter() + .filter(|impl_item_ref| { + matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. }) + }) + .flat_map(|impl_item_ref| { + let impl_fn_def_id = + impl_item_ref.id.owner_id.def_id.to_def_id(); + tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id) + }) + .map(|def_id| *def_id) + })), + ) + } else { + tcx.arena.alloc_from_iter( + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), + ) + } + } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } } @@ -290,8 +318,40 @@ fn impl_associated_item_for_impl_trait_in_trait( ) -> LocalDefId { let impl_def_id = tcx.local_parent(impl_fn_def_id); - let span = tcx.def_span(trait_assoc_def_id); + // FIXME fix the span, we probably want the def_id of the return type of the function + let span = tcx.def_span(impl_fn_def_id); let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy); - impl_assoc_ty.def_id() + let local_def_id = impl_assoc_ty.def_id(); + let def_id = local_def_id.to_def_id(); + + impl_assoc_ty.opt_def_kind(Some(DefKind::AssocTy)); + + // There's no HIR associated with this new synthesized `def_id`, so feed + // `opt_local_def_id_to_hir_id` with `None`. + impl_assoc_ty.opt_local_def_id_to_hir_id(None); + + // Add the def_id of the function that generated this synthesized associated type. + impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl { + fn_def_id: impl_fn_def_id.to_def_id(), + })); + + impl_assoc_ty.associated_item(ty::AssocItem { + name: kw::Empty, + kind: ty::AssocKind::Type, + def_id, + trait_item_def_id: Some(trait_assoc_def_id.to_def_id()), + container: ty::ImplContainer, + fn_has_self_parameter: false, + }); + + // Copy impl_defaultness of the containing function. + impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id)); + + // Copy generics_of the trait's associated item. + // FIXME: This is not correct, in particular the parent is going to be wrong. So we would need + // to copy from trait_assoc_def_id and adjust things. + impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone()); + + local_def_id } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 76daceecd7b..27f6659049c 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -144,6 +144,7 @@ mod c_char_definition { ) ), all(target_os = "fuchsia", target_arch = "aarch64"), + all(target_os = "nto", target_arch = "aarch64"), target_os = "horizon" ))] { pub type c_char = u8; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index bcfed726fdf..24bad799fc8 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -233,6 +233,7 @@ #![feature(simd_ffi)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(target_feature_11)] #![feature(trait_alias)] #![feature(transparent_unions)] #![feature(try_blocks)] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 00bcaf3e18c..040a59184a6 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -305,6 +305,50 @@ impl AtomicBool { AtomicBool { v: UnsafeCell::new(v as u8) } } + /// Creates a new `AtomicBool` from a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_ptr, pointer_is_aligned)] + /// use std::sync::atomic::{self, AtomicBool}; + /// use std::mem::align_of; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut bool = Box::into_raw(Box::new(false)); + /// + /// assert!(ptr.is_aligned_to(align_of::<AtomicBool>())); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicBool::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(true, atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, true); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`. + /// + /// [valid]: crate::ptr#safety + #[unstable(feature = "atomic_from_ptr", issue = "108652")] + #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")] + pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -1017,6 +1061,50 @@ impl<T> AtomicPtr<T> { AtomicPtr { p: UnsafeCell::new(p) } } + /// Creates a new `AtomicPtr` from a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_ptr, pointer_is_aligned)] + /// use std::sync::atomic::{self, AtomicPtr}; + /// use std::mem::align_of; + /// + /// // Get a pointer to an allocated value + /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut())); + /// + /// assert!(ptr.is_aligned_to(align_of::<AtomicPtr<u8>>())); + /// + /// { + /// // Create an atomic view of the allocated value + /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) }; + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert!(!unsafe { *ptr }.is_null()); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`). + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`. + /// + /// [valid]: crate::ptr#safety + #[unstable(feature = "atomic_from_ptr", issue = "108652")] + #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")] + pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + /// Returns a mutable reference to the underlying pointer. /// /// This is safe because the mutable reference guarantees that no other threads are @@ -1958,6 +2046,53 @@ macro_rules! atomic_int { Self {v: UnsafeCell::new(v)} } + /// Creates a new reference to an atomic integer from a pointer. + /// + /// # Examples + /// + /// ``` + /// #![feature(atomic_from_ptr, pointer_is_aligned)] + #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")] + /// use std::mem::align_of; + /// + /// // Get a pointer to an allocated value + #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")] + /// + #[doc = concat!("assert!(ptr.is_aligned_to(align_of::<", stringify!($atomic_type), ">()));")] + /// + /// { + /// // Create an atomic view of the allocated value + // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above) + #[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")] + /// + /// // Use `atomic` for atomic operations, possibly share it with other threads + /// atomic.store(1, atomic::Ordering::Relaxed); + /// } + /// + /// // It's ok to non-atomically access the value behind `ptr`, + /// // since the reference to the atomic ended its lifetime in the block above + /// assert_eq!(unsafe { *ptr }, 1); + /// + /// // Deallocate the value + /// unsafe { drop(Box::from_raw(ptr)) } + /// ``` + /// + /// # Safety + /// + /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`). + #[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")] + /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. + /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`. + /// + /// [valid]: crate::ptr#safety + #[unstable(feature = "atomic_from_ptr", issue = "108652")] + #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")] + pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { + // SAFETY: guaranteed by the caller + unsafe { &*ptr.cast() } + } + + /// Returns a mutable reference to the underlying integer. /// /// This is safe because the mutable reference guarantees that no other threads are diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 311b2e21c17..598a4bf9282 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.139", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.87" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/library/std/build.rs b/library/std/build.rs index 8b1a06ee750..ea879667558 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -31,6 +31,7 @@ fn main() { || target.contains("espidf") || target.contains("solid") || target.contains("nintendo-3ds") + || target.contains("nto") { // These platforms don't have any special requirements. } else { diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index 8c0adcfb0eb..e019bc0b67a 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -670,7 +670,10 @@ fn debug() { // FIXME: re-enabled openbsd tests once their socket timeout code // no longer has rounding errors. // VxWorks ignores SO_SNDTIMEO. -#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] +#[cfg_attr( + any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"), + ignore +)] #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 #[test] fn timeouts() { diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs index f82904ffbbf..892fe2ba8ba 100644 --- a/library/std/src/net/udp/tests.rs +++ b/library/std/src/net/udp/tests.rs @@ -180,7 +180,10 @@ fn debug() { // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code // no longer has rounding errors. // VxWorks ignores SO_SNDTIMEO. -#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] +#[cfg_attr( + any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"), + ignore +)] #[test] fn timeouts() { let addr = next_test_ip4(); diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index af137c9bd85..b148d8a0091 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -127,6 +127,8 @@ pub mod l4re; pub mod macos; #[cfg(target_os = "netbsd")] pub mod netbsd; +#[cfg(target_os = "nto")] +pub mod nto; #[cfg(target_os = "openbsd")] pub mod openbsd; #[cfg(target_os = "redox")] diff --git a/library/std/src/os/nto/fs.rs b/library/std/src/os/nto/fs.rs new file mode 100644 index 00000000000..8f915b08c9e --- /dev/null +++ b/library/std/src/os/nto/fs.rs @@ -0,0 +1,92 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atim.tv_sec as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atim.tv_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtim.tv_sec as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtim.tv_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctim.tv_sec as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctim.tv_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/nto/mod.rs b/library/std/src/os/nto/mod.rs new file mode 100644 index 00000000000..3e591dace92 --- /dev/null +++ b/library/std/src/os/nto/mod.rs @@ -0,0 +1,4 @@ +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub(super) mod raw; diff --git a/library/std/src/os/nto/raw.rs b/library/std/src/os/nto/raw.rs new file mode 100644 index 00000000000..90e9ad54643 --- /dev/null +++ b/library/std/src/os/nto/raw.rs @@ -0,0 +1,40 @@ +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] + +use crate::os::raw::c_int; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = u32; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = u32; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = c_int; + +#[doc(inline)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, time_t}; + +mod arch { + use crate::os::raw::c_long; + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = i64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = i32; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = u32; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = i64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = c_long; +} diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index f97fa0fb06f..eb2d7ce1174 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -65,6 +65,8 @@ mod platform { pub use crate::os::macos::*; #[cfg(target_os = "netbsd")] pub use crate::os::netbsd::*; + #[cfg(target_os = "nto")] + pub use crate::os::nto::*; #[cfg(target_os = "openbsd")] pub use crate::os::openbsd::*; #[cfg(target_os = "redox")] @@ -95,7 +97,8 @@ pub mod thread; target_os = "watchos", target_os = "macos", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", + target_os = "nto", ))] pub mod ucred; diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index f758f88d0a3..272b4f5dcd5 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -19,7 +19,8 @@ use crate::{fmt, io}; target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku" + target_os = "haiku", + target_os = "nto", ))] use libc::MSG_NOSIGNAL; #[cfg(not(any( @@ -29,7 +30,8 @@ use libc::MSG_NOSIGNAL; target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku" + target_os = "haiku", + target_os = "nto", )))] const MSG_NOSIGNAL: libc::c_int = 0x0; diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 37fcfa8446b..f8c29a6d3a1 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -167,6 +167,7 @@ fn long_path() { } #[test] +#[cfg(not(target_os = "nto"))] fn timeouts() { let dir = tmpdir(); let socket_path = dir.path().join("sock"); diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 09b2bfe39f0..729c63d184f 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -12,15 +12,23 @@ use crate::sealed::Sealed; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] -type UserId = u32; -#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] -type GroupId = u32; - -#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] -type UserId = u16; -#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] -type GroupId = u16; +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] { + type UserId = u16; + type GroupId = u16; + } else if #[cfg(target_os = "nto")] { + // 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 + type UserId = i32; + type GroupId = i32; + } else { + type UserId = u32; + type GroupId = u32; + } +} /// Unix-specific extensions to the [`process::Command`] builder. /// diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs index ae4faf27b4d..95967eac295 100644 --- a/library/std/src/os/unix/ucred.rs +++ b/library/std/src/os/unix/ucred.rs @@ -79,7 +79,8 @@ pub mod impl_linux { target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", - target_os = "netbsd" + target_os = "netbsd", + target_os = "nto", ))] pub mod impl_bsd { use super::UCred; diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index a5ce6d5120d..3d79058b320 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -69,7 +69,8 @@ impl DoubleEndedIterator for Args { target_os = "fuchsia", target_os = "redox", target_os = "vxworks", - target_os = "horizon" + target_os = "horizon", + target_os = "nto", ))] mod imp { use super::Args; diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index c9ba661c829..1a9276f1110 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -185,6 +185,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "nto")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "nto"; + 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 = "redox")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 66c33d58d6c..53523ca8c1d 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -53,7 +53,12 @@ const fn max_iov() -> usize { libc::IOV_MAX as usize } -#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))] +#[cfg(any( + target_os = "android", + target_os = "emscripten", + target_os = "linux", + target_os = "nto", +))] const fn max_iov() -> usize { libc::UIO_MAXIOV as usize } @@ -67,6 +72,7 @@ const fn max_iov() -> usize { target_os = "linux", target_os = "macos", target_os = "netbsd", + target_os = "nto", target_os = "openbsd", target_os = "horizon", target_os = "watchos", @@ -207,7 +213,8 @@ impl FileDesc { target_os = "linux", target_os = "haiku", target_os = "redox", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", )))] pub fn set_cloexec(&self) -> io::Result<()> { unsafe { @@ -225,7 +232,8 @@ impl FileDesc { target_os = "linux", target_os = "haiku", target_os = "redox", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", ))] pub fn set_cloexec(&self) -> io::Result<()> { unsafe { diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 8e1f35d6cc9..bdccb784674 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -13,7 +13,8 @@ use crate::mem; target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", ))] use crate::mem::MaybeUninit; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; @@ -54,7 +55,8 @@ use libc::fstatat64; target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", ))] use libc::readdir as readdir64; #[cfg(target_os = "linux")] @@ -69,7 +71,8 @@ use libc::readdir64_r; target_os = "illumos", target_os = "l4re", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", )))] use libc::readdir_r as readdir64_r; #[cfg(target_os = "android")] @@ -277,7 +280,8 @@ unsafe impl Sync for Dir {} target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", ))] pub struct DirEntry { dir: Arc<InnerReadDir>, @@ -297,11 +301,12 @@ pub struct DirEntry { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", ))] struct dirent64_min { d_ino: u64, - #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] + #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))] d_type: u8, } @@ -311,7 +316,8 @@ struct dirent64_min { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", )))] pub struct DirEntry { dir: Arc<InnerReadDir>, @@ -438,7 +444,7 @@ impl FileAttr { } } -#[cfg(not(target_os = "netbsd"))] +#[cfg(not(any(target_os = "netbsd", target_os = "nto")))] impl FileAttr { #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))] pub fn modified(&self) -> io::Result<SystemTime> { @@ -524,6 +530,21 @@ impl FileAttr { } } +#[cfg(target_os = "nto")] +impl FileAttr { + pub fn modified(&self) -> io::Result<SystemTime> { + Ok(SystemTime::new(self.stat.st_mtim.tv_sec, self.stat.st_mtim.tv_nsec)) + } + + pub fn accessed(&self) -> io::Result<SystemTime> { + Ok(SystemTime::new(self.stat.st_atim.tv_sec, self.stat.st_atim.tv_nsec)) + } + + pub fn created(&self) -> io::Result<SystemTime> { + Ok(SystemTime::new(self.stat.st_ctim.tv_sec, self.stat.st_ctim.tv_nsec)) + } +} + impl AsInner<stat64> for FileAttr { fn as_inner(&self) -> &stat64 { &self.stat @@ -603,7 +624,8 @@ impl Iterator for ReadDir { target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", ))] fn next(&mut self) -> Option<io::Result<DirEntry>> { if self.end_of_stream { @@ -686,7 +708,11 @@ impl Iterator for ReadDir { let entry = dirent64_min { d_ino: *offset_ptr!(entry_ptr, d_ino) as u64, - #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "nto", + )))] d_type: *offset_ptr!(entry_ptr, d_type) as u8, }; @@ -705,7 +731,8 @@ impl Iterator for ReadDir { target_os = "solaris", target_os = "fuchsia", target_os = "redox", - target_os = "illumos" + target_os = "illumos", + target_os = "nto", )))] fn next(&mut self) -> Option<io::Result<DirEntry>> { if self.end_of_stream { @@ -794,7 +821,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "haiku", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", ))] pub fn file_type(&self) -> io::Result<FileType> { self.metadata().map(|m| m.file_type()) @@ -804,7 +832,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "haiku", - target_os = "vxworks" + target_os = "vxworks", + target_os = "nto", )))] pub fn file_type(&self) -> io::Result<FileType> { match self.entry.d_type { @@ -834,7 +863,8 @@ impl DirEntry { target_os = "redox", target_os = "vxworks", target_os = "espidf", - target_os = "horizon" + target_os = "horizon", + target_os = "nto", ))] pub fn ino(&self) -> u64 { self.entry.d_ino as u64 @@ -887,7 +917,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", )))] fn name_cstr(&self) -> &CStr { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) } @@ -898,7 +929,8 @@ impl DirEntry { target_os = "solaris", target_os = "illumos", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_os = "nto", ))] fn name_cstr(&self) -> &CStr { &self.name @@ -1051,7 +1083,8 @@ impl File { target_os = "linux", target_os = "android", target_os = "netbsd", - target_os = "openbsd" + target_os = "openbsd", + target_os = "nto", ))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fdatasync(fd) @@ -1065,6 +1098,7 @@ impl File { target_os = "netbsd", target_os = "openbsd", target_os = "watchos", + target_os = "nto", )))] unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) @@ -1750,13 +1784,25 @@ pub fn chroot(dir: &Path) -> io::Result<()> { pub use remove_dir_impl::remove_dir_all; // Fallback for REDOX, ESP-ID, Horizon, and Miri -#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri))] +#[cfg(any( + target_os = "redox", + target_os = "espidf", + target_os = "horizon", + target_os = "nto", + miri +))] mod remove_dir_impl { pub use crate::sys_common::fs::remove_dir_all; } // Modern implementation using openat(), unlinkat() and fdopendir() -#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))] +#[cfg(not(any( + target_os = "redox", + target_os = "espidf", + target_os = "horizon", + target_os = "nto", + miri +)))] mod remove_dir_impl { use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir}; use crate::ffi::CStr; diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs index 6be1abc2b08..192fa216dfa 100644 --- a/library/std/src/sys/unix/locks/pthread_condvar.rs +++ b/library/std/src/sys/unix/locks/pthread_condvar.rs @@ -2,7 +2,10 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; use crate::sys::locks::{pthread_mutex, Mutex}; +#[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; +#[cfg(target_os = "nto")] +use crate::sys::time::TIMESPEC_MAX_CAPPED; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; @@ -132,10 +135,18 @@ impl Condvar { let mutex = pthread_mutex::raw(mutex); self.verify(mutex); + #[cfg(not(target_os = "nto"))] let timeout = Timespec::now(libc::CLOCK_MONOTONIC) .checked_add_duration(&dur) .and_then(|t| t.to_timespec()) .unwrap_or(TIMESPEC_MAX); + + #[cfg(target_os = "nto")] + let timeout = Timespec::now(libc::CLOCK_MONOTONIC) + .checked_add_duration(&dur) + .and_then(|t| t.to_timespec_capped()) + .unwrap_or(TIMESPEC_MAX_CAPPED); + let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout); assert!(r == libc::ETIMEDOUT || r == 0); r == 0 diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index c86f80972a6..8e05b618daa 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -78,6 +78,7 @@ impl Socket { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "nto", ))] { // On platforms that support it we pass the SOCK_CLOEXEC // flag to atomically create the socket and set it as @@ -115,6 +116,7 @@ impl Socket { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "nto", ))] { // 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/unix/os.rs b/library/std/src/sys/unix/os.rs index 2f2663db607..21b035fb373 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -62,6 +62,7 @@ extern "C" { link_name = "__errno" )] #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")] + #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")] #[cfg_attr( any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"), link_name = "__error" @@ -361,6 +362,17 @@ pub fn current_exe() -> io::Result<PathBuf> { } } +#[cfg(target_os = "nto")] +pub fn current_exe() -> io::Result<PathBuf> { + let mut e = crate::fs::read("/proc/self/exefile")?; + // Current versions of QNX Neutrino provide a null-terminated path. + // Ensure the trailing null byte is not returned here. + if let Some(0) = e.last() { + e.pop(); + } + Ok(PathBuf::from(OsString::from_vec(e))) +} + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] pub fn current_exe() -> io::Result<PathBuf> { unsafe { diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 3bc17b7754d..ceaff596684 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -18,6 +18,7 @@ use crate::sys::weak::raw_syscall; target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), + target_os = "nto", ))] use crate::sys::weak::weak; @@ -30,6 +31,15 @@ use libc::{c_int, pid_t}; #[cfg(not(any(target_os = "vxworks", target_os = "l4re")))] use libc::{gid_t, uid_t}; +cfg_if::cfg_if! { + if #[cfg(all(target_os = "nto", target_env = "nto71"))] { + use crate::thread; + use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; + // arbitrary number of tries: + const MAX_FORKSPAWN_TRIES: u32 = 4; + } +} + //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// @@ -140,11 +150,31 @@ 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(target_os = "linux"))] + #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))] unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> { cvt(libc::fork()).map(|res| (res, -1)) } + // On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened + // 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(all(target_os = "nto", target_env = "nto71"))] + unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> { + use crate::sys::os::errno; + + let mut tries_left = MAX_FORKSPAWN_TRIES; + loop { + let r = libc::fork(); + if r == -1 as libc::pid_t && tries_left > 0 && errno() as libc::c_int == libc::EBADF { + thread::yield_now(); + tries_left -= 1; + } else { + return cvt(r).map(|res| (res, -1)); + } + } + } + // Attempts to fork the process. If successful, returns Ok((0, -1)) // in the child, and Ok((child_pid, child_pidfd)) in the parent. #[cfg(target_os = "linux")] @@ -389,6 +419,7 @@ impl Command { target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), + target_os = "nto", )))] fn posix_spawn( &mut self, @@ -405,6 +436,7 @@ impl Command { target_os = "freebsd", all(target_os = "linux", target_env = "gnu"), all(target_os = "linux", target_env = "musl"), + target_os = "nto", ))] fn posix_spawn( &mut self, @@ -436,6 +468,34 @@ impl Command { } } + // On QNX Neutrino, posix_spawnp can fail with EBADF in case "another thread might have opened + // 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(all(target_os = "nto", target_env = "nto71"))] + unsafe fn retrying_libc_posix_spawnp( + pid: *mut pid_t, + file: *const c_char, + file_actions: *const posix_spawn_file_actions_t, + attrp: *const posix_spawnattr_t, + argv: *const *mut c_char, + envp: *const *mut c_char, + ) -> i32 { + let mut tries_left = MAX_FORKSPAWN_TRIES; + loop { + match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) { + libc::EBADF if tries_left > 0 => { + thread::yield_now(); + tries_left -= 1; + continue; + } + r => { + return r; + } + } + } + } + // Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory, // and maybe others will gain this non-POSIX function too. We'll check // for this weak symbol as soon as it's needed, so we can return early @@ -555,7 +615,12 @@ impl Command { // Make sure we synchronize access to the global `environ` resource let _env_lock = sys::os::env_read_lock(); let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _); - cvt_nz(libc::posix_spawnp( + + #[cfg(not(target_os = "nto"))] + let spawn_fn = libc::posix_spawnp; + #[cfg(target_os = "nto")] + let spawn_fn = retrying_libc_posix_spawnp; + cvt_nz(spawn_fn( &mut p.pid, self.get_program_cstr().as_ptr(), file_actions.0.as_ptr(), @@ -760,7 +825,7 @@ fn signal_string(signal: i32) -> &'static str { ) ))] libc::SIGSTKFLT => " (SIGSTKFLT)", - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "nto"))] libc::SIGPWR => " (SIGPWR)", #[cfg(any( target_os = "macos", @@ -769,7 +834,8 @@ fn signal_string(signal: i32) -> &'static str { target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", - target_os = "dragonfly" + target_os = "dragonfly", + target_os = "nto", ))] libc::SIGEMT => " (SIGEMT)", #[cfg(any( diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index cc0e5929569..15070b1f6a7 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -9,7 +9,7 @@ use crate::time::Duration; #[cfg(all(target_os = "linux", target_env = "gnu"))] use crate::sys::weak::dlsym; -#[cfg(any(target_os = "solaris", target_os = "illumos"))] +#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))] use crate::sys::weak::weak; #[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; @@ -173,7 +173,7 @@ impl Thread { } } - #[cfg(any(target_os = "solaris", target_os = "illumos"))] + #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))] pub fn set_name(name: &CStr) { weak! { fn pthread_setname_np( @@ -381,6 +381,17 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> { } Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) + } else if #[cfg(target_os = "nto")] { + unsafe { + use libc::_syspage_ptr; + if _syspage_ptr.is_null() { + Err(io::const_io_error!(io::ErrorKind::NotFound, "No syspage available")) + } else { + let cpus = (*_syspage_ptr).num_cpu; + NonZeroUsize::new(cpus as usize) + .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) + } + } } else if #[cfg(target_os = "haiku")] { // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus` // `get_system_info` calls then `smp_get_num_cpus` diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs index 082d25e68f5..43046ed07b8 100644 --- a/library/std/src/sys/unix/thread_parking/pthread.rs +++ b/library/std/src/sys/unix/thread_parking/pthread.rs @@ -6,7 +6,10 @@ use crate::pin::Pin; use crate::ptr::addr_of_mut; use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::SeqCst; +#[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; +#[cfg(target_os = "nto")] +use crate::sys::time::TIMESPEC_MAX_CAPPED; use crate::time::Duration; const EMPTY: usize = 0; @@ -80,8 +83,14 @@ unsafe fn wait_timeout( (Timespec::now(libc::CLOCK_MONOTONIC), dur) }; + #[cfg(not(target_os = "nto"))] let timeout = now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); + #[cfg(target_os = "nto")] + let timeout = now + .checked_add_duration(&dur) + .and_then(|t| t.to_timespec_capped()) + .unwrap_or(TIMESPEC_MAX_CAPPED); let r = libc::pthread_cond_timedwait(cond, lock, &timeout); debug_assert!(r == libc::ETIMEDOUT || r == 0); } diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 2daad981b73..0f11de8f5b8 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -9,6 +9,14 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() }; pub const TIMESPEC_MAX: libc::timespec = libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 }; +// This additional constant is only used when calling +// `libc::pthread_cond_timedwait`. +#[cfg(target_os = "nto")] +pub(super) 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, +}; + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(0)] @@ -144,6 +152,20 @@ impl Timespec { tv_nsec: self.tv_nsec.0.try_into().ok()?, }) } + + // On QNX Neutrino, the maximum timespec for e.g. pthread_cond_timedwait + // is 2^64 nanoseconds + #[cfg(target_os = "nto")] + pub(super) fn to_timespec_capped(&self) -> Option<libc::timespec> { + // Check if timeout in nanoseconds would fit into an u64 + if (self.tv_nsec.0 as u64) + .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?) + .is_none() + { + return None; + } + self.to_timespec() + } } impl From<libc::timespec> for Timespec { diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index f1d804ef40c..8752f46ff81 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -91,6 +91,19 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: if stop { return false; } + #[cfg(target_os = "nto")] + if libc::__my_thread_exit as *mut libc::c_void == frame.ip() { + if !hit && start { + use crate::backtrace_rs::SymbolName; + res = bt_fmt.frame().print_raw( + frame.ip(), + Some(SymbolName::new("__my_thread_exit".as_bytes())), + None, + None, + ); + } + return false; + } if !hit && start { res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); } diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 2c38dfecf97..85ecc1def3a 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -21,7 +21,7 @@ cfg_if::cfg_if! { target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "watchos", target_os = "openbsd", target_os = "netbsd", target_os = "illumos", - target_os = "solaris", target_os = "haiku", target_os = "l4re"))] { + target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; } else { @@ -35,7 +35,7 @@ cfg_if::cfg_if! { target_os = "linux", target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "haiku"))] { + target_os = "haiku", target_os = "nto"))] { use libc::MSG_NOSIGNAL; } else { const MSG_NOSIGNAL: c_int = 0x0; @@ -46,7 +46,8 @@ cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", - target_os = "solaris", target_os = "illumos"))] { + target_os = "solaris", target_os = "illumos", + target_os = "nto"))] { use crate::ffi::c_uchar; type IpV4MultiCastType = c_uchar; } else { diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs index 2672a2a75b0..89360e45601 100644 --- a/library/std/src/sys_common/thread_local_key.rs +++ b/library/std/src/sys_common/thread_local_key.rs @@ -117,9 +117,15 @@ pub struct Key { /// This value specifies no destructor by default. pub const INIT: StaticKey = StaticKey::new(None); -// Define a sentinel value that is unlikely to be returned -// as a TLS key (but it may be returned). +// Define a sentinel value that is likely not to be returned +// as a TLS key. +#[cfg(not(target_os = "nto"))] const KEY_SENTVAL: usize = 0; +// On QNX Neutrino, 0 is always returned when currently not in use. +// Using 0 would mean to always create two keys and remote the first +// one (with value of 0) immediately afterwards. +#[cfg(target_os = "nto")] +const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; impl StaticKey { #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 3753071d5f0..edc10aa39af 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -127,3 +127,7 @@ extern "C" {} #[cfg(target_os = "haiku")] #[link(name = "gcc_s")] extern "C" {} + +#[cfg(target_os = "nto")] +#[link(name = "gcc_s")] +extern "C" {} diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 681ecbfeb5b..5a105007f21 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -11,6 +11,11 @@ fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { + if crate::native::is_ci_llvm_modified(&parse("")) { + eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); + return; + } + let parse_llvm = |s| parse(s).llvm_from_ci; let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\""); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 04e798e3949..ab3d0829296 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -442,6 +442,8 @@ def to_toml(value): return value else: return "'" + value + "'" + elif isinstance(value, dict): + return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}" else: raise RuntimeError('no toml') diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 21157b02a78..5987b641b39 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -216,21 +216,24 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { } } - if CiEnv::is_ci() { + if is_ci_llvm_modified(config) { + eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); + return false; + } + + true +} + +/// Returns true if we're running in CI with modified LLVM (and thus can't download it) +pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool { + CiEnv::is_ci() && { // We assume we have access to git, so it's okay to unconditionally pass // `true` here. let llvm_sha = detect_llvm_sha(config, true); let head_sha = output(config.git().arg("rev-parse").arg("HEAD")); let head_sha = head_sha.trim(); - if llvm_sha == head_sha { - eprintln!( - "Detected LLVM as non-available: running in CI and modified LLVM in this change" - ); - return false; - } + llvm_sha == head_sha } - - true } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index c3d532c4b27..e7d1d9781d5 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -9,6 +9,7 @@ https://doc.rust-lang.org/stable/rustc/platform-support/fuchsia.html#aarch64-unk import argparse from dataclasses import dataclass +import fcntl import glob import hashlib import json @@ -146,6 +147,9 @@ class TestEnvironment: def zxdb_script_path(self): return os.path.join(self.tmp_dir(), "zxdb_script") + def pm_lockfile_path(self): + return os.path.join(self.tmp_dir(), "pm.lock") + def log_info(self, msg): print(msg) @@ -460,6 +464,9 @@ class TestEnvironment: stderr=self.subprocess_output(), ) + # Create lockfiles + open(self.pm_lockfile_path(), 'a').close() + # Write to file self.write_to_file() @@ -676,19 +683,25 @@ class TestEnvironment: log("Publishing package to repo...") # Publish package to repo - subprocess.check_call( - [ - self.tool_path("pm"), - "publish", - "-a", - "-repo", - self.repo_dir(), - "-f", - far_path, - ], - stdout=log_file, - stderr=log_file, - ) + with open(self.pm_lockfile_path(), 'w') as pm_lockfile: + fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_EX) + subprocess.check_call( + [ + self.tool_path("pm"), + "publish", + "-a", + "-repo", + self.repo_dir(), + "-f", + far_path, + ], + stdout=log_file, + stderr=log_file, + ) + # This lock should be released automatically when the pm + # lockfile is closed, but we'll be polite and unlock it now + # since the spec leaves some wiggle room. + fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_UN) log("Running ffx test...") diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index ad9c308ad85..11f1532bef5 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -78,7 +78,7 @@ x--expand-yaml-anchors--remove: <<: *base-job - &job-macos-xl - os: macos-latest # We don't have an XL builder for this + os: macos-12-xl <<: *base-job - &job-windows-xl diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index e653b7f1e10..9eafa27e2b7 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -218,7 +218,7 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | -[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS | +[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) @@ -310,7 +310,7 @@ target | std | host | notes `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator -[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS | +[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 56322d0da43..4d97b8c6cb9 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -716,7 +716,7 @@ run the full `tests/ui` test suite: --stage=2 \ test tests/ui \ --target x86_64-unknown-fuchsia \ - --run=always --jobs 1 \ + --run=always \ --test-args --target-rustcflags \ --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \ --test-args --target-rustcflags \ @@ -728,9 +728,6 @@ run the full `tests/ui` test suite: ) ``` -*Note: The test suite cannot be run in parallel at the moment, so `x.py` -must be run with `--jobs 1` to ensure only one test runs at a time.* - By default, `x.py` compiles test binaries with `panic=unwind`. If you built your Rust toolchain with `-Cpanic=abort`, you need to tell `x.py` to compile test binaries with `panic=abort` as well: @@ -907,7 +904,7 @@ through our `x.py` invocation. The full invocation is: --stage=2 \ test tests/${TEST} \ --target x86_64-unknown-fuchsia \ - --run=always --jobs 1 \ + --run=always \ --test-args --target-rustcflags \ --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \ --test-args --target-rustcflags \ diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 37d0c31976c..38198fe6c3a 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -2,9 +2,9 @@ **Tier: 3** -[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system. +[QNX®][BlackBerry] Neutrino (nto) Real-time operating system. The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit] -and [BlackBerry][BlackBerry]. +and [Blackberry QNX][BlackBerry]. [BlackBerry]: https://blackberry.qnx.com [Elektrobit]: https://www.elektrobit.com @@ -19,19 +19,24 @@ and [BlackBerry][BlackBerry]. Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian). Adding other architectures that are supported by QNX Neutrino is possible. -The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can -be compiled. +The standard library, including `core` and `alloc` (with default allocator) are supported. -`core` and `alloc` (with default allocator) are supported. +For building or using the Rust toolchain for QNX Neutrino, 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. -Applications must link against `libc.so` (see example). This is required because applications -always link against the `crt` library and `crt` depends on `libc.so`. - -The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the -QNX Neutrino toolchain). +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. ### 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] @@ -89,30 +94,150 @@ changelog-seen = 2 2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets) -Run the following: +Compiling the Rust toolchain requires the same environment variables used for compiling C binaries. +Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html). + +To compile for QNX Neutrino (aarch64 and x86_64) and Linux (x86_64): ```bash -env \ - CC_aarch64-unknown-nto-qnx710="qcc" \ - CFLAGS_aarch64-unknown-nto-qnx710="-Vgcc_ntoaarch64le_cxx" \ - CXX_aarch64-unknown-nto-qnx710="qcc" \ - AR_aarch64_unknown_nto_qnx710="ntoaarch64-ar" \ - CC_x86_64-pc-nto-qnx710="qcc" \ - CFLAGS_x86_64-pc-nto-qnx710="-Vgcc_ntox86_64_cxx" \ - CXX_x86_64-pc-nto-qnx710="qcc" \ - AR_x86_64_pc_nto_qnx710="ntox86_64-ar" \ - ./x.py build --target aarch64-unknown-nto-qnx710 --target x86_64-pc-nto-qnx710 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/ +export build_env=' + CC_aarch64-unknown-nto-qnx710=qcc + CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx + CXX_aarch64-unknown-nto-qnx710=qcc + AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar + CC_x86_64-pc-nto-qnx710=qcc + CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx + CXX_x86_64-pc-nto-qnx710=qcc + AR_x86_64_pc_nto_qnx710=ntox86_64-ar' + +env $build_env \ + ./x.py build \ + --target aarch64-unknown-nto-qnx710 \ + --target x86_64-pc-nto-qnx710 \ + --target x86_64-unknown-linux-gnu \ + rustc library/core library/alloc ``` +## 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. + +To run all tests on a x86_64 QNX Neutrino target: + +```bash +export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel +export build_env=' + CC_aarch64-unknown-nto-qnx710=qcc + CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx + CXX_aarch64-unknown-nto-qnx710=qcc + AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar + CC_x86_64-pc-nto-qnx710=qcc + CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx + CXX_x86_64-pc-nto-qnx710=qcc + AR_x86_64_pc_nto_qnx710=ntox86_64-ar' + +# Disable tests that only work on the host or don't make sense for this target. +# See also: +# - src/ci/docker/host-x86_64/i686-gnu/Dockerfile +# - https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Running.20tests.20on.20remote.20target +# - .github/workflows/ci.yml +export exclude_tests=' + --exclude src/bootstrap + --exclude src/tools/error_index_generator + --exclude src/tools/linkchecker + --exclude tests/ui-fulldeps + --exclude rustc + --exclude rustdoc + --exclude tests/run-make-fulldeps' + +env $build_env \ + ./x.py test -j 1 \ + $exclude_tests \ + --stage 1 \ + --target x86_64-pc-nto-qnx710 +``` + +Currently, only one thread can be used when testing due to limitations in `libc::fork` and `libc::posix_spawnp`. +See [fork documentation](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html) +(error section) for more information. +This can be achieved by using the `-j 1` parameter in the `x.py` call. +This issue is being researched and we will try to allow parallelism in the future. + ## 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. +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 directly be run on QNX Neutrino. +Compiled executables can run directly on QNX Neutrino. + +### Rust std library test suite + +The target needs sufficient resources to execute all tests. The commands below assume that a QEMU image +is used. + +* Ensure that the temporary directory used by `remote-test-server` has enough free space and inodes. + 5GB of free space and 40000 inodes are known to be sufficient (the test will create more than 32k files). + To create a QEMU image in an empty directory, run this command inside the directory: + + ```bash + mkqnximage --type=qemu --ssh-ident=$HOME/.ssh/id_ed25519.pub --data-size=5000 --data-inodes=40000 + ``` + + `/data` should have enough free resources. + Set the `TMPDIR` environment variable accordingly when running `remote-test-server`, e.g.: + ```bash + TMPDIR=/data/tmp/rust remote-test-server --bind 0.0.0.0:12345 + ``` + +* Ensure the TCP stack can handle enough parallel connections (default is 200, should be 300 or higher). + After creating an image (see above), edit the file `output/build/startup.sh`: + 1. Search for `io-pkt-v6-hc` + 2. Add the parameter `-ptcpip threads_max=300`, e.g.: + ```text + io-pkt-v6-hc -U 33:33 -d e1000 -ptcpip threads_max=300 + ``` + 3. Update the image by running `mkqnximage` again with the same parameters as above for creating it. + +* Running and stopping the virtual machine + + To start the virtual machine, run inside the directory of the VM: + + ```bash + mkqnximage --run=-h + ``` + + To stop the virtual machine, run inside the directory of the VM: + + ```bash + mkqnximage --stop + ``` + +* Ensure local networking + + Ensure that 'localhost' is getting resolved to 127.0.0.1. If you can't ping the localhost, some tests may fail. + Ensure it's appended to /etc/hosts (if first `ping` command fails). + Commands have to be executed inside the virtual machine! + + ```bash + $ ping localhost + ping: Cannot resolve "localhost" (Host name lookup failure) + + $ echo "127.0.0.1 localhost" >> /etc/hosts + + $ ping localhost + PING localhost (127.0.0.1): 56 data bytes + 64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms + ``` ## Cross-compilation toolchains and C code -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. +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. diff --git a/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md new file mode 100644 index 00000000000..c7f10afaccc --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md @@ -0,0 +1,43 @@ +# `export-executable-symbols` + +The tracking issue for this feature is: [#84161](https://github.com/rust-lang/rust/issues/84161). + +------------------------ + +The `-Zexport-executable-symbols` compiler flag makes `rustc` export symbols from executables. The resulting binary is runnable, but can also be used as a dynamic library. This is useful for interoperating with programs written in other languages, in particular languages with a runtime like Java or Lua. + +For example on windows: +```rust +#[no_mangle] +fn my_function() -> usize { + return 42; +} + +fn main() { + println!("Hello, world!"); +} +``` + +A standard `cargo build` will produce a `.exe` without an export directory. When the `export-executable-symbols` flag is added + +```Bash +export RUSTFLAGS="-Zexport-executable-symbols" +cargo build +``` + +the binary has an export directory with the functions: + +```plain +The Export Tables (interpreted .edata section contents) + +... + +[Ordinal/Name Pointer] Table + [ 0] my_function + [ 1] main +``` +(the output of `objdump -x` on the binary) + +Please note that the `#[no_mangle]` attribute is required. Without it, the symbol is not exported. + +The equivalent of this flag in C and C++ compilers is the `__declspec(dllexport)` annotation or the `-rdynamic` linker flag. diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index fcd925bb358..1a34530c2d1 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -90,7 +90,6 @@ module.exports = { "no-return-assign": "error", "no-script-url": "error", "no-sequences": "error", - "no-throw-literal": "error", "no-div-regex": "error", } }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d18b56eb19c..95528e70e35 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1260,6 +1260,11 @@ a.tooltip:hover::after { color: var(--search-tab-title-count-color); } +#search .error code { + border-radius: 3px; + background-color: var(--search-error-code-background-color); +} + #src-sidebar-toggle { position: sticky; top: 0; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 472a725f053..90cf689ad33 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -43,6 +43,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --search-result-link-focus-background-color: #3c3c3c; --search-result-border-color: #aaa3; --search-color: #fff; + --search-error-code-background-color: #4f4c4c; --search-results-alias-color: #c5c5c5; --search-results-grey-color: #999; --search-tab-title-count-color: #888; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 5612bde96a8..e8cd0693139 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -38,6 +38,7 @@ --search-result-link-focus-background-color: #616161; --search-result-border-color: #aaa3; --search-color: #111; + --search-error-code-background-color: #484848; --search-results-alias-color: #fff; --search-results-grey-color: #ccc; --search-tab-title-count-color: #888; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 34b35c405a8..5e3f14e483f 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -38,6 +38,7 @@ --search-result-link-focus-background-color: #ccc; --search-result-border-color: #aaa3; --search-color: #000; + --search-error-code-background-color: #d0cccc; --search-results-alias-color: #000; --search-results-grey-color: #999; --search-tab-title-count-color: #888; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 6501d32531f..5a46729156d 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -144,7 +144,7 @@ function initSearch(rawSearchIndex) { function itemTypeFromName(typename) { const index = itemTypes.findIndex(i => i === typename); if (index < 0) { - throw new Error("Unknown type filter `" + typename + "`"); + throw ["Unknown type filter ", typename]; } return index; } @@ -164,21 +164,21 @@ function initSearch(rawSearchIndex) { */ function getStringElem(query, parserState, isInGenerics) { if (isInGenerics) { - throw new Error("`\"` cannot be used in generics"); + throw ["Unexpected ", "\"", " in generics"]; } else if (query.literalSearch) { - throw new Error("Cannot have more than one literal search element"); + throw ["Cannot have more than one literal search element"]; } else if (parserState.totalElems - parserState.genericsElems > 0) { - throw new Error("Cannot use literal search when there is more than one element"); + throw ["Cannot use literal search when there is more than one element"]; } parserState.pos += 1; const start = parserState.pos; const end = getIdentEndPosition(parserState); if (parserState.pos >= parserState.length) { - throw new Error("Unclosed `\"`"); + throw ["Unclosed ", "\""]; } else if (parserState.userQuery[end] !== "\"") { - throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`); + throw ["Unexpected ", parserState.userQuery[end], " in a string element"]; } else if (start === end) { - throw new Error("Cannot have empty string element"); + throw ["Cannot have empty string element"]; } // To skip the quote at the end. parserState.pos += 1; @@ -257,7 +257,7 @@ function initSearch(rawSearchIndex) { return; } if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { - throw new Error("You cannot have more than one element if you use quotes"); + throw ["You cannot have more than one element if you use quotes"]; } const pathSegments = name.split("::"); if (pathSegments.length > 1) { @@ -266,17 +266,17 @@ function initSearch(rawSearchIndex) { if (pathSegment.length === 0) { if (i === 0) { - throw new Error("Paths cannot start with `::`"); + throw ["Paths cannot start with ", "::"]; } else if (i + 1 === len) { - throw new Error("Paths cannot end with `::`"); + throw ["Paths cannot end with ", "::"]; } - throw new Error("Unexpected `::::`"); + throw ["Unexpected ", "::::"]; } } } // In case we only have something like `<p>`, there is no name. if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) { - throw new Error("Found generics without a path"); + throw ["Found generics without a path"]; } parserState.totalElems += 1; if (isInGenerics) { @@ -308,15 +308,15 @@ function initSearch(rawSearchIndex) { if (!isIdentCharacter(c)) { if (c === "!") { if (foundExclamation !== -1) { - throw new Error("Cannot have more than one `!` in an ident"); + throw ["Cannot have more than one ", "!", " in an ident"]; } else if (parserState.pos + 1 < parserState.length && isIdentCharacter(parserState.userQuery[parserState.pos + 1]) ) { - throw new Error("`!` can only be at the end of an ident"); + throw ["Unexpected ", "!", ": it can only be at the end of an ident"]; } foundExclamation = parserState.pos; } else if (isErrorCharacter(c)) { - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } else if ( isStopCharacter(c) || isSpecialStartCharacter(c) || @@ -329,7 +329,7 @@ function initSearch(rawSearchIndex) { } if (foundExclamation !== -1) { if (start <= (end - 2)) { - throw new Error("Cannot have associated items in macros"); + throw ["Cannot have associated items in macros"]; } else { // if start == end - 1, we got the never type // while the never type has no associated macros, we still @@ -340,7 +340,7 @@ function initSearch(rawSearchIndex) { // Skip current ":". parserState.pos += 1; } else { - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } } parserState.pos += 1; @@ -351,8 +351,13 @@ function initSearch(rawSearchIndex) { if (parserState.typeFilter === null) { parserState.typeFilter = "macro"; } else if (parserState.typeFilter !== "macro") { - throw new Error("Invalid search type: macro `!` and " + - `\`${parserState.typeFilter}\` both specified`); + throw [ + "Invalid search type: macro ", + "!", + " and ", + parserState.typeFilter, + " both specified", + ]; } end = foundExclamation; } @@ -382,9 +387,9 @@ function initSearch(rawSearchIndex) { parserState.userQuery[parserState.pos] === "<" ) { if (isInGenerics) { - throw new Error("Unexpected `<` after `<`"); + throw ["Unexpected ", "<", " after ", "<"]; } else if (start >= end) { - throw new Error("Found generics without a path"); + throw ["Found generics without a path"]; } parserState.pos += 1; getItemsBefore(query, parserState, generics, ">"); @@ -428,21 +433,39 @@ function initSearch(rawSearchIndex) { foundStopChar = true; continue; } else if (c === ":" && isPathStart(parserState)) { - throw new Error("Unexpected `::`: paths cannot start with `::`"); + throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; } else if (c === ":" || isEndCharacter(c)) { let extra = ""; if (endChar === ">") { - extra = "`<`"; + extra = "<"; } else if (endChar === "") { - extra = "`->`"; + extra = "->"; + } else { + extra = endChar; } - throw new Error("Unexpected `" + c + "` after " + extra); + throw ["Unexpected ", c, " after ", extra]; } if (!foundStopChar) { if (endChar !== "") { - throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + " or ", + endChar, + ", found ", + c, + ]; } - throw new Error(`Expected \`,\` or \` \`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + " or ", + " ", // whitespace + ", found ", + c, + ]; } const posBefore = parserState.pos; getNextElem(query, parserState, elems, endChar === ">"); @@ -470,7 +493,7 @@ function initSearch(rawSearchIndex) { for (let pos = 0; pos < parserState.pos; ++pos) { if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) { - throw new Error(`Unexpected \`${query[pos]}\` in type filter`); + throw ["Unexpected ", query[pos], " in type filter"]; } } } @@ -496,19 +519,19 @@ function initSearch(rawSearchIndex) { if (isReturnArrow(parserState)) { break; } - throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`); + throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; } - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } else if (c === ":" && !isPathStart(parserState)) { if (parserState.typeFilter !== null) { - throw new Error("Unexpected `:`"); + throw ["Unexpected ", ":"]; } if (query.elems.length === 0) { - throw new Error("Expected type filter before `:`"); + throw ["Expected type filter before ", ":"]; } else if (query.elems.length !== 1 || parserState.totalElems !== 1) { - throw new Error("Unexpected `:`"); + throw ["Unexpected ", ":"]; } else if (query.literalSearch) { - throw new Error("You cannot use quotes on type filter"); + throw ["You cannot use quotes on type filter"]; } checkExtraTypeFilterCharacters(parserState); // The type filter doesn't count as an element since it's a modifier. @@ -521,9 +544,29 @@ function initSearch(rawSearchIndex) { } if (!foundStopChar) { if (parserState.typeFilter !== null) { - throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + " or ", + "->", // arrow + ", found ", + c, + ]; } - throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + ", ", + ":", // colon + " or ", + "->", // arrow + ", found ", + c, + ]; } const before = query.elems.length; getNextElem(query, parserState, query.elems, false); @@ -540,7 +583,7 @@ function initSearch(rawSearchIndex) { getItemsBefore(query, parserState, query.returned, ""); // Nothing can come afterward! if (query.returned.length === 0) { - throw new Error("Expected at least one item after `->`"); + throw ["Expected at least one item after ", "->"]; } break; } else { @@ -694,7 +737,7 @@ function initSearch(rawSearchIndex) { } } catch (err) { query = newParsedQuery(userQuery); - query.error = err.message; + query.error = err; query.typeFilter = -1; return query; } @@ -1760,7 +1803,16 @@ function initSearch(rawSearchIndex) { let output = `<h1 class="search-results-title">Results${crates}</h1>`; if (results.query.error !== null) { - output += `<h3>Query parser error: "${results.query.error}".</h3>`; + const error = results.query.error; + error.forEach((value, index) => { + value = value.split("<").join("<").split(">").join(">"); + if (index % 2 !== 0) { + error[index] = `<code>${value}</code>`; + } else { + error[index] = value; + } + }); + output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`; output += "<div id=\"search-tabs\">" + makeTabHeader(0, "In Names", ret_others[1]) + "</div>"; diff --git a/src/llvm-project b/src/llvm-project -Subproject 477e7285b12f876ad105188cfcfc8adda7dc29a +Subproject fd949f3034f8a422ecfffa889c2823485dde4bd diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 4604ae5c2c7..50bef370930 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -287,15 +287,12 @@ impl<'a> VecArgs<'a> { Some(VecArgs::Repeat(&args[0], &args[1])) } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { // `vec![a, b, c]` case - if_chain! { - if let hir::ExprKind::Box(boxed) = args[0].kind; - if let hir::ExprKind::Array(args) = boxed.kind; - then { - return Some(VecArgs::Vec(args)); - } + if let hir::ExprKind::Call(_, [arg]) = &args[0].kind + && let hir::ExprKind::Array(args) = arg.kind { + Some(VecArgs::Vec(args)) + } else { + None } - - None } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() { Some(VecArgs::Vec(&[])) } else { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7824ef81d7a..41c23ff86b2 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1432,12 +1432,13 @@ impl<'test> TestCx<'test> { expect_help: bool, expect_note: bool, ) -> bool { - match actual_error.kind { - Some(ErrorKind::Help) => expect_help, - Some(ErrorKind::Note) => expect_note, - Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, - Some(ErrorKind::Suggestion) | None => false, - } + !actual_error.msg.is_empty() + && match actual_error.kind { + Some(ErrorKind::Help) => expect_help, + Some(ErrorKind::Note) => expect_note, + Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, + Some(ErrorKind::Suggestion) | None => false, + } } fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8bbf9f87b43..969c81f7e32 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -777,10 +777,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { type Provenance = Provenance; type ProvenanceExtra = ProvenanceExtra; + type Bytes = Box<[u8]>; type MemoryMap = MonoHashMap< AllocId, - (MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra>), + (MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra, Self::Bytes>), >; const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 3da4fed33e1..ea5780f66d7 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) { error_text.push('==> Unknown key "' + key + '"'); break; } + let result_v = result[key]; + if (result_v !== null && key === "error") { + result_v.forEach((value, index) => { + value = value.split(" ").join(" "); + if (index % 2 === 1) { + result_v[index] = "`" + value + "`"; + } else { + result_v[index] = value; + } + }); + result_v = result_v.join(""); + } const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key; - valueCheck(obj_path, expected[key], result[key], error_text, queryName); + valueCheck(obj_path, expected[key], result_v, error_text, queryName); } } else { expectedValue = JSON.stringify(expected); diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs index 0f1b29ca79b..aa7fab7fb17 100644 --- a/tests/codegen/thread-local.rs +++ b/tests/codegen/thread-local.rs @@ -4,6 +4,7 @@ // ignore-wasm globals are used instead of thread locals // ignore-emscripten globals are used instead of thread locals // ignore-android does not use #[thread_local] +// ignore-nto does not use #[thread_local] #![crate_type = "lib"] diff --git a/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff b/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff index c7978ac328f..e30a5e116ea 100644 --- a/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff +++ b/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff @@ -4,14 +4,14 @@ fn inlined_no_sanitize() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:37: +0:37 let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 -+ scope 1 (inlined no_sanitize) { // at $DIR/inline_compatibility.rs:23:5: 23:18 ++ scope 1 (inlined no_sanitize) { // at $DIR/inline_compatibility.rs:24:5: 24:18 + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 - _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 - // mir::Constant -- // + span: $DIR/inline_compatibility.rs:23:5: 23:16 +- // + span: $DIR/inline_compatibility.rs:24:5: 24:16 - // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(<ZST>) } - } - diff --git a/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff b/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff index 2fe277ae37b..c2b3c46a30c 100644 --- a/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff +++ b/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff @@ -4,14 +4,14 @@ fn inlined_target_feature() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:40: +0:40 let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 -+ scope 1 (inlined target_feature) { // at $DIR/inline_compatibility.rs:12:5: 12:21 ++ scope 1 (inlined target_feature) { // at $DIR/inline_compatibility.rs:13:5: 13:21 + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 - _1 = target_feature() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 - // mir::Constant -- // + span: $DIR/inline_compatibility.rs:12:5: 12:19 +- // + span: $DIR/inline_compatibility.rs:13:5: 13:19 - // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(<ZST>) } - } - diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff index 9803ca0f8a4..0ca5a5f70b7 100644 --- a/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff @@ -12,7 +12,7 @@ StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:9: +1:10 _1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:13: +1:52 // mir::Constant - // + span: $DIR/inline_compatibility.rs:41:13: 41:16 + // + span: $DIR/inline_compatibility.rs:42:13: 42:16 // + literal: Const { ty: unsafe extern "C" fn(u32, ...) -> u32 {sum}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff index 356ab4b51c2..00d405c77f9 100644 --- a/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff @@ -9,7 +9,7 @@ StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 // mir::Constant - // + span: $DIR/inline_compatibility.rs:28:5: 28:16 + // + span: $DIR/inline_compatibility.rs:29:5: 29:16 // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff index f0fee4ca98a..8b9c86f5515 100644 --- a/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff @@ -9,7 +9,7 @@ StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 _1 = target_feature() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 // mir::Constant - // + span: $DIR/inline_compatibility.rs:17:5: 17:19 + // + span: $DIR/inline_compatibility.rs:18:5: 18:19 // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/inline_compatibility.rs b/tests/mir-opt/inline/inline_compatibility.rs index ec6ce3d0258..30aff0a64ef 100644 --- a/tests/mir-opt/inline/inline_compatibility.rs +++ b/tests/mir-opt/inline/inline_compatibility.rs @@ -4,6 +4,7 @@ #![crate_type = "lib"] #![feature(no_sanitize)] +#![feature(target_feature_11)] #![feature(c_variadic)] // EMIT_MIR inline_compatibility.inlined_target_feature.Inline.diff diff --git a/tests/rustdoc-gui/search-error.goml b/tests/rustdoc-gui/search-error.goml new file mode 100644 index 00000000000..2a10a647b53 --- /dev/null +++ b/tests/rustdoc-gui/search-error.goml @@ -0,0 +1,39 @@ +// Checks that the crate search filtering is handled correctly and changes the results. +goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds" +show-text: true + +define-function: ( + "check-colors", + (theme, error_background), + block { + // Setting the theme. + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + // We reload the page so the local storage settings are being used. + reload: + + wait-for: "#search .error code" + assert-css: ("#search .error code", {"background-color": |error_background|}) + } +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "error_background": "rgb(79, 76, 76)", + }, +) +call-function: ( + "check-colors", + { + "theme": "dark", + "error_background": "rgb(72, 72, 72)", + }, +) +call-function: ( + "check-colors", + { + "theme": "light", + "error_background": "rgb(208, 204, 204)", + }, +) diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index f82a2472063..6c5a7770283 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -67,7 +67,7 @@ const PARSED = [ returned: [], typeFilter: -1, userQuery: "a<\"p\">", - error: "`\"` cannot be used in generics", + error: "Unexpected `\"` in generics", }, { elems: [], @@ -373,7 +373,7 @@ const PARSED = [ returned: [], typeFilter: -1, userQuery: "a!a", - error: '`!` can only be at the end of an ident', + error: 'Unexpected `!`: it can only be at the end of an ident', }, { elems: [], diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs index 6d934538f4c..a455eef42ea 100644 --- a/tests/ui/abi/stack-probes-lto.rs +++ b/tests/ui/abi/stack-probes-lto.rs @@ -13,5 +13,6 @@ // ignore-fuchsia no exception handler registered for segfault // compile-flags: -C lto // no-prefer-dynamic +// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino include!("stack-probes.rs"); diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs index e7b91644b3b..8dba54c3f81 100644 --- a/tests/ui/abi/stack-probes.rs +++ b/tests/ui/abi/stack-probes.rs @@ -9,6 +9,7 @@ // ignore-emscripten no processes // ignore-sgx no processes // ignore-fuchsia no exception handler registered for segfault +// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino use std::env; use std::mem::MaybeUninit; diff --git a/tests/ui/asm/x86_64/issue-89875.rs b/tests/ui/asm/x86_64/issue-89875.rs index e793690ddbe..669fd7e7e46 100644 --- a/tests/ui/asm/x86_64/issue-89875.rs +++ b/tests/ui/asm/x86_64/issue-89875.rs @@ -2,6 +2,8 @@ // needs-asm-support // only-x86_64 +#![feature(target_feature_11)] + use std::arch::asm; #[target_feature(enable = "avx")] diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr index ae4d0d5853c..5ae1d78a92b 100644 --- a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr +++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -17,8 +17,9 @@ error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not a --> $DIR/ret-impl-trait-one.rs:16:80 | LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { - | ____________________________________--__________________________________________^ - | | | + | ____________________________________--___________________________--------------_^ + | | | | + | | | opaque type defined here | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here LL | | LL | | (a, b) diff --git a/tests/ui/attributes/rustc-box.rs b/tests/ui/attributes/rustc-box.rs new file mode 100644 index 00000000000..b3726fb3867 --- /dev/null +++ b/tests/ui/attributes/rustc-box.rs @@ -0,0 +1,18 @@ +#![feature(rustc_attrs, stmt_expr_attributes)] + +fn foo(_: u32, _: u32) {} +fn bar(_: u32) {} + +fn main() { + #[rustc_box] + Box::new(1); // OK + #[rustc_box] + Box::pin(1); //~ ERROR `#[rustc_box]` attribute used incorrectly + #[rustc_box] + foo(1, 1); //~ ERROR `#[rustc_box]` attribute used incorrectly + #[rustc_box] + bar(1); //~ ERROR `#[rustc_box]` attribute used incorrectly + #[rustc_box] //~ ERROR `#[rustc_box]` attribute used incorrectly + #[rustfmt::skip] + Box::new(1); +} diff --git a/tests/ui/attributes/rustc-box.stderr b/tests/ui/attributes/rustc-box.stderr new file mode 100644 index 00000000000..073a18c7d58 --- /dev/null +++ b/tests/ui/attributes/rustc-box.stderr @@ -0,0 +1,34 @@ +error: `#[rustc_box]` attribute used incorrectly + --> $DIR/rustc-box.rs:10:5 + | +LL | Box::pin(1); + | ^^^^^^^^^^^ + | + = note: `#[rustc_box]` may only be applied to a `Box::new()` call + +error: `#[rustc_box]` attribute used incorrectly + --> $DIR/rustc-box.rs:12:5 + | +LL | foo(1, 1); + | ^^^^^^^^^ + | + = note: `#[rustc_box]` may only be applied to a `Box::new()` call + +error: `#[rustc_box]` attribute used incorrectly + --> $DIR/rustc-box.rs:14:5 + | +LL | bar(1); + | ^^^^^^ + | + = note: `#[rustc_box]` may only be applied to a `Box::new()` call + +error: `#[rustc_box]` attribute used incorrectly + --> $DIR/rustc-box.rs:15:5 + | +LL | #[rustc_box] + | ^^^^^^^^^^^^ + | + = note: no other attributes may be applied + +error: aborting due to 4 previous errors + diff --git a/tests/ui/command/command-setgroups.rs b/tests/ui/command/command-setgroups.rs index aff67f91bba..7e321f2f0cd 100644 --- a/tests/ui/command/command-setgroups.rs +++ b/tests/ui/command/command-setgroups.rs @@ -3,6 +3,7 @@ // ignore-emscripten // ignore-sgx // ignore-musl - returns dummy result for _SC_NGROUPS_MAX +// ignore-nto - does not have `/bin/id`, expects groups to be i32 (not u32) #![feature(rustc_private)] #![feature(setgroups)] diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs index 5134c672f5f..0fbd851431e 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs @@ -18,11 +18,85 @@ struct Burrito<F> { filling: F, } +impl<It: Iterator> T1 for Option<It> {} + +impl<'a, A: T1> T1 for &'a A {} + fn want<V: T1>(_x: V) {} +enum ExampleTuple<T> { + ExampleTupleVariant(T), +} +use ExampleDifferentTupleVariantName as ExampleYetAnotherTupleVariantName; +use ExampleTuple as ExampleOtherTuple; +use ExampleTuple::ExampleTupleVariant as ExampleDifferentTupleVariantName; +use ExampleTuple::*; + +impl<A> T1 for ExampleTuple<A> where A: T3 {} + +enum ExampleStruct<T> { + ExampleStructVariant { field: T }, +} +use ExampleDifferentStructVariantName as ExampleYetAnotherStructVariantName; +use ExampleStruct as ExampleOtherStruct; +use ExampleStruct::ExampleStructVariant as ExampleDifferentStructVariantName; +use ExampleStruct::*; + +impl<A> T1 for ExampleStruct<A> where A: T3 {} + +struct ExampleActuallyTupleStruct<T>(T, i32); +use ExampleActuallyTupleStruct as ExampleActuallyTupleStructOther; + +impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {} + fn example<Q>(q: Q) { want(Wrapper { value: Burrito { filling: q } }); //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + want(Some(())); + //~^ ERROR `()` is not an iterator [E0277] + + want(Some(q)); + //~^ ERROR `Q` is not an iterator [E0277] + + want(&Some(q)); + //~^ ERROR `Q` is not an iterator [E0277] + + want(&ExampleTuple::ExampleTupleVariant(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleTupleVariant(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleOtherTuple::ExampleTupleVariant(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleDifferentTupleVariantName(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleYetAnotherTupleVariantName(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleStruct::ExampleStructVariant { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleStructVariant { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleOtherStruct::ExampleStructVariant { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleDifferentStructVariantName { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleYetAnotherStructVariantName { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleActuallyTupleStruct(q, 0)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleActuallyTupleStructOther(q, 0)); + //~^ ERROR `Q: T3` is not satisfied [E0277] } fn main() {} diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index 27b002db130..9228a047e87 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Q: T3` is not satisfied - --> $DIR/blame-trait-error.rs:24:46 + --> $DIR/blame-trait-error.rs:53:46 | LL | want(Wrapper { value: Burrito { filling: q } }); | ---- ^ the trait `T3` is not implemented for `Q` @@ -21,7 +21,7 @@ LL | impl<B: T2> T1 for Wrapper<B> {} | | | unsatisfied trait bound introduced here note: required by a bound in `want` - --> $DIR/blame-trait-error.rs:21:12 + --> $DIR/blame-trait-error.rs:25:12 | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` @@ -30,6 +30,373 @@ help: consider restricting type parameter `Q` LL | fn example<Q: T3>(q: Q) { | ++++ -error: aborting due to previous error +error[E0277]: `()` is not an iterator + --> $DIR/blame-trait-error.rs:56:15 + | +LL | want(Some(())); + | ---- ^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + = help: the trait `T1` is implemented for `Option<It>` +note: required for `Option<()>` to implement `T1` + --> $DIR/blame-trait-error.rs:21:20 + | +LL | impl<It: Iterator> T1 for Option<It> {} + | -------- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` + +error[E0277]: `Q` is not an iterator + --> $DIR/blame-trait-error.rs:59:15 + | +LL | want(Some(q)); + | ---- ^ `Q` is not an iterator + | | + | required by a bound introduced by this call + | +note: required for `Option<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:21:20 + | +LL | impl<It: Iterator> T1 for Option<It> {} + | -------- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: std::iter::Iterator>(q: Q) { + | +++++++++++++++++++++ + +error[E0277]: `Q` is not an iterator + --> $DIR/blame-trait-error.rs:62:16 + | +LL | want(&Some(q)); + | ---- ^ `Q` is not an iterator + | | + | required by a bound introduced by this call + | +note: required for `Option<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:21:20 + | +LL | impl<It: Iterator> T1 for Option<It> {} + | -------- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&Option<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: std::iter::Iterator>(q: Q) { + | +++++++++++++++++++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:65:45 + | +LL | want(&ExampleTuple::ExampleTupleVariant(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl<A> T1 for ExampleTuple<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:68:31 + | +LL | want(&ExampleTupleVariant(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl<A> T1 for ExampleTuple<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:71:50 + | +LL | want(&ExampleOtherTuple::ExampleTupleVariant(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl<A> T1 for ExampleTuple<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:74:44 + | +LL | want(&ExampleDifferentTupleVariantName(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl<A> T1 for ExampleTuple<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:77:45 + | +LL | want(&ExampleYetAnotherTupleVariantName(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl<A> T1 for ExampleTuple<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:80:56 + | +LL | want(&ExampleStruct::ExampleStructVariant { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl<A> T1 for ExampleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:83:41 + | +LL | want(&ExampleStructVariant { field: q }); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl<A> T1 for ExampleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:86:61 + | +LL | want(&ExampleOtherStruct::ExampleStructVariant { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl<A> T1 for ExampleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:89:54 + | +LL | want(&ExampleDifferentStructVariantName { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl<A> T1 for ExampleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:92:55 + | +LL | want(&ExampleYetAnotherStructVariantName { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl<A> T1 for ExampleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:95:38 + | +LL | want(&ExampleActuallyTupleStruct(q, 0)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:50:9 + | +LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:98:43 + | +LL | want(&ExampleActuallyTupleStructOther(q, 0)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1` + --> $DIR/blame-trait-error.rs:50:9 + | +LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want<V: T1>(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example<Q: T3>(q: Q) { + | ++++ + +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr index 6913771f288..b6a24e12bcc 100644 --- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -91,10 +91,10 @@ LL | fn example<Q: T3>(q: Q) { | ++++ error[E0277]: the trait bound `Q: T3` is not satisfied - --> $DIR/blame-trait-error-spans-on-exprs.rs:93:27 + --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53 | LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) }); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q` | | | required by a bound introduced by this call | diff --git a/tests/ui/extenv/extenv-not-defined-default.rs b/tests/ui/extenv/extenv-not-defined-default.rs index 30a06a25465..1fb046c78f2 100644 --- a/tests/ui/extenv/extenv-not-defined-default.rs +++ b/tests/ui/extenv/extenv-not-defined-default.rs @@ -1,4 +1,4 @@ fn main() { - env!("__HOPEFULLY_NOT_DEFINED__"); - //~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined + env!("CARGO__HOPEFULLY_NOT_DEFINED__"); + //~^ ERROR: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined } diff --git a/tests/ui/extenv/extenv-not-defined-default.stderr b/tests/ui/extenv/extenv-not-defined-default.stderr index 884875dca53..e3dce000530 100644 --- a/tests/ui/extenv/extenv-not-defined-default.stderr +++ b/tests/ui/extenv/extenv-not-defined-default.stderr @@ -1,9 +1,10 @@ -error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined +error: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined at compile time --> $DIR/extenv-not-defined-default.rs:2:5 | -LL | env!("__HOPEFULLY_NOT_DEFINED__"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | env!("CARGO__HOPEFULLY_NOT_DEFINED__"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr index 92e8a44b55f..5752a965e35 100644 --- a/tests/ui/extenv/issue-55897.stderr +++ b/tests/ui/extenv/issue-55897.stderr @@ -1,9 +1,10 @@ -error: environment variable `NON_EXISTENT` not defined +error: environment variable `NON_EXISTENT` not defined at compile time --> $DIR/issue-55897.rs:11:22 | LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ | + = help: Use `std::env::var("NON_EXISTENT")` to read the variable at run time = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: suffixes on string literals are invalid diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.stderr index 3cc47e1e89d..bc8f559fdee 100644 --- a/tests/ui/impl-trait/hidden-lifetimes.stderr +++ b/tests/ui/impl-trait/hidden-lifetimes.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a --> $DIR/hidden-lifetimes.rs:29:5 | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { - | -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here + | -- -------------- opaque type defined here + | | + | hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here LL | x | ^ | @@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a --> $DIR/hidden-lifetimes.rs:46:5 | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { - | -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here + | -- -------------- opaque type defined here + | | + | hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here LL | x | ^ | diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr index 433b76b7afa..d56e1273f24 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -1,6 +1,8 @@ error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 | +LL | fn a() -> impl Fn(&u8) -> impl Debug { + | ---------- opaque type defined here LL | |x| x | --- ^ | | diff --git a/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs new file mode 100644 index 00000000000..dfce973d770 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn foo() -> impl Sized; +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr index 90875708094..5b0b1cc5e42 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -1,6 +1,9 @@ error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds --> $DIR/error-handling-2.rs:22:5 | +LL | type E<'a, 'b> = impl Sized; + | ---------- opaque type defined here +LL | LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { | -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here ... diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index ec49a61795a..68ac22a05f4 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n --> $DIR/ordinary-bounds-unrelated.rs:28:33 | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here + | -- ------------------ opaque type defined here + | | + | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here ... LL | if condition() { a } else { b } | ^ diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index c36f9bc6957..493a9e66eaf 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n --> $DIR/ordinary-bounds-unsuited.rs:31:33 | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here + | -- ------------------ opaque type defined here + | | + | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here ... LL | if condition() { a } else { b } | ^ diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 9c81791fbcb..55e3cd95064 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | ---- ^ - | | + | ---- --------- ^ + | | | + | | opaque type defined here | hidden type `&i32` captures the anonymous lifetime defined here | help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound @@ -15,8 +16,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | -- ^ - | | + | -- --------- ^ + | | | + | | opaque type defined here | hidden type `&'a i32` captures the lifetime `'a` as defined here | help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound @@ -100,7 +102,9 @@ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not --> $DIR/must_outlive_least_region_or_bound.rs:38:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { - | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here + | -- ---------------- opaque type defined here + | | + | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr index e761a60e79c..907822ebbc3 100644 --- a/tests/ui/impl-trait/nested-return-type4.stderr +++ b/tests/ui/impl-trait/nested-return-type4.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti --> $DIR/nested-return-type4.rs:4:5 | LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> { - | -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here + | -- --------------------------------------------- opaque type defined here + | | + | hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here LL | async move { let _s = s; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/impl-trait/region-escape-via-bound.stderr b/tests/ui/impl-trait/region-escape-via-bound.stderr index 44a790cb1a4..e4556bc21a7 100644 --- a/tests/ui/impl-trait/region-escape-via-bound.stderr +++ b/tests/ui/impl-trait/region-escape-via-bound.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not a --> $DIR/region-escape-via-bound.rs:17:5 | LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> - | -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here + | -- -------------- opaque type defined here + | | + | hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here ... LL | x | ^ diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.stderr b/tests/ui/impl-trait/static-return-lifetime-infered.stderr index c451f8e37c4..488cb821c10 100644 --- a/tests/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/tests/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that --> $DIR/static-return-lifetime-infered.rs:7:9 | LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> { - | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here + | ----- ----------------------- opaque type defined here + | | + | hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that --> $DIR/static-return-lifetime-infered.rs:11:9 | LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> { - | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here + | -- ----------------------- opaque type defined here + | | + | hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index c8b1ff1dbce..b99bb39d062 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -22,7 +22,9 @@ mod rusti { target_os = "netbsd", target_os = "openbsd", target_os = "solaris", - target_os = "vxworks"))] + target_os = "vxworks", + target_os = "nto", +))] mod m { #[cfg(target_arch = "x86")] pub fn main() { diff --git a/tests/ui/lifetimes/issue-105227.stderr b/tests/ui/lifetimes/issue-105227.stderr index d2114593735..b514db461b4 100644 --- a/tests/ui/lifetimes/issue-105227.stderr +++ b/tests/ui/lifetimes/issue-105227.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha --> $DIR/issue-105227.rs:7:5 | LL | fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> { - | ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here + | ----- -------------------------- opaque type defined here + | | + | hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here LL | LL | v.0.chars().chain(v.1.chars()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +18,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha --> $DIR/issue-105227.rs:13:5 | LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> { - | ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here + | ----- -------------------------- opaque type defined here + | | + | hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here LL | LL | v0.chars().chain(v1.chars()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +35,10 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha | LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> | ---- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here -... +LL | +LL | (impl Iterator<Item = char>, &'b str) + | -------------------------- opaque type defined here +LL | { LL | (v0.chars().chain(v1.chars()), v2) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr index d42f6c179b7..93fbc9c8a44 100644 --- a/tests/ui/macros/macros-nonfatal-errors.stderr +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -150,18 +150,19 @@ error: expected string literal LL | env!(invalid); | ^^^^^^^ -error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:105:10 +error: env! takes 1 or 2 arguments + --> $DIR/macros-nonfatal-errors.rs:105:5 | LL | env!(foo, abr, baz); - | ^^^ + | ^^^^^^^^^^^^^^^^^^^ -error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined +error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time --> $DIR/macros-nonfatal-errors.rs:106:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: Use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr index c340c2d32b3..bd51378cf1a 100644 --- a/tests/ui/methods/method-call-err-msg.stderr +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -48,14 +48,17 @@ LL | .two(0, /* isize */); error[E0599]: `Foo` is not an iterator --> $DIR/method-call-err-msg.rs:19:7 | -LL | pub struct Foo; - | -------------- - | | - | method `take` not found for this struct - | doesn't satisfy `Foo: Iterator` +LL | pub struct Foo; + | -------------- + | | + | method `take` not found for this struct + | doesn't satisfy `Foo: Iterator` ... -LL | .take() - | ^^^^ `Foo` is not an iterator +LL | / y.zero() +LL | | .take() + | | -^^^^ `Foo` is not an iterator + | |______| + | | = note: the following trait bounds were not satisfied: `Foo: Iterator` diff --git a/tests/ui/nll/issue-73159-rpit-static.stderr b/tests/ui/nll/issue-73159-rpit-static.stderr index 260b9b59772..4d3a9015316 100644 --- a/tests/ui/nll/issue-73159-rpit-static.stderr +++ b/tests/ui/nll/issue-73159-rpit-static.stderr @@ -4,6 +4,7 @@ error[E0700]: hidden type for `impl Iterator<Item = u8>` captures lifetime that LL | impl<'a> Foo<'a> { | -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here LL | fn make_it(&self) -> impl Iterator<Item = u8> { + | ------------------------ opaque type defined here LL | self.0.iter().copied() | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr index 1e6ef614dee..e0d476a33b2 100644 --- a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr +++ b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr @@ -24,7 +24,9 @@ error[E0700]: hidden type for `impl Cap<'b> + Cap<'c>` captures lifetime that do --> $DIR/min-choice-reject-ambiguous.rs:39:5 | LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> - | -- hidden type `&'a u8` captures the lifetime `'a` as defined here + | -- ---------------------- opaque type defined here + | | + | hidden type `&'a u8` captures the lifetime `'a` as defined here ... LL | s | ^ diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr index 6824e27ead0..483b5822b9d 100644 --- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr +++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` --> $DIR/nested-impl-trait-fail.rs:17:5 | LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> - | -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here + | -- ------------------------------------------------ opaque type defined here + | | + | hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here ... LL | [a] | ^^^ @@ -20,7 +22,9 @@ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that do --> $DIR/nested-impl-trait-fail.rs:17:5 | LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> - | -- hidden type `&'s u8` captures the lifetime `'s` as defined here + | -- ---------------------- opaque type defined here + | | + | hidden type `&'s u8` captures the lifetime `'s` as defined here ... LL | [a] | ^^^ @@ -40,6 +44,8 @@ error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` LL | fn fail_late_bound<'s, 'a, 'b>( | -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here ... +LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> { + | ------------------------------------------------ opaque type defined here LL | [a] | ^^^ | @@ -58,6 +64,8 @@ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that do LL | fn fail_late_bound<'s, 'a, 'b>( | -- hidden type `&'s u8` captures the lifetime `'s` as defined here ... +LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> { + | ---------------------- opaque type defined here LL | [a] | ^^^ | diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 7b9ed171d2d..7fcb68252cf 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::fo --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { - | -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here + | -- ------------ opaque type defined here + | | + | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here LL | x | ^ | diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs new file mode 100644 index 00000000000..f97edd510c9 --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-105626.rs @@ -0,0 +1,17 @@ +// run-pass +// only-x86 +// min-system-llvm-version: 16 +// compile-flags: -Ctarget-feature=+sse2 + +use std::hint::black_box; + +fn main() { + let n: i64 = black_box(0x3fffffdfffffff); + let r = f32::from_bits(0x5a7fffff); + + assert_ne!((n as f64) as f32, n as f32); + + // FIXME: these assertions fail if only x87 is enabled + assert_eq!(n as i64 as f32, r); + assert_eq!(n as u64 as f32, r); +} diff --git a/tests/ui/parser/issues/issue-104367.rs b/tests/ui/parser/issues/issue-104367.rs new file mode 100644 index 00000000000..861761b64f4 --- /dev/null +++ b/tests/ui/parser/issues/issue-104367.rs @@ -0,0 +1,6 @@ +#[derive(A)] +struct S { + d: [u32; { + #![cfg] { + #![w,) //~ ERROR mismatched closing delimiter + //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr new file mode 100644 index 00000000000..e6e76535761 --- /dev/null +++ b/tests/ui/parser/issues/issue-104367.stderr @@ -0,0 +1,26 @@ +error: mismatched closing delimiter: `)` + --> $DIR/issue-104367.rs:5:15 + | +LL | #![w,) + | ^ ^ mismatched closing delimiter + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104367.rs:6:71 + | +LL | struct S { + | - unclosed delimiter +LL | d: [u32; { + | - - unclosed delimiter + | | + | unclosed delimiter +LL | #![cfg] { + | - unclosed delimiter +LL | #![w,) + | - missing open `(` for this delimiter +LL | + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-105209.rs b/tests/ui/parser/issues/issue-105209.rs new file mode 100644 index 00000000000..6146b795de1 --- /dev/null +++ b/tests/ui/parser/issues/issue-105209.rs @@ -0,0 +1,3 @@ +// compile-flags: -Zunpretty=ast-tree +#![c={#![c[)x //~ ERROR mismatched closing delimiter + //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr new file mode 100644 index 00000000000..c75eafa1833 --- /dev/null +++ b/tests/ui/parser/issues/issue-105209.stderr @@ -0,0 +1,22 @@ +error: mismatched closing delimiter: `)` + --> $DIR/issue-105209.rs:2:11 + | +LL | #![c={#![c[)x + | ^^ mismatched closing delimiter + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-105209.rs:3:68 + | +LL | #![c={#![c[)x + | - - - - missing open `(` for this delimiter + | | | | + | | | unclosed delimiter + | | unclosed delimiter + | unclosed delimiter +LL | + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs index 107eba45dc2..7ae14c6b84d 100644 --- a/tests/ui/process/process-sigpipe.rs +++ b/tests/ui/process/process-sigpipe.rs @@ -15,6 +15,7 @@ // ignore-emscripten no threads support // ignore-vxworks no 'sh' // ignore-fuchsia no 'sh' +// ignore-nto no 'yes' use std::process; use std::thread; diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs index 2ae0dd92717..e0842bfa4cd 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs @@ -11,6 +11,8 @@ // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck +#![feature(target_feature_11)] + #[target_feature(enable = "sse2")] const fn sse2() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs index e96a3e5f6cd..a59d7c2d784 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs @@ -5,6 +5,8 @@ // [thir]compile-flags: -Z thir-unsafeck // only-x86_64 +#![feature(target_feature_11)] + #[target_feature(enable="avx")] fn also_use_avx() { println!("Hello from AVX") diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs new file mode 100644 index 00000000000..975d7a1f694 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs @@ -0,0 +1,6 @@ +// only-x86_64 + +#[target_feature(enable = "sse2")] //~ ERROR can only be applied to `unsafe` functions +fn foo() {} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr new file mode 100644 index 00000000000..18917fd2556 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr @@ -0,0 +1,14 @@ +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/feature-gate-target_feature_11.rs:3:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() {} + | -------- not an `unsafe` function + | + = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr index fa6561b74d9..b0ac5dc44ad 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/fn-ptr.rs:9:21 + --> $DIR/fn-ptr.rs:11:21 | LL | #[target_feature(enable = "sse2")] | ---------------------------------- `#[target_feature]` added here diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs index 7df172e80eb..c95d4a08e48 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs @@ -2,6 +2,8 @@ // [thir]compile-flags: -Z thir-unsafeck // only-x86_64 +#![feature(target_feature_11)] + #[target_feature(enable = "sse2")] fn foo() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr index fa6561b74d9..b0ac5dc44ad 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/fn-ptr.rs:9:21 + --> $DIR/fn-ptr.rs:11:21 | LL | #[target_feature(enable = "sse2")] | ---------------------------------- `#[target_feature]` added here diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 392cdc4bd36..43bda49624e 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -1,5 +1,7 @@ // only-x86_64 +#![feature(target_feature_11)] + #[target_feature(enable = "avx")] fn foo() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index aa0f57dee41..fc7bf22775d 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -1,5 +1,5 @@ error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}` - --> $DIR/fn-traits.rs:22:10 + --> $DIR/fn-traits.rs:24:10 | LL | call(foo); | ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}` @@ -10,13 +10,13 @@ LL | call(foo); = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` - --> $DIR/fn-traits.rs:9:17 + --> $DIR/fn-traits.rs:11:17 | LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}` - --> $DIR/fn-traits.rs:23:14 + --> $DIR/fn-traits.rs:25:14 | LL | call_mut(foo); | -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}` @@ -27,13 +27,13 @@ LL | call_mut(foo); = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:13:21 + --> $DIR/fn-traits.rs:15:21 | LL | fn call_mut(f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}` - --> $DIR/fn-traits.rs:24:15 + --> $DIR/fn-traits.rs:26:15 | LL | call_once(foo); | --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}` @@ -44,13 +44,13 @@ LL | call_once(foo); = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` - --> $DIR/fn-traits.rs:17:22 + --> $DIR/fn-traits.rs:19:22 | LL | fn call_once(f: impl FnOnce()) { | ^^^^^^^^ required by this bound in `call_once` error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` - --> $DIR/fn-traits.rs:26:10 + --> $DIR/fn-traits.rs:28:10 | LL | call(foo_unsafe); | ---- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` @@ -61,13 +61,13 @@ LL | call(foo_unsafe); = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` - --> $DIR/fn-traits.rs:9:17 + --> $DIR/fn-traits.rs:11:17 | LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` - --> $DIR/fn-traits.rs:28:14 + --> $DIR/fn-traits.rs:30:14 | LL | call_mut(foo_unsafe); | -------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` @@ -78,13 +78,13 @@ LL | call_mut(foo_unsafe); = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:13:21 + --> $DIR/fn-traits.rs:15:21 | LL | fn call_mut(f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` - --> $DIR/fn-traits.rs:30:15 + --> $DIR/fn-traits.rs:32:15 | LL | call_once(foo_unsafe); | --------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` @@ -95,7 +95,7 @@ LL | call_once(foo_unsafe); = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` - --> $DIR/fn-traits.rs:17:22 + --> $DIR/fn-traits.rs:19:22 | LL | fn call_once(f: impl FnOnce()) { | ^^^^^^^^ required by this bound in `call_once` diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs index e4ee511d07f..033dcdfc08d 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs @@ -1,5 +1,7 @@ // check-pass +#![feature(target_feature_11)] + struct S<T>(T) where [T; (|| {}, 1).1]: Copy; diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr index 76b99dca842..0ef7b8b09f1 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:21:5 + --> $DIR/safe-calls.rs:23:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -7,7 +7,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:24:5 + --> $DIR/safe-calls.rs:26:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -15,7 +15,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:27:5 + --> $DIR/safe-calls.rs:29:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -23,7 +23,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:34:5 + --> $DIR/safe-calls.rs:36:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -31,7 +31,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:37:5 + --> $DIR/safe-calls.rs:39:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -39,7 +39,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:44:5 + --> $DIR/safe-calls.rs:46:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -47,7 +47,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:47:5 + --> $DIR/safe-calls.rs:49:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -55,7 +55,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:50:5 + --> $DIR/safe-calls.rs:52:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -63,7 +63,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:58:5 + --> $DIR/safe-calls.rs:60:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -71,7 +71,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:63:18 + --> $DIR/safe-calls.rs:65:18 | LL | const name: () = sse2(); | ^^^^^^ call to function with `#[target_feature]` diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs index de78fbf0df4..cebc6f94784 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -2,6 +2,8 @@ // [thir]compile-flags: -Z thir-unsafeck // only-x86_64 +#![feature(target_feature_11)] + #[target_feature(enable = "sse2")] const fn sse2() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr index daca221fe5d..c75ac6e8b9a 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr @@ -1,5 +1,5 @@ error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:21:5 + --> $DIR/safe-calls.rs:23:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -7,7 +7,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:24:5 + --> $DIR/safe-calls.rs:26:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -15,7 +15,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:27:5 + --> $DIR/safe-calls.rs:29:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -23,7 +23,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:34:5 + --> $DIR/safe-calls.rs:36:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -31,7 +31,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:37:5 + --> $DIR/safe-calls.rs:39:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -39,7 +39,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:44:5 + --> $DIR/safe-calls.rs:46:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -47,7 +47,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:47:5 + --> $DIR/safe-calls.rs:49:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -55,7 +55,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:50:5 + --> $DIR/safe-calls.rs:52:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -63,7 +63,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:58:5 + --> $DIR/safe-calls.rs:60:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -71,7 +71,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:63:18 + --> $DIR/safe-calls.rs:65:18 | LL | const name: () = sse2(); | ^^^^^^ call to function with `#[target_feature]` diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs index 3cdbf41d878..7314fa8cced 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs @@ -1,5 +1,7 @@ // only-x86_64 +#![feature(target_feature_11)] + trait Foo { fn foo(&self); unsafe fn unsf_foo(&self); diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr index eb385d359ac..07d6e090059 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr @@ -1,5 +1,5 @@ error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/trait-impl.rs:11:5 + --> $DIR/trait-impl.rs:13:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs index 6873abc49b2..ff45ace7857 100644 --- a/tests/ui/runtime/out-of-stack.rs +++ b/tests/ui/runtime/out-of-stack.rs @@ -6,6 +6,7 @@ // ignore-emscripten no processes // ignore-sgx no processes // ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590) +// ignore-nto no stack overflow handler used (no alternate stack available) #![feature(core_intrinsics)] #![feature(rustc_private)] diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs index 8a6d738959e..37c602ae0b0 100644 --- a/tests/ui/runtime/signal-alternate-stack-cleanup.rs +++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs @@ -7,6 +7,7 @@ // ignore-windows // ignore-sgx no libc // ignore-vxworks no SIGWINCH in user space +// ignore-nto no SA_ONSTACK #![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index eb3d3e4a67a..944cdc5f55d 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ----- ^^^^^^^^ - | | + | ----- ---------- ^^^^^^^^ + | | | + | | opaque type defined here | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 2c0b2a0d919..8a9b397ca70 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ----- ^^^^ - | | + | ----- ---------- ^^^^ + | | | + | | opaque type defined here | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here | help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index 40ede9705f1..f21c9b2c808 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -43,7 +43,9 @@ struct Outer { target_os = "netbsd", target_os = "openbsd", target_os = "solaris", - target_os = "vxworks"))] + target_os = "vxworks", + target_os = "nto", +))] mod m { #[cfg(target_arch = "x86")] pub mod m { diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index c5c3f7b468c..93cfa60b5ab 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -10,7 +10,9 @@ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not ap --> $DIR/missing-lifetimes-in-signature.rs:19:5 | LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() - | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here + | ------ ------------- opaque type defined here + | | + | hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here ... LL | / move || { LL | | diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs new file mode 100644 index 00000000000..fbaf41245e9 --- /dev/null +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs @@ -0,0 +1,8 @@ +pub struct Bar<S>(S); + +pub trait Foo {} + +impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {} +//~^ ERROR ambiguous associated type + +fn main() {} diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr new file mode 100644 index 00000000000..0ca5b9b9207 --- /dev/null +++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38 + | +LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {} + | ^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'a S as IntoIterator>::Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs index a04bb0afed5..ad1b6e96be6 100644 --- a/tests/ui/target-feature/invalid-attribute.rs +++ b/tests/ui/target-feature/invalid-attribute.rs @@ -26,6 +26,12 @@ unsafe fn foo() {} #[target_feature(enable = "sse2")] +//~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions +//~| NOTE see issue #69098 +fn bar() {} +//~^ NOTE not an `unsafe` function + +#[target_feature(enable = "sse2")] //~^ ERROR attribute should be applied to a function mod another {} //~^ NOTE not a function @@ -69,8 +75,8 @@ trait Quux { impl Quux for Foo { #[target_feature(enable = "sse2")] - //~^ ERROR `#[target_feature(..)]` cannot be applied to safe trait method - //~| NOTE cannot be applied to safe trait method + //~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions + //~| NOTE see issue #69098 fn foo() {} //~^ NOTE not an `unsafe` function } @@ -80,8 +86,9 @@ fn main() { //~^ ERROR attribute should be applied to a function unsafe { foo(); + bar(); } - //~^^^ NOTE not a function + //~^^^^ NOTE not a function #[target_feature(enable = "sse2")] //~^ ERROR attribute should be applied to a function diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index 22105bcca8d..a2adfc67f08 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -5,7 +5,7 @@ LL | #[target_feature = "+sse2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]` error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:28:1 + --> $DIR/invalid-attribute.rs:34:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | mod another {} | -------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:33:1 + --> $DIR/invalid-attribute.rs:39:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | const FOO: usize = 7; | --------------------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:38:1 + --> $DIR/invalid-attribute.rs:44:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | struct Foo; | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:43:1 + --> $DIR/invalid-attribute.rs:49:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | enum Bar {} | ----------- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:48:1 + --> $DIR/invalid-attribute.rs:54:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | | } | |_- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:56:1 + --> $DIR/invalid-attribute.rs:62:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,18 +63,19 @@ LL | trait Baz {} | ------------ not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:79:5 + --> $DIR/invalid-attribute.rs:85:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | / unsafe { LL | | foo(); +LL | | bar(); LL | | } | |_____- not a function definition error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:86:5 + --> $DIR/invalid-attribute.rs:93:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,20 +101,36 @@ error: malformed `target_feature` attribute input LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/invalid-attribute.rs:28:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn bar() {} + | -------- not an `unsafe` function + | + = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable + error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:61:1 + --> $DIR/invalid-attribute.rs:67:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ -error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/invalid-attribute.rs:71:5 +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/invalid-attribute.rs:77:5 | LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | fn foo() {} | -------- not an `unsafe` function + | + = note: see issue #69098 <https://github.com/rust-lang/rust/issues/69098> for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout index c31e6a218ce..910c0da2737 100644 --- a/tests/ui/thir-print/thir-flat.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -17,21 +17,16 @@ Thir { ], exprs: [ Expr { - ty: (), - temp_lifetime: Some( - Node(2), - ), - span: $DIR/thir-flat.rs:4:15: 4:17 (#0), kind: Block { block: b0, }, - }, - Expr { ty: (), temp_lifetime: Some( Node(2), ), span: $DIR/thir-flat.rs:4:15: 4:17 (#0), + }, + Expr { kind: Scope { region_scope: Node(2), lint_level: Explicit( @@ -39,18 +34,23 @@ Thir { ), value: e0, }, - }, - Expr { ty: (), temp_lifetime: Some( Node(2), ), span: $DIR/thir-flat.rs:4:15: 4:17 (#0), + }, + Expr { kind: Scope { region_scope: Destruction(2), lint_level: Inherited, value: e1, }, + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-flat.rs:4:15: 4:17 (#0), }, ], stmts: [], diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs index fbd3413885f..f03bd3f991b 100644 --- a/tests/ui/thread-local/tls.rs +++ b/tests/ui/thread-local/tls.rs @@ -1,6 +1,7 @@ // run-pass // ignore-emscripten no threads support // compile-flags: -O +// ignore-nto Doesn't work without emulated TLS enabled (in LLVM) #![feature(thread_local)] diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr index 0ed8a703b6d..e52d5f9de69 100644 --- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr @@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not app --> $DIR/imply_bounds_from_bounds_param.rs:24:5 | LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { - | -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here + | -- ------------ opaque type defined here + | | + | hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here LL | <&'a mut i32 as Callable>::call(y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 65a0af0d22f..d666e668d36 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -1,6 +1,8 @@ error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:4:47 | +LL | type Opaque<'a, T> = impl Sized; + | ---------- opaque type defined here LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } | -- ^ | | diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr index 8346c9a0aae..b622122f33e 100644 --- a/tests/ui/typeck/issue-31173.stderr +++ b/tests/ui/typeck/issue-31173.stderr @@ -24,8 +24,17 @@ note: required by a bound in `cloned` error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied --> $DIR/issue-31173.rs:12:10 | -LL | .collect(); - | ^^^^^^^ method cannot be called due to unsatisfied trait bounds +LL | let temp: Vec<u8> = it + | _________________________- +LL | | .take_while(|&x| { +LL | | found_e = true; +LL | | false +LL | | }) +LL | | .cloned() +LL | | .collect(); + | | -^^^^^^^ method cannot be called due to unsatisfied trait bounds + | |_________| + | --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL | = note: doesn't satisfy `<_ as Iterator>::Item = &_` diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs index 674c26a43f2..82a1dd63713 100644 --- a/tests/ui/wait-forked-but-failed-child.rs +++ b/tests/ui/wait-forked-but-failed-child.rs @@ -3,6 +3,7 @@ // ignore-sgx no processes // ignore-vxworks no 'ps' // ignore-fuchsia no 'ps' +// ignore-nto no 'ps' #![feature(rustc_private)] |
