Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #99422

Merged
merged 15 commits into from
Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ pub fn from_fn_attrs<'ll, 'tcx>(
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
// HACK(jubilee): "indirect branch tracking" works by attaching prologues to functions.
// And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules.
// Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768
to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
// Need this for AArch64.
to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
// apply to return place instead of function (unlike all other attributes applied in this function)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ pub enum AttributeKind {
StackProtect = 32,
NoUndef = 33,
SanitizeMemTag = 34,
NoCfCheck = 35,
}

/// LLVMIntPredicate
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_const_eval/src/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,9 @@ macro_rules! make_value_visitor {
// The second `Box` field is the allocator, which we recursively check for validity
// like in regular structs.
self.visit_field(v, 1, &alloc)?;

// We visited all parts of this one.
return Ok(());
}
_ => {},
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum LLVMRustAttribute {
StackProtect = 32,
NoUndef = 33,
SanitizeMemTag = 34,
NoCfCheck = 35,
};

typedef struct OpaqueRustString *RustStringRef;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
return Attribute::NoAlias;
case NoCapture:
return Attribute::NoCapture;
case NoCfCheck:
return Attribute::NoCfCheck;
case NoInline:
return Attribute::NoInline;
case NonNull:
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,17 +443,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Next, let's construct the error
let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
hir::ExprKind::Call(
hir::Expr {
span,
kind:
hir::ExprKind::Path(hir::QPath::Resolved(
_,
hir::Path { res: Res::Def(DefKind::Ctor(of, _), _), .. },
)),
..
},
hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
_,
) => (call_span, *span, Some(of)),
) => {
if let Res::Def(DefKind::Ctor(of, _), _) =
self.typeck_results.borrow().qpath_res(qpath, *hir_id)
{
(call_span, *span, Some(of))
} else {
(call_span, *span, None)
}
}
hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
hir::ExprKind::MethodCall(path_segment, _, span) => {
let ident_span = path_segment.ident.span;
Expand Down
5 changes: 4 additions & 1 deletion library/alloc/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,14 @@ pub use std::alloc::Global;
/// # Examples
///
/// ```
/// use std::alloc::{alloc, dealloc, Layout};
/// use std::alloc::{alloc, dealloc, handle_alloc_error, Layout};
///
/// unsafe {
/// let layout = Layout::new::<u16>();
/// let ptr = alloc(layout);
/// if ptr.is_null() {
/// handle_alloc_error(layout);
/// }
///
/// *(ptr as *mut u16) = 42;
/// assert_eq!(*(ptr as *mut u16), 42);
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,8 @@ pub fn copy<T: Copy>(x: &T) -> T {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
assert!(size_of::<T>() >= size_of::<U>(), "cannot transmute_copy if U is larger than T");

// If U has a higher alignment requirement, src might not be suitably aligned.
if align_of::<U>() > align_of::<T>() {
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.
Expand Down
40 changes: 40 additions & 0 deletions library/core/tests/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,46 @@ fn test_transmute_copy() {
assert_eq!(1, unsafe { transmute_copy(&1) });
}

#[test]
fn test_transmute_copy_shrink() {
assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
}

#[test]
fn test_transmute_copy_unaligned() {
#[repr(C)]
#[derive(Default)]
struct Unaligned {
a: u8,
b: [u8; 8],
}

let u = Unaligned::default();
assert_eq!(0_u64, unsafe { transmute_copy(&u.b) });
}

#[test]
#[cfg(panic = "unwind")]
fn test_transmute_copy_grow_panics() {
use std::panic;

let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
let _unused: u64 = transmute_copy(&1_u8);
}));

match err {
Ok(_) => unreachable!(),
Err(payload) => {
payload
.downcast::<&'static str>()
.and_then(|s| {
if *s == "cannot transmute_copy if U is larger than T" { Ok(s) } else { Err(s) }
})
.unwrap_or_else(|p| panic::resume_unwind(p));
}
}
}

#[test]
#[allow(dead_code)]
fn test_discriminant_send_sync() {
Expand Down
42 changes: 37 additions & 5 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,43 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
.map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)),
);
items.extend(self.mods.iter().map(|x| x.clean(cx)));
items.extend(
self.items
.iter()
.flat_map(|(item, renamed)| clean_maybe_renamed_item(cx, item, *renamed)),
);

// Split up imports from all other items.
//
// This covers the case where somebody does an import which should pull in an item,
// but there's already an item with the same namespace and same name. Rust gives
// priority to the not-imported one, so we should, too.
let mut inserted = FxHashSet::default();
items.extend(self.items.iter().flat_map(|(item, renamed)| {
// First, lower everything other than imports.
if matches!(item.kind, hir::ItemKind::Use(..)) {
return Vec::new();
}
let v = clean_maybe_renamed_item(cx, item, *renamed);
for item in &v {
if let Some(name) = item.name {
inserted.insert((item.type_(), name));
}
}
v
}));
items.extend(self.items.iter().flat_map(|(item, renamed)| {
// Now we actually lower the imports, skipping everything else.
if !matches!(item.kind, hir::ItemKind::Use(..)) {
return Vec::new();
}
let mut v = clean_maybe_renamed_item(cx, item, *renamed);
v.drain_filter(|item| {
if let Some(name) = item.name {
// If an item with the same type and name already exists,
// it takes priority over the inlined stuff.
!inserted.insert((item.type_(), name))
} else {
false
}
});
v
}));

// determine if we should display the inner contents or
// the outer `mod` item for the source code.
Expand Down
21 changes: 21 additions & 0 deletions src/test/assembly/aarch64-naked-fn-no-bti-prolog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// compile-flags: -C no-prepopulate-passes -Zbranch-protection=bti
// assembly-output: emit-asm
// needs-asm-support
// only-aarch64

#![crate_type = "lib"]
#![feature(naked_functions)]
use std::arch::asm;

// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
// meaning "no prologue whatsoever, no, really, not one instruction."
// Unfortunately, aarch64's "branch target identification" works via hints at landing sites.
// LLVM implements this via making sure of that, even for functions with the naked attribute.
// So, we must emit an appropriate instruction instead!
#[no_mangle]
#[naked]
pub unsafe extern "C" fn _hlt() -> ! {
// CHECK-NOT: hint #34
// CHECK: hlt #0x1
asm!("hlt #1", options(noreturn))
}
24 changes: 24 additions & 0 deletions src/test/assembly/x86_64-naked-fn-no-cet-prolog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// compile-flags: -C no-prepopulate-passes -Zcf-protection=full
// assembly-output: emit-asm
// needs-asm-support
// only-x86_64

#![crate_type = "lib"]
#![feature(naked_functions)]
use std::arch::asm;

// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions",
// meaning "no prologue whatsoever, no, really, not one instruction."
// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection,
// works by using an instruction for each possible landing site,
// and LLVM implements this via making sure of that.
#[no_mangle]
#[naked]
pub unsafe extern "sysv64" fn will_halt() -> ! {
// CHECK-NOT: endbr{{32|64}}
// CHECK: hlt
asm!("hlt", options(noreturn))
}

// what about aarch64?
// "branch-protection"=false
2 changes: 1 addition & 1 deletion src/test/codegen/naked-noinline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ pub unsafe fn g() {
f();
}

// CHECK: attributes [[ATTR]] = { naked noinline{{.*}} }
// CHECK: attributes [[ATTR]] = { naked{{.*}}noinline{{.*}} }
20 changes: 20 additions & 0 deletions src/test/rustdoc/auxiliary/issue-99221-aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
pub struct Option;
impl Option {
pub fn unwrap(self) {}
}

mod macros {
use crate::Option;
/// [`Option::unwrap`]
#[macro_export]
macro_rules! print {
() => ()
}
}

mod structs {
use crate::Option;
/// [`Option::unwrap`]
pub struct Print;
}
pub use structs::Print;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// aux-build:issue-99221-aux.rs
// build-aux-docs
// ignore-cross-compile

#![crate_name = "foo"]

#[macro_use]
extern crate issue_99221_aux;

pub use issue_99221_aux::*;

// @count foo/index.html '//a[@class="macro"]' 1

mod inner {
#[macro_export]
macro_rules! print {
() => ()
}
}
17 changes: 17 additions & 0 deletions src/test/rustdoc/issue-99221-multiple-macro-rules-w-same-name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// aux-build:issue-99221-aux.rs
// build-aux-docs
// ignore-cross-compile

#![crate_name = "foo"]

#[macro_use]
extern crate issue_99221_aux;

pub use issue_99221_aux::*;

// @count foo/index.html '//a[@class="macro"]' 1

#[macro_export]
macro_rules! print {
() => ()
}
14 changes: 14 additions & 0 deletions src/test/rustdoc/issue-99221-multiple-structs-w-same-name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// aux-build:issue-99221-aux.rs
// build-aux-docs
// ignore-cross-compile

#![crate_name = "foo"]

#[macro_use]
extern crate issue_99221_aux;

pub use issue_99221_aux::*;

// @count foo/index.html '//a[@class="struct"][@title="foo::Print struct"]' 1

pub struct Print;
7 changes: 7 additions & 0 deletions src/test/ui/hrtb/issue-95230.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// check-pass

pub struct Bar
where
for<'a> &'a mut Self:;

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LL | fn ts_variant() {
LL | Self::TSVariant(());
| --------------- ^^ expected type parameter `T`, found `()`
| |
| arguments to this function are incorrect
| arguments to this enum variant are incorrect
|
= note: expected type parameter `T`
found unit type `()`
Expand Down Expand Up @@ -55,7 +55,7 @@ LL | impl<T> Enum<T> {
LL | Self::<()>::TSVariant(());
| --------------------- ^^ expected type parameter `T`, found `()`
| |
| arguments to this function are incorrect
| arguments to this enum variant are incorrect
|
= note: expected type parameter `T`
found unit type `()`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ impl E2 {
}

fn main() {
<E>::V(); //~ ERROR this function takes 1 argument but 0 arguments were supplied
<E>::V(); //~ ERROR this enum variant takes 1 argument but 0 arguments were supplied
let _: u8 = <E2>::V; //~ ERROR mismatched types
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0061]: this function takes 1 argument but 0 arguments were supplied
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
|
LL | <E>::V();
Expand Down