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

[beta] backports #115442

Merged
merged 8 commits into from
Sep 1, 2023
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
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/type_of.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading
Loading