Skip to content

Commit 2d5ffc5

Browse files
committed
Auto merge of #140596 - matthiaskrgr:rollup-s7tzr34, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #140485 (Optimize the codegen for `Span::from_expansion`) - #140509 (transmutability: merge contiguous runs with a common destination) - #140519 (Use select in projection lookup in `report_projection_error`) - #140521 (interpret: better error message for out-of-bounds pointer arithmetic and accesses) - #140536 (Rename `*Guard::try_map` to `filter_map`.) - #140550 (Stabilize `select_unpredictable`) - #140563 (extend the list of registered dylibs on `test::prepare_cargo_test`) - #140572 (Add useful comments on `ExprKind::If` variants.) - #140574 (Add regression test for 133065) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 4824c2b + 6f7f3ce commit 2d5ffc5

File tree

100 files changed

+403
-309
lines changed

Some content is hidden

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

100 files changed

+403
-309
lines changed

compiler/rustc_ast/src/ast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,9 @@ pub enum ExprKind {
16331633
/// An `if` block, with an optional `else` block.
16341634
///
16351635
/// `if expr { block } else { expr }`
1636+
///
1637+
/// If present, the "else" expr is always `ExprKind::Block` (for `else`) or
1638+
/// `ExprKind::If` (for `else if`).
16361639
If(P<Expr>, P<Block>, Option<P<Expr>>),
16371640
/// A while loop, with an optional label.
16381641
///

compiler/rustc_const_eval/messages.ftl

+35-35
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,27 @@ const_eval_already_reported =
1212
const_eval_assume_false =
1313
`assume` called with `false`
1414
15+
const_eval_bad_pointer_op = {$operation ->
16+
[MemoryAccess] memory access failed
17+
[InboundsPointerArithmetic] in-bounds pointer arithmetic failed
18+
*[Dereferenceable] pointer not dereferenceable
19+
}
20+
const_eval_bad_pointer_op_attempting = {const_eval_bad_pointer_op}: {$operation ->
21+
[MemoryAccess] attempting to access {$inbounds_size ->
22+
[1] 1 byte
23+
*[x] {$inbounds_size} bytes
24+
}
25+
[InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size ->
26+
[1] 1 byte
27+
*[x] {$inbounds_size} bytes
28+
}
29+
*[Dereferenceable] pointer must {$inbounds_size ->
30+
[0] point to some allocation
31+
[1] be dereferenceable for 1 byte
32+
*[x] be dereferenceable for {$inbounds_size} bytes
33+
}
34+
}
35+
1536
const_eval_bounds_check_failed =
1637
indexing out of bounds: the len is {$len} but the index is {$index}
1738
const_eval_call_nonzero_intrinsic =
@@ -39,9 +60,9 @@ const_eval_copy_nonoverlapping_overlapping =
3960
`copy_nonoverlapping` called on overlapping ranges
4061
4162
const_eval_dangling_int_pointer =
42-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} which is a dangling pointer (it has no provenance)
63+
{const_eval_bad_pointer_op_attempting}, but got {$pointer} which is a dangling pointer (it has no provenance)
4364
const_eval_dangling_null_pointer =
44-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got a null pointer
65+
{const_eval_bad_pointer_op_attempting}, but got null pointer
4566
4667
const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind}
4768
const_eval_dead_local =
@@ -77,21 +98,6 @@ const_eval_error = {$error_kind ->
7798
const_eval_exact_div_has_remainder =
7899
exact_div: {$a} cannot be divided by {$b} without remainder
79100
80-
const_eval_expected_inbounds_pointer =
81-
expected a pointer to {$inbounds_size_abs ->
82-
[0] some allocation
83-
*[x] {$inbounds_size_is_neg ->
84-
[false] {$inbounds_size_abs ->
85-
[1] 1 byte of memory
86-
*[x] {$inbounds_size_abs} bytes of memory
87-
}
88-
*[true] the end of {$inbounds_size_abs ->
89-
[1] 1 byte of memory
90-
*[x] {$inbounds_size_abs} bytes of memory
91-
}
92-
}
93-
}
94-
95101
const_eval_extern_static =
96102
cannot access extern static `{$did}`
97103
const_eval_extern_type_field = `extern type` field does not have a known offset
@@ -111,7 +117,6 @@ const_eval_frame_note_inner = inside {$where_ ->
111117
112118
const_eval_frame_note_last = the failure occurred here
113119
114-
const_eval_in_bounds_test = out-of-bounds pointer use
115120
const_eval_incompatible_calling_conventions =
116121
calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
117122
@@ -206,7 +211,6 @@ const_eval_long_running =
206211
207212
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
208213
209-
const_eval_memory_access_test = memory access failed
210214
const_eval_memory_exhausted =
211215
tried to allocate more memory than available to compiler
212216
@@ -287,8 +291,6 @@ const_eval_offset_from_out_of_bounds =
287291
`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation
288292
const_eval_offset_from_overflow =
289293
`{$name}` called when first pointer is too far ahead of second
290-
const_eval_offset_from_test =
291-
out-of-bounds `offset_from` origin
292294
const_eval_offset_from_underflow =
293295
`{$name}` called when first pointer is too far before second
294296
const_eval_offset_from_unsigned_overflow =
@@ -312,27 +314,25 @@ const_eval_partial_pointer_overwrite =
312314
unable to overwrite parts of a pointer in memory at {$ptr}
313315
const_eval_pointer_arithmetic_overflow =
314316
overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
315-
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
317+
316318
const_eval_pointer_out_of_bounds =
317-
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
318-
[true] which points to before the beginning of the allocation
319-
*[false] {$inbounds_size_is_neg ->
320-
[true] {$ptr_offset_abs ->
321-
[0] which is at the beginning of the allocation
322-
*[other] which does not have enough space to the beginning of the allocation
323-
}
324-
*[false] {$alloc_size_minus_ptr_offset ->
325-
[0] which is at or beyond the end of the allocation of size {$alloc_size ->
319+
{const_eval_bad_pointer_op_attempting}, but got {$pointer} which {$inbounds_size_is_neg ->
320+
[false] {$alloc_size_minus_ptr_offset ->
321+
[0] is at or beyond the end of the allocation of size {$alloc_size ->
326322
[1] 1 byte
327323
*[x] {$alloc_size} bytes
328324
}
329-
[1] which is only 1 byte from the end of the allocation
330-
*[x] which is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
325+
[1] is only 1 byte from the end of the allocation
326+
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
327+
}
328+
*[true] {$ptr_offset_abs ->
329+
[0] is at the beginning of the allocation
330+
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
331331
}
332-
}
333332
}
333+
334334
const_eval_pointer_use_after_free =
335-
{$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling
335+
{const_eval_bad_pointer_op}: {$alloc_id} has been freed, so this pointer is dangling
336336
const_eval_ptr_as_bytes_1 =
337337
this code performed an operation that depends on the underlying bytes representing a pointer
338338
const_eval_ptr_as_bytes_2 =

compiler/rustc_const_eval/src/errors.rs

+10-23
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ use either::Either;
55
use rustc_abi::WrappingRange;
66
use rustc_errors::codes::*;
77
use rustc_errors::{
8-
Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
9-
MultiSpan, Subdiagnostic,
8+
Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, Subdiagnostic,
109
};
1110
use rustc_hir::ConstContext;
1211
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
1312
use rustc_middle::mir::interpret::{
14-
CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind,
15-
InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
16-
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
13+
CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind, InvalidProgramInfo,
14+
Misalignment, Pointer, PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo,
15+
UnsupportedOpInfo, ValidationErrorInfo,
1716
};
1817
use rustc_middle::ty::{self, Mutability, Ty};
1918
use rustc_span::{Span, Symbol};
@@ -498,19 +497,6 @@ pub trait ReportErrorExt {
498497
}
499498
}
500499

501-
fn bad_pointer_message(msg: CheckInAllocMsg, dcx: DiagCtxtHandle<'_>) -> String {
502-
use crate::fluent_generated::*;
503-
504-
let msg = match msg {
505-
CheckInAllocMsg::MemoryAccessTest => const_eval_memory_access_test,
506-
CheckInAllocMsg::PointerArithmeticTest => const_eval_pointer_arithmetic_test,
507-
CheckInAllocMsg::OffsetFromTest => const_eval_offset_from_test,
508-
CheckInAllocMsg::InboundsTest => const_eval_in_bounds_test,
509-
};
510-
511-
dcx.eagerly_translate_to_string(msg, [].into_iter())
512-
}
513-
514500
impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
515501
fn diagnostic_message(&self) -> DiagMessage {
516502
use UndefinedBehaviorInfo::*;
@@ -564,7 +550,6 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
564550

565551
fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
566552
use UndefinedBehaviorInfo::*;
567-
let dcx = diag.dcx;
568553
match self {
569554
Ub(_) => {}
570555
Custom(custom) => {
@@ -612,12 +597,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
612597
diag.arg("vtable_dyn_type", vtable_dyn_type.to_string());
613598
}
614599
PointerUseAfterFree(alloc_id, msg) => {
615-
diag.arg("alloc_id", alloc_id)
616-
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
600+
diag.arg("alloc_id", alloc_id).arg("operation", format!("{:?}", msg));
617601
}
618602
PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
619603
diag.arg("alloc_size", alloc_size.bytes());
620-
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
621604
diag.arg("pointer", {
622605
let mut out = format!("{:?}", alloc_id);
623606
if ptr_offset > 0 {
@@ -627,14 +610,17 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
627610
}
628611
out
629612
});
613+
diag.arg("inbounds_size", inbounds_size);
630614
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
631615
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
616+
diag.arg("ptr_offset", ptr_offset);
632617
diag.arg("ptr_offset_is_neg", ptr_offset < 0);
633618
diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs());
634619
diag.arg(
635620
"alloc_size_minus_ptr_offset",
636621
alloc_size.bytes().saturating_sub(ptr_offset as u64),
637622
);
623+
diag.arg("operation", format!("{:?}", msg));
638624
}
639625
DanglingIntPointer { addr, inbounds_size, msg } => {
640626
if addr != 0 {
@@ -644,9 +630,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
644630
);
645631
}
646632

633+
diag.arg("inbounds_size", inbounds_size);
647634
diag.arg("inbounds_size_is_neg", inbounds_size < 0);
648635
diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
649-
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
636+
diag.arg("operation", format!("{:?}", msg));
650637
}
651638
AlignmentCheckFailed(Misalignment { required, has }, msg) => {
652639
diag.arg("required", required.bytes());

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
348348

349349
// Check that the memory between them is dereferenceable at all, starting from the
350350
// origin pointer: `dist` is `a - b`, so it is based on `b`.
351-
self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)
351+
self.check_ptr_access_signed(b, dist, CheckInAllocMsg::Dereferenceable)
352352
.map_err_kind(|_| {
353353
// This could mean they point to different allocations, or they point to the same allocation
354354
// but not the entire range between the pointers is in-bounds.
@@ -372,7 +372,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
372372
self.check_ptr_access_signed(
373373
a,
374374
dist.checked_neg().unwrap(), // i64::MIN is impossible as no allocation can be that large
375-
CheckInAllocMsg::OffsetFromTest,
375+
CheckInAllocMsg::Dereferenceable,
376376
)
377377
.map_err_kind(|_| {
378378
// Make the error more specific.
@@ -651,7 +651,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
651651
offset_bytes: i64,
652652
) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
653653
// The offset must be in bounds starting from `ptr`.
654-
self.check_ptr_access_signed(ptr, offset_bytes, CheckInAllocMsg::PointerArithmeticTest)?;
654+
self.check_ptr_access_signed(
655+
ptr,
656+
offset_bytes,
657+
CheckInAllocMsg::InboundsPointerArithmetic,
658+
)?;
655659
// This also implies that there is no overflow, so we are done.
656660
interp_ok(ptr.wrapping_signed_offset(offset_bytes, self))
657661
}

compiler/rustc_const_eval/src/interpret/memory.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
351351
kind = "static_mem"
352352
)
353353
}
354-
None => err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccessTest)),
354+
None => err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccess)),
355355
})
356356
.into();
357357
};
@@ -414,10 +414,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
414414
self,
415415
ptr,
416416
size,
417-
CheckInAllocMsg::MemoryAccessTest,
417+
CheckInAllocMsg::MemoryAccess,
418418
|this, alloc_id, offset, prov| {
419-
let (size, align) = this
420-
.get_live_alloc_size_and_align(alloc_id, CheckInAllocMsg::MemoryAccessTest)?;
419+
let (size, align) =
420+
this.get_live_alloc_size_and_align(alloc_id, CheckInAllocMsg::MemoryAccess)?;
421421
interp_ok((size, align, (alloc_id, offset, prov)))
422422
},
423423
)
@@ -613,7 +613,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
613613
}
614614
Some(GlobalAlloc::Function { .. }) => throw_ub!(DerefFunctionPointer(id)),
615615
Some(GlobalAlloc::VTable(..)) => throw_ub!(DerefVTablePointer(id)),
616-
None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccessTest)),
616+
None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccess)),
617617
Some(GlobalAlloc::Static(def_id)) => {
618618
assert!(self.tcx.is_static(def_id));
619619
// Thread-local statics do not have a constant address. They *must* be accessed via
@@ -707,7 +707,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
707707
self,
708708
ptr,
709709
size_i64,
710-
CheckInAllocMsg::MemoryAccessTest,
710+
CheckInAllocMsg::MemoryAccess,
711711
|this, alloc_id, offset, prov| {
712712
let alloc = this.get_alloc_raw(alloc_id)?;
713713
interp_ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc)))
@@ -809,7 +809,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
809809
self,
810810
ptr,
811811
size_i64,
812-
CheckInAllocMsg::MemoryAccessTest,
812+
CheckInAllocMsg::MemoryAccess,
813813
|this, alloc_id, offset, prov| {
814814
let (alloc, machine) = this.get_alloc_raw_mut(alloc_id)?;
815815
interp_ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc, machine)))
@@ -1615,7 +1615,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
16151615
err_ub!(DanglingIntPointer {
16161616
addr: offset,
16171617
inbounds_size: size,
1618-
msg: CheckInAllocMsg::InboundsTest
1618+
msg: CheckInAllocMsg::Dereferenceable
16191619
})
16201620
})
16211621
.into()

compiler/rustc_const_eval/src/interpret/validity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
510510
self.ecx.check_ptr_access(
511511
place.ptr(),
512512
size,
513-
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
513+
CheckInAllocMsg::Dereferenceable, // will anyway be replaced by validity message
514514
),
515515
self.path,
516516
Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind },

compiler/rustc_hir/src/hir.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,9 @@ pub enum ExprKind<'hir> {
27412741
/// An `if` block, with an optional else block.
27422742
///
27432743
/// I.e., `if <expr> { <expr> } else { <expr> }`.
2744+
///
2745+
/// The "then" expr is always `ExprKind::Block`. If present, the "else" expr is always
2746+
/// `ExprKind::Block` (for `else`) or `ExprKind::If` (for `else if`).
27442747
If(&'hir Expr<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
27452748
/// A conditionless loop (can be exited with `break`, `continue`, or `return`).
27462749
///

compiler/rustc_middle/src/mir/interpret/error.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,11 @@ pub enum InvalidProgramInfo<'tcx> {
221221
#[derive(Debug, Copy, Clone)]
222222
pub enum CheckInAllocMsg {
223223
/// We are access memory.
224-
MemoryAccessTest,
224+
MemoryAccess,
225225
/// We are doing pointer arithmetic.
226-
PointerArithmeticTest,
227-
/// We are doing pointer offset_from.
228-
OffsetFromTest,
226+
InboundsPointerArithmetic,
229227
/// None of the above -- generic/unspecific inbounds test.
230-
InboundsTest,
228+
Dereferenceable,
231229
}
232230

233231
/// Details of which pointer is not aligned.

compiler/rustc_middle/src/thir.rs

+3
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,10 @@ pub enum ExprKind<'tcx> {
292292
If {
293293
if_then_scope: region::Scope,
294294
cond: ExprId,
295+
/// `then` is always `ExprKind::Block`.
295296
then: ExprId,
297+
/// If present, the `else_opt` expr is always `ExprKind::Block` (for
298+
/// `else`) or `ExprKind::If` (for `else if`).
296299
else_opt: Option<ExprId>,
297300
},
298301
/// A function call. Method calls and overloaded operators are converted to plain function calls.

compiler/rustc_span/src/span_encoding.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,21 @@ impl Span {
306306
/// Returns `true` if this span comes from any kind of macro, desugaring or inlining.
307307
#[inline]
308308
pub fn from_expansion(self) -> bool {
309-
// If the span is fully inferred then ctxt > MAX_CTXT
310-
self.inline_ctxt().map_or(true, |ctxt| !ctxt.is_root())
309+
let ctxt = match_span_kind! {
310+
self,
311+
// All branches here, except `InlineParent`, actually return `span.ctxt_or_parent_or_marker`.
312+
// Since `Interned` is selected if the field contains `CTXT_INTERNED_MARKER` returning that value
313+
// as the context allows the compiler to optimize out the branch that selects between either
314+
// `Interned` and `PartiallyInterned`.
315+
//
316+
// Interned contexts can never be the root context and `CTXT_INTERNED_MARKER` has a different value
317+
// than the root context so this works for checking is this is an expansion.
318+
InlineCtxt(span) => SyntaxContext::from_u16(span.ctxt),
319+
InlineParent(_span) => SyntaxContext::root(),
320+
PartiallyInterned(span) => SyntaxContext::from_u16(span.ctxt),
321+
Interned(_span) => SyntaxContext::from_u16(CTXT_INTERNED_MARKER),
322+
};
323+
!ctxt.is_root()
311324
}
312325

313326
/// Returns `true` if this is a dummy span with any hygienic context.

0 commit comments

Comments
 (0)