From 89b2e0c9d5a4cf87769d2bd51fe6753bbdf6448f Mon Sep 17 00:00:00 2001 From: woppopo Date: Wed, 24 Nov 2021 13:05:26 +0900 Subject: [PATCH 01/13] Make `intrinsics::write_bytes` const --- .../src/interpret/intrinsics.rs | 24 +++++++++++++++ library/core/src/intrinsics.rs | 20 +++++++++++-- library/core/tests/intrinsics.rs | 30 +++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 44da27a43db0a..27a75a470bbbb 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -322,6 +322,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::copy => { self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?; } + sym::write_bytes => { + self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?; + } sym::offset => { let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; @@ -543,6 +546,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.memory.copy(src, align, dst, align, size, nonoverlapping) } + pub(crate) fn write_bytes_intrinsic( + &mut self, + dst: &OpTy<'tcx, >::PointerTag>, + byte: &OpTy<'tcx, >::PointerTag>, + count: &OpTy<'tcx, >::PointerTag>, + ) -> InterpResult<'tcx> { + let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?; + + let dst = self.read_pointer(&dst)?; + let byte = self.read_scalar(&byte)?.to_u8()?; + let count = self.read_scalar(&count)?.to_machine_usize(self)?; + + let len = layout + .size + .checked_mul(count, self) + .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?; + + let bytes = std::iter::repeat(byte).take(len.bytes_usize()); + self.memory.write_bytes(dst, bytes) + } + pub(crate) fn raw_eq_intrinsic( &mut self, lhs: &OpTy<'tcx, >::PointerTag>, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 0f57fb5b14180..0b83cbc1849e4 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2242,13 +2242,29 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { /// assert_eq!(*v, 42); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline] -pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { +pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] fn write_bytes(dst: *mut T, val: u8, count: usize); } - debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); + #[cfg(debug_assertions)] + fn runtime_check(ptr: *mut T) { + debug_assert!( + is_aligned_and_not_null(ptr), + "attempt to write to unaligned or null pointer" + ); + } + #[cfg(debug_assertions)] + const fn compiletime_check(_ptr: *mut T) {} + #[cfg(debug_assertions)] + // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to + // not do them during compile time + unsafe { + const_eval_select((dst,), compiletime_check, runtime_check); + } // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. unsafe { write_bytes(dst, val, count) } diff --git a/library/core/tests/intrinsics.rs b/library/core/tests/intrinsics.rs index de163a60c98f4..84cef53b3584b 100644 --- a/library/core/tests/intrinsics.rs +++ b/library/core/tests/intrinsics.rs @@ -35,3 +35,33 @@ fn test_assume_can_be_in_const_contexts() { let rs = unsafe { foo(42, 97) }; assert_eq!(rs, 0); } + +#[test] +#[cfg(not(bootstrap))] +const fn test_write_bytes_in_const_contexts() { + use core::intrinsics::write_bytes; + + const TEST: [u32; 3] = { + let mut arr = [1u32, 2, 3]; + unsafe { + write_bytes(arr.as_mut_ptr(), 0, 2); + } + arr + }; + + assert!(TEST[0] == 0); + assert!(TEST[1] == 0); + assert!(TEST[2] == 3); + + const TEST2: [u32; 3] = { + let mut arr = [1u32, 2, 3]; + unsafe { + write_bytes(arr.as_mut_ptr(), 1, 2); + } + arr + }; + + assert!(TEST2[0] == 16843009); + assert!(TEST2[1] == 16843009); + assert!(TEST2[2] == 3); +} From 8716f2780e067c3590a6be4545cf40d0b6d8865a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 7 Dec 2021 23:46:38 +0000 Subject: [PATCH 02/13] asm: Allow using r9 (ARM) and x18 (AArch64) if they are not reserved by the current target. --- compiler/rustc_ast_lowering/src/asm.rs | 7 +++- .../rustc_codegen_ssa/src/target_features.rs | 1 + compiler/rustc_target/src/asm/aarch64.rs | 20 +++++++++-- compiler/rustc_target/src/asm/arm.rs | 19 +++++++++-- compiler/rustc_target/src/asm/mod.rs | 34 ++++++++++++++++--- 5 files changed, 72 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 9f27ace25ab4b..9c28f3c7f5899 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -64,7 +64,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut clobber_abis = FxHashMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse( + asm_arch, + |feature| self.sess.target_features.contains(&Symbol::intern(feature)), + &self.sess.target, + *abi_name, + ) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index ba72e3cfafce2..63cc6faf9ec5e 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -36,6 +36,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), ("thumb2", Some(sym::arm_target_feature)), + ("reserve-r9", Some(sym::arm_target_feature)), ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 76e50678314ae..4bf909ce46d25 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,4 +1,5 @@ use super::{InlineAsmArch, InlineAsmType}; +use crate::spec::Target; use rustc_macros::HashStable_Generic; use std::fmt; @@ -70,6 +71,22 @@ impl AArch64InlineAsmRegClass { } } +pub fn reserved_x18( + _arch: InlineAsmArch, + _has_feature: impl FnMut(&str) -> bool, + target: &Target, +) -> Result<(), &'static str> { + if target.os == "android" + || target.is_like_fuchsia + || target.is_like_osx + || target.is_like_windows + { + Err("x18 is a reserved register on this target") + } else { + Ok(()) + } +} + def_regs! { AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass { x0: reg = ["x0", "w0"], @@ -90,6 +107,7 @@ def_regs! { x15: reg = ["x15", "w15"], x16: reg = ["x16", "w16"], x17: reg = ["x17", "w17"], + x18: reg = ["x18", "w18"] % reserved_x18, x20: reg = ["x20", "w20"], x21: reg = ["x21", "w21"], x22: reg = ["x22", "w22"], @@ -149,8 +167,6 @@ def_regs! { p14: preg = ["p14"], p15: preg = ["p15"], ffr: preg = ["ffr"], - #error = ["x18", "w18"] => - "x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm", #error = ["x19", "w19"] => "x19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x29", "w29", "fp", "wfp"] => diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 4eeb7fcc71bce..b03594b3151a3 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -99,6 +99,22 @@ fn not_thumb1( } } +fn reserved_r9( + arch: InlineAsmArch, + mut has_feature: impl FnMut(&str) -> bool, + target: &Target, +) -> Result<(), &'static str> { + not_thumb1(arch, &mut has_feature, target)?; + + // We detect this using the reserved-r9 feature instead of using the target + // because the relocation model can be changed with compiler options. + if has_feature("reserved-r9") { + Err("the RWPI static base register (r9) cannot be used as an operand for inline asm") + } else { + Ok(()) + } +} + def_regs! { Arm ArmInlineAsmReg ArmInlineAsmRegClass { r0: reg = ["r0", "a1"], @@ -109,6 +125,7 @@ def_regs! { r5: reg = ["r5", "v2"], r7: reg = ["r7", "v4"] % frame_pointer_r7, r8: reg = ["r8", "v5"] % not_thumb1, + r9: reg = ["r9", "v6", "rfp"] % reserved_r9, r10: reg = ["r10", "sl"] % not_thumb1, r11: reg = ["r11", "fp"] % frame_pointer_r11, r12: reg = ["r12", "ip"] % not_thumb1, @@ -195,8 +212,6 @@ def_regs! { q15: qreg = ["q15"], #error = ["r6", "v3"] => "r6 is used internally by LLVM and cannot be used as an operand for inline asm", - #error = ["r9", "v6", "rfp"] => - "r9 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r13", "sp"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["r15", "pc"] => diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index cf940594bc459..f1f5f4389e3e9 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -785,6 +785,7 @@ pub enum InlineAsmClobberAbi { X86_64SysV, Arm, AArch64, + AArch64NoX18, RiscV, } @@ -793,6 +794,7 @@ impl InlineAsmClobberAbi { /// clobber ABIs for the target. pub fn parse( arch: InlineAsmArch, + has_feature: impl FnMut(&str) -> bool, target: &Target, name: Symbol, ) -> Result { @@ -816,7 +818,13 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system", "efiapi", "aapcs"]), }, InlineAsmArch::AArch64 => match name { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64), + "C" | "system" | "efiapi" => { + Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() { + InlineAsmClobberAbi::AArch64NoX18 + } else { + InlineAsmClobberAbi::AArch64 + }) + } _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { @@ -891,8 +899,25 @@ impl InlineAsmClobberAbi { AArch64 AArch64InlineAsmReg { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, - // x18 is platform-reserved or temporary, but we exclude it - // here since it is a reserved register. + x16, x17, x18, x30, + + // Technically the low 64 bits of v8-v15 are preserved, but + // we have no way of expressing this using clobbers. + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + + p0, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11, p12, p13, p14, p15, + ffr, + + } + }, + InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { + AArch64 AArch64InlineAsmReg { + x0, x1, x2, x3, x4, x5, x6, x7, + x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x30, // Technically the low 64 bits of v8-v15 are preserved, but @@ -910,7 +935,8 @@ impl InlineAsmClobberAbi { }, InlineAsmClobberAbi::Arm => clobbered_regs! { Arm ArmInlineAsmReg { - // r9 is platform-reserved and is treated as callee-saved. + // r9 is either platform-reserved or callee-saved. Either + // way we don't need to clobber it. r0, r1, r2, r3, r12, r14, // The finest-grained register variant is used here so that From 3cf9ae6ff30f2648b6233ede61ad0d1e75a30d14 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 10 Dec 2021 13:05:06 +0530 Subject: [PATCH 03/13] inline slice panics on panic_immediate_abort --- library/core/src/slice/index.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index f722430354991..0298bba8d329e 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -27,35 +27,40 @@ where } } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_start_index_len_fail(index: usize, len: usize) -> ! { panic!("range start index {} out of range for slice of length {}", index, len); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_end_index_len_fail(index: usize, len: usize) -> ! { panic!("range end index {} out of range for slice of length {}", index, len); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_index_order_fail(index: usize, end: usize) -> ! { panic!("slice index starts at {} but ends at {}", index, end); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_start_index_overflow_fail() -> ! { panic!("attempted to index slice from after maximum usize"); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_end_index_overflow_fail() -> ! { From 0adee2c01eb5ecb91df3b4ac1c045b18f8a4c2f5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 10 Dec 2021 13:08:06 +0530 Subject: [PATCH 04/13] inline Option panics on panic_immediate_abort --- library/core/src/option.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 7b9c6e43960f7..aae3af81a5204 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1656,7 +1656,8 @@ impl Option> { } // This is a separate function to reduce the code size of .expect() itself. -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] const fn expect_failed(msg: &str) -> ! { From 917dafc73a9eb257b9b5c2d357c4abd8bb1c3a8e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 10 Dec 2021 13:12:26 +0530 Subject: [PATCH 05/13] Add separate impl of unwrap_failed to avoid constructing trait objects --- library/core/src/result.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index e6b8c8ec3385a..ab067d57d082a 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1653,6 +1653,7 @@ impl Result { } // This is a separate function to reduce the code size of the methods +#[cfg(not(feature = "panic_immediate_abort"))] #[inline(never)] #[cold] #[track_caller] @@ -1660,6 +1661,18 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { panic!("{}: {:?}", msg, error) } +// This is a separate function to avoid constructing a `dyn Debug` +// that gets immediately thrown away, since vtables don't get cleaned up +// by dead code elimination if a trait object is constructed even if it goes +// unused +#[cfg(feature = "panic_immediate_abort")] +#[inline] +#[cold] +#[track_caller] +fn unwrap_failed(_msg: &str, _error: &T) -> ! { + panic!() +} + ///////////////////////////////////////////////////////////////////////////// // Trait implementations ///////////////////////////////////////////////////////////////////////////// From 04cdad0fa587dea94bbde60a39dd55967f7ac7f0 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 10 Dec 2021 09:55:36 -0700 Subject: [PATCH 06/13] Add regression test for #78160 --- .../doc-notable_trait-mut_t_is_not_ref_t.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs diff --git a/src/test/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs b/src/test/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs new file mode 100644 index 0000000000000..b359dcea0ff47 --- /dev/null +++ b/src/test/rustdoc/doc-notable_trait-mut_t_is_not_ref_t.rs @@ -0,0 +1,21 @@ +//! Test case for [#78160]. +//! +//! A SomeTrait that is implemented for `&mut T` should not be marked as +//! "notable" for return values that are `&T`. +//! +//! [#78160]: https://github.com/rust-lang/rust/issues/78160 + +#![feature(rustdoc_internals)] + +#[doc(primitive = "reference")] +/// Some useless docs, wouhou! +/// +/// We need to put this in here, because notable traits +/// that are implemented on foreign types don't show up. +mod reference {} + +// @has doc_notable_trait_mut_t_is_not_ref_t/fn.fn_no_matches.html +// @!has - '//code[@class="content"]' "impl<'_, I> Iterator for &'_ mut I" +pub fn fn_no_matches<'a, T: Iterator + 'a>() -> &'a T { + loop {} +} From 67ada7abeff96ac84510b8c723554105c2ac8a68 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 3 Feb 2021 00:25:29 +0100 Subject: [PATCH 07/13] Remove hir::Node::hir_id. --- compiler/rustc_hir/src/hir.rs | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 487ae87052ba3..ad042acd5ba72 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3209,34 +3209,6 @@ impl<'hir> Node<'hir> { } } - pub fn hir_id(&self) -> Option { - match self { - Node::Item(Item { def_id, .. }) - | Node::TraitItem(TraitItem { def_id, .. }) - | Node::ImplItem(ImplItem { def_id, .. }) - | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)), - Node::Field(FieldDef { hir_id, .. }) - | Node::AnonConst(AnonConst { hir_id, .. }) - | Node::Expr(Expr { hir_id, .. }) - | Node::Stmt(Stmt { hir_id, .. }) - | Node::Ty(Ty { hir_id, .. }) - | Node::Binding(Pat { hir_id, .. }) - | Node::Pat(Pat { hir_id, .. }) - | Node::Arm(Arm { hir_id, .. }) - | Node::Block(Block { hir_id, .. }) - | Node::Local(Local { hir_id, .. }) - | Node::Lifetime(Lifetime { hir_id, .. }) - | Node::Param(Param { hir_id, .. }) - | Node::Infer(InferArg { hir_id, .. }) - | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id), - Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id), - Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id, - Node::Variant(Variant { id, .. }) => Some(*id), - Node::Ctor(variant) => variant.ctor_hir_id(), - Node::Crate(_) | Node::Visibility(_) => None, - } - } - /// Returns `Constness::Const` when this node is a const fn/impl/item. pub fn constness_for_typeck(&self) -> Constness { match self { From d9e997d9ebaf3b3d9bd547c22620ecdf3aee8a3e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 11 Dec 2021 00:56:21 +0100 Subject: [PATCH 08/13] Remove useless variant. --- compiler/rustc_lint/src/context.rs | 21 +-------------------- compiler/rustc_lint_defs/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 4c936dec6f2cd..3c79020523a9f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -22,9 +22,7 @@ use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; -use rustc_errors::{ - add_elided_lifetime_in_path_suggestion, struct_span_err, Applicability, SuggestionStyle, -}; +use rustc_errors::{struct_span_err, Applicability, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -670,23 +668,6 @@ pub trait LintContext: Sized { ) => { db.span_note(span_def, "the macro is defined here"); } - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ) => { - add_elided_lifetime_in_path_suggestion( - sess.source_map(), - &mut db, - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ); - } BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect); } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index feac2a7cfa48a..3f504d75dfc92 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -289,7 +289,6 @@ pub enum BuiltinLintDiagnostics { AbsPathWithModule(Span), ProcMacroDeriveResolutionFallback(Span), MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), - ElidedLifetimesInPaths(usize, Span, bool, Span, String), UnknownCrateTypes(Span, String, String), UnusedImports(String, Vec<(Span, String)>), RedundantImport(Vec<(Span, bool)>, Ident), From 9a680037425b730787dc3071bb0837aaeee8d3fb Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 11 Dec 2021 00:58:13 +0100 Subject: [PATCH 09/13] Do not ICE when suggesting elided lifetimes on non-existent spans. --- compiler/rustc_resolve/src/late/diagnostics.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 72ba3f7b980cb..feb4f82ce8ddc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2115,6 +2115,11 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { }) .map(|(formatter, span)| (*span, formatter(name))) .collect(); + if spans_suggs.is_empty() { + // If all the spans come from macros, we cannot extract snippets and then + // `formatters` only contains None and `spans_suggs` is empty. + return; + } err.multipart_suggestion_verbose( &format!( "consider using the `{}` lifetime", From 989d1de91bb357ba7bb360dd85a4a1308862ceb6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 11 Dec 2021 10:35:37 +0100 Subject: [PATCH 10/13] Add test. --- .../ui/lifetimes/auxiliary/issue-91763-aux.rs | 47 +++++++++++++++++++ src/test/ui/lifetimes/issue-91763.rs | 11 +++++ src/test/ui/lifetimes/issue-91763.stderr | 14 ++++++ 3 files changed, 72 insertions(+) create mode 100644 src/test/ui/lifetimes/auxiliary/issue-91763-aux.rs create mode 100644 src/test/ui/lifetimes/issue-91763.rs create mode 100644 src/test/ui/lifetimes/issue-91763.stderr diff --git a/src/test/ui/lifetimes/auxiliary/issue-91763-aux.rs b/src/test/ui/lifetimes/auxiliary/issue-91763-aux.rs new file mode 100644 index 0000000000000..0335f72b7846f --- /dev/null +++ b/src/test/ui/lifetimes/auxiliary/issue-91763-aux.rs @@ -0,0 +1,47 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +//#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; + +#[proc_macro_attribute] +pub fn repro(_args: TokenStream, input: TokenStream) -> TokenStream { + let call_site = Span::call_site(); + let span = input.into_iter().nth(8).unwrap().span(); + + //fn f(_: &::std::fmt::Formatter) {} + TokenStream::from_iter([ + TokenTree::Ident(Ident::new("fn", call_site)), + TokenTree::Ident(Ident::new("f", call_site)), + TokenTree::Group(Group::new( + Delimiter::Parenthesis, + TokenStream::from_iter([ + TokenTree::Ident(Ident::new("_", call_site)), + TokenTree::Punct(punct(':', Spacing::Alone, call_site)), + TokenTree::Punct(punct('&', Spacing::Alone, call_site)), + TokenTree::Punct(punct(':', Spacing::Joint, span)), + TokenTree::Punct(punct(':', Spacing::Alone, span)), + TokenTree::Ident(Ident::new("std", span)), + TokenTree::Punct(punct(':', Spacing::Joint, span)), + TokenTree::Punct(punct(':', Spacing::Alone, span)), + TokenTree::Ident(Ident::new("fmt", span)), + TokenTree::Punct(punct(':', Spacing::Joint, span)), + TokenTree::Punct(punct(':', Spacing::Alone, span)), + TokenTree::Ident(Ident::new("Formatter", span)), + ]), + )), + TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), + ]) +} + +fn punct(ch: char, spacing: Spacing, span: Span) -> Punct { + let mut punct = Punct::new(ch, spacing); + punct.set_span(span); + punct +} diff --git a/src/test/ui/lifetimes/issue-91763.rs b/src/test/ui/lifetimes/issue-91763.rs new file mode 100644 index 0000000000000..2e8807fe639ac --- /dev/null +++ b/src/test/ui/lifetimes/issue-91763.rs @@ -0,0 +1,11 @@ +// aux-build:issue-91763-aux.rs + +#![deny(elided_lifetimes_in_paths)] + +extern crate issue_91763_aux; + +#[issue_91763_aux::repro] +fn f() -> Ptr; +//~^ ERROR hidden lifetime parameters in types are deprecated + +fn main() {} diff --git a/src/test/ui/lifetimes/issue-91763.stderr b/src/test/ui/lifetimes/issue-91763.stderr new file mode 100644 index 0000000000000..1b1912c8e4544 --- /dev/null +++ b/src/test/ui/lifetimes/issue-91763.stderr @@ -0,0 +1,14 @@ +error: hidden lifetime parameters in types are deprecated + --> $DIR/issue-91763.rs:8:20 + | +LL | fn f() -> Ptr; + | ^ expected named lifetime parameter + | +note: the lint level is defined here + --> $DIR/issue-91763.rs:3:9 + | +LL | #![deny(elided_lifetimes_in_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 9063b64cff102c63f542452fa23d414c75a25ba7 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 11 Dec 2021 17:10:56 +0100 Subject: [PATCH 11/13] Fix zero-sized reference to deallocated memory fixes #91772 --- library/alloc/src/vec/drain.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 089cd4db64c1d..1bff19d05c10d 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -128,10 +128,6 @@ impl Drop for Drain<'_, T, A> { let iter = mem::replace(&mut self.iter, (&mut []).iter()); let drop_len = iter.len(); - let drop_ptr = iter.as_slice().as_ptr(); - - // forget iter so there's no aliasing reference - drop(iter); let mut vec = self.vec; @@ -155,6 +151,12 @@ impl Drop for Drain<'_, T, A> { return; } + // as_slice() must only be called when iter.len() is > 0 because + // vec::Splice modifies vec::Drain fields and may grow the vec which would invalidate + // the iterator's internal pointers. Creating a reference to deallocated memory + // is invalid even when it is zero-length + let drop_ptr = iter.as_slice().as_ptr(); + unsafe { // drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place // a pointer with mutable provenance is necessary. Therefore we must reconstruct From 17766f88ff4661fc25d4c86ae15e187200be74fc Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 11 Dec 2021 17:29:29 +0000 Subject: [PATCH 12/13] Fix AArch64 asm ui tests --- src/test/ui/asm/aarch64/bad-reg.rs | 2 -- src/test/ui/asm/aarch64/bad-reg.stderr | 28 ++++++++++---------------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs index 4d7a7fd31feca..e346f8d992aa5 100644 --- a/src/test/ui/asm/aarch64/bad-reg.rs +++ b/src/test/ui/asm/aarch64/bad-reg.rs @@ -29,8 +29,6 @@ fn main() { //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand asm!("", in("xzr") foo); //~^ ERROR invalid register `xzr`: the zero register cannot be used as an operand - asm!("", in("x18") foo); - //~^ ERROR invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm asm!("", in("x19") foo); //~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm diff --git a/src/test/ui/asm/aarch64/bad-reg.stderr b/src/test/ui/asm/aarch64/bad-reg.stderr index 091e6077ef404..42f2a5d72ec09 100644 --- a/src/test/ui/asm/aarch64/bad-reg.stderr +++ b/src/test/ui/asm/aarch64/bad-reg.stderr @@ -74,38 +74,32 @@ error: invalid register `xzr`: the zero register cannot be used as an operand fo LL | asm!("", in("xzr") foo); | ^^^^^^^^^^^^^ -error: invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 - | -LL | asm!("", in("x18") foo); - | ^^^^^^^^^^^^^ - error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:32:18 | LL | asm!("", in("x19") foo); | ^^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:37:18 + --> $DIR/bad-reg.rs:35:18 | LL | asm!("", in("p0") foo); | ^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:40:20 + --> $DIR/bad-reg.rs:38:20 | LL | asm!("{}", in(preg) foo); | ^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:42:20 + --> $DIR/bad-reg.rs:40:20 | LL | asm!("{}", out(preg) _); | ^^^^^^^^^^^ error: register `x0` conflicts with register `x0` - --> $DIR/bad-reg.rs:48:32 + --> $DIR/bad-reg.rs:46:32 | LL | asm!("", in("x0") foo, in("w0") bar); | ------------ ^^^^^^^^^^^^ register `x0` @@ -113,7 +107,7 @@ LL | asm!("", in("x0") foo, in("w0") bar); | register `x0` error: register `x0` conflicts with register `x0` - --> $DIR/bad-reg.rs:50:32 + --> $DIR/bad-reg.rs:48:32 | LL | asm!("", in("x0") foo, out("x0") bar); | ------------ ^^^^^^^^^^^^^ register `x0` @@ -121,13 +115,13 @@ LL | asm!("", in("x0") foo, out("x0") bar); | register `x0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:50:18 + --> $DIR/bad-reg.rs:48:18 | LL | asm!("", in("x0") foo, out("x0") bar); | ^^^^^^^^^^^^ error: register `v0` conflicts with register `v0` - --> $DIR/bad-reg.rs:53:32 + --> $DIR/bad-reg.rs:51:32 | LL | asm!("", in("v0") foo, in("q0") bar); | ------------ ^^^^^^^^^^^^ register `v0` @@ -135,7 +129,7 @@ LL | asm!("", in("v0") foo, in("q0") bar); | register `v0` error: register `v0` conflicts with register `v0` - --> $DIR/bad-reg.rs:55:32 + --> $DIR/bad-reg.rs:53:32 | LL | asm!("", in("v0") foo, out("q0") bar); | ------------ ^^^^^^^^^^^^^ register `v0` @@ -143,10 +137,10 @@ LL | asm!("", in("v0") foo, out("q0") bar); | register `v0` | help: use `lateout` instead of `out` to avoid conflict - --> $DIR/bad-reg.rs:55:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", in("v0") foo, out("q0") bar); | ^^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors From 34eaf52829b193c8a87c17b4011e342ebf7ca90a Mon Sep 17 00:00:00 2001 From: woppopo Date: Sun, 12 Dec 2021 04:27:43 +0900 Subject: [PATCH 13/13] Make `Unique`s methods `const` --- library/core/src/lib.rs | 1 + library/core/src/ptr/unique.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 78383b54c5d1e..d9a40a9b2ec0d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -124,6 +124,7 @@ #![feature(const_option)] #![feature(const_pin)] #![feature(const_replace)] +#![feature(const_ptr_is_null)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] #![feature(const_ptr_read)] diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index d650a6f974b97..f5c624c225f26 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -92,7 +92,7 @@ impl Unique { /// Creates a new `Unique` if `ptr` is non-null. #[inline] - pub fn new(ptr: *mut T) -> Option { + pub const fn new(ptr: *mut T) -> Option { if !ptr.is_null() { // SAFETY: The pointer has already been checked and is not null. Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }) @@ -115,7 +115,7 @@ impl Unique { /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. #[must_use] #[inline] - pub unsafe fn as_ref(&self) -> &T { + pub const unsafe fn as_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.as_ptr() } @@ -128,7 +128,7 @@ impl Unique { /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. #[must_use] #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { + pub const unsafe fn as_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a mutable reference. unsafe { &mut *self.as_ptr() }