Skip to content

Commit

Permalink
Auto merge of rust-lang#115442 - cuviper:beta-next, r=cuviper
Browse files Browse the repository at this point in the history
[beta] backports

- Contents of reachable statics is reachable rust-lang#115114
- Revert "Suggest using `Arc` on `!Send`/`!Sync` types" rust-lang#115311
- Stop emitting non-power-of-two vectors in (non-portable-SIMD) codegen rust-lang#115236
- Do not forget to pass DWARF fragment information to LLVM. rust-lang#115139
- rustdoc: use unicode-aware checks for redundant explicit link fastpath rust-lang#115070

r? cuviper
  • Loading branch information
bors committed Sep 1, 2023
2 parents bc28abf + 20ddd45 commit 9f37cd4
Show file tree
Hide file tree
Showing 125 changed files with 193 additions and 268 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/type_of.rs
Expand Up @@ -405,7 +405,11 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {

// Vectors, even for non-power-of-two sizes, have the same layout as
// arrays but don't count as aggregate types
// While LLVM theoretically supports non-power-of-two sizes, and they
// often work fine, sometimes x86-isel deals with them horribly
// (see #115212) so for now only use power-of-two ones.
if let FieldsShape::Array { count, .. } = self.layout.fields()
&& count.is_power_of_two()
&& let element = self.field(cx, 0)
&& element.ty.is_integral()
{
Expand Down
37 changes: 28 additions & 9 deletions compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
Expand Up @@ -435,9 +435,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.store(place.llval, alloca.llval, alloca.align);

// Point the debug info to `*alloca` for the current variable
bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
bx.dbg_var_addr(
dbg_var,
dbg_loc,
alloca.llval,
Size::ZERO,
&[Size::ZERO],
var.fragment,
);
} else {
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
bx.dbg_var_addr(
dbg_var,
dbg_loc,
base.llval,
direct_offset,
&indirect_offsets,
var.fragment,
);
}
}

Expand Down Expand Up @@ -560,17 +574,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}

let place = fragment.contents;
let fragment = if fragment_layout.size == Size::ZERO {
// Fragment is a ZST, so does not represent anything.
continue;
} else if fragment_layout.size == var_layout.size {
// Fragment covers entire variable, so as far as
// DWARF is concerned, it's not really a fragment.
None
} else {
Some(fragment_start..fragment_start + fragment_layout.size)
};

per_local[place.local].push(PerLocalVarDebugInfo {
name: var.name,
source_info: var.source_info,
dbg_var,
fragment: if fragment_layout.size == var_layout.size {
// Fragment covers entire variable, so as far as
// DWARF is concerned, it's not really a fragment.
None
} else {
Some(fragment_start..fragment_start + fragment_layout.size)
},
fragment,
projection: place.projection,
});
}
Expand Down
10 changes: 3 additions & 7 deletions compiler/rustc_passes/src/reachable.rs
Expand Up @@ -98,15 +98,11 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
self.worklist.push(def_id);
} else {
match res {
// If this path leads to a constant, then we need to
// recurse into the constant to continue finding
// items that are reachable.
Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
// Reachable constants and reachable statics can have their contents inlined
// into other crates. Mark them as reachable and recurse into their body.
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static(_), _) => {
self.worklist.push(def_id);
}

// If this wasn't a static, then the destination is
// surely reachable.
_ => {
self.reachable_symbols.insert(def_id);
}
Expand Down
Expand Up @@ -2743,12 +2743,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::BindingObligation(item_def_id, span)
| ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
if self.tcx.is_diagnostic_item(sym::Send, item_def_id)
|| self.tcx.lang_items().sync_trait() == Some(item_def_id)
{
return;
}

let item_name = tcx.def_path_str(item_def_id);
let short_item_name = with_forced_trimmed_paths!(tcx.def_path_str(item_def_id));
let mut multispan = MultiSpan::from(span);
Expand Down
10 changes: 2 additions & 8 deletions library/core/src/marker.rs
Expand Up @@ -76,11 +76,8 @@ macro marker_impls {
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Send")]
#[rustc_on_unimplemented(
on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"),
message = "`{Self}` cannot be sent between threads safely",
label = "`{Self}` cannot be sent between threads safely",
note = "consider using `std::sync::Arc<{Self}>`; for more information visit \
<https://doc.rust-lang.org/book/ch16-03-shared-state.html>"
label = "`{Self}` cannot be sent between threads safely"
)]
pub unsafe auto trait Send {
// empty.
Expand Down Expand Up @@ -631,11 +628,8 @@ impl<T: ?Sized> Copy for &T {}
any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
),
on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"),
message = "`{Self}` cannot be shared between threads safely",
label = "`{Self}` cannot be shared between threads safely",
note = "consider using `std::sync::Arc<{Self}>`; for more information visit \
<https://doc.rust-lang.org/book/ch16-03-shared-state.html>"
label = "`{Self}` cannot be shared between threads safely"
)]
pub unsafe auto trait Sync {
// FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
Expand Down
11 changes: 3 additions & 8 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Expand Up @@ -1430,20 +1430,15 @@ impl LinkCollector<'_, '_> {
// Otherwise, check if 2 links are same, if so, skip the resolve process.
//
// Notice that this algorithm is passive, might possibly miss actual redudant cases.
let explicit_link = &explicit_link.to_string();
let explicit_link = explicit_link.to_string();
let display_text = ori_link.display_text.as_ref().unwrap();
let display_len = display_text.len();
let explicit_len = explicit_link.len();

if display_len == explicit_len {
if display_text.len() == explicit_link.len() {
// Whether they are same or not, skip the resolve process.
return;
}

if (explicit_len >= display_len
&& &explicit_link[(explicit_len - display_len)..] == display_text)
|| (display_len >= explicit_len
&& &display_text[(display_len - explicit_len)..] == explicit_link)
if explicit_link.ends_with(&display_text[..]) || display_text.ends_with(&explicit_link[..])
{
self.resolve_with_disambiguator_cached(
display_res_info,
Expand Down
7 changes: 1 addition & 6 deletions src/librustdoc/passes/lint/redundant_explicit_links.rs
Expand Up @@ -98,13 +98,8 @@ fn check_redundant_explicit_link<'md>(

let explicit_link = dest.to_string();
let display_link = link_data.resolvable_link.clone()?;
let explicit_len = explicit_link.len();
let display_len = display_link.len();

if (explicit_len >= display_len
&& &explicit_link[(explicit_len - display_len)..] == display_link)
|| (display_len >= explicit_len
&& &display_link[(display_len - explicit_len)..] == explicit_link)
if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link)
{
match link_type {
LinkType::Inline | LinkType::ReferenceUnknown => {
Expand Down
21 changes: 15 additions & 6 deletions tests/codegen/mem-replace-simple-type.rs
Expand Up @@ -33,12 +33,21 @@ pub fn replace_ref_str<'a>(r: &mut &'a str, v: &'a str) -> &'a str {
}

#[no_mangle]
// CHECK-LABEL: @replace_short_array(
pub fn replace_short_array(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] {
// CHECK-LABEL: @replace_short_array_3(
pub fn replace_short_array_3(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] {
// CHECK-NOT: alloca
// CHECK: %[[R:.+]] = load <3 x i32>, ptr %r, align 4
// CHECK: store <3 x i32> %[[R]], ptr %result
// CHECK: %[[V:.+]] = load <3 x i32>, ptr %v, align 4
// CHECK: store <3 x i32> %[[V]], ptr %r
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %result, ptr align 4 %r, i64 12, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %r, ptr align 4 %v, i64 12, i1 false)
std::mem::replace(r, v)
}

#[no_mangle]
// CHECK-LABEL: @replace_short_array_4(
pub fn replace_short_array_4(r: &mut [u32; 4], v: [u32; 4]) -> [u32; 4] {
// CHECK-NOT: alloca
// CHECK: %[[R:.+]] = load <4 x i32>, ptr %r, align 4
// CHECK: store <4 x i32> %[[R]], ptr %result
// CHECK: %[[V:.+]] = load <4 x i32>, ptr %v, align 4
// CHECK: store <4 x i32> %[[V]], ptr %r
std::mem::replace(r, v)
}
46 changes: 46 additions & 0 deletions tests/codegen/sroa-fragment-debuginfo.rs
@@ -0,0 +1,46 @@
// compile-flags: -g -Zmir-opt-level=0 -Zmir-enable-passes=+ScalarReplacementOfAggregates
// compile-flags: -Cno-prepopulate-passes
//
// Tested offsets are only correct for x86_64.
// only-x86_64

#![crate_type = "lib"]

pub struct ExtraSlice<'input> {
slice: &'input [u8],
extra: u32,
}

#[no_mangle]
pub fn extra(s: &[u8]) {
// CHECK: void @extra(
// CHECK: %slice.dbg.spill1 = alloca i32,
// CHECK: %slice.dbg.spill = alloca { ptr, i64 },
// CHECK: %s.dbg.spill = alloca { ptr, i64 },
// CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_EXTRA:.*]], metadata !DIExpression()),
// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_EXTRA:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128)),
// CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_EXTRA]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32)),
let slice = ExtraSlice { slice: s, extra: s.len() as u32 };
}

struct Zst;

pub struct ZstSlice<'input> {
slice: &'input [u8],
extra: Zst,
}

#[no_mangle]
pub fn zst(s: &[u8]) {
// The field `extra` is a ZST. The fragment for the field `slice` encompasses the whole
// variable, so is not a fragment. In that case, the variable must have no fragment.

// CHECK: void @zst(
// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata !{}, metadata !DIExpression(DW_OP_LLVM_fragment,
// CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST:.*]], metadata !DIExpression()),
// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[SLICE_ZST]],
let slice = ZstSlice { slice: s, extra: Zst };
}

// CHECK: ![[S_EXTRA]] = !DILocalVariable(name: "s",
// CHECK: ![[SLICE_EXTRA]] = !DILocalVariable(name: "slice",
33 changes: 24 additions & 9 deletions tests/codegen/swap-small-types.rs
Expand Up @@ -11,11 +11,12 @@ type RGB48 = [u16; 3];
// CHECK-LABEL: @swap_rgb48_manually(
#[no_mangle]
pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) {
// CHECK-NOT: alloca
// CHECK: %[[TEMP0:.+]] = load <3 x i16>, ptr %x, align 2
// CHECK: %[[TEMP1:.+]] = load <3 x i16>, ptr %y, align 2
// CHECK: store <3 x i16> %[[TEMP1]], ptr %x, align 2
// CHECK: store <3 x i16> %[[TEMP0]], ptr %y, align 2
// FIXME: See #115212 for why this has an alloca again

// CHECK: alloca [3 x i16], align 2
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)

let temp = *x;
*x = *y;
Expand All @@ -25,11 +26,25 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) {
// CHECK-LABEL: @swap_rgb48
#[no_mangle]
pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) {
// FIXME: See #115212 for why this has an alloca again

// CHECK: alloca [3 x i16], align 2
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false)
swap(x, y)
}

type RGBA64 = [u16; 4];

// CHECK-LABEL: @swap_rgba64
#[no_mangle]
pub fn swap_rgba64(x: &mut RGBA64, y: &mut RGBA64) {
// CHECK-NOT: alloca
// CHECK: load <3 x i16>
// CHECK: load <3 x i16>
// CHECK: store <3 x i16>
// CHECK: store <3 x i16>
// CHECK-DAG: %[[XVAL:.+]] = load <4 x i16>, ptr %x, align 2
// CHECK-DAG: %[[YVAL:.+]] = load <4 x i16>, ptr %y, align 2
// CHECK-DAG: store <4 x i16> %[[YVAL]], ptr %x, align 2
// CHECK-DAG: store <4 x i16> %[[XVAL]], ptr %y, align 2
swap(x, y)
}

Expand Down
18 changes: 18 additions & 0 deletions tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs
@@ -0,0 +1,18 @@
// check-pass

/// [`…foo`] [`…bar`] [`Err`]
pub struct Broken {}

/// [`…`] [`…`] [`Err`]
pub struct Broken2 {}

/// [`…`][…] [`…`][…] [`Err`]
pub struct Broken3 {}

/// […………………………][Broken3]
pub struct Broken4 {}

/// [Broken3][…………………………]
pub struct Broken5 {}

pub struct Err;
Expand Up @@ -5,7 +5,6 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
| ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
= note: consider using `std::sync::Arc<<<Self as Case1>::C as Iterator>::Item>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
Expand All @@ -30,7 +29,6 @@ LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
| ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
= note: consider using `std::sync::Arc<<<Self as Case1>::C as Iterator>::Item>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
help: consider further restricting the associated type
|
LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
Expand Down
Expand Up @@ -14,7 +14,6 @@ LL | is_send(foo::<T>());
| ^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = Result<(), ()>>`, the trait `Send` is not implemented for `impl Future<Output = Result<(), ()>>`
= note: consider using `std::sync::Arc<impl Future<Output = Result<(), ()>>>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/basic.rs:13:5
|
Expand Down
Expand Up @@ -5,7 +5,6 @@ LL | is_send(foo(Some(true)));
| ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:11:15
|
Expand Down Expand Up @@ -33,7 +32,6 @@ LL | is_send(foo2(Some(true)));
| required by a bound introduced by this call
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: required because it's used within this `async fn` body
--> $DIR/async-await-let-else.rs:27:29
|
Expand Down Expand Up @@ -66,7 +64,6 @@ LL | is_send(foo3(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:33:29
|
Expand All @@ -88,7 +85,6 @@ LL | is_send(foo4(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:41:15
|
Expand Down
Expand Up @@ -5,7 +5,6 @@ LL | is_send(foo(Some(true)));
| ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:11:15
|
Expand All @@ -31,7 +30,6 @@ LL | is_send(foo2(Some(true)));
| required by a bound introduced by this call
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: required because it's used within this `async fn` body
--> $DIR/async-await-let-else.rs:27:29
|
Expand Down Expand Up @@ -64,7 +62,6 @@ LL | is_send(foo3(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:33:29
|
Expand All @@ -85,7 +82,6 @@ LL | is_send(foo4(Some(true)));
| ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
= note: use `std::sync::Arc` instead of `std::rc::Rc`
note: future is not `Send` as this value is used across an await
--> $DIR/async-await-let-else.rs:41:15
|
Expand Down

0 comments on commit 9f37cd4

Please sign in to comment.