Skip to content

Commit a955f1c

Browse files
committed
Auto merge of #144440 - matthiaskrgr:rollup-peb88gb, r=matthiaskrgr
Rollup of 12 pull requests Successful merges: - #142569 (Suggest clone in user-write-code instead of inside macro) - #143401 (tests: Don't check for self-printed output in std-backtrace.rs test) - #143424 (clippy fix: rely on autoderef) - #143970 (Update core::mem::copy documentation) - #143979 (Test fixes for Arm64EC Windows) - #144200 (Tweak output for non-`Clone` values moved into closures) - #144209 (Don't emit two `assume`s in transmutes when one is a subset of the other) - #144314 (Hint that choose_pivot returns index in bounds) - #144340 (UI test suite clarity changes: Rename `tests/ui/SUMMARY.md` and update rustc dev guide on `error-pattern`) - #144368 (resolve: Remove `Scope::CrateRoot`) - #144390 (Remove dead code and extend test coverage and diagnostics around it) - #144392 (rustc_public: Remove movability from `RigidTy/AggregateKind::Coroutine`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents b56aaec + 1caf701 commit a955f1c

File tree

50 files changed

+511
-261
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+511
-261
lines changed

compiler/rustc_abi/src/layout.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
313313
scalar_valid_range: (Bound<u128>, Bound<u128>),
314314
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
315315
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
316-
dont_niche_optimize_enum: bool,
317316
always_sized: bool,
318317
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
319318
let (present_first, present_second) = {
@@ -352,13 +351,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
352351
// structs. (We have also handled univariant enums
353352
// that allow representation optimization.)
354353
assert!(is_enum);
355-
self.layout_of_enum(
356-
repr,
357-
variants,
358-
discr_range_of_repr,
359-
discriminants,
360-
dont_niche_optimize_enum,
361-
)
354+
self.layout_of_enum(repr, variants, discr_range_of_repr, discriminants)
362355
}
363356
}
364357

@@ -599,7 +592,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
599592
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
600593
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
601594
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
602-
dont_niche_optimize_enum: bool,
603595
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
604596
// Until we've decided whether to use the tagged or
605597
// niche filling LayoutData, we don't want to intern the
@@ -618,7 +610,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
618610
}
619611

620612
let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> {
621-
if dont_niche_optimize_enum {
613+
if repr.inhibit_enum_layout_opt() {
622614
return None;
623615
}
624616

compiler/rustc_abi/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,28 @@ impl WrappingRange {
13761376
}
13771377
}
13781378

1379+
/// Returns `true` if all the values in `other` are contained in this range,
1380+
/// when the values are considered as having width `size`.
1381+
#[inline(always)]
1382+
pub fn contains_range(&self, other: Self, size: Size) -> bool {
1383+
if self.is_full_for(size) {
1384+
true
1385+
} else {
1386+
let trunc = |x| size.truncate(x);
1387+
1388+
let delta = self.start;
1389+
let max = trunc(self.end.wrapping_sub(delta));
1390+
1391+
let other_start = trunc(other.start.wrapping_sub(delta));
1392+
let other_end = trunc(other.end.wrapping_sub(delta));
1393+
1394+
// Having shifted both input ranges by `delta`, now we only need to check
1395+
// whether `0..=max` contains `other_start..=other_end`, which can only
1396+
// happen if the other doesn't wrap since `self` isn't everything.
1397+
(other_start <= other_end) && (other_end <= max)
1398+
}
1399+
}
1400+
13791401
/// Returns `self` with replaced `start`
13801402
#[inline(always)]
13811403
fn with_start(mut self, start: u128) -> Self {

compiler/rustc_abi/src/tests.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,66 @@ fn align_constants() {
55
assert_eq!(Align::ONE, Align::from_bytes(1).unwrap());
66
assert_eq!(Align::EIGHT, Align::from_bytes(8).unwrap());
77
}
8+
9+
#[test]
10+
fn wrapping_range_contains_range() {
11+
let size16 = Size::from_bytes(16);
12+
13+
let a = WrappingRange { start: 10, end: 20 };
14+
assert!(a.contains_range(a, size16));
15+
assert!(a.contains_range(WrappingRange { start: 11, end: 19 }, size16));
16+
assert!(a.contains_range(WrappingRange { start: 10, end: 10 }, size16));
17+
assert!(a.contains_range(WrappingRange { start: 20, end: 20 }, size16));
18+
assert!(!a.contains_range(WrappingRange { start: 10, end: 21 }, size16));
19+
assert!(!a.contains_range(WrappingRange { start: 9, end: 20 }, size16));
20+
assert!(!a.contains_range(WrappingRange { start: 4, end: 6 }, size16));
21+
assert!(!a.contains_range(WrappingRange { start: 24, end: 26 }, size16));
22+
23+
assert!(!a.contains_range(WrappingRange { start: 16, end: 14 }, size16));
24+
25+
let b = WrappingRange { start: 20, end: 10 };
26+
assert!(b.contains_range(b, size16));
27+
assert!(b.contains_range(WrappingRange { start: 20, end: 20 }, size16));
28+
assert!(b.contains_range(WrappingRange { start: 10, end: 10 }, size16));
29+
assert!(b.contains_range(WrappingRange { start: 0, end: 10 }, size16));
30+
assert!(b.contains_range(WrappingRange { start: 20, end: 30 }, size16));
31+
assert!(b.contains_range(WrappingRange { start: 20, end: 9 }, size16));
32+
assert!(b.contains_range(WrappingRange { start: 21, end: 10 }, size16));
33+
assert!(b.contains_range(WrappingRange { start: 999, end: 9999 }, size16));
34+
assert!(b.contains_range(WrappingRange { start: 999, end: 9 }, size16));
35+
assert!(!b.contains_range(WrappingRange { start: 19, end: 19 }, size16));
36+
assert!(!b.contains_range(WrappingRange { start: 11, end: 11 }, size16));
37+
assert!(!b.contains_range(WrappingRange { start: 19, end: 11 }, size16));
38+
assert!(!b.contains_range(WrappingRange { start: 11, end: 19 }, size16));
39+
40+
let f = WrappingRange { start: 0, end: u128::MAX };
41+
assert!(f.contains_range(WrappingRange { start: 10, end: 20 }, size16));
42+
assert!(f.contains_range(WrappingRange { start: 20, end: 10 }, size16));
43+
44+
let g = WrappingRange { start: 2, end: 1 };
45+
assert!(g.contains_range(WrappingRange { start: 10, end: 20 }, size16));
46+
assert!(g.contains_range(WrappingRange { start: 20, end: 10 }, size16));
47+
48+
let size1 = Size::from_bytes(1);
49+
let u8r = WrappingRange { start: 0, end: 255 };
50+
let i8r = WrappingRange { start: 128, end: 127 };
51+
assert!(u8r.contains_range(i8r, size1));
52+
assert!(i8r.contains_range(u8r, size1));
53+
assert!(!u8r.contains_range(i8r, size16));
54+
assert!(i8r.contains_range(u8r, size16));
55+
56+
let boolr = WrappingRange { start: 0, end: 1 };
57+
assert!(u8r.contains_range(boolr, size1));
58+
assert!(i8r.contains_range(boolr, size1));
59+
assert!(!boolr.contains_range(u8r, size1));
60+
assert!(!boolr.contains_range(i8r, size1));
61+
62+
let cmpr = WrappingRange { start: 255, end: 1 };
63+
assert!(u8r.contains_range(cmpr, size1));
64+
assert!(i8r.contains_range(cmpr, size1));
65+
assert!(!cmpr.contains_range(u8r, size1));
66+
assert!(!cmpr.contains_range(i8r, size1));
67+
68+
assert!(!boolr.contains_range(cmpr, size1));
69+
assert!(cmpr.contains_range(boolr, size1));
70+
}

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
115115
fn append_to_grouped_errors(
116116
&self,
117117
grouped_errors: &mut Vec<GroupedMoveError<'tcx>>,
118-
error: MoveError<'tcx>,
118+
MoveError { place: original_path, location, kind }: MoveError<'tcx>,
119119
) {
120-
let MoveError { place: original_path, location, kind } = error;
121-
122120
// Note: that the only time we assign a place isn't a temporary
123121
// to a user variable is when initializing it.
124122
// If that ever stops being the case, then the ever initialized
@@ -251,54 +249,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
251249
}
252250

253251
fn report(&mut self, error: GroupedMoveError<'tcx>) {
254-
let (mut err, err_span) = {
255-
let (span, use_spans, original_path, kind) = match error {
256-
GroupedMoveError::MovesFromPlace { span, original_path, ref kind, .. }
257-
| GroupedMoveError::MovesFromValue { span, original_path, ref kind, .. } => {
258-
(span, None, original_path, kind)
259-
}
260-
GroupedMoveError::OtherIllegalMove { use_spans, original_path, ref kind } => {
261-
(use_spans.args_or_use(), Some(use_spans), original_path, kind)
262-
}
263-
};
264-
debug!(
265-
"report: original_path={:?} span={:?}, kind={:?} \
266-
original_path.is_upvar_field_projection={:?}",
267-
original_path,
268-
span,
269-
kind,
270-
self.is_upvar_field_projection(original_path.as_ref())
271-
);
272-
if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) {
273-
// If the type may implement Copy, skip the error.
274-
// It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
275-
self.dcx().span_delayed_bug(
252+
let (span, use_spans, original_path, kind) = match error {
253+
GroupedMoveError::MovesFromPlace { span, original_path, ref kind, .. }
254+
| GroupedMoveError::MovesFromValue { span, original_path, ref kind, .. } => {
255+
(span, None, original_path, kind)
256+
}
257+
GroupedMoveError::OtherIllegalMove { use_spans, original_path, ref kind } => {
258+
(use_spans.args_or_use(), Some(use_spans), original_path, kind)
259+
}
260+
};
261+
debug!(
262+
"report: original_path={:?} span={:?}, kind={:?} \
263+
original_path.is_upvar_field_projection={:?}",
264+
original_path,
265+
span,
266+
kind,
267+
self.is_upvar_field_projection(original_path.as_ref())
268+
);
269+
if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) {
270+
// If the type may implement Copy, skip the error.
271+
// It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
272+
self.dcx()
273+
.span_delayed_bug(span, "Type may implement copy, but there is no other error.");
274+
return;
275+
}
276+
let mut err = match kind {
277+
&IllegalMoveOriginKind::BorrowedContent { target_place } => self
278+
.report_cannot_move_from_borrowed_content(
279+
original_path,
280+
target_place,
276281
span,
277-
"Type may implement copy, but there is no other error.",
278-
);
279-
return;
282+
use_spans,
283+
),
284+
&IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
285+
self.cannot_move_out_of_interior_of_drop(span, ty)
286+
}
287+
&IllegalMoveOriginKind::InteriorOfSliceOrArray { ty, is_index } => {
288+
self.cannot_move_out_of_interior_noncopy(span, ty, Some(is_index))
280289
}
281-
(
282-
match kind {
283-
&IllegalMoveOriginKind::BorrowedContent { target_place } => self
284-
.report_cannot_move_from_borrowed_content(
285-
original_path,
286-
target_place,
287-
span,
288-
use_spans,
289-
),
290-
&IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
291-
self.cannot_move_out_of_interior_of_drop(span, ty)
292-
}
293-
&IllegalMoveOriginKind::InteriorOfSliceOrArray { ty, is_index } => {
294-
self.cannot_move_out_of_interior_noncopy(span, ty, Some(is_index))
295-
}
296-
},
297-
span,
298-
)
299290
};
300291

301-
self.add_move_hints(error, &mut err, err_span);
292+
self.add_move_hints(error, &mut err, span);
302293
self.buffer_error(err);
303294
}
304295

@@ -483,7 +474,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
483474
self.cannot_move_out_of_interior_noncopy(span, ty, None)
484475
}
485476
ty::Closure(def_id, closure_args)
486-
if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
477+
if def_id.as_local() == Some(self.mir_def_id())
478+
&& let Some(upvar_field) = upvar_field =>
487479
{
488480
let closure_kind_ty = closure_args.as_closure().kind_ty();
489481
let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
@@ -496,7 +488,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
496488
let capture_description =
497489
format!("captured variable in an `{closure_kind}` closure");
498490

499-
let upvar = &self.upvars[upvar_field.unwrap().index()];
491+
let upvar = &self.upvars[upvar_field.index()];
500492
let upvar_hir_id = upvar.get_root_variable();
501493
let upvar_name = upvar.to_string(tcx);
502494
let upvar_span = tcx.hir_span(upvar_hir_id);
@@ -606,7 +598,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
606598
}
607599
// No binding. Nothing to suggest.
608600
GroupedMoveError::OtherIllegalMove { ref original_path, use_spans, .. } => {
609-
let use_span = use_spans.var_or_use();
601+
let mut use_span = use_spans.var_or_use();
610602
let place_ty = original_path.ty(self.body, self.infcx.tcx).ty;
611603
let place_desc = match self.describe_place(original_path.as_ref()) {
612604
Some(desc) => format!("`{desc}`"),
@@ -623,19 +615,59 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
623615
);
624616
}
625617

618+
if let Some(upvar_field) = self
619+
.prefixes(original_path.as_ref(), PrefixSet::All)
620+
.find_map(|p| self.is_upvar_field_projection(p))
621+
{
622+
// Look for the introduction of the original binding being moved.
623+
let upvar = &self.upvars[upvar_field.index()];
624+
let upvar_hir_id = upvar.get_root_variable();
625+
use_span = match self.infcx.tcx.parent_hir_node(upvar_hir_id) {
626+
hir::Node::Param(param) => {
627+
// Instead of pointing at the path where we access the value within a
628+
// closure, we point at the type of the outer `fn` argument.
629+
param.ty_span
630+
}
631+
hir::Node::LetStmt(stmt) => match (stmt.ty, stmt.init) {
632+
// We point at the type of the outer let-binding.
633+
(Some(ty), _) => ty.span,
634+
// We point at the initializer of the outer let-binding, but only if it
635+
// isn't something that spans multiple lines, like a closure, as the
636+
// ASCII art gets messy.
637+
(None, Some(init))
638+
if !self.infcx.tcx.sess.source_map().is_multiline(init.span) =>
639+
{
640+
init.span
641+
}
642+
_ => use_span,
643+
},
644+
_ => use_span,
645+
};
646+
}
647+
626648
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
627649
is_partial_move: false,
628650
ty: place_ty,
629651
place: &place_desc,
630652
span: use_span,
631653
});
632654

655+
let mut pointed_at_span = false;
633656
use_spans.args_subdiag(err, |args_span| {
657+
if args_span == span || args_span == use_span {
658+
pointed_at_span = true;
659+
}
634660
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
635-
place: place_desc,
661+
place: place_desc.clone(),
636662
args_span,
637663
}
638664
});
665+
if !pointed_at_span && use_span != span {
666+
err.subdiagnostic(crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
667+
place: place_desc,
668+
args_span: span,
669+
});
670+
}
639671

640672
self.add_note_for_packed_struct_derive(err, original_path.local);
641673
}

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
288288
// valid ranges. For example, `char`s are passed as just `i32`, with no
289289
// way for LLVM to know that they're 0x10FFFF at most. Thus we assume
290290
// the range of the input value too, not just the output range.
291-
assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
291+
assume_scalar_range(bx, imm, from_scalar, from_backend_ty, None);
292292

293293
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
294294
(Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed),
@@ -1064,7 +1064,7 @@ pub(super) fn transmute_scalar<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
10641064
// That said, last time we tried removing this, it didn't actually help
10651065
// the rustc-perf results, so might as well keep doing it
10661066
// <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182>
1067-
assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
1067+
assume_scalar_range(bx, imm, from_scalar, from_backend_ty, Some(&to_scalar));
10681068

10691069
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
10701070
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
@@ -1092,22 +1092,42 @@ pub(super) fn transmute_scalar<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
10921092
// since it's never passed to something with parameter metadata (especially
10931093
// after MIR inlining) so the only way to tell the backend about the
10941094
// constraint that the `transmute` introduced is to `assume` it.
1095-
assume_scalar_range(bx, imm, to_scalar, to_backend_ty);
1095+
assume_scalar_range(bx, imm, to_scalar, to_backend_ty, Some(&from_scalar));
10961096

10971097
imm = bx.to_immediate_scalar(imm, to_scalar);
10981098
imm
10991099
}
11001100

1101+
/// Emits an `assume` call that `imm`'s value is within the known range of `scalar`.
1102+
///
1103+
/// If `known` is `Some`, only emits the assume if it's more specific than
1104+
/// whatever is already known from the range of *that* scalar.
11011105
fn assume_scalar_range<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
11021106
bx: &mut Bx,
11031107
imm: Bx::Value,
11041108
scalar: abi::Scalar,
11051109
backend_ty: Bx::Type,
1110+
known: Option<&abi::Scalar>,
11061111
) {
1107-
if matches!(bx.cx().sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(bx.cx()) {
1112+
if matches!(bx.cx().sess().opts.optimize, OptLevel::No) {
11081113
return;
11091114
}
11101115

1116+
match (scalar, known) {
1117+
(abi::Scalar::Union { .. }, _) => return,
1118+
(_, None) => {
1119+
if scalar.is_always_valid(bx.cx()) {
1120+
return;
1121+
}
1122+
}
1123+
(abi::Scalar::Initialized { valid_range, .. }, Some(known)) => {
1124+
let known_range = known.valid_range(bx.cx());
1125+
if valid_range.contains_range(known_range, scalar.size(bx.cx())) {
1126+
return;
1127+
}
1128+
}
1129+
}
1130+
11111131
match scalar.primitive() {
11121132
abi::Primitive::Int(..) => {
11131133
let range = scalar.valid_range(bx.cx());

0 commit comments

Comments
 (0)