Skip to content

Commit f858854

Browse files
committed
Auto merge of rust-lang#99422 - Dylan-DPC:rollup-htjofm6, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - rust-lang#98839 (Add assertion that `transmute_copy`'s U is not larger than T) - rust-lang#98998 (Remove branch target prologues from `#[naked] fn`) - rust-lang#99198 (add missing null ptr check in alloc example) - rust-lang#99344 (rustdoc: avoid inlining items with duplicate `(type, name)`) - rust-lang#99351 (Use `typeck_results` to get accurate qpath res for arg mismatch error) - rust-lang#99378 (interpret/visitor: add missing early return) - rust-lang#99394 (Add regression test for rust-lang#95230) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents ed91732 + 068a559 commit f858854

21 files changed

+233
-21
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

+6
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ pub fn from_fn_attrs<'ll, 'tcx>(
299299
}
300300
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
301301
to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
302+
// HACK(jubilee): "indirect branch tracking" works by attaching prologues to functions.
303+
// And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules.
304+
// Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768
305+
to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
306+
// Need this for AArch64.
307+
to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
302308
}
303309
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
304310
// apply to return place instead of function (unlike all other attributes applied in this function)

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ pub enum AttributeKind {
191191
StackProtect = 32,
192192
NoUndef = 33,
193193
SanitizeMemTag = 34,
194+
NoCfCheck = 35,
194195
}
195196

196197
/// LLVMIntPredicate

compiler/rustc_const_eval/src/interpret/visitor.rs

+3
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,9 @@ macro_rules! make_value_visitor {
473473
// The second `Box` field is the allocator, which we recursively check for validity
474474
// like in regular structs.
475475
self.visit_field(v, 1, &alloc)?;
476+
477+
// We visited all parts of this one.
478+
return Ok(());
476479
}
477480
_ => {},
478481
};

compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum LLVMRustAttribute {
8484
StackProtect = 32,
8585
NoUndef = 33,
8686
SanitizeMemTag = 34,
87+
NoCfCheck = 35,
8788
};
8889

8990
typedef struct OpaqueRustString *RustStringRef;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
176176
return Attribute::NoAlias;
177177
case NoCapture:
178178
return Attribute::NoCapture;
179+
case NoCfCheck:
180+
return Attribute::NoCfCheck;
179181
case NoInline:
180182
return Attribute::NoInline;
181183
case NonNull:

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -443,17 +443,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
443443
// Next, let's construct the error
444444
let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
445445
hir::ExprKind::Call(
446-
hir::Expr {
447-
span,
448-
kind:
449-
hir::ExprKind::Path(hir::QPath::Resolved(
450-
_,
451-
hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. },
452-
)),
453-
..
454-
},
446+
hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
455447
_,
456-
) => (call_span, *span, Some(of)),
448+
) => {
449+
if let Res::Def(DefKind::Ctor(of, _), _) =
450+
self.typeck_results.borrow().qpath_res(qpath, *hir_id)
451+
{
452+
(call_span, *span, Some(of))
453+
} else {
454+
(call_span, *span, None)
455+
}
456+
}
457457
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
458458
hir::ExprKind::MethodCall(path_segment, _, span) => {
459459
let ident_span = path_segment.ident.span;

library/alloc/src/alloc.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,14 @@ pub use std::alloc::Global;
7070
/// # Examples
7171
///
7272
/// ```
73-
/// use std::alloc::{alloc, dealloc, Layout};
73+
/// use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
7474
///
7575
/// unsafe {
7676
/// let layout = Layout::new::<u16>();
7777
/// let ptr = alloc(layout);
78+
/// if ptr.is_null() {
79+
/// handle_alloc_error(layout);
80+
/// }
7881
///
7982
/// *(ptr as *mut u16) = 42;
8083
/// assert_eq!(*(ptr as *mut u16), 42);

library/core/src/mem/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,8 @@ pub fn copy<T: Copy>(x: &T) -> T {
10401040
#[stable(feature = "rust1", since = "1.0.0")]
10411041
#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
10421042
pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
1043+
assert!(size_of::<T>() >= size_of::<U>(), "cannot transmute_copy if U is larger than T");
1044+
10431045
// If U has a higher alignment requirement, src might not be suitably aligned.
10441046
if align_of::<U>() > align_of::<T>() {
10451047
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.

library/core/tests/mem.rs

+40
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,46 @@ fn test_transmute_copy() {
9797
assert_eq!(1, unsafe { transmute_copy(&1) });
9898
}
9999

100+
#[test]
101+
fn test_transmute_copy_shrink() {
102+
assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
103+
}
104+
105+
#[test]
106+
fn test_transmute_copy_unaligned() {
107+
#[repr(C)]
108+
#[derive(Default)]
109+
struct Unaligned {
110+
a: u8,
111+
b: [u8; 8],
112+
}
113+
114+
let u = Unaligned::default();
115+
assert_eq!(0_u64, unsafe { transmute_copy(&u.b) });
116+
}
117+
118+
#[test]
119+
#[cfg(panic = "unwind")]
120+
fn test_transmute_copy_grow_panics() {
121+
use std::panic;
122+
123+
let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
124+
let _unused: u64 = transmute_copy(&1_u8);
125+
}));
126+
127+
match err {
128+
Ok(_) => unreachable!(),
129+
Err(payload) => {
130+
payload
131+
.downcast::<&'static str>()
132+
.and_then(|s| {
133+
if *s == "cannot transmute_copy if U is larger than T" { Ok(s) } else { Err(s) }
134+
})
135+
.unwrap_or_else(|p| panic::resume_unwind(p));
136+
}
137+
}
138+
}
139+
100140
#[test]
101141
#[allow(dead_code)]
102142
fn test_discriminant_send_sync() {

src/librustdoc/clean/mod.rs

+37-5
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,43 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
5757
.map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)),
5858
);
5959
items.extend(self.mods.iter().map(|x| x.clean(cx)));
60-
items.extend(
61-
self.items
62-
.iter()
63-
.flat_map(|(item, renamed)| clean_maybe_renamed_item(cx, item, *renamed)),
64-
);
60+
61+
// Split up imports from all other items.
62+
//
63+
// This covers the case where somebody does an import which should pull in an item,
64+
// but there's already an item with the same namespace and same name. Rust gives
65+
// priority to the not-imported one, so we should, too.
66+
let mut inserted = FxHashSet::default();
67+
items.extend(self.items.iter().flat_map(|(item, renamed)| {
68+
// First, lower everything other than imports.
69+
if matches!(item.kind, hir::ItemKind::Use(..)) {
70+
return Vec::new();
71+
}
72+
let v = clean_maybe_renamed_item(cx, item, *renamed);
73+
for item in &v {
74+
if let Some(name) = item.name {
75+
inserted.insert((item.type_(), name));
76+
}
77+
}
78+
v
79+
}));
80+
items.extend(self.items.iter().flat_map(|(item, renamed)| {
81+
// Now we actually lower the imports, skipping everything else.
82+
if !matches!(item.kind, hir::ItemKind::Use(..)) {
83+
return Vec::new();
84+
}
85+
let mut v = clean_maybe_renamed_item(cx, item, *renamed);
86+
v.drain_filter(|item| {
87+
if let Some(name) = item.name {
88+
// If an item with the same type and name already exists,
89+
// it takes priority over the inlined stuff.
90+
!inserted.insert((item.type_(), name))
91+
} else {
92+
false
93+
}
94+
});
95+
v
96+
}));
6597

6698
// determine if we should display the inner contents or
6799
// the outer `mod` item for the source code.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -C no-prepopulate-passes -Zbranch-protection=bti
2+
// assembly-output: emit-asm
3+
// needs-asm-support
4+
// only-aarch64
5+
6+
#![crate_type = "lib"]
7+
#![feature(naked_functions)]
8+
use std::arch::asm;
9+
10+
// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
11+
// meaning "no prologue whatsoever, no, really, not one instruction."
12+
// Unfortunately, aarch64's "branch target identification" works via hints at landing sites.
13+
// LLVM implements this via making sure of that, even for functions with the naked attribute.
14+
// So, we must emit an appropriate instruction instead!
15+
#[no_mangle]
16+
#[naked]
17+
pub unsafe extern "C" fn _hlt() -> ! {
18+
// CHECK-NOT: hint #34
19+
// CHECK: hlt #0x1
20+
asm!("hlt #1", options(noreturn))
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// compile-flags: -C no-prepopulate-passes -Zcf-protection=full
2+
// assembly-output: emit-asm
3+
// needs-asm-support
4+
// only-x86_64
5+
6+
#![crate_type = "lib"]
7+
#![feature(naked_functions)]
8+
use std::arch::asm;
9+
10+
// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
11+
// meaning "no prologue whatsoever, no, really, not one instruction."
12+
// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection,
13+
// works by using an instruction for each possible landing site,
14+
// and LLVM implements this via making sure of that.
15+
#[no_mangle]
16+
#[naked]
17+
pub unsafe extern "sysv64" fn will_halt() -> ! {
18+
// CHECK-NOT: endbr{{32|64}}
19+
// CHECK: hlt
20+
asm!("hlt", options(noreturn))
21+
}
22+
23+
// what about aarch64?
24+
// "branch-protection"=false

src/test/codegen/naked-noinline.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ pub unsafe fn g() {
2828
f();
2929
}
3030

31-
// CHECK: attributes [[ATTR]] = { naked noinline{{.*}} }
31+
// CHECK: attributes [[ATTR]] = { naked{{.*}}noinline{{.*}} }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
pub struct Option;
2+
impl Option {
3+
pub fn unwrap(self) {}
4+
}
5+
6+
mod macros {
7+
use crate::Option;
8+
/// [`Option::unwrap`]
9+
#[macro_export]
10+
macro_rules! print {
11+
() => ()
12+
}
13+
}
14+
15+
mod structs {
16+
use crate::Option;
17+
/// [`Option::unwrap`]
18+
pub struct Print;
19+
}
20+
pub use structs::Print;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// aux-build:issue-99221-aux.rs
2+
// build-aux-docs
3+
// ignore-cross-compile
4+
5+
#![crate_name = "foo"]
6+
7+
#[macro_use]
8+
extern crate issue_99221_aux;
9+
10+
pub use issue_99221_aux::*;
11+
12+
// @count foo/index.html '//a[@class="macro"]' 1
13+
14+
mod inner {
15+
#[macro_export]
16+
macro_rules! print {
17+
() => ()
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// aux-build:issue-99221-aux.rs
2+
// build-aux-docs
3+
// ignore-cross-compile
4+
5+
#![crate_name = "foo"]
6+
7+
#[macro_use]
8+
extern crate issue_99221_aux;
9+
10+
pub use issue_99221_aux::*;
11+
12+
// @count foo/index.html '//a[@class="macro"]' 1
13+
14+
#[macro_export]
15+
macro_rules! print {
16+
() => ()
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// aux-build:issue-99221-aux.rs
2+
// build-aux-docs
3+
// ignore-cross-compile
4+
5+
#![crate_name = "foo"]
6+
7+
#[macro_use]
8+
extern crate issue_99221_aux;
9+
10+
pub use issue_99221_aux::*;
11+
12+
// @count foo/index.html '//a[@class="struct"][@title="foo::Print struct"]' 1
13+
14+
pub struct Print;

src/test/ui/hrtb/issue-95230.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// check-pass
2+
3+
pub struct Bar
4+
where
5+
for<'a> &'a mut Self:;
6+
7+
fn main() {}

src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | fn ts_variant() {
77
LL | Self::TSVariant(());
88
| --------------- ^^ expected type parameter `T`, found `()`
99
| |
10-
| arguments to this function are incorrect
10+
| arguments to this enum variant are incorrect
1111
|
1212
= note: expected type parameter `T`
1313
found unit type `()`
@@ -55,7 +55,7 @@ LL | impl<T> Enum<T> {
5555
LL | Self::<()>::TSVariant(());
5656
| --------------------- ^^ expected type parameter `T`, found `()`
5757
| |
58-
| arguments to this function are incorrect
58+
| arguments to this enum variant are incorrect
5959
|
6060
= note: expected type parameter `T`
6161
found unit type `()`

src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ impl E2 {
1818
}
1919

2020
fn main() {
21-
<E>::V(); //~ ERROR this function takes 1 argument but 0 arguments were supplied
21+
<E>::V(); //~ ERROR this enum variant takes 1 argument but 0 arguments were supplied
2222
let _: u8 = <E2>::V; //~ ERROR mismatched types
2323
}

src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0061]: this function takes 1 argument but 0 arguments were supplied
1+
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
22
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
33
|
44
LL | <E>::V();

0 commit comments

Comments
 (0)