Skip to content

Commit e70e4d4

Browse files
committed
Auto merge of rust-lang#91813 - matthiaskrgr:rollup-nryyeyj, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#90081 (Make `intrinsics::write_bytes` const) - rust-lang#91643 (asm: Allow using r9 (ARM) and x18 (AArch64) if they are not reserved by the current target) - rust-lang#91737 (Make certain panicky stdlib functions behave better under panic_immediate_abort) - rust-lang#91750 (rustdoc: Add regression test for Iterator as notable trait on &T) - rust-lang#91764 (Do not ICE when suggesting elided lifetimes on non-existent spans.) - rust-lang#91780 (Remove hir::Node::hir_id.) - rust-lang#91797 (Fix zero-sized reference to deallocated memory) - rust-lang#91806 (Make `Unique`s methods `const`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 229d0a9 + 9031ac4 commit e70e4d4

File tree

24 files changed

+289
-92
lines changed

24 files changed

+289
-92
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6464
let mut clobber_abis = FxHashMap::default();
6565
if let Some(asm_arch) = asm_arch {
6666
for (abi_name, abi_span) in &asm.clobber_abis {
67-
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) {
67+
match asm::InlineAsmClobberAbi::parse(
68+
asm_arch,
69+
|feature| self.sess.target_features.contains(&Symbol::intern(feature)),
70+
&self.sess.target,
71+
*abi_name,
72+
) {
6873
Ok(abi) => {
6974
// If the abi was already in the list, emit an error
7075
match clobber_abis.get(&abi) {

compiler/rustc_codegen_ssa/src/target_features.rs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
3636
// #[target_feature].
3737
("thumb-mode", Some(sym::arm_target_feature)),
3838
("thumb2", Some(sym::arm_target_feature)),
39+
("reserve-r9", Some(sym::arm_target_feature)),
3940
];
4041

4142
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+24
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
322322
sym::copy => {
323323
self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
324324
}
325+
sym::write_bytes => {
326+
self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?;
327+
}
325328
sym::offset => {
326329
let ptr = self.read_pointer(&args[0])?;
327330
let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?;
@@ -567,6 +570,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
567570
self.memory.copy(src, align, dst, align, size, nonoverlapping)
568571
}
569572

573+
pub(crate) fn write_bytes_intrinsic(
574+
&mut self,
575+
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
576+
byte: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
577+
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
578+
) -> InterpResult<'tcx> {
579+
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?;
580+
581+
let dst = self.read_pointer(&dst)?;
582+
let byte = self.read_scalar(&byte)?.to_u8()?;
583+
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
584+
585+
let len = layout
586+
.size
587+
.checked_mul(count, self)
588+
.ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?;
589+
590+
let bytes = std::iter::repeat(byte).take(len.bytes_usize());
591+
self.memory.write_bytes(dst, bytes)
592+
}
593+
570594
pub(crate) fn raw_eq_intrinsic(
571595
&mut self,
572596
lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,

compiler/rustc_hir/src/hir.rs

-28
Original file line numberDiff line numberDiff line change
@@ -3210,34 +3210,6 @@ impl<'hir> Node<'hir> {
32103210
}
32113211
}
32123212

3213-
pub fn hir_id(&self) -> Option<HirId> {
3214-
match self {
3215-
Node::Item(Item { def_id, .. })
3216-
| Node::TraitItem(TraitItem { def_id, .. })
3217-
| Node::ImplItem(ImplItem { def_id, .. })
3218-
| Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)),
3219-
Node::Field(FieldDef { hir_id, .. })
3220-
| Node::AnonConst(AnonConst { hir_id, .. })
3221-
| Node::Expr(Expr { hir_id, .. })
3222-
| Node::Stmt(Stmt { hir_id, .. })
3223-
| Node::Ty(Ty { hir_id, .. })
3224-
| Node::Binding(Pat { hir_id, .. })
3225-
| Node::Pat(Pat { hir_id, .. })
3226-
| Node::Arm(Arm { hir_id, .. })
3227-
| Node::Block(Block { hir_id, .. })
3228-
| Node::Local(Local { hir_id, .. })
3229-
| Node::Lifetime(Lifetime { hir_id, .. })
3230-
| Node::Param(Param { hir_id, .. })
3231-
| Node::Infer(InferArg { hir_id, .. })
3232-
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
3233-
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
3234-
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
3235-
Node::Variant(Variant { id, .. }) => Some(*id),
3236-
Node::Ctor(variant) => variant.ctor_hir_id(),
3237-
Node::Crate(_) | Node::Visibility(_) => None,
3238-
}
3239-
}
3240-
32413213
/// Returns `Constness::Const` when this node is a const fn/impl/item.
32423214
pub fn constness_for_typeck(&self) -> Constness {
32433215
match self {

compiler/rustc_lint/src/context.rs

+1-20
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
2222
use rustc_ast as ast;
2323
use rustc_data_structures::fx::FxHashMap;
2424
use rustc_data_structures::sync;
25-
use rustc_errors::{
26-
add_elided_lifetime_in_path_suggestion, struct_span_err, Applicability, SuggestionStyle,
27-
};
25+
use rustc_errors::{struct_span_err, Applicability, SuggestionStyle};
2826
use rustc_hir as hir;
2927
use rustc_hir::def::Res;
3028
use rustc_hir::def_id::{CrateNum, DefId};
@@ -670,23 +668,6 @@ pub trait LintContext: Sized {
670668
) => {
671669
db.span_note(span_def, "the macro is defined here");
672670
}
673-
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
674-
n,
675-
path_span,
676-
incl_angl_brckt,
677-
insertion_span,
678-
anon_lts,
679-
) => {
680-
add_elided_lifetime_in_path_suggestion(
681-
sess.source_map(),
682-
&mut db,
683-
n,
684-
path_span,
685-
incl_angl_brckt,
686-
insertion_span,
687-
anon_lts,
688-
);
689-
}
690671
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
691672
db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
692673
}

compiler/rustc_lint_defs/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ pub enum BuiltinLintDiagnostics {
289289
AbsPathWithModule(Span),
290290
ProcMacroDeriveResolutionFallback(Span),
291291
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
292-
ElidedLifetimesInPaths(usize, Span, bool, Span, String),
293292
UnknownCrateTypes(Span, String, String),
294293
UnusedImports(String, Vec<(Span, String)>),
295294
RedundantImport(Vec<(Span, bool)>, Ident),

compiler/rustc_resolve/src/late/diagnostics.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,11 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
21152115
})
21162116
.map(|(formatter, span)| (*span, formatter(name)))
21172117
.collect();
2118+
if spans_suggs.is_empty() {
2119+
// If all the spans come from macros, we cannot extract snippets and then
2120+
// `formatters` only contains None and `spans_suggs` is empty.
2121+
return;
2122+
}
21182123
err.multipart_suggestion_verbose(
21192124
&format!(
21202125
"consider using the `{}` lifetime",

compiler/rustc_target/src/asm/aarch64.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{InlineAsmArch, InlineAsmType};
2+
use crate::spec::Target;
23
use rustc_macros::HashStable_Generic;
34
use std::fmt;
45

@@ -70,6 +71,22 @@ impl AArch64InlineAsmRegClass {
7071
}
7172
}
7273

74+
pub fn reserved_x18(
75+
_arch: InlineAsmArch,
76+
_has_feature: impl FnMut(&str) -> bool,
77+
target: &Target,
78+
) -> Result<(), &'static str> {
79+
if target.os == "android"
80+
|| target.is_like_fuchsia
81+
|| target.is_like_osx
82+
|| target.is_like_windows
83+
{
84+
Err("x18 is a reserved register on this target")
85+
} else {
86+
Ok(())
87+
}
88+
}
89+
7390
def_regs! {
7491
AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass {
7592
x0: reg = ["x0", "w0"],
@@ -90,6 +107,7 @@ def_regs! {
90107
x15: reg = ["x15", "w15"],
91108
x16: reg = ["x16", "w16"],
92109
x17: reg = ["x17", "w17"],
110+
x18: reg = ["x18", "w18"] % reserved_x18,
93111
x20: reg = ["x20", "w20"],
94112
x21: reg = ["x21", "w21"],
95113
x22: reg = ["x22", "w22"],
@@ -149,8 +167,6 @@ def_regs! {
149167
p14: preg = ["p14"],
150168
p15: preg = ["p15"],
151169
ffr: preg = ["ffr"],
152-
#error = ["x18", "w18"] =>
153-
"x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm",
154170
#error = ["x19", "w19"] =>
155171
"x19 is used internally by LLVM and cannot be used as an operand for inline asm",
156172
#error = ["x29", "w29", "fp", "wfp"] =>

compiler/rustc_target/src/asm/arm.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,22 @@ fn not_thumb1(
9999
}
100100
}
101101

102+
fn reserved_r9(
103+
arch: InlineAsmArch,
104+
mut has_feature: impl FnMut(&str) -> bool,
105+
target: &Target,
106+
) -> Result<(), &'static str> {
107+
not_thumb1(arch, &mut has_feature, target)?;
108+
109+
// We detect this using the reserved-r9 feature instead of using the target
110+
// because the relocation model can be changed with compiler options.
111+
if has_feature("reserved-r9") {
112+
Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
113+
} else {
114+
Ok(())
115+
}
116+
}
117+
102118
def_regs! {
103119
Arm ArmInlineAsmReg ArmInlineAsmRegClass {
104120
r0: reg = ["r0", "a1"],
@@ -109,6 +125,7 @@ def_regs! {
109125
r5: reg = ["r5", "v2"],
110126
r7: reg = ["r7", "v4"] % frame_pointer_r7,
111127
r8: reg = ["r8", "v5"] % not_thumb1,
128+
r9: reg = ["r9", "v6", "rfp"] % reserved_r9,
112129
r10: reg = ["r10", "sl"] % not_thumb1,
113130
r11: reg = ["r11", "fp"] % frame_pointer_r11,
114131
r12: reg = ["r12", "ip"] % not_thumb1,
@@ -195,8 +212,6 @@ def_regs! {
195212
q15: qreg = ["q15"],
196213
#error = ["r6", "v3"] =>
197214
"r6 is used internally by LLVM and cannot be used as an operand for inline asm",
198-
#error = ["r9", "v6", "rfp"] =>
199-
"r9 is used internally by LLVM and cannot be used as an operand for inline asm",
200215
#error = ["r13", "sp"] =>
201216
"the stack pointer cannot be used as an operand for inline asm",
202217
#error = ["r15", "pc"] =>

compiler/rustc_target/src/asm/mod.rs

+30-4
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ pub enum InlineAsmClobberAbi {
785785
X86_64SysV,
786786
Arm,
787787
AArch64,
788+
AArch64NoX18,
788789
RiscV,
789790
}
790791

@@ -793,6 +794,7 @@ impl InlineAsmClobberAbi {
793794
/// clobber ABIs for the target.
794795
pub fn parse(
795796
arch: InlineAsmArch,
797+
has_feature: impl FnMut(&str) -> bool,
796798
target: &Target,
797799
name: Symbol,
798800
) -> Result<Self, &'static [&'static str]> {
@@ -816,7 +818,13 @@ impl InlineAsmClobberAbi {
816818
_ => Err(&["C", "system", "efiapi", "aapcs"]),
817819
},
818820
InlineAsmArch::AArch64 => match name {
819-
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64),
821+
"C" | "system" | "efiapi" => {
822+
Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() {
823+
InlineAsmClobberAbi::AArch64NoX18
824+
} else {
825+
InlineAsmClobberAbi::AArch64
826+
})
827+
}
820828
_ => Err(&["C", "system", "efiapi"]),
821829
},
822830
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
@@ -891,8 +899,25 @@ impl InlineAsmClobberAbi {
891899
AArch64 AArch64InlineAsmReg {
892900
x0, x1, x2, x3, x4, x5, x6, x7,
893901
x8, x9, x10, x11, x12, x13, x14, x15,
894-
// x18 is platform-reserved or temporary, but we exclude it
895-
// here since it is a reserved register.
902+
x16, x17, x18, x30,
903+
904+
// Technically the low 64 bits of v8-v15 are preserved, but
905+
// we have no way of expressing this using clobbers.
906+
v0, v1, v2, v3, v4, v5, v6, v7,
907+
v8, v9, v10, v11, v12, v13, v14, v15,
908+
v16, v17, v18, v19, v20, v21, v22, v23,
909+
v24, v25, v26, v27, v28, v29, v30, v31,
910+
911+
p0, p1, p2, p3, p4, p5, p6, p7,
912+
p8, p9, p10, p11, p12, p13, p14, p15,
913+
ffr,
914+
915+
}
916+
},
917+
InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! {
918+
AArch64 AArch64InlineAsmReg {
919+
x0, x1, x2, x3, x4, x5, x6, x7,
920+
x8, x9, x10, x11, x12, x13, x14, x15,
896921
x16, x17, x30,
897922

898923
// Technically the low 64 bits of v8-v15 are preserved, but
@@ -910,7 +935,8 @@ impl InlineAsmClobberAbi {
910935
},
911936
InlineAsmClobberAbi::Arm => clobbered_regs! {
912937
Arm ArmInlineAsmReg {
913-
// r9 is platform-reserved and is treated as callee-saved.
938+
// r9 is either platform-reserved or callee-saved. Either
939+
// way we don't need to clobber it.
914940
r0, r1, r2, r3, r12, r14,
915941

916942
// The finest-grained register variant is used here so that

library/alloc/src/vec/drain.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,6 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
128128

129129
let iter = mem::replace(&mut self.iter, (&mut []).iter());
130130
let drop_len = iter.len();
131-
let drop_ptr = iter.as_slice().as_ptr();
132-
133-
// forget iter so there's no aliasing reference
134-
drop(iter);
135131

136132
let mut vec = self.vec;
137133

@@ -155,6 +151,12 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
155151
return;
156152
}
157153

154+
// as_slice() must only be called when iter.len() is > 0 because
155+
// vec::Splice modifies vec::Drain fields and may grow the vec which would invalidate
156+
// the iterator's internal pointers. Creating a reference to deallocated memory
157+
// is invalid even when it is zero-length
158+
let drop_ptr = iter.as_slice().as_ptr();
159+
158160
unsafe {
159161
// drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place
160162
// a pointer with mutable provenance is necessary. Therefore we must reconstruct

library/core/src/intrinsics.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -2244,13 +2244,29 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
22442244
/// assert_eq!(*v, 42);
22452245
/// ```
22462246
#[stable(feature = "rust1", since = "1.0.0")]
2247+
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
22472248
#[inline]
2248-
pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
2249+
pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
22492250
extern "rust-intrinsic" {
2251+
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
22502252
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
22512253
}
22522254

2253-
debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
2255+
#[cfg(debug_assertions)]
2256+
fn runtime_check<T>(ptr: *mut T) {
2257+
debug_assert!(
2258+
is_aligned_and_not_null(ptr),
2259+
"attempt to write to unaligned or null pointer"
2260+
);
2261+
}
2262+
#[cfg(debug_assertions)]
2263+
const fn compiletime_check<T>(_ptr: *mut T) {}
2264+
#[cfg(debug_assertions)]
2265+
// SAFETY: runtime debug-assertions are a best-effort basis; it's fine to
2266+
// not do them during compile time
2267+
unsafe {
2268+
const_eval_select((dst,), compiletime_check, runtime_check);
2269+
}
22542270

22552271
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
22562272
unsafe { write_bytes(dst, val, count) }

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
#![feature(const_option)]
125125
#![feature(const_pin)]
126126
#![feature(const_replace)]
127+
#![feature(const_ptr_is_null)]
127128
#![feature(const_ptr_offset)]
128129
#![feature(const_ptr_offset_from)]
129130
#![feature(const_ptr_read)]

library/core/src/option.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,8 @@ impl<T, E> Option<Result<T, E>> {
16711671
}
16721672

16731673
// This is a separate function to reduce the code size of .expect() itself.
1674-
#[inline(never)]
1674+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
1675+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
16751676
#[cold]
16761677
#[track_caller]
16771678
const fn expect_failed(msg: &str) -> ! {

0 commit comments

Comments
 (0)