mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #114424 - matthiaskrgr:rollup-cegblvo, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #113657 (Expand, rename and improve `incorrect_fn_null_checks` lint) - #114237 (parser: more friendly hints for handling `async move` in the 2015 edition) - #114300 (Suggests turbofish in patterns) - #114372 (const validation: point at where we found a pointer but expected an integer) - #114395 ([rustc_span][perf] Hoist lookup sorted by words out of the loop.) - #114403 (fix the span in the suggestion of remove question mark) - #114408 (Temporary remove myself from review rotation) - #114415 (Skip checking of `rustc_codegen_gcc` with vendoring enabled) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
474709a9a2
@ -15,9 +15,6 @@ const_eval_await_non_const =
|
||||
cannot convert `{$ty}` into a future in {const_eval_const_context}s
|
||||
const_eval_bounds_check_failed =
|
||||
indexing out of bounds: the len is {$len} but the index is {$index}
|
||||
const_eval_box_to_mut = {$front_matter}: encountered a box pointing to mutable memory in a constant
|
||||
const_eval_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
|
||||
const_eval_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
|
||||
const_eval_call_nonzero_intrinsic =
|
||||
`{$name}` called on 0
|
||||
|
||||
@ -41,18 +38,12 @@ const_eval_const_context = {$kind ->
|
||||
const_eval_copy_nonoverlapping_overlapping =
|
||||
`copy_nonoverlapping` called on overlapping ranges
|
||||
|
||||
const_eval_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
|
||||
const_eval_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
|
||||
const_eval_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
|
||||
const_eval_dangling_int_pointer =
|
||||
{$bad_pointer_message}: {$pointer} is a dangling pointer (it has no provenance)
|
||||
const_eval_dangling_null_pointer =
|
||||
{$bad_pointer_message}: null pointer is a dangling pointer (it has no provenance)
|
||||
const_eval_dangling_ptr_in_final = encountered dangling pointer in final constant
|
||||
|
||||
const_eval_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance)
|
||||
const_eval_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)
|
||||
const_eval_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free)
|
||||
const_eval_dead_local =
|
||||
accessing a dead local variable
|
||||
const_eval_dealloc_immutable =
|
||||
@ -105,7 +96,6 @@ const_eval_error = {$error_kind ->
|
||||
const_eval_exact_div_has_remainder =
|
||||
exact_div: {$a} cannot be divided by {$b} without remainder
|
||||
|
||||
const_eval_expected_non_ptr = {$front_matter}: encountered `{$value}`, but expected plain (non-pointer) bytes
|
||||
const_eval_fn_ptr_call =
|
||||
function pointers need an RFC before allowed to be called in {const_eval_const_context}s
|
||||
const_eval_for_loop_into_iter_non_const =
|
||||
@ -156,8 +146,6 @@ const_eval_invalid_align_details =
|
||||
|
||||
const_eval_invalid_bool =
|
||||
interpreting an invalid 8-bit value as a bool: 0x{$value}
|
||||
const_eval_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object
|
||||
const_eval_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object
|
||||
const_eval_invalid_char =
|
||||
interpreting an invalid 32-bit value as a char: 0x{$value}
|
||||
const_eval_invalid_dealloc =
|
||||
@ -168,16 +156,12 @@ const_eval_invalid_dealloc =
|
||||
*[other] {""}
|
||||
}
|
||||
|
||||
const_eval_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag
|
||||
const_eval_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer
|
||||
const_eval_invalid_function_pointer =
|
||||
using {$pointer} as function pointer but it does not point to a function
|
||||
const_eval_invalid_meta =
|
||||
invalid metadata in wide pointer: total size is bigger than largest supported object
|
||||
const_eval_invalid_meta_slice =
|
||||
invalid metadata in wide pointer: slice is bigger than largest supported object
|
||||
const_eval_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
|
||||
const_eval_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
const_eval_invalid_str =
|
||||
this string is not valid UTF-8: {$err}
|
||||
const_eval_invalid_tag =
|
||||
@ -189,14 +173,10 @@ const_eval_invalid_uninit_bytes =
|
||||
reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory
|
||||
const_eval_invalid_uninit_bytes_unknown =
|
||||
using uninitialized data, but this operation requires initialized memory
|
||||
const_eval_invalid_value = constructing invalid value
|
||||
const_eval_invalid_value_with_path = constructing invalid value at {$path}
|
||||
## The `front_matter`s here refer to either `middle_invalid_value` or `middle_invalid_value_with_path`.
|
||||
|
||||
const_eval_invalid_vtable_pointer =
|
||||
using {$pointer} as vtable pointer but it does not point to a vtable
|
||||
|
||||
const_eval_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
|
||||
|
||||
const_eval_live_drop =
|
||||
destructor of `{$dropped_ty}` cannot be evaluated at compile-time
|
||||
@ -218,14 +198,13 @@ const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant
|
||||
const_eval_memory_access_test = memory access failed
|
||||
const_eval_memory_exhausted =
|
||||
tried to allocate more memory than available to compiler
|
||||
|
||||
const_eval_modified_global =
|
||||
modifying a static's initial value from another static's initializer
|
||||
|
||||
const_eval_mut_deref =
|
||||
mutation through a reference is not allowed in {const_eval_const_context}s
|
||||
|
||||
const_eval_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const`
|
||||
const_eval_never_val = {$front_matter}: encountered a value of the never type `!`
|
||||
const_eval_non_const_fmt_macro_call =
|
||||
cannot call non-const formatting macro in {const_eval_const_context}s
|
||||
|
||||
@ -241,10 +220,6 @@ const_eval_noreturn_asm_returned =
|
||||
const_eval_not_enough_caller_args =
|
||||
calling a function with fewer arguments than it requires
|
||||
|
||||
const_eval_null_box = {$front_matter}: encountered a null box
|
||||
const_eval_null_fn_ptr = {$front_matter}: encountered a null function pointer
|
||||
const_eval_null_ref = {$front_matter}: encountered a null reference
|
||||
const_eval_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_nullary_intrinsic_fail =
|
||||
could not evaluate nullary intrinsic
|
||||
|
||||
@ -257,7 +232,6 @@ const_eval_offset_from_underflow =
|
||||
|
||||
const_eval_operator_non_const =
|
||||
cannot call non-const operator in {const_eval_const_context}s
|
||||
const_eval_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
|
||||
const_eval_overflow =
|
||||
overflow executing `{$name}`
|
||||
|
||||
@ -287,7 +261,6 @@ const_eval_ptr_as_bytes_1 =
|
||||
this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
const_eval_ptr_as_bytes_2 =
|
||||
the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
const_eval_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_question_branch_non_const =
|
||||
`?` cannot determine the branch of `{$ty}` in {const_eval_const_context}s
|
||||
|
||||
@ -315,8 +288,8 @@ const_eval_raw_ptr_to_int =
|
||||
|
||||
const_eval_read_extern_static =
|
||||
cannot read from extern static ({$did})
|
||||
const_eval_read_pointer_as_bytes =
|
||||
unable to turn pointer into raw bytes
|
||||
const_eval_read_pointer_as_int =
|
||||
unable to turn pointer into integer
|
||||
const_eval_realloc_or_alloc_with_offset =
|
||||
{$kind ->
|
||||
[dealloc] deallocating
|
||||
@ -324,9 +297,6 @@ const_eval_realloc_or_alloc_with_offset =
|
||||
*[other] {""}
|
||||
} {$ptr} which does not point to the beginning of an object
|
||||
|
||||
const_eval_ref_to_mut = {$front_matter}: encountered a reference pointing to mutable memory in a constant
|
||||
const_eval_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
|
||||
const_eval_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
|
||||
const_eval_remainder_by_zero =
|
||||
calculating the remainder with a divisor of zero
|
||||
const_eval_remainder_overflow =
|
||||
@ -363,8 +333,6 @@ const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in
|
||||
|
||||
const_eval_try_block_from_output_non_const =
|
||||
`try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
|
||||
const_eval_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
const_eval_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s
|
||||
|
||||
const_eval_unallowed_heap_allocations =
|
||||
@ -408,29 +376,14 @@ const_eval_undefined_behavior =
|
||||
const_eval_undefined_behavior_note =
|
||||
The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
const_eval_uninhabited_enum_tag = {$front_matter}: encountered an uninhabited enum variant
|
||||
const_eval_uninhabited_enum_variant_read =
|
||||
read discriminant of an uninhabited enum variant
|
||||
const_eval_uninhabited_enum_variant_written =
|
||||
writing discriminant of an uninhabited enum variant
|
||||
const_eval_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}`
|
||||
const_eval_uninit = {$front_matter}: encountered uninitialized bytes
|
||||
const_eval_uninit_bool = {$front_matter}: encountered uninitialized memory, but expected a boolean
|
||||
const_eval_uninit_box = {$front_matter}: encountered uninitialized memory, but expected a box
|
||||
const_eval_uninit_char = {$front_matter}: encountered uninitialized memory, but expected a unicode scalar value
|
||||
const_eval_uninit_enum_tag = {$front_matter}: encountered uninitialized bytes, but expected a valid enum tag
|
||||
const_eval_uninit_float = {$front_matter}: encountered uninitialized memory, but expected a floating point number
|
||||
const_eval_uninit_fn_ptr = {$front_matter}: encountered uninitialized memory, but expected a function pointer
|
||||
const_eval_uninit_init_scalar = {$front_matter}: encountered uninitialized memory, but expected initialized scalar value
|
||||
const_eval_uninit_int = {$front_matter}: encountered uninitialized memory, but expected an integer
|
||||
const_eval_uninit_raw_ptr = {$front_matter}: encountered uninitialized memory, but expected a raw pointer
|
||||
const_eval_uninit_ref = {$front_matter}: encountered uninitialized memory, but expected a reference
|
||||
const_eval_uninit_str = {$front_matter}: encountered uninitialized data in `str`
|
||||
const_eval_unreachable = entering unreachable code
|
||||
const_eval_unreachable_unwind =
|
||||
unwinding past a stack frame that does not allow unwinding
|
||||
|
||||
const_eval_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const`
|
||||
const_eval_unsigned_offset_from_overflow =
|
||||
`ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
|
||||
|
||||
@ -453,8 +406,63 @@ const_eval_unwind_past_top =
|
||||
const_eval_upcast_mismatch =
|
||||
upcast on a pointer whose vtable does not match its type
|
||||
|
||||
## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
|
||||
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
|
||||
const_eval_validation_box_to_mut = {$front_matter}: encountered a box pointing to mutable memory in a constant
|
||||
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
|
||||
const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
|
||||
const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
|
||||
const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
|
||||
const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
|
||||
const_eval_validation_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance)
|
||||
const_eval_validation_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)
|
||||
const_eval_validation_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free)
|
||||
|
||||
const_eval_validation_expected_bool = expected a boolean
|
||||
const_eval_validation_expected_box = expected a box
|
||||
const_eval_validation_expected_char = expected a unicode scalar value
|
||||
const_eval_validation_expected_enum_tag = expected a valid enum tag
|
||||
const_eval_validation_expected_float = expected a floating point number
|
||||
const_eval_validation_expected_fn_ptr = expected a function pointer
|
||||
const_eval_validation_expected_init_scalar = expected initialized scalar value
|
||||
const_eval_validation_expected_int = expected an integer
|
||||
const_eval_validation_expected_raw_ptr = expected a raw pointer
|
||||
const_eval_validation_expected_ref = expected a reference
|
||||
const_eval_validation_expected_str = expected a string
|
||||
|
||||
const_eval_validation_front_matter_invalid_value = constructing invalid value
|
||||
const_eval_validation_front_matter_invalid_value_with_path = constructing invalid value at {$path}
|
||||
|
||||
const_eval_validation_invalid_bool = {$front_matter}: encountered {$value}, but expected a boolean
|
||||
const_eval_validation_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object
|
||||
const_eval_validation_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object
|
||||
const_eval_validation_invalid_char = {$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
|
||||
|
||||
const_eval_validation_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag
|
||||
const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer
|
||||
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
|
||||
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
|
||||
const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const`
|
||||
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
|
||||
const_eval_validation_null_box = {$front_matter}: encountered a null box
|
||||
const_eval_validation_null_fn_ptr = {$front_matter}: encountered a null function pointer
|
||||
const_eval_validation_null_ref = {$front_matter}: encountered a null reference
|
||||
const_eval_validation_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
|
||||
const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
|
||||
const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
|
||||
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_validation_ref_to_mut = {$front_matter}: encountered a reference pointing to mutable memory in a constant
|
||||
const_eval_validation_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
|
||||
const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
|
||||
const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
const_eval_validation_uninhabited_enum_variant = {$front_matter}: encountered an uninhabited enum variant
|
||||
const_eval_validation_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}`
|
||||
const_eval_validation_uninit = {$front_matter}: encountered uninitialized memory, but {$expected}
|
||||
const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const`
|
||||
|
||||
const_eval_write_to_read_only =
|
||||
writing to {$allocation} which is read-only
|
||||
const_eval_zst_pointer_out_of_bounds =
|
||||
|
@ -513,7 +513,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
||||
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
|
||||
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
|
||||
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
|
||||
Validation(e) => e.diagnostic_message(),
|
||||
ValidationError(e) => e.diagnostic_message(),
|
||||
Custom(x) => (x.msg)(),
|
||||
}
|
||||
}
|
||||
@ -587,13 +587,13 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
||||
InvalidUninitBytes(Some((alloc, info))) => {
|
||||
builder.set_arg("alloc", alloc);
|
||||
builder.set_arg("access", info.access);
|
||||
builder.set_arg("uninit", info.uninit);
|
||||
builder.set_arg("uninit", info.bad);
|
||||
}
|
||||
ScalarSizeMismatch(info) => {
|
||||
builder.set_arg("target_size", info.target_size);
|
||||
builder.set_arg("data_size", info.data_size);
|
||||
}
|
||||
Validation(e) => e.add_args(handler, builder),
|
||||
ValidationError(e) => e.add_args(handler, builder),
|
||||
Custom(custom) => {
|
||||
(custom.add_args)(&mut |name, value| {
|
||||
builder.set_arg(name, value);
|
||||
@ -608,74 +608,72 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
||||
use crate::fluent_generated::*;
|
||||
use rustc_middle::mir::interpret::ValidationErrorKind::*;
|
||||
match self.kind {
|
||||
PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => const_eval_box_to_uninhabited,
|
||||
PtrToUninhabited { ptr_kind: PointerKind::Ref, .. } => const_eval_ref_to_uninhabited,
|
||||
PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => {
|
||||
const_eval_validation_box_to_uninhabited
|
||||
}
|
||||
PtrToUninhabited { ptr_kind: PointerKind::Ref, .. } => {
|
||||
const_eval_validation_ref_to_uninhabited
|
||||
}
|
||||
|
||||
PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_box_to_static,
|
||||
PtrToStatic { ptr_kind: PointerKind::Ref } => const_eval_ref_to_static,
|
||||
PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_static,
|
||||
PtrToStatic { ptr_kind: PointerKind::Ref } => const_eval_validation_ref_to_static,
|
||||
|
||||
PtrToMut { ptr_kind: PointerKind::Box } => const_eval_box_to_mut,
|
||||
PtrToMut { ptr_kind: PointerKind::Ref } => const_eval_ref_to_mut,
|
||||
PtrToMut { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_mut,
|
||||
PtrToMut { ptr_kind: PointerKind::Ref } => const_eval_validation_ref_to_mut,
|
||||
|
||||
ExpectedNonPtr { .. } => const_eval_expected_non_ptr,
|
||||
MutableRefInConst => const_eval_mutable_ref_in_const,
|
||||
NullFnPtr => const_eval_null_fn_ptr,
|
||||
NeverVal => const_eval_never_val,
|
||||
NullablePtrOutOfRange { .. } => const_eval_nullable_ptr_out_of_range,
|
||||
PtrOutOfRange { .. } => const_eval_ptr_out_of_range,
|
||||
OutOfRange { .. } => const_eval_out_of_range,
|
||||
UnsafeCell => const_eval_unsafe_cell,
|
||||
UninhabitedVal { .. } => const_eval_uninhabited_val,
|
||||
InvalidEnumTag { .. } => const_eval_invalid_enum_tag,
|
||||
UninhabitedEnumTag => const_eval_uninhabited_enum_tag,
|
||||
UninitEnumTag => const_eval_uninit_enum_tag,
|
||||
UninitStr => const_eval_uninit_str,
|
||||
Uninit { expected: ExpectedKind::Bool } => const_eval_uninit_bool,
|
||||
Uninit { expected: ExpectedKind::Reference } => const_eval_uninit_ref,
|
||||
Uninit { expected: ExpectedKind::Box } => const_eval_uninit_box,
|
||||
Uninit { expected: ExpectedKind::RawPtr } => const_eval_uninit_raw_ptr,
|
||||
Uninit { expected: ExpectedKind::InitScalar } => const_eval_uninit_init_scalar,
|
||||
Uninit { expected: ExpectedKind::Char } => const_eval_uninit_char,
|
||||
Uninit { expected: ExpectedKind::Float } => const_eval_uninit_float,
|
||||
Uninit { expected: ExpectedKind::Int } => const_eval_uninit_int,
|
||||
Uninit { expected: ExpectedKind::FnPtr } => const_eval_uninit_fn_ptr,
|
||||
UninitVal => const_eval_uninit,
|
||||
InvalidVTablePtr { .. } => const_eval_invalid_vtable_ptr,
|
||||
PointerAsInt { .. } => const_eval_validation_pointer_as_int,
|
||||
PartialPointer => const_eval_validation_partial_pointer,
|
||||
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
|
||||
NullFnPtr => const_eval_validation_null_fn_ptr,
|
||||
NeverVal => const_eval_validation_never_val,
|
||||
NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
|
||||
PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
|
||||
OutOfRange { .. } => const_eval_validation_out_of_range,
|
||||
UnsafeCell => const_eval_validation_unsafe_cell,
|
||||
UninhabitedVal { .. } => const_eval_validation_uninhabited_val,
|
||||
InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag,
|
||||
UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
|
||||
Uninit { .. } => const_eval_validation_uninit,
|
||||
InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
|
||||
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
|
||||
const_eval_invalid_box_slice_meta
|
||||
const_eval_validation_invalid_box_slice_meta
|
||||
}
|
||||
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref } => {
|
||||
const_eval_invalid_ref_slice_meta
|
||||
const_eval_validation_invalid_ref_slice_meta
|
||||
}
|
||||
|
||||
InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => const_eval_invalid_box_meta,
|
||||
InvalidMetaTooLarge { ptr_kind: PointerKind::Ref } => const_eval_invalid_ref_meta,
|
||||
UnalignedPtr { ptr_kind: PointerKind::Ref, .. } => const_eval_unaligned_ref,
|
||||
UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_unaligned_box,
|
||||
InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => {
|
||||
const_eval_validation_invalid_box_meta
|
||||
}
|
||||
InvalidMetaTooLarge { ptr_kind: PointerKind::Ref } => {
|
||||
const_eval_validation_invalid_ref_meta
|
||||
}
|
||||
UnalignedPtr { ptr_kind: PointerKind::Ref, .. } => const_eval_validation_unaligned_ref,
|
||||
UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box,
|
||||
|
||||
NullPtr { ptr_kind: PointerKind::Box } => const_eval_null_box,
|
||||
NullPtr { ptr_kind: PointerKind::Ref } => const_eval_null_ref,
|
||||
NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box,
|
||||
NullPtr { ptr_kind: PointerKind::Ref } => const_eval_validation_null_ref,
|
||||
DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
|
||||
const_eval_dangling_box_no_provenance
|
||||
const_eval_validation_dangling_box_no_provenance
|
||||
}
|
||||
DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref, .. } => {
|
||||
const_eval_dangling_ref_no_provenance
|
||||
const_eval_validation_dangling_ref_no_provenance
|
||||
}
|
||||
DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => {
|
||||
const_eval_dangling_box_out_of_bounds
|
||||
const_eval_validation_dangling_box_out_of_bounds
|
||||
}
|
||||
DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref } => {
|
||||
const_eval_dangling_ref_out_of_bounds
|
||||
const_eval_validation_dangling_ref_out_of_bounds
|
||||
}
|
||||
DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => {
|
||||
const_eval_dangling_box_use_after_free
|
||||
const_eval_validation_dangling_box_use_after_free
|
||||
}
|
||||
DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref } => {
|
||||
const_eval_dangling_ref_use_after_free
|
||||
const_eval_validation_dangling_ref_use_after_free
|
||||
}
|
||||
InvalidBool { .. } => const_eval_validation_invalid_bool,
|
||||
InvalidChar { .. } => const_eval_validation_invalid_char,
|
||||
InvalidFnPtr { .. } => const_eval_invalid_fn_ptr,
|
||||
InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
@ -683,13 +681,21 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
||||
use crate::fluent_generated as fluent;
|
||||
use rustc_middle::mir::interpret::ValidationErrorKind::*;
|
||||
|
||||
if let PointerAsInt { .. } | PartialPointer = self.kind {
|
||||
err.help(fluent::const_eval_ptr_as_bytes_1);
|
||||
err.help(fluent::const_eval_ptr_as_bytes_2);
|
||||
}
|
||||
|
||||
let message = if let Some(path) = self.path {
|
||||
handler.eagerly_translate_to_string(
|
||||
fluent::const_eval_invalid_value_with_path,
|
||||
fluent::const_eval_validation_front_matter_invalid_value_with_path,
|
||||
[("path".into(), DiagnosticArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
|
||||
)
|
||||
} else {
|
||||
handler.eagerly_translate_to_string(fluent::const_eval_invalid_value, [].into_iter())
|
||||
handler.eagerly_translate_to_string(
|
||||
fluent::const_eval_validation_front_matter_invalid_value,
|
||||
[].into_iter(),
|
||||
)
|
||||
};
|
||||
|
||||
err.set_arg("front_matter", message);
|
||||
@ -729,8 +735,24 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
||||
PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
|
||||
err.set_arg("ty", ty);
|
||||
}
|
||||
ExpectedNonPtr { value }
|
||||
| InvalidEnumTag { value }
|
||||
PointerAsInt { expected } | Uninit { expected } => {
|
||||
let msg = match expected {
|
||||
ExpectedKind::Reference => fluent::const_eval_validation_expected_ref,
|
||||
ExpectedKind::Box => fluent::const_eval_validation_expected_box,
|
||||
ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr,
|
||||
ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar,
|
||||
ExpectedKind::Bool => fluent::const_eval_validation_expected_bool,
|
||||
ExpectedKind::Char => fluent::const_eval_validation_expected_char,
|
||||
ExpectedKind::Float => fluent::const_eval_validation_expected_float,
|
||||
ExpectedKind::Int => fluent::const_eval_validation_expected_int,
|
||||
ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr,
|
||||
ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag,
|
||||
ExpectedKind::Str => fluent::const_eval_validation_expected_str,
|
||||
};
|
||||
let msg = handler.eagerly_translate_to_string(msg, [].into_iter());
|
||||
err.set_arg("expected", msg);
|
||||
}
|
||||
InvalidEnumTag { value }
|
||||
| InvalidVTablePtr { value }
|
||||
| InvalidBool { value }
|
||||
| InvalidChar { value }
|
||||
@ -758,15 +780,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
||||
| NullFnPtr
|
||||
| NeverVal
|
||||
| UnsafeCell
|
||||
| UninitEnumTag
|
||||
| UninitStr
|
||||
| Uninit { .. }
|
||||
| UninitVal
|
||||
| InvalidMetaSliceTooLarge { .. }
|
||||
| InvalidMetaTooLarge { .. }
|
||||
| DanglingPtrUseAfterFree { .. }
|
||||
| DanglingPtrOutOfBounds { .. }
|
||||
| UninhabitedEnumTag => {}
|
||||
| UninhabitedEnumVariant
|
||||
| PartialPointer => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -776,9 +795,9 @@ impl ReportErrorExt for UnsupportedOpInfo {
|
||||
use crate::fluent_generated::*;
|
||||
match self {
|
||||
UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
|
||||
UnsupportedOpInfo::PartialPointerOverwrite(_) => const_eval_partial_pointer_overwrite,
|
||||
UnsupportedOpInfo::PartialPointerCopy(_) => const_eval_partial_pointer_copy,
|
||||
UnsupportedOpInfo::ReadPointerAsBytes => const_eval_read_pointer_as_bytes,
|
||||
UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite,
|
||||
UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
|
||||
UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
|
||||
UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
|
||||
UnsupportedOpInfo::ReadExternStatic(_) => const_eval_read_extern_static,
|
||||
}
|
||||
@ -787,13 +806,16 @@ impl ReportErrorExt for UnsupportedOpInfo {
|
||||
use crate::fluent_generated::*;
|
||||
|
||||
use UnsupportedOpInfo::*;
|
||||
if let ReadPointerAsBytes | PartialPointerOverwrite(_) | PartialPointerCopy(_) = self {
|
||||
if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self {
|
||||
builder.help(const_eval_ptr_as_bytes_1);
|
||||
builder.help(const_eval_ptr_as_bytes_2);
|
||||
}
|
||||
match self {
|
||||
Unsupported(_) | ReadPointerAsBytes => {}
|
||||
PartialPointerOverwrite(ptr) | PartialPointerCopy(ptr) => {
|
||||
// `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to
|
||||
// be further processed by validity checking which then turns it into something nice to
|
||||
// print. So it's not worth the effort of having diagnostics that can print the `info`.
|
||||
Unsupported(_) | ReadPointerAsInt(_) => {}
|
||||
OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
|
||||
builder.set_arg("ptr", ptr);
|
||||
}
|
||||
ThreadLocalStatic(did) | ReadExternStatic(did) => {
|
||||
|
@ -25,13 +25,17 @@ use rustc_target::abi::{
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
// for the validation errors
|
||||
use super::UndefinedBehaviorInfo::*;
|
||||
use super::{
|
||||
AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy,
|
||||
Machine, MemPlaceMeta, OpTy, Pointer, Projectable, Scalar, ValueVisitor,
|
||||
};
|
||||
|
||||
// for the validation errors
|
||||
use super::InterpError::UndefinedBehavior as Ub;
|
||||
use super::InterpError::Unsupported as Unsup;
|
||||
use super::UndefinedBehaviorInfo::*;
|
||||
use super::UnsupportedOpInfo::*;
|
||||
|
||||
macro_rules! throw_validation_failure {
|
||||
($where:expr, $kind: expr) => {{
|
||||
let where_ = &$where;
|
||||
@ -43,7 +47,7 @@ macro_rules! throw_validation_failure {
|
||||
None
|
||||
};
|
||||
|
||||
throw_ub!(Validation(ValidationErrorInfo { path, kind: $kind }))
|
||||
throw_ub!(ValidationError(ValidationErrorInfo { path, kind: $kind }))
|
||||
}};
|
||||
}
|
||||
|
||||
@ -85,16 +89,16 @@ macro_rules! try_validation {
|
||||
Ok(x) => x,
|
||||
// We catch the error and turn it into a validation failure. We are okay with
|
||||
// allocation here as this can only slow down builds that fail anyway.
|
||||
Err(e) => match e.into_parts() {
|
||||
Err(e) => match e.kind() {
|
||||
$(
|
||||
(InterpError::UndefinedBehavior($($p)|+), _) =>
|
||||
$($p)|+ =>
|
||||
throw_validation_failure!(
|
||||
$where,
|
||||
$kind
|
||||
)
|
||||
),+,
|
||||
#[allow(unreachable_patterns)]
|
||||
(e, rest) => Err::<!, _>($crate::interpret::InterpErrorInfo::from_parts(e, rest))?,
|
||||
_ => Err::<!, _>(e)?,
|
||||
}
|
||||
}
|
||||
}};
|
||||
@ -294,7 +298,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
Ok(try_validation!(
|
||||
self.ecx.read_immediate(op),
|
||||
self.path,
|
||||
InvalidUninitBytes(None) => Uninit { expected }
|
||||
Ub(InvalidUninitBytes(None)) =>
|
||||
Uninit { expected },
|
||||
// The `Unsup` cases can only occur during CTFE
|
||||
Unsup(ReadPointerAsInt(_)) =>
|
||||
PointerAsInt { expected },
|
||||
Unsup(ReadPartialPointer(_)) =>
|
||||
PartialPointer,
|
||||
))
|
||||
}
|
||||
|
||||
@ -319,8 +329,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
let (_ty, _trait) = try_validation!(
|
||||
self.ecx.get_ptr_vtable(vtable),
|
||||
self.path,
|
||||
DanglingIntPointer(..) |
|
||||
InvalidVTablePointer(..) => InvalidVTablePtr { value: format!("{vtable}") }
|
||||
Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
|
||||
InvalidVTablePtr { value: format!("{vtable}") }
|
||||
);
|
||||
// FIXME: check if the type/trait match what ty::Dynamic says?
|
||||
}
|
||||
@ -356,7 +366,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
let size_and_align = try_validation!(
|
||||
self.ecx.size_and_align_of_mplace(&place),
|
||||
self.path,
|
||||
InvalidMeta(msg) => match msg {
|
||||
Ub(InvalidMeta(msg)) => match msg {
|
||||
InvalidMetaKind::SliceTooBig => InvalidMetaSliceTooLarge { ptr_kind },
|
||||
InvalidMetaKind::TooBig => InvalidMetaTooLarge { ptr_kind },
|
||||
}
|
||||
@ -375,23 +385,23 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
|
||||
),
|
||||
self.path,
|
||||
AlignmentCheckFailed { required, has } => UnalignedPtr {
|
||||
Ub(AlignmentCheckFailed { required, has }) => UnalignedPtr {
|
||||
ptr_kind,
|
||||
required_bytes: required.bytes(),
|
||||
found_bytes: has.bytes()
|
||||
},
|
||||
DanglingIntPointer(0, _) => NullPtr { ptr_kind },
|
||||
DanglingIntPointer(i, _) => DanglingPtrNoProvenance {
|
||||
Ub(DanglingIntPointer(0, _)) => NullPtr { ptr_kind },
|
||||
Ub(DanglingIntPointer(i, _)) => DanglingPtrNoProvenance {
|
||||
ptr_kind,
|
||||
// FIXME this says "null pointer" when null but we need translate
|
||||
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i))
|
||||
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(*i))
|
||||
},
|
||||
PointerOutOfBounds { .. } => DanglingPtrOutOfBounds {
|
||||
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
|
||||
ptr_kind
|
||||
},
|
||||
// This cannot happen during const-eval (because interning already detects
|
||||
// dangling pointers), but it can happen in Miri.
|
||||
PointerUseAfterFree(..) => DanglingPtrUseAfterFree {
|
||||
Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree {
|
||||
ptr_kind,
|
||||
},
|
||||
);
|
||||
@ -477,7 +487,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
try_validation!(
|
||||
value.to_bool(),
|
||||
self.path,
|
||||
InvalidBool(..) => ValidationErrorKind::InvalidBool {
|
||||
Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool {
|
||||
value: format!("{value:x}"),
|
||||
}
|
||||
);
|
||||
@ -488,7 +498,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
try_validation!(
|
||||
value.to_char(),
|
||||
self.path,
|
||||
InvalidChar(..) => ValidationErrorKind::InvalidChar {
|
||||
Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar {
|
||||
value: format!("{value:x}"),
|
||||
}
|
||||
);
|
||||
@ -497,7 +507,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
|
||||
// NOTE: Keep this in sync with the array optimization for int/float
|
||||
// types below!
|
||||
let value = self.read_scalar(
|
||||
self.read_scalar(
|
||||
value,
|
||||
if matches!(ty.kind(), ty::Float(..)) {
|
||||
ExpectedKind::Float
|
||||
@ -505,14 +515,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
ExpectedKind::Int
|
||||
},
|
||||
)?;
|
||||
// As a special exception we *do* match on a `Scalar` here, since we truly want
|
||||
// to know its underlying representation (and *not* cast it to an integer).
|
||||
if matches!(value, Scalar::Ptr(..)) {
|
||||
throw_validation_failure!(
|
||||
self.path,
|
||||
ExpectedNonPtr { value: format!("{value:x}") }
|
||||
)
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
@ -546,10 +548,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
let _fn = try_validation!(
|
||||
self.ecx.get_ptr_fn(ptr),
|
||||
self.path,
|
||||
DanglingIntPointer(..) |
|
||||
InvalidFunctionPointer(..) => InvalidFnPtr {
|
||||
value: format!("{ptr}"),
|
||||
},
|
||||
Ub(DanglingIntPointer(..) | InvalidFunctionPointer(..)) =>
|
||||
InvalidFnPtr { value: format!("{ptr}") },
|
||||
);
|
||||
// FIXME: Check if the signature matches
|
||||
} else {
|
||||
@ -657,11 +657,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
Ok(try_validation!(
|
||||
this.ecx.read_discriminant(op),
|
||||
this.path,
|
||||
InvalidTag(val) => InvalidEnumTag {
|
||||
Ub(InvalidTag(val)) => InvalidEnumTag {
|
||||
value: format!("{val:x}"),
|
||||
},
|
||||
UninhabitedEnumVariantRead(_) => UninhabitedEnumTag,
|
||||
InvalidUninitBytes(None) => UninitEnumTag,
|
||||
Ub(UninhabitedEnumVariantRead(_)) => UninhabitedEnumVariant,
|
||||
// Uninit / bad provenance are not possible since the field was already previously
|
||||
// checked at its integer type.
|
||||
))
|
||||
})
|
||||
}
|
||||
@ -740,7 +741,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
try_validation!(
|
||||
self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)),
|
||||
self.path,
|
||||
InvalidUninitBytes(..) => { UninitStr },
|
||||
Ub(InvalidUninitBytes(..)) => Uninit { expected: ExpectedKind::Str },
|
||||
Unsup(ReadPointerAsInt(_)) => PointerAsInt { expected: ExpectedKind::Str }
|
||||
);
|
||||
}
|
||||
ty::Array(tys, ..) | ty::Slice(tys)
|
||||
@ -752,6 +754,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..))
|
||||
=>
|
||||
{
|
||||
let expected = if tys.is_integral() { ExpectedKind::Int } else { ExpectedKind::Float };
|
||||
// Optimized handling for arrays of integer/float type.
|
||||
|
||||
// This is the length of the array/slice.
|
||||
@ -770,7 +773,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
Left(mplace) => mplace,
|
||||
Right(imm) => match *imm {
|
||||
Immediate::Uninit =>
|
||||
throw_validation_failure!(self.path, UninitVal),
|
||||
throw_validation_failure!(self.path, Uninit { expected }),
|
||||
Immediate::Scalar(..) | Immediate::ScalarPair(..) =>
|
||||
bug!("arrays/slices can never have Scalar/ScalarPair layout"),
|
||||
}
|
||||
@ -796,17 +799,21 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
// For some errors we might be able to provide extra information.
|
||||
// (This custom logic does not fit the `try_validation!` macro.)
|
||||
match err.kind() {
|
||||
err_ub!(InvalidUninitBytes(Some((_alloc_id, access)))) => {
|
||||
Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
|
||||
// Some byte was uninitialized, determine which
|
||||
// element that byte belongs to so we can
|
||||
// provide an index.
|
||||
let i = usize::try_from(
|
||||
access.uninit.start.bytes() / layout.size.bytes(),
|
||||
access.bad.start.bytes() / layout.size.bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
self.path.push(PathElem::ArrayElem(i));
|
||||
|
||||
throw_validation_failure!(self.path, UninitVal)
|
||||
if matches!(err.kind(), Ub(InvalidUninitBytes(_))) {
|
||||
throw_validation_failure!(self.path, Uninit { expected })
|
||||
} else {
|
||||
throw_validation_failure!(self.path, PointerAsInt { expected })
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate upwards (that will also check for unexpected errors).
|
||||
@ -892,17 +899,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// Run it.
|
||||
match visitor.visit_value(&op) {
|
||||
Ok(()) => Ok(()),
|
||||
// Pass through validation failures.
|
||||
Err(err) if matches!(err.kind(), err_ub!(Validation { .. })) => Err(err),
|
||||
// Complain about any other kind of UB error -- those are bad because we'd like to
|
||||
// Pass through validation failures and "invalid program" issues.
|
||||
Err(err)
|
||||
if matches!(
|
||||
err.kind(),
|
||||
err_ub!(ValidationError { .. }) | InterpError::InvalidProgram(_)
|
||||
) =>
|
||||
{
|
||||
Err(err)
|
||||
}
|
||||
// Complain about any other kind of error -- those are bad because we'd like to
|
||||
// report them in a way that shows *where* in the value the issue lies.
|
||||
Err(err) if matches!(err.kind(), InterpError::UndefinedBehavior(_)) => {
|
||||
Err(err) => {
|
||||
let (err, backtrace) = err.into_parts();
|
||||
backtrace.print_backtrace();
|
||||
bug!("Unexpected Undefined Behavior error during validation: {err:?}");
|
||||
}
|
||||
// Pass through everything else.
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -764,7 +764,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
Some(ty) if expected == ty => {
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
err.span_suggestion(
|
||||
source_map.end_point(cause.span),
|
||||
source_map.end_point(cause.span()),
|
||||
"try removing this `?`",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
|
@ -213,9 +213,6 @@ lint_expectation = this lint expectation is unfulfilled
|
||||
.note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
.rationale = {$rationale}
|
||||
|
||||
lint_fn_null_check = function pointers are not nullable, so checking them for null will always return false
|
||||
.help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
lint_for_loops_over_fallibles =
|
||||
for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
|
||||
.suggestion = consider using `if let` to clear intent
|
||||
@ -454,6 +451,13 @@ lint_path_statement_drop = path statement drops value
|
||||
|
||||
lint_path_statement_no_effect = path statement with no effect
|
||||
|
||||
lint_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false
|
||||
.help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
.label = expression has type `{$orig_ty}`
|
||||
|
||||
lint_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false
|
||||
.label = expression has type `{$orig_ty}`
|
||||
|
||||
lint_query_instability = using `{$query}` can result in unstable query results
|
||||
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
|
||||
|
||||
|
@ -1,112 +0,0 @@
|
||||
use crate::{lints::FnNullCheckDiag, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_lint! {
|
||||
/// The `incorrect_fn_null_checks` lint checks for expression that checks if a
|
||||
/// function pointer is null.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn test() {}
|
||||
/// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
|
||||
/// # test;
|
||||
///
|
||||
/// if (fn_ptr as *const ()).is_null() { /* ... */ }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Function pointers are assumed to be non-null, checking them for null will always
|
||||
/// return false.
|
||||
INCORRECT_FN_NULL_CHECKS,
|
||||
Warn,
|
||||
"incorrect checking of null function pointer"
|
||||
}
|
||||
|
||||
declare_lint_pass!(IncorrectFnNullChecks => [INCORRECT_FN_NULL_CHECKS]);
|
||||
|
||||
fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
let mut expr = expr.peel_blocks();
|
||||
let mut had_at_least_one_cast = false;
|
||||
while let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
|
||||
&& let TyKind::Ptr(_) = cast_ty.kind {
|
||||
expr = cast_expr.peel_blocks();
|
||||
had_at_least_one_cast = true;
|
||||
}
|
||||
had_at_least_one_cast && cx.typeck_results().expr_ty_adjusted(expr).is_fn()
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for IncorrectFnNullChecks {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
match expr.kind {
|
||||
// Catching:
|
||||
// <*<const/mut> <ty>>::is_null(fn_ptr as *<const/mut> <ty>)
|
||||
ExprKind::Call(path, [arg])
|
||||
if let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(def_id),
|
||||
Some(sym::ptr_const_is_null | sym::ptr_is_null)
|
||||
)
|
||||
&& is_fn_ptr_cast(cx, arg) =>
|
||||
{
|
||||
cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
|
||||
}
|
||||
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>).is_null()
|
||||
ExprKind::MethodCall(_, receiver, _, _)
|
||||
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(def_id),
|
||||
Some(sym::ptr_const_is_null | sym::ptr_is_null)
|
||||
)
|
||||
&& is_fn_ptr_cast(cx, receiver) =>
|
||||
{
|
||||
cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
|
||||
}
|
||||
|
||||
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
|
||||
let to_check: &Expr<'_>;
|
||||
if is_fn_ptr_cast(cx, left) {
|
||||
to_check = right;
|
||||
} else if is_fn_ptr_cast(cx, right) {
|
||||
to_check = left;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
match to_check.kind {
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
|
||||
ExprKind::Cast(cast_expr, _)
|
||||
if let ExprKind::Lit(spanned) = cast_expr.kind
|
||||
&& let LitKind::Int(v, _) = spanned.node && v == 0 =>
|
||||
{
|
||||
cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
|
||||
},
|
||||
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
|
||||
ExprKind::Call(path, [])
|
||||
if let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
|
||||
&& (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut) =>
|
||||
{
|
||||
cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
@ -57,7 +57,6 @@ mod early;
|
||||
mod enum_intrinsics_non_enums;
|
||||
mod errors;
|
||||
mod expect;
|
||||
mod fn_null_check;
|
||||
mod for_loops_over_fallibles;
|
||||
pub mod hidden_unicode_codepoints;
|
||||
mod internal;
|
||||
@ -76,6 +75,7 @@ mod noop_method_call;
|
||||
mod opaque_hidden_inferred_bound;
|
||||
mod pass_by_value;
|
||||
mod passes;
|
||||
mod ptr_nulls;
|
||||
mod redundant_semicolon;
|
||||
mod reference_casting;
|
||||
mod traits;
|
||||
@ -102,7 +102,6 @@ use builtin::*;
|
||||
use deref_into_dyn_supertrait::*;
|
||||
use drop_forget_useless::*;
|
||||
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
|
||||
use fn_null_check::*;
|
||||
use for_loops_over_fallibles::*;
|
||||
use hidden_unicode_codepoints::*;
|
||||
use internal::*;
|
||||
@ -117,6 +116,7 @@ use nonstandard_style::*;
|
||||
use noop_method_call::*;
|
||||
use opaque_hidden_inferred_bound::*;
|
||||
use pass_by_value::*;
|
||||
use ptr_nulls::*;
|
||||
use redundant_semicolon::*;
|
||||
use reference_casting::*;
|
||||
use traits::*;
|
||||
@ -227,7 +227,7 @@ late_lint_methods!(
|
||||
// Depends on types used in type definitions
|
||||
MissingCopyImplementations: MissingCopyImplementations,
|
||||
// Depends on referenced function signatures in expressions
|
||||
IncorrectFnNullChecks: IncorrectFnNullChecks,
|
||||
PtrNullChecks: PtrNullChecks,
|
||||
MutableTransmutes: MutableTransmutes,
|
||||
TypeAliasBounds: TypeAliasBounds,
|
||||
TrivialConstraints: TrivialConstraints,
|
||||
|
@ -613,11 +613,23 @@ pub struct ExpectationNote {
|
||||
pub rationale: Symbol,
|
||||
}
|
||||
|
||||
// fn_null_check.rs
|
||||
// ptr_nulls.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_fn_null_check)]
|
||||
#[help]
|
||||
pub struct FnNullCheckDiag;
|
||||
pub enum PtrNullChecksDiag<'a> {
|
||||
#[diag(lint_ptr_null_checks_fn_ptr)]
|
||||
#[help(lint_help)]
|
||||
FnPtr {
|
||||
orig_ty: Ty<'a>,
|
||||
#[label]
|
||||
label: Span,
|
||||
},
|
||||
#[diag(lint_ptr_null_checks_ref)]
|
||||
Ref {
|
||||
orig_ty: Ty<'a>,
|
||||
#[label]
|
||||
label: Span,
|
||||
},
|
||||
}
|
||||
|
||||
// for_loops_over_fallibles.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
|
146
compiler/rustc_lint/src/ptr_nulls.rs
Normal file
146
compiler/rustc_lint/src/ptr_nulls.rs
Normal file
@ -0,0 +1,146 @@
|
||||
use crate::{lints::PtrNullChecksDiag, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_lint! {
|
||||
/// The `useless_ptr_null_checks` lint checks for useless null checks against pointers
|
||||
/// obtained from non-null types.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn test() {}
|
||||
/// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
|
||||
/// # test;
|
||||
///
|
||||
/// if (fn_ptr as *const ()).is_null() { /* ... */ }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Function pointers and references are assumed to be non-null, checking them for null
|
||||
/// will always return false.
|
||||
USELESS_PTR_NULL_CHECKS,
|
||||
Warn,
|
||||
"useless checking of non-null-typed pointer"
|
||||
}
|
||||
|
||||
declare_lint_pass!(PtrNullChecks => [USELESS_PTR_NULL_CHECKS]);
|
||||
|
||||
/// This function detects and returns the original expression from a series of consecutive casts,
|
||||
/// ie. `(my_fn as *const _ as *mut _).cast_mut()` would return the expression for `my_fn`.
|
||||
fn ptr_cast_chain<'a>(cx: &'a LateContext<'_>, mut e: &'a Expr<'a>) -> Option<&'a Expr<'a>> {
|
||||
let mut had_at_least_one_cast = false;
|
||||
loop {
|
||||
e = e.peel_blocks();
|
||||
e = if let ExprKind::Cast(expr, t) = e.kind
|
||||
&& let TyKind::Ptr(_) = t.kind {
|
||||
had_at_least_one_cast = true;
|
||||
expr
|
||||
} else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
|
||||
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
|
||||
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_cast | sym::ptr_cast_mut)) {
|
||||
had_at_least_one_cast = true;
|
||||
expr
|
||||
} else if let ExprKind::Call(path, [arg]) = e.kind
|
||||
&& let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_from_ref | sym::ptr_from_mut)) {
|
||||
had_at_least_one_cast = true;
|
||||
arg
|
||||
} else if had_at_least_one_cast {
|
||||
return Some(e);
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn incorrect_check<'a>(cx: &LateContext<'a>, expr: &Expr<'_>) -> Option<PtrNullChecksDiag<'a>> {
|
||||
let expr = ptr_cast_chain(cx, expr)?;
|
||||
|
||||
let orig_ty = cx.typeck_results().expr_ty(expr);
|
||||
if orig_ty.is_fn() {
|
||||
Some(PtrNullChecksDiag::FnPtr { orig_ty, label: expr.span })
|
||||
} else if orig_ty.is_ref() {
|
||||
Some(PtrNullChecksDiag::Ref { orig_ty, label: expr.span })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
match expr.kind {
|
||||
// Catching:
|
||||
// <*<const/mut> <ty>>::is_null(fn_ptr as *<const/mut> <ty>)
|
||||
ExprKind::Call(path, [arg])
|
||||
if let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(def_id),
|
||||
Some(sym::ptr_const_is_null | sym::ptr_is_null)
|
||||
)
|
||||
&& let Some(diag) = incorrect_check(cx, arg) =>
|
||||
{
|
||||
cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
|
||||
}
|
||||
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>).is_null()
|
||||
ExprKind::MethodCall(_, receiver, _, _)
|
||||
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
|
||||
&& matches!(
|
||||
cx.tcx.get_diagnostic_name(def_id),
|
||||
Some(sym::ptr_const_is_null | sym::ptr_is_null)
|
||||
)
|
||||
&& let Some(diag) = incorrect_check(cx, receiver) =>
|
||||
{
|
||||
cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
|
||||
}
|
||||
|
||||
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
|
||||
let to_check: &Expr<'_>;
|
||||
let diag: PtrNullChecksDiag<'_>;
|
||||
if let Some(ddiag) = incorrect_check(cx, left) {
|
||||
to_check = right;
|
||||
diag = ddiag;
|
||||
} else if let Some(ddiag) = incorrect_check(cx, right) {
|
||||
to_check = left;
|
||||
diag = ddiag;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
match to_check.kind {
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
|
||||
ExprKind::Cast(cast_expr, _)
|
||||
if let ExprKind::Lit(spanned) = cast_expr.kind
|
||||
&& let LitKind::Int(v, _) = spanned.node && v == 0 =>
|
||||
{
|
||||
cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
|
||||
},
|
||||
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
|
||||
ExprKind::Call(path, [])
|
||||
if let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
|
||||
&& (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut) =>
|
||||
{
|
||||
cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
@ -18,9 +18,9 @@ use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::{Align, HasDataLayout, Size};
|
||||
|
||||
use super::{
|
||||
read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance,
|
||||
ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess,
|
||||
UnsupportedOpInfo,
|
||||
read_target_uint, write_target_uint, AllocId, BadBytesAccess, InterpError, InterpResult,
|
||||
Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
|
||||
UndefinedBehaviorInfo, UnsupportedOpInfo,
|
||||
};
|
||||
use crate::ty;
|
||||
use init_mask::*;
|
||||
@ -173,13 +173,13 @@ pub enum AllocError {
|
||||
/// A scalar had the wrong size.
|
||||
ScalarSizeMismatch(ScalarSizeMismatch),
|
||||
/// Encountered a pointer where we needed raw bytes.
|
||||
ReadPointerAsBytes,
|
||||
ReadPointerAsInt(Option<BadBytesAccess>),
|
||||
/// Partially overwriting a pointer.
|
||||
PartialPointerOverwrite(Size),
|
||||
OverwritePartialPointer(Size),
|
||||
/// Partially copying a pointer.
|
||||
PartialPointerCopy(Size),
|
||||
ReadPartialPointer(Size),
|
||||
/// Using uninitialized data where it is not allowed.
|
||||
InvalidUninitBytes(Option<UninitBytesAccess>),
|
||||
InvalidUninitBytes(Option<BadBytesAccess>),
|
||||
}
|
||||
pub type AllocResult<T = ()> = Result<T, AllocError>;
|
||||
|
||||
@ -196,12 +196,14 @@ impl AllocError {
|
||||
ScalarSizeMismatch(s) => {
|
||||
InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
|
||||
}
|
||||
ReadPointerAsBytes => InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes),
|
||||
PartialPointerOverwrite(offset) => InterpError::Unsupported(
|
||||
UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)),
|
||||
ReadPointerAsInt(info) => InterpError::Unsupported(
|
||||
UnsupportedOpInfo::ReadPointerAsInt(info.map(|b| (alloc_id, b))),
|
||||
),
|
||||
PartialPointerCopy(offset) => InterpError::Unsupported(
|
||||
UnsupportedOpInfo::PartialPointerCopy(Pointer::new(alloc_id, offset)),
|
||||
OverwritePartialPointer(offset) => InterpError::Unsupported(
|
||||
UnsupportedOpInfo::OverwritePartialPointer(Pointer::new(alloc_id, offset)),
|
||||
),
|
||||
ReadPartialPointer(offset) => InterpError::Unsupported(
|
||||
UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
|
||||
),
|
||||
InvalidUninitBytes(info) => InterpError::UndefinedBehavior(
|
||||
UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
|
||||
@ -433,14 +435,26 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
range: AllocRange,
|
||||
) -> AllocResult<&[u8]> {
|
||||
self.init_mask.is_range_initialized(range).map_err(|uninit_range| {
|
||||
AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
|
||||
AllocError::InvalidUninitBytes(Some(BadBytesAccess {
|
||||
access: range,
|
||||
uninit: uninit_range,
|
||||
bad: uninit_range,
|
||||
}))
|
||||
})?;
|
||||
if !Prov::OFFSET_IS_ADDR {
|
||||
if !self.provenance.range_empty(range, cx) {
|
||||
return Err(AllocError::ReadPointerAsBytes);
|
||||
// Find the provenance.
|
||||
let (offset, _prov) = self
|
||||
.provenance
|
||||
.range_get_ptrs(range, cx)
|
||||
.first()
|
||||
.copied()
|
||||
.expect("there must be provenance somewhere here");
|
||||
let start = offset.max(range.start); // the pointer might begin before `range`!
|
||||
let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`!
|
||||
return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess {
|
||||
access: range,
|
||||
bad: AllocRange::from(start..end),
|
||||
})));
|
||||
}
|
||||
}
|
||||
Ok(self.get_bytes_unchecked(range))
|
||||
@ -536,23 +550,25 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
// Now use this provenance.
|
||||
let ptr = Pointer::new(prov, Size::from_bytes(bits));
|
||||
return Ok(Scalar::from_maybe_pointer(ptr, cx));
|
||||
} else {
|
||||
// Without OFFSET_IS_ADDR, the only remaining case we can handle is total absence of
|
||||
// provenance.
|
||||
if self.provenance.range_empty(range, cx) {
|
||||
return Ok(Scalar::from_uint(bits, range.size));
|
||||
}
|
||||
// Else we have mixed provenance, that doesn't work.
|
||||
return Err(AllocError::ReadPartialPointer(range.start));
|
||||
}
|
||||
} else {
|
||||
// We are *not* reading a pointer.
|
||||
// If we can just ignore provenance, do exactly that.
|
||||
if Prov::OFFSET_IS_ADDR {
|
||||
// If we can just ignore provenance or there is none, that's easy.
|
||||
if Prov::OFFSET_IS_ADDR || self.provenance.range_empty(range, cx) {
|
||||
// We just strip provenance.
|
||||
return Ok(Scalar::from_uint(bits, range.size));
|
||||
}
|
||||
// There is some provenance and we don't have OFFSET_IS_ADDR. This doesn't work.
|
||||
return Err(AllocError::ReadPointerAsInt(None));
|
||||
}
|
||||
|
||||
// Fallback path for when we cannot treat provenance bytewise or ignore it.
|
||||
assert!(!Prov::OFFSET_IS_ADDR);
|
||||
if !self.provenance.range_empty(range, cx) {
|
||||
return Err(AllocError::ReadPointerAsBytes);
|
||||
}
|
||||
// There is no provenance, we can just return the bits.
|
||||
Ok(Scalar::from_uint(bits, range.size))
|
||||
}
|
||||
|
||||
/// Writes a *non-ZST* scalar.
|
||||
|
@ -66,7 +66,11 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
/// Returns all ptr-sized provenance in the given range.
|
||||
/// If the range has length 0, returns provenance that crosses the edge between `start-1` and
|
||||
/// `start`.
|
||||
fn range_get_ptrs(&self, range: AllocRange, cx: &impl HasDataLayout) -> &[(Size, Prov)] {
|
||||
pub(super) fn range_get_ptrs(
|
||||
&self,
|
||||
range: AllocRange,
|
||||
cx: &impl HasDataLayout,
|
||||
) -> &[(Size, Prov)] {
|
||||
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
|
||||
// the beginning of this range.
|
||||
let adjusted_start = Size::from_bytes(
|
||||
@ -158,7 +162,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
if first < start {
|
||||
if !Prov::OFFSET_IS_ADDR {
|
||||
// We can't split up the provenance into less than a pointer.
|
||||
return Err(AllocError::PartialPointerOverwrite(first));
|
||||
return Err(AllocError::OverwritePartialPointer(first));
|
||||
}
|
||||
// Insert the remaining part in the bytewise provenance.
|
||||
let prov = self.ptrs[&first];
|
||||
@ -171,7 +175,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
let begin_of_last = last - cx.data_layout().pointer_size;
|
||||
if !Prov::OFFSET_IS_ADDR {
|
||||
// We can't split up the provenance into less than a pointer.
|
||||
return Err(AllocError::PartialPointerOverwrite(begin_of_last));
|
||||
return Err(AllocError::OverwritePartialPointer(begin_of_last));
|
||||
}
|
||||
// Insert the remaining part in the bytewise provenance.
|
||||
let prov = self.ptrs[&begin_of_last];
|
||||
@ -246,10 +250,10 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
|
||||
if !Prov::OFFSET_IS_ADDR {
|
||||
// There can't be any bytewise provenance, and we cannot split up the begin/end overlap.
|
||||
if let Some(entry) = begin_overlap {
|
||||
return Err(AllocError::PartialPointerCopy(entry.0));
|
||||
return Err(AllocError::ReadPartialPointer(entry.0));
|
||||
}
|
||||
if let Some(entry) = end_overlap {
|
||||
return Err(AllocError::PartialPointerCopy(entry.0));
|
||||
return Err(AllocError::ReadPartialPointer(entry.0));
|
||||
}
|
||||
debug_assert!(self.bytes.is_none());
|
||||
} else {
|
||||
|
@ -134,10 +134,6 @@ impl InterpErrorBacktrace {
|
||||
}
|
||||
|
||||
impl<'tcx> InterpErrorInfo<'tcx> {
|
||||
pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
|
||||
Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
|
||||
}
|
||||
|
||||
pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
|
||||
let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
|
||||
(kind, backtrace)
|
||||
@ -226,13 +222,13 @@ impl IntoDiagnosticArg for InvalidMetaKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// Details of an access to uninitialized bytes where it is not allowed.
|
||||
/// Details of an access to uninitialized bytes / bad pointer bytes where it is not allowed.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct UninitBytesAccess {
|
||||
pub struct BadBytesAccess {
|
||||
/// Range of the original memory access.
|
||||
pub access: AllocRange,
|
||||
/// Range of the uninit memory that was encountered. (Might not be maximal.)
|
||||
pub uninit: AllocRange,
|
||||
/// Range of the bad memory that was encountered. (Might not be maximal.)
|
||||
pub bad: AllocRange,
|
||||
}
|
||||
|
||||
/// Information about a size mismatch.
|
||||
@ -316,7 +312,7 @@ pub enum UndefinedBehaviorInfo<'a> {
|
||||
/// Using a string that is not valid UTF-8,
|
||||
InvalidStr(std::str::Utf8Error),
|
||||
/// Using uninitialized data where it is not allowed.
|
||||
InvalidUninitBytes(Option<(AllocId, UninitBytesAccess)>),
|
||||
InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
|
||||
/// Working with a local that is not currently live.
|
||||
DeadLocal,
|
||||
/// Data size is not equal to target size.
|
||||
@ -326,7 +322,7 @@ pub enum UndefinedBehaviorInfo<'a> {
|
||||
/// An uninhabited enum variant is projected.
|
||||
UninhabitedEnumVariantRead(VariantIdx),
|
||||
/// Validation error.
|
||||
Validation(ValidationErrorInfo<'a>),
|
||||
ValidationError(ValidationErrorInfo<'a>),
|
||||
// FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
|
||||
// dispatched
|
||||
/// A custom (free-form) error, created by `err_ub_custom!`.
|
||||
@ -368,6 +364,8 @@ pub enum ExpectedKind {
|
||||
Float,
|
||||
Int,
|
||||
FnPtr,
|
||||
EnumTag,
|
||||
Str,
|
||||
}
|
||||
|
||||
impl From<PointerKind> for ExpectedKind {
|
||||
@ -381,10 +379,11 @@ impl From<PointerKind> for ExpectedKind {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ValidationErrorKind<'tcx> {
|
||||
PointerAsInt { expected: ExpectedKind },
|
||||
PartialPointer,
|
||||
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
|
||||
PtrToStatic { ptr_kind: PointerKind },
|
||||
PtrToMut { ptr_kind: PointerKind },
|
||||
ExpectedNonPtr { value: String },
|
||||
MutableRefInConst,
|
||||
NullFnPtr,
|
||||
NeverVal,
|
||||
@ -394,11 +393,8 @@ pub enum ValidationErrorKind<'tcx> {
|
||||
UnsafeCell,
|
||||
UninhabitedVal { ty: Ty<'tcx> },
|
||||
InvalidEnumTag { value: String },
|
||||
UninhabitedEnumTag,
|
||||
UninitEnumTag,
|
||||
UninitStr,
|
||||
UninhabitedEnumVariant,
|
||||
Uninit { expected: ExpectedKind },
|
||||
UninitVal,
|
||||
InvalidVTablePtr { value: String },
|
||||
InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
|
||||
InvalidMetaTooLarge { ptr_kind: PointerKind },
|
||||
@ -426,12 +422,12 @@ pub enum UnsupportedOpInfo {
|
||||
//
|
||||
/// Overwriting parts of a pointer; without knowing absolute addresses, the resulting state
|
||||
/// cannot be represented by the CTFE interpreter.
|
||||
PartialPointerOverwrite(Pointer<AllocId>),
|
||||
/// Attempting to `copy` parts of a pointer to somewhere else; without knowing absolute
|
||||
OverwritePartialPointer(Pointer<AllocId>),
|
||||
/// Attempting to read or copy parts of a pointer to somewhere else; without knowing absolute
|
||||
/// addresses, the resulting state cannot be represented by the CTFE interpreter.
|
||||
PartialPointerCopy(Pointer<AllocId>),
|
||||
/// Encountered a pointer where we needed raw bytes.
|
||||
ReadPointerAsBytes,
|
||||
ReadPartialPointer(Pointer<AllocId>),
|
||||
/// Encountered a pointer where we needed an integer.
|
||||
ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
|
||||
/// Accessing thread local statics
|
||||
ThreadLocalStatic(DefId),
|
||||
/// Accessing an unsupported extern static.
|
||||
@ -497,7 +493,7 @@ impl InterpError<'_> {
|
||||
matches!(
|
||||
self,
|
||||
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
|
||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Validation { .. })
|
||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
|
||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
||||
)
|
||||
}
|
||||
|
@ -142,11 +142,11 @@ use crate::ty::GenericArgKind;
|
||||
use crate::ty::{self, Instance, Ty, TyCtxt};
|
||||
|
||||
pub use self::error::{
|
||||
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
|
||||
EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind,
|
||||
InvalidProgramInfo, MachineStopType, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
|
||||
ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
|
||||
ValidationErrorInfo, ValidationErrorKind,
|
||||
struct_error, BadBytesAccess, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult,
|
||||
EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo,
|
||||
InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, PointerKind,
|
||||
ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo,
|
||||
UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind,
|
||||
};
|
||||
|
||||
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
|
||||
|
@ -378,15 +378,16 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
||||
#[inline]
|
||||
pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
|
||||
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
|
||||
self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err(
|
||||
|size| {
|
||||
self.try_to_int()
|
||||
.map_err(|_| err_unsup!(ReadPointerAsInt(None)))?
|
||||
.to_bits(target_size)
|
||||
.map_err(|size| {
|
||||
err_ub!(ScalarSizeMismatch(ScalarSizeMismatch {
|
||||
target_size: target_size.bytes(),
|
||||
data_size: size.bytes(),
|
||||
}))
|
||||
.into()
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -23,6 +23,8 @@ parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or late
|
||||
parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
|
||||
.label = to use `async fn`, switch to Rust 2018 or later
|
||||
|
||||
parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later
|
||||
|
||||
parse_async_move_order_incorrect = the order of `move` and `async` is incorrect
|
||||
.suggestion = try switching the order
|
||||
|
||||
@ -270,6 +272,8 @@ parse_found_expr_would_be_stmt = expected expression, found `{$token}`
|
||||
parse_function_body_equals_expr = function body cannot be `= expression;`
|
||||
.suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`
|
||||
|
||||
parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax
|
||||
|
||||
parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
|
||||
.suggestion = surround the type parameters with angle brackets
|
||||
|
||||
|
@ -1434,6 +1434,13 @@ pub(crate) struct AsyncBlockIn2015 {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_async_move_block_in_2015)]
|
||||
pub(crate) struct AsyncMoveBlockIn2015 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_self_argument_pointer)]
|
||||
pub(crate) struct SelfArgumentPointer {
|
||||
@ -2731,3 +2738,17 @@ pub(crate) struct WhereClauseBeforeConstBodySugg {
|
||||
#[suggestion_part(code = "")]
|
||||
pub right: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_generic_args_in_pat_require_turbofish_syntax)]
|
||||
pub(crate) struct GenericArgsInPatRequireTurbofishSyntax {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(
|
||||
parse_sugg_turbofish_syntax,
|
||||
style = "verbose",
|
||||
code = "::",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub suggest_turbofish: Span,
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ use super::{
|
||||
TokenExpectType, TokenType,
|
||||
};
|
||||
use crate::errors::{
|
||||
AmbiguousPlus, AttributeOnParamType, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi,
|
||||
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
|
||||
ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything,
|
||||
DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
||||
AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, BadQPathStage2, BadTypePlus,
|
||||
BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained,
|
||||
ComparisonOperatorsCannotBeChainedSugg, ConstGenericWithoutBraces,
|
||||
ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, DocCommentOnParamType,
|
||||
DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
||||
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
|
||||
HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon,
|
||||
IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg,
|
||||
@ -573,6 +574,12 @@ impl<'a> Parser<'a> {
|
||||
return Err(self.sess.create_err(UseEqInstead { span: self.token.span }));
|
||||
}
|
||||
|
||||
if self.token.is_keyword(kw::Move) && self.prev_token.is_keyword(kw::Async) {
|
||||
// The 2015 edition is in use because parsing of `async move` has failed.
|
||||
let span = self.prev_token.span.to(self.token.span);
|
||||
return Err(self.sess.create_err(AsyncMoveBlockIn2015 { span }));
|
||||
}
|
||||
|
||||
let expect = tokens_to_string(&expected);
|
||||
let actual = super::token_descr(&self.token);
|
||||
let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
|
||||
@ -2100,7 +2107,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
|
||||
let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName))?;
|
||||
let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
|
||||
self.expect(&token::Colon)?;
|
||||
let ty = self.parse_ty()?;
|
||||
|
||||
@ -2508,7 +2515,7 @@ impl<'a> Parser<'a> {
|
||||
// Skip the `:`.
|
||||
snapshot_pat.bump();
|
||||
snapshot_type.bump();
|
||||
match snapshot_pat.parse_pat_no_top_alt(expected) {
|
||||
match snapshot_pat.parse_pat_no_top_alt(expected, None) {
|
||||
Err(inner_err) => {
|
||||
inner_err.cancel();
|
||||
}
|
||||
@ -2772,7 +2779,7 @@ impl<'a> Parser<'a> {
|
||||
/// sequence of patterns until `)` is reached.
|
||||
fn skip_pat_list(&mut self) -> PResult<'a, ()> {
|
||||
while !self.check(&token::CloseDelim(Delimiter::Parenthesis)) {
|
||||
self.parse_pat_no_top_alt(None)?;
|
||||
self.parse_pat_no_top_alt(None, None)?;
|
||||
if !self.eat(&token::Comma) {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -2338,7 +2338,7 @@ impl<'a> Parser<'a> {
|
||||
let lo = self.token.span;
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
|
||||
let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName))?;
|
||||
let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?;
|
||||
let ty = if this.eat(&token::Colon) {
|
||||
this.parse_ty()?
|
||||
} else {
|
||||
@ -2781,7 +2781,7 @@ impl<'a> Parser<'a> {
|
||||
return None;
|
||||
}
|
||||
let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
|
||||
match self.parse_pat_no_top_alt(None) {
|
||||
match self.parse_pat_no_top_alt(None, None) {
|
||||
Ok(_pat) => {
|
||||
if self.token.kind == token::FatArrow {
|
||||
// Reached arm end.
|
||||
|
@ -131,7 +131,7 @@ impl<'a> Parser<'a> {
|
||||
},
|
||||
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
|
||||
token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
|
||||
NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
|
||||
NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
|
||||
NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
|
||||
None,
|
||||
RecoverComma::No,
|
||||
|
@ -2,10 +2,11 @@ use super::{ForceCollect, Parser, PathStyle, TrailingToken};
|
||||
use crate::errors::{
|
||||
self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
|
||||
DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
|
||||
ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow,
|
||||
InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect,
|
||||
RemoveLet, RepeatedMutInPattern, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
|
||||
TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
||||
ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
|
||||
InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
|
||||
PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
|
||||
TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
|
||||
UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
|
||||
UnexpectedVertVertInPattern,
|
||||
};
|
||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||
@ -80,7 +81,8 @@ enum EatOrResult {
|
||||
}
|
||||
|
||||
/// The syntax location of a given pattern. Used for diagnostics.
|
||||
pub(super) enum PatternLocation {
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum PatternLocation {
|
||||
LetBinding,
|
||||
FunctionParameter,
|
||||
}
|
||||
@ -91,8 +93,12 @@ impl<'a> Parser<'a> {
|
||||
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
|
||||
/// at the top level. Used when parsing the parameters of lambda expressions,
|
||||
/// functions, function pointers, and `pat` macro fragments.
|
||||
pub fn parse_pat_no_top_alt(&mut self, expected: Option<Expected>) -> PResult<'a, P<Pat>> {
|
||||
self.parse_pat_with_range_pat(true, expected)
|
||||
pub fn parse_pat_no_top_alt(
|
||||
&mut self,
|
||||
expected: Option<Expected>,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, P<Pat>> {
|
||||
self.parse_pat_with_range_pat(true, expected, syntax_loc)
|
||||
}
|
||||
|
||||
/// Parses a pattern.
|
||||
@ -110,7 +116,7 @@ impl<'a> Parser<'a> {
|
||||
ra: RecoverColon,
|
||||
rt: CommaRecoveryMode,
|
||||
) -> PResult<'a, P<Pat>> {
|
||||
self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt).map(|(pat, _)| pat)
|
||||
self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat)
|
||||
}
|
||||
|
||||
/// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
|
||||
@ -121,6 +127,7 @@ impl<'a> Parser<'a> {
|
||||
rc: RecoverComma,
|
||||
ra: RecoverColon,
|
||||
rt: CommaRecoveryMode,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, (P<Pat>, bool)> {
|
||||
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
|
||||
// suggestions (which bothers rustfix).
|
||||
@ -133,7 +140,7 @@ impl<'a> Parser<'a> {
|
||||
};
|
||||
|
||||
// Parse the first pattern (`p_0`).
|
||||
let mut first_pat = self.parse_pat_no_top_alt(expected)?;
|
||||
let mut first_pat = self.parse_pat_no_top_alt(expected, syntax_loc)?;
|
||||
if rc == RecoverComma::Yes {
|
||||
self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
|
||||
}
|
||||
@ -172,7 +179,7 @@ impl<'a> Parser<'a> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| {
|
||||
let pat = self.parse_pat_no_top_alt(expected, syntax_loc).map_err(|mut err| {
|
||||
err.span_label(lo, WHILE_PARSING_OR_MSG);
|
||||
err
|
||||
})?;
|
||||
@ -208,6 +215,7 @@ impl<'a> Parser<'a> {
|
||||
rc,
|
||||
RecoverColon::No,
|
||||
CommaRecoveryMode::LikelyTuple,
|
||||
Some(syntax_loc),
|
||||
)?;
|
||||
let colon = self.eat(&token::Colon);
|
||||
|
||||
@ -319,6 +327,7 @@ impl<'a> Parser<'a> {
|
||||
&mut self,
|
||||
allow_range_pat: bool,
|
||||
expected: Option<Expected>,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, P<Pat>> {
|
||||
maybe_recover_from_interpolated_ty_qpath!(self, true);
|
||||
maybe_whole!(self, NtPat, |x| x);
|
||||
@ -358,11 +367,11 @@ impl<'a> Parser<'a> {
|
||||
// Parse _
|
||||
PatKind::Wild
|
||||
} else if self.eat_keyword(kw::Mut) {
|
||||
self.parse_pat_ident_mut()?
|
||||
self.parse_pat_ident_mut(syntax_loc)?
|
||||
} else if self.eat_keyword(kw::Ref) {
|
||||
// Parse ref ident @ pat / ref mut ident @ pat
|
||||
let mutbl = self.parse_mutability();
|
||||
self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl))?
|
||||
self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl), syntax_loc)?
|
||||
} else if self.eat_keyword(kw::Box) {
|
||||
self.parse_pat_box()?
|
||||
} else if self.check_inline_const(0) {
|
||||
@ -384,7 +393,7 @@ impl<'a> Parser<'a> {
|
||||
// Parse `ident @ pat`
|
||||
// This can give false positives and parse nullary enums,
|
||||
// they are dealt with later in resolve.
|
||||
self.parse_pat_ident(BindingAnnotation::NONE)?
|
||||
self.parse_pat_ident(BindingAnnotation::NONE, syntax_loc)?
|
||||
} else if self.is_start_of_pat_with_path() {
|
||||
// Parse pattern starting with a path
|
||||
let (qself, path) = if self.eat_lt() {
|
||||
@ -485,7 +494,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
// At this point we attempt to parse `@ $pat_rhs` and emit an error.
|
||||
self.bump(); // `@`
|
||||
let mut rhs = self.parse_pat_no_top_alt(None)?;
|
||||
let mut rhs = self.parse_pat_no_top_alt(None, None)?;
|
||||
let whole_span = lhs.span.to(rhs.span);
|
||||
|
||||
if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
|
||||
@ -541,7 +550,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
let mutbl = self.parse_mutability();
|
||||
let subpat = self.parse_pat_with_range_pat(false, expected)?;
|
||||
let subpat = self.parse_pat_with_range_pat(false, expected, None)?;
|
||||
Ok(PatKind::Ref(subpat, mutbl))
|
||||
}
|
||||
|
||||
@ -566,12 +575,12 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse a mutable binding with the `mut` token already eaten.
|
||||
fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> {
|
||||
fn parse_pat_ident_mut(&mut self, syntax_loc: Option<PatternLocation>) -> PResult<'a, PatKind> {
|
||||
let mut_span = self.prev_token.span;
|
||||
|
||||
if self.eat_keyword(kw::Ref) {
|
||||
self.sess.emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) });
|
||||
return self.parse_pat_ident(BindingAnnotation::REF_MUT);
|
||||
return self.parse_pat_ident(BindingAnnotation::REF_MUT, syntax_loc);
|
||||
}
|
||||
|
||||
self.recover_additional_muts();
|
||||
@ -584,7 +593,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// Parse the pattern we hope to be an identifier.
|
||||
let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier))?;
|
||||
let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?;
|
||||
|
||||
// If we don't have `mut $ident (@ pat)?`, error.
|
||||
if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
|
||||
@ -810,10 +819,25 @@ impl<'a> Parser<'a> {
|
||||
/// Parses `ident` or `ident @ pat`.
|
||||
/// Used by the copy foo and ref foo patterns to give a good
|
||||
/// error message when parsing mistakes like `ref foo(a, b)`.
|
||||
fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
|
||||
fn parse_pat_ident(
|
||||
&mut self,
|
||||
binding_annotation: BindingAnnotation,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, PatKind> {
|
||||
let ident = self.parse_ident()?;
|
||||
|
||||
if !matches!(syntax_loc, Some(PatternLocation::FunctionParameter))
|
||||
&& self.check_noexpect(&token::Lt)
|
||||
&& self.look_ahead(1, |t| t.can_begin_type())
|
||||
{
|
||||
return Err(self.sess.create_err(GenericArgsInPatRequireTurbofishSyntax {
|
||||
span: self.token.span,
|
||||
suggest_turbofish: self.token.span.shrink_to_lo(),
|
||||
}));
|
||||
}
|
||||
|
||||
let sub = if self.eat(&token::At) {
|
||||
Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
|
||||
Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -902,14 +926,14 @@ impl<'a> Parser<'a> {
|
||||
// We cannot use `parse_pat_ident()` since it will complain `box`
|
||||
// is not an identifier.
|
||||
let sub = if self.eat(&token::At) {
|
||||
Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
|
||||
Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
|
||||
} else {
|
||||
let pat = self.parse_pat_with_range_pat(false, None)?;
|
||||
let pat = self.parse_pat_with_range_pat(false, None, None)?;
|
||||
self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
|
||||
Ok(PatKind::Box(pat))
|
||||
}
|
||||
|
@ -238,8 +238,9 @@ fn find_best_match_for_name_impl(
|
||||
}
|
||||
|
||||
fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option<Symbol> {
|
||||
let lookup_sorted_by_words = sort_by_words(lookup);
|
||||
iter_names.iter().fold(None, |result, candidate| {
|
||||
if sort_by_words(candidate.as_str()) == sort_by_words(lookup) {
|
||||
if sort_by_words(candidate.as_str()) == lookup_sorted_by_words {
|
||||
Some(*candidate)
|
||||
} else {
|
||||
result
|
||||
|
@ -1155,8 +1155,10 @@ symbols! {
|
||||
profiler_builtins,
|
||||
profiler_runtime,
|
||||
ptr,
|
||||
ptr_cast,
|
||||
ptr_cast_mut,
|
||||
ptr_const_is_null,
|
||||
ptr_from_mut,
|
||||
ptr_from_ref,
|
||||
ptr_guaranteed_cmp,
|
||||
ptr_is_null,
|
||||
|
@ -710,6 +710,7 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
#[unstable(feature = "ptr_from_ref", issue = "106116")]
|
||||
#[rustc_diagnostic_item = "ptr_from_mut"]
|
||||
pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
|
||||
r
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ impl<T: ?Sized> *mut T {
|
||||
/// Casts to a pointer of another type.
|
||||
#[stable(feature = "ptr_cast", since = "1.38.0")]
|
||||
#[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
|
||||
#[rustc_diagnostic_item = "ptr_cast"]
|
||||
#[inline(always)]
|
||||
pub const fn cast<U>(self) -> *mut U {
|
||||
self as _
|
||||
|
@ -307,6 +307,12 @@ impl Step for CodegenBackend {
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
// FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
|
||||
if builder.build.config.vendor && &self.backend == "gcc" {
|
||||
println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
let compiler = builder.compiler(builder.top_stage, builder.config.build);
|
||||
let target = self.target;
|
||||
let backend = self.backend;
|
||||
|
@ -43,7 +43,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
||||
("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
|
||||
("clippy::forget_copy", "forgetting_copy_types"),
|
||||
("clippy::forget_ref", "forgetting_references"),
|
||||
("clippy::fn_null_check", "incorrect_fn_null_checks"),
|
||||
("clippy::fn_null_check", "useless_ptr_null_checks"),
|
||||
("clippy::into_iter_on_array", "array_into_iter"),
|
||||
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
|
||||
("clippy::invalid_ref", "invalid_value"),
|
||||
|
@ -38,7 +38,7 @@
|
||||
#![allow(for_loops_over_fallibles)]
|
||||
#![allow(forgetting_copy_types)]
|
||||
#![allow(forgetting_references)]
|
||||
#![allow(incorrect_fn_null_checks)]
|
||||
#![allow(useless_ptr_null_checks)]
|
||||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
@ -92,7 +92,7 @@
|
||||
#![warn(for_loops_over_fallibles)]
|
||||
#![warn(forgetting_copy_types)]
|
||||
#![warn(forgetting_references)]
|
||||
#![warn(incorrect_fn_null_checks)]
|
||||
#![warn(useless_ptr_null_checks)]
|
||||
#![warn(array_into_iter)]
|
||||
#![warn(invalid_atomic_ordering)]
|
||||
#![warn(invalid_value)]
|
||||
|
@ -38,7 +38,7 @@
|
||||
#![allow(for_loops_over_fallibles)]
|
||||
#![allow(forgetting_copy_types)]
|
||||
#![allow(forgetting_references)]
|
||||
#![allow(incorrect_fn_null_checks)]
|
||||
#![allow(useless_ptr_null_checks)]
|
||||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
|
@ -246,11 +246,11 @@ error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
|
||||
LL | #![warn(clippy::forget_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
|
||||
|
||||
error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks`
|
||||
error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
|
||||
--> $DIR/rename.rs:95:9
|
||||
|
|
||||
LL | #![warn(clippy::fn_null_check)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||
--> $DIR/rename.rs:96:9
|
||||
|
@ -273,6 +273,8 @@ pub fn report_error<'tcx, 'mir>(
|
||||
} else {
|
||||
#[rustfmt::skip]
|
||||
let title = match e.kind() {
|
||||
UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(e)) if matches!(e.kind, ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer) =>
|
||||
bug!("This validation error should be impossible in Miri: {:?}", e.kind),
|
||||
UndefinedBehavior(_) =>
|
||||
"Undefined Behavior",
|
||||
ResourceExhaustion(_) =>
|
||||
@ -377,7 +379,7 @@ pub fn report_error<'tcx, 'mir>(
|
||||
if let Some((alloc_id, access)) = extra {
|
||||
eprintln!(
|
||||
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
|
||||
range = access.uninit,
|
||||
range = access.bad,
|
||||
);
|
||||
eprintln!("{:?}", ecx.dump_alloc(alloc_id));
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized bytes
|
||||
error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized memory, but expected a floating point number
|
||||
--> $DIR/uninit_float.rs:LL:CC
|
||||
|
|
||||
LL | let _val: [f32; 1] = unsafe { std::mem::uninitialized() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .value[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .value[0]: encountered uninitialized memory, but expected a floating point number
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized bytes
|
||||
error: Undefined Behavior: constructing invalid value at .value[0]: encountered uninitialized memory, but expected an integer
|
||||
--> $DIR/uninit_integer.rs:LL:CC
|
||||
|
|
||||
LL | let _val = unsafe { std::mem::MaybeUninit::<[usize; 1]>::uninit().assume_init() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .value[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .value[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -56,7 +56,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||
);
|
||||
parse_macro_arg!(
|
||||
Pat,
|
||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None),
|
||||
|parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None, None),
|
||||
|x: ptr::P<ast::Pat>| Some(x)
|
||||
);
|
||||
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
|
||||
|
@ -41,7 +41,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/forbidden_slices.rs:26:1
|
||||
|
|
||||
LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
@ -52,8 +52,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/forbidden_slices.rs:28:1
|
||||
|
|
||||
LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
@ -75,7 +76,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/forbidden_slices.rs:33:1
|
||||
|
|
||||
LL | pub static S7: &[u16] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
@ -143,7 +144,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/forbidden_slices.rs:53:1
|
||||
|
|
||||
LL | pub static R4: &[u8] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
@ -154,8 +155,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/forbidden_slices.rs:58:1
|
||||
|
|
||||
LL | pub static R5: &[u8] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:26:49
|
||||
|
|
||||
LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -11,7 +11,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:29:43
|
||||
|
|
||||
LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:32:45
|
||||
|
|
||||
LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -29,7 +29,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:35:45
|
||||
|
|
||||
LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -38,7 +38,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:38:45
|
||||
|
|
||||
LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -53,7 +53,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:45:43
|
||||
|
|
||||
LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -62,7 +62,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:48:45
|
||||
|
|
||||
LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -71,7 +71,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:51:45
|
||||
|
|
||||
LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -80,7 +80,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:54:45
|
||||
|
|
||||
LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -95,7 +95,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:61:45
|
||||
|
|
||||
LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -104,7 +104,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:64:45
|
||||
|
|
||||
LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -113,7 +113,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:67:47
|
||||
|
|
||||
LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -122,7 +122,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:70:47
|
||||
|
|
||||
LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -131,7 +131,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:73:39
|
||||
|
|
||||
LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -140,7 +140,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:76:41
|
||||
|
|
||||
LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -149,7 +149,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:79:41
|
||||
|
|
||||
LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -158,7 +158,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:82:41
|
||||
|
|
||||
LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -167,7 +167,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:85:43
|
||||
|
|
||||
LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -176,7 +176,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:88:39
|
||||
|
|
||||
LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -185,7 +185,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:91:41
|
||||
|
|
||||
LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -194,7 +194,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:94:41
|
||||
|
|
||||
LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -203,7 +203,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:97:41
|
||||
|
|
||||
LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -212,7 +212,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:100:43
|
||||
|
|
||||
LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -221,7 +221,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:103:41
|
||||
|
|
||||
LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -230,7 +230,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:106:41
|
||||
|
|
||||
LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -239,7 +239,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:109:43
|
||||
|
|
||||
LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -248,7 +248,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-pointer-values-in-various-types.rs:112:43
|
||||
|
|
||||
LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -266,7 +266,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:144:1
|
||||
|
|
||||
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
@ -277,7 +277,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:146:1
|
||||
|
|
||||
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
@ -288,8 +288,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:148:1
|
||||
|
|
||||
LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼....
|
||||
}
|
||||
@ -516,7 +517,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:215:1
|
||||
|
|
||||
LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
@ -527,8 +528,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:218:1
|
||||
|
|
||||
LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
|
||||
}
|
||||
@ -550,7 +552,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:225:1
|
||||
|
|
||||
LL | pub static S7: &[u16] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
@ -561,7 +563,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:232:1
|
||||
|
|
||||
LL | pub static R4: &[u8] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
@ -572,8 +574,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:237:1
|
||||
|
|
||||
LL | pub static R5: &[u8] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼....
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:144:1
|
||||
|
|
||||
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
@ -277,7 +277,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:146:1
|
||||
|
|
||||
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
@ -288,8 +288,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:148:1
|
||||
|
|
||||
LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
@ -516,7 +517,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:215:1
|
||||
|
|
||||
LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
@ -527,8 +528,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:218:1
|
||||
|
|
||||
LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
@ -550,7 +552,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:225:1
|
||||
|
|
||||
LL | pub static S7: &[u16] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
@ -561,7 +563,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:232:1
|
||||
|
|
||||
LL | pub static R4: &[u8] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
@ -572,8 +574,9 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/raw-bytes.rs:237:1
|
||||
|
|
||||
LL | pub static R5: &[u8] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ref_to_int_match.rs:24:27
|
||||
|
|
||||
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
|
||||
| ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ref_to_int_match.rs:24:27
|
||||
|
|
||||
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
|
||||
| ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:30:1
|
||||
|
|
||||
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -22,7 +22,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:33:1
|
||||
|
|
||||
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -42,7 +42,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:47:1
|
||||
|
|
||||
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -51,7 +51,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:50:1
|
||||
|
|
||||
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -66,7 +66,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:64:1
|
||||
|
|
||||
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:30:1
|
||||
|
|
||||
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -22,7 +22,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:33:1
|
||||
|
|
||||
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -42,7 +42,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:47:1
|
||||
|
|
||||
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -51,7 +51,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:50:1
|
||||
|
|
||||
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -66,7 +66,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-enum.rs:64:1
|
||||
|
|
||||
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -1,20 +1,35 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-int-array.rs:15:9
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:19:1
|
||||
|
|
||||
LL | MaybeUninit { uninit: () }.init,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | const UNINIT_INT_0: [u32; 3] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 12, align: 4) {
|
||||
__ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........
|
||||
}
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-int-array.rs:30:13
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:24:1
|
||||
|
|
||||
LL | MaybeUninit { uninit: () }.init,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | const UNINIT_INT_1: [u32; 3] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 12, align: 4) {
|
||||
00 00 00 00 01 __ 01 01 02 02 __ 02 │ .....░....░.
|
||||
}
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-int-array.rs:56:13
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:42:1
|
||||
|
|
||||
LL | MaybeUninit { uninit: () }.init,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | const UNINIT_INT_2: [u32; 3] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 12, align: 4) {
|
||||
00 00 00 00 01 01 01 01 02 02 02 __ │ ...........░
|
||||
}
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,20 +1,35 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-int-array.rs:15:9
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:19:1
|
||||
|
|
||||
LL | MaybeUninit { uninit: () }.init,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | const UNINIT_INT_0: [u32; 3] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 12, align: 4) {
|
||||
__ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........
|
||||
}
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-int-array.rs:30:13
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:24:1
|
||||
|
|
||||
LL | MaybeUninit { uninit: () }.init,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | const UNINIT_INT_1: [u32; 3] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 12, align: 4) {
|
||||
00 00 00 00 01 __ 01 01 02 02 __ 02 │ .....░....░.
|
||||
}
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-int-array.rs:56:13
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:42:1
|
||||
|
|
||||
LL | MaybeUninit { uninit: () }.init,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
LL | const UNINIT_INT_2: [u32; 3] = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized memory, but expected an integer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: 12, align: 4) {
|
||||
00 00 00 00 01 01 01 01 02 02 02 __ │ ...........░
|
||||
}
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -10,54 +10,52 @@ union MaybeUninit<T: Copy> {
|
||||
init: T,
|
||||
}
|
||||
|
||||
impl<T: Copy> MaybeUninit<T> {
|
||||
const fn new(t: T) -> Self {
|
||||
MaybeUninit { init: t }
|
||||
}
|
||||
}
|
||||
|
||||
const UNINIT_INT_0: [u32; 3] = unsafe {
|
||||
[
|
||||
MaybeUninit { uninit: () }.init,
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
//~| uninitialized
|
||||
1,
|
||||
2,
|
||||
]
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~| invalid value at [0]
|
||||
mem::transmute([MaybeUninit { uninit: () }, MaybeUninit::new(1), MaybeUninit::new(2)])
|
||||
};
|
||||
const UNINIT_INT_1: [u32; 3] = unsafe {
|
||||
mem::transmute(
|
||||
[
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
1u8,
|
||||
MaybeUninit { uninit: () }.init,
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
//~| uninitialized
|
||||
1u8,
|
||||
1u8,
|
||||
2u8,
|
||||
2u8,
|
||||
MaybeUninit { uninit: () }.init,
|
||||
2u8,
|
||||
]
|
||||
)
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~| invalid value at [1]
|
||||
mem::transmute([
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit { uninit: () },
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit::new(2u8),
|
||||
MaybeUninit::new(2u8),
|
||||
MaybeUninit { uninit: () },
|
||||
MaybeUninit::new(2u8),
|
||||
])
|
||||
};
|
||||
const UNINIT_INT_2: [u32; 3] = unsafe {
|
||||
mem::transmute(
|
||||
[
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
1u8,
|
||||
1u8,
|
||||
1u8,
|
||||
1u8,
|
||||
2u8,
|
||||
2u8,
|
||||
2u8,
|
||||
MaybeUninit { uninit: () }.init,
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
//~| uninitialized
|
||||
]
|
||||
)
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~| invalid value at [2]
|
||||
mem::transmute([
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(0u8),
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit::new(1u8),
|
||||
MaybeUninit::new(2u8),
|
||||
MaybeUninit::new(2u8),
|
||||
MaybeUninit::new(2u8),
|
||||
MaybeUninit { uninit: () },
|
||||
])
|
||||
};
|
||||
|
||||
fn main() {}
|
||||
|
@ -46,7 +46,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-ref-ptr.rs:33:1
|
||||
|
|
||||
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -55,7 +55,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-ref-ptr.rs:36:39
|
||||
|
|
||||
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -70,7 +70,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-ref-ptr.rs:39:86
|
||||
|
|
||||
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -24,7 +24,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-wide-ptr.rs:43:1
|
||||
|
|
||||
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -33,7 +33,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-wide-ptr.rs:46:1
|
||||
|
|
||||
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -53,7 +53,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:52:1
|
||||
|
|
||||
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
@ -64,7 +64,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:55:1
|
||||
|
|
||||
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
@ -103,7 +103,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-wide-ptr.rs:75:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
@ -123,7 +123,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-wide-ptr.rs:81:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -1,7 +1,7 @@
|
||||
// revisions: no_flag with_flag
|
||||
// [no_flag] check-pass
|
||||
// [with_flag] compile-flags: -Zextra-const-ub-checks
|
||||
#![feature(never_type)]
|
||||
#![feature(never_type, pointer_byte_offsets)]
|
||||
|
||||
use std::mem::transmute;
|
||||
use std::ptr::addr_of;
|
||||
@ -12,6 +12,9 @@ enum E { A, B }
|
||||
#[derive(Clone, Copy)]
|
||||
enum Never {}
|
||||
|
||||
#[repr(usize)]
|
||||
enum PtrSizedEnum { V }
|
||||
|
||||
// An enum with uninhabited variants but also at least 2 inhabited variants -- so the uninhabited
|
||||
// variants *do* have a discriminant.
|
||||
#[derive(Clone, Copy)]
|
||||
@ -31,12 +34,20 @@ const INVALID_BOOL: () = unsafe {
|
||||
const INVALID_PTR_IN_INT: () = unsafe {
|
||||
let _x: usize = transmute(&3u8);
|
||||
//[with_flag]~^ ERROR: evaluation of constant value failed
|
||||
//[with_flag]~| invalid value
|
||||
};
|
||||
|
||||
const INVALID_PTR_IN_ENUM: () = unsafe {
|
||||
let _x: PtrSizedEnum = transmute(&3u8);
|
||||
//[with_flag]~^ ERROR: evaluation of constant value failed
|
||||
//[with_flag]~| invalid value
|
||||
};
|
||||
|
||||
const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe {
|
||||
let x: &[u8] = &[0; 32];
|
||||
let _x: (usize, usize) = transmute(x);
|
||||
//[with_flag]~^ ERROR: evaluation of constant value failed
|
||||
//[with_flag]~| invalid value
|
||||
};
|
||||
|
||||
const UNALIGNED_PTR: () = unsafe {
|
||||
@ -50,6 +61,27 @@ const UNINHABITED_VARIANT: () = unsafe {
|
||||
// Not using transmute, we want to hit the ImmTy code path.
|
||||
let v = *addr_of!(data).cast::<UninhDiscriminant>();
|
||||
//[with_flag]~^ ERROR: evaluation of constant value failed
|
||||
//[with_flag]~| invalid value
|
||||
};
|
||||
|
||||
const PARTIAL_POINTER: () = unsafe {
|
||||
#[repr(C, packed)]
|
||||
struct Packed {
|
||||
pad1: u8,
|
||||
ptr: *const u8,
|
||||
pad2: [u8; 7],
|
||||
}
|
||||
// `Align` ensures that the entire thing has pointer alignment again.
|
||||
#[repr(C)]
|
||||
struct Align {
|
||||
p: Packed,
|
||||
align: usize,
|
||||
}
|
||||
let mem = Packed { pad1: 0, ptr: &0u8 as *const u8, pad2: [0; 7] };
|
||||
let mem = Align { p: mem, align: 0 };
|
||||
let _val = *(&mem as *const Align as *const [*const u8; 2]);
|
||||
//[with_flag]~^ ERROR: evaluation of constant value failed
|
||||
//[with_flag]~| invalid value
|
||||
};
|
||||
|
||||
// Regression tests for an ICE (related to <https://github.com/rust-lang/rust/issues/113988>).
|
||||
|
@ -1,39 +1,57 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:26:20
|
||||
--> $DIR/detect-extra-ub.rs:29:20
|
||||
|
|
||||
LL | let _x: bool = transmute(3u8);
|
||||
| ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:32:21
|
||||
--> $DIR/detect-extra-ub.rs:35:21
|
||||
|
|
||||
LL | let _x: usize = transmute(&3u8);
|
||||
| ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a pointer, but expected an integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:38:30
|
||||
--> $DIR/detect-extra-ub.rs:41:28
|
||||
|
|
||||
LL | let _x: PtrSizedEnum = transmute(&3u8);
|
||||
| ^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:48:30
|
||||
|
|
||||
LL | let _x: (usize, usize) = transmute(x);
|
||||
| ^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
| ^^^^^^^^^^^^ constructing invalid value at .0: encountered a pointer, but expected an integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:43:20
|
||||
--> $DIR/detect-extra-ub.rs:54:20
|
||||
|
|
||||
LL | let _x: &u32 = transmute(&[0u8; 4]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:51:13
|
||||
--> $DIR/detect-extra-ub.rs:62:13
|
||||
|
|
||||
LL | let v = *addr_of!(data).cast::<UninhDiscriminant>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/detect-extra-ub.rs:82:16
|
||||
|
|
||||
LL | let _val = *(&mem as *const Align as *const [*const u8; 2]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a partial pointer or a mix of pointers
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -1,9 +0,0 @@
|
||||
// Strip out raw byte dumps to make comparison platform-independent:
|
||||
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
|
||||
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||
|
||||
use std::mem;
|
||||
struct MyStr(str);
|
||||
const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
|
||||
//~^ ERROR: it is undefined behavior to use this value
|
||||
fn main() {}
|
@ -1,15 +0,0 @@
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/issue-83182.rs:7:1
|
||||
|
|
||||
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
||||
|
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
@ -1,7 +1,7 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
|
||||
= note: unable to turn pointer into raw bytes
|
||||
= note: unable to turn pointer into integer
|
||||
|
|
||||
note: inside `std::ptr::read::<u8>`
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
|
@ -1,5 +1,5 @@
|
||||
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_intrinsics, pointer_byte_offsets)]
|
||||
|
||||
// During CTFE, we prevent pointer-to-int casts.
|
||||
// Pointer comparisons are prevented in the trait system.
|
||||
@ -15,7 +15,7 @@ static PTR_INT_TRANSMUTE: () = unsafe {
|
||||
let x: usize = std::mem::transmute(&0);
|
||||
let _v = x + 0;
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
//~| unable to turn pointer into raw bytes
|
||||
//~| unable to turn pointer into integer
|
||||
};
|
||||
|
||||
// I'd love to test pointer comparison, but that is not possible since
|
||||
|
@ -8,7 +8,7 @@ error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ptr_arith.rs:16:14
|
||||
|
|
||||
LL | let _v = x + 0;
|
||||
| ^ unable to turn pointer into raw bytes
|
||||
| ^ unable to turn pointer into integer
|
||||
|
|
||||
= help: this code performed an operation that depends on the underlying bytes representing a pointer
|
||||
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
|
||||
|
@ -2,6 +2,7 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_ptr_is_null)]
|
||||
#![allow(useless_ptr_null_checks)]
|
||||
|
||||
const FOO: &usize = &42;
|
||||
|
||||
|
11
tests/ui/did_you_mean/issue-114112.rs
Normal file
11
tests/ui/did_you_mean/issue-114112.rs
Normal file
@ -0,0 +1,11 @@
|
||||
enum E<T> {
|
||||
A(T)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match E::<i32>::A(1) {
|
||||
E<i32>::A(v) => { //~ ERROR generic args in patterns require the turbofish syntax
|
||||
println!("{v:?}");
|
||||
},
|
||||
}
|
||||
}
|
13
tests/ui/did_you_mean/issue-114112.stderr
Normal file
13
tests/ui/did_you_mean/issue-114112.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
error: generic args in patterns require the turbofish syntax
|
||||
--> $DIR/issue-114112.rs:7:10
|
||||
|
|
||||
LL | E<i32>::A(v) => {
|
||||
| ^
|
||||
|
|
||||
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||
|
|
||||
LL | E::<i32>::A(v) => {
|
||||
| ++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
17
tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
Normal file
17
tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_intrinsic_raw_eq)]
|
||||
|
||||
const RAW_EQ_PADDING: bool = unsafe {
|
||||
std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
//~| requires initialized memory
|
||||
};
|
||||
|
||||
const RAW_EQ_PTR: bool = unsafe {
|
||||
std::intrinsics::raw_eq(&(&0), &(&1))
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
//~| `raw_eq` on bytes with provenance
|
||||
};
|
||||
|
||||
pub fn main() {
|
||||
}
|
@ -1,9 +1,15 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/intrinsic-raw_eq-const-padding.rs:5:5
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:5:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/intrinsic-raw_eq-const-bad.rs:11:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(&0), &(&1))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
@ -1,10 +0,0 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(const_intrinsic_raw_eq)]
|
||||
|
||||
const BAD_RAW_EQ_CALL: bool = unsafe {
|
||||
std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
};
|
||||
|
||||
pub fn main() {
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// check-pass
|
||||
|
||||
fn main() {
|
||||
let fn_ptr = main;
|
||||
|
||||
if (fn_ptr as *mut ()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *const u8).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *const ()) == std::ptr::null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *mut ()) == std::ptr::null_mut() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *const ()) == (0 as *const ()) {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if <*const _>::is_null(fn_ptr as *const ()) {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as fn() as *const ()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
|
||||
const ZPTR: *const () = 0 as *const _;
|
||||
const NOT_ZPTR: *const () = 1 as *const _;
|
||||
|
||||
// unlike the uplifted clippy::fn_null_check lint we do
|
||||
// not lint on them
|
||||
if (fn_ptr as *const ()) == ZPTR {}
|
||||
if (fn_ptr as *const ()) == NOT_ZPTR {}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:6:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut ()).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
= note: `#[warn(incorrect_fn_null_checks)]` on by default
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:8:8
|
||||
|
|
||||
LL | if (fn_ptr as *const u8).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:10:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == std::ptr::null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:12:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut ()) == std::ptr::null_mut() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:14:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == (0 as *const ()) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:16:8
|
||||
|
|
||||
LL | if <*const _>::is_null(fn_ptr as *const ()) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:18:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/fn_null_check.rs:20:8
|
||||
|
|
||||
LL | if (fn_ptr as fn() as *const ()).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: 8 warnings emitted
|
||||
|
76
tests/ui/lint/ptr_null_checks.rs
Normal file
76
tests/ui/lint/ptr_null_checks.rs
Normal file
@ -0,0 +1,76 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(ptr_from_ref)]
|
||||
|
||||
use std::ptr;
|
||||
|
||||
extern "C" fn c_fn() {}
|
||||
fn static_i32() -> &'static i32 { &1 }
|
||||
|
||||
fn main() {
|
||||
let fn_ptr = main;
|
||||
|
||||
// ------------- Function pointers ---------------
|
||||
if (fn_ptr as *mut ()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *const u8).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *const ()) == std::ptr::null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *mut ()) == std::ptr::null_mut() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *const ()) == (0 as *const ()) {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if <*const _>::is_null(fn_ptr as *const ()) {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as *mut fn() as *const fn()).cast_mut().is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if ((fn_ptr as *mut fn()).cast() as *const fn()).cast_mut().is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (fn_ptr as fn() as *const ()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
if (c_fn as *const fn()).is_null() {}
|
||||
//~^ WARN function pointers are not nullable
|
||||
|
||||
// ---------------- References ------------------
|
||||
if (&mut 8 as *mut i32).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if ptr::from_mut(&mut 8).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (&8 as *const i32).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if ptr::from_ref(&8).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if ptr::from_ref(&8).cast_mut().is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (ptr::from_ref(&8).cast_mut() as *mut i32).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (&8 as *const i32) == std::ptr::null() {}
|
||||
//~^ WARN references are not nullable
|
||||
let ref_num = &8;
|
||||
if (ref_num as *const i32) == std::ptr::null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (b"\0" as *const u8).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if ("aa" as *const str).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (&[1, 2] as *const i32).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (&mut [1, 2] as *mut i32) == std::ptr::null_mut() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (static_i32() as *const i32).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
if (&*{ static_i32() } as *const i32).is_null() {}
|
||||
//~^ WARN references are not nullable
|
||||
|
||||
// ----------------------------------------------
|
||||
const ZPTR: *const () = 0 as *const _;
|
||||
const NOT_ZPTR: *const () = 1 as *const _;
|
||||
|
||||
// unlike the uplifted clippy::fn_null_check lint we do
|
||||
// not lint on them
|
||||
if (fn_ptr as *const ()) == ZPTR {}
|
||||
if (fn_ptr as *const ()) == NOT_ZPTR {}
|
||||
}
|
225
tests/ui/lint/ptr_null_checks.stderr
Normal file
225
tests/ui/lint/ptr_null_checks.stderr
Normal file
@ -0,0 +1,225 @@
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:14:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut ()).is_null() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
= note: `#[warn(useless_ptr_null_checks)]` on by default
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:16:8
|
||||
|
|
||||
LL | if (fn_ptr as *const u8).is_null() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:18:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == std::ptr::null() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:20:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut ()) == std::ptr::null_mut() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:22:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == (0 as *const ()) {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:24:8
|
||||
|
|
||||
LL | if <*const _>::is_null(fn_ptr as *const ()) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:26:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:28:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut fn() as *const fn()).cast_mut().is_null() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:30:8
|
||||
|
|
||||
LL | if ((fn_ptr as *mut fn()).cast() as *const fn()).cast_mut().is_null() {}
|
||||
| ^^------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn() {main}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:32:8
|
||||
|
|
||||
LL | if (fn_ptr as fn() as *const ()).is_null() {}
|
||||
| ^--------------^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `fn()`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: function pointers are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:34:8
|
||||
|
|
||||
LL | if (c_fn as *const fn()).is_null() {}
|
||||
| ^----^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `extern "C" fn() {c_fn}`
|
||||
|
|
||||
= help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:38:8
|
||||
|
|
||||
LL | if (&mut 8 as *mut i32).is_null() {}
|
||||
| ^------^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&mut i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:40:8
|
||||
|
|
||||
LL | if ptr::from_mut(&mut 8).is_null() {}
|
||||
| ^^^^^^^^^^^^^^------^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&mut i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:42:8
|
||||
|
|
||||
LL | if (&8 as *const i32).is_null() {}
|
||||
| ^--^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:44:8
|
||||
|
|
||||
LL | if ptr::from_ref(&8).is_null() {}
|
||||
| ^^^^^^^^^^^^^^--^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:46:8
|
||||
|
|
||||
LL | if ptr::from_ref(&8).cast_mut().is_null() {}
|
||||
| ^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:48:8
|
||||
|
|
||||
LL | if (ptr::from_ref(&8).cast_mut() as *mut i32).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:50:8
|
||||
|
|
||||
LL | if (&8 as *const i32) == std::ptr::null() {}
|
||||
| ^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:53:8
|
||||
|
|
||||
LL | if (ref_num as *const i32) == std::ptr::null() {}
|
||||
| ^-------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:55:8
|
||||
|
|
||||
LL | if (b"\0" as *const u8).is_null() {}
|
||||
| ^-----^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&[u8; 1]`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:57:8
|
||||
|
|
||||
LL | if ("aa" as *const str).is_null() {}
|
||||
| ^----^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&str`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:59:8
|
||||
|
|
||||
LL | if (&[1, 2] as *const i32).is_null() {}
|
||||
| ^-------^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&[i32; 2]`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:61:8
|
||||
|
|
||||
LL | if (&mut [1, 2] as *mut i32) == std::ptr::null_mut() {}
|
||||
| ^-----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&mut [i32; 2]`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:63:8
|
||||
|
|
||||
LL | if (static_i32() as *const i32).is_null() {}
|
||||
| ^------------^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: references are not nullable, so checking them for null will always return false
|
||||
--> $DIR/ptr_null_checks.rs:65:8
|
||||
|
|
||||
LL | if (&*{ static_i32() } as *const i32).is_null() {}
|
||||
| ^------------------^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expression has type `&i32`
|
||||
|
||||
warning: 25 warnings emitted
|
||||
|
4
tests/ui/parser/issues/issue-114219.rs
Normal file
4
tests/ui/parser/issues/issue-114219.rs
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
async move {};
|
||||
//~^ ERROR `async move` blocks are only allowed in Rust 2018 or later
|
||||
}
|
8
tests/ui/parser/issues/issue-114219.stderr
Normal file
8
tests/ui/parser/issues/issue-114219.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: `async move` blocks are only allowed in Rust 2018 or later
|
||||
--> $DIR/issue-114219.rs:2:5
|
||||
|
|
||||
LL | async move {};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,5 +1,5 @@
|
||||
fn main() {
|
||||
let caller<F> = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
|
||||
let caller<F> = |f: F| //~ ERROR generic args in patterns require the turbofish syntax
|
||||
where F: Fn() -> i32
|
||||
{
|
||||
let x = f();
|
||||
|
@ -1,8 +1,13 @@
|
||||
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
|
||||
error: generic args in patterns require the turbofish syntax
|
||||
--> $DIR/issue-22647.rs:2:15
|
||||
|
|
||||
LL | let caller<F> = |f: F|
|
||||
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
|
||||
| ^
|
||||
|
|
||||
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||
|
|
||||
LL | let caller::<F> = |f: F|
|
||||
| ++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,7 +3,7 @@ struct Foo<B> {
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
let Foo<Vec<u8>> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
|
||||
let Foo<Vec<u8>> //~ ERROR generic args in patterns require the turbofish syntax
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,13 @@
|
||||
error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<`
|
||||
error: generic args in patterns require the turbofish syntax
|
||||
--> $DIR/issue-22712.rs:6:12
|
||||
|
|
||||
LL | let Foo<Vec<u8>>
|
||||
| ^ expected one of `:`, `;`, `=`, `@`, or `|`
|
||||
| ^
|
||||
|
|
||||
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||
|
|
||||
LL | let Foo::<Vec<u8>>
|
||||
| ++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,8 +3,7 @@ struct Foo<T>(T, T);
|
||||
impl<T> Foo<T> {
|
||||
fn foo(&self) {
|
||||
match *self {
|
||||
Foo<T>(x, y) => {
|
||||
//~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
||||
Foo<T>(x, y) => { //~ ERROR generic args in patterns require the turbofish syntax
|
||||
println!("Goodbye, World!")
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
||||
error: generic args in patterns require the turbofish syntax
|
||||
--> $DIR/pat-lt-bracket-3.rs:6:16
|
||||
|
|
||||
LL | Foo<T>(x, y) => {
|
||||
| ^ expected one of `=>`, `@`, `if`, or `|`
|
||||
| ^
|
||||
|
|
||||
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||
|
|
||||
LL | Foo::<T>(x, y) => {
|
||||
| ++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,7 +5,7 @@ enum BtNode {
|
||||
|
||||
fn main() {
|
||||
let y = match 10 {
|
||||
Foo<T>::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
||||
Foo<T>::A(value) => value, //~ ERROR generic args in patterns require the turbofish syntax
|
||||
Foo<T>::B => 7,
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
error: expected one of `=>`, `@`, `if`, or `|`, found `<`
|
||||
error: generic args in patterns require the turbofish syntax
|
||||
--> $DIR/pat-lt-bracket-4.rs:8:12
|
||||
|
|
||||
LL | Foo<T>::A(value) => value,
|
||||
| ^ expected one of `=>`, `@`, `if`, or `|`
|
||||
| ^
|
||||
|
|
||||
help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
|
||||
|
|
||||
LL | Foo::<T>::A(value) => value,
|
||||
| ++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
// https://github.com/rust-lang/rust/issues/114392
|
||||
|
||||
fn foo() -> Option<()> {
|
||||
let x = Some(());
|
||||
(x?)
|
||||
//~^ ERROR `?` operator has incompatible types
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,22 @@
|
||||
error[E0308]: `?` operator has incompatible types
|
||||
--> $DIR/remove-question-symbol-with-paren.rs:5:6
|
||||
|
|
||||
LL | (x?)
|
||||
| ^^ expected `Option<()>`, found `()`
|
||||
|
|
||||
= note: `?` operator cannot convert from `()` to `Option<()>`
|
||||
= note: expected enum `Option<()>`
|
||||
found unit type `()`
|
||||
help: try removing this `?`
|
||||
|
|
||||
LL - (x?)
|
||||
LL + (x)
|
||||
|
|
||||
help: try wrapping the expression in `Some`
|
||||
|
|
||||
LL | (Some(x?))
|
||||
| +++++ +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -490,7 +490,7 @@ cc = ["@nnethercote"]
|
||||
[assign]
|
||||
warn_non_default_branch = true
|
||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||
users_on_vacation = ["jyn514"]
|
||||
users_on_vacation = ["jyn514", "WaffleLapkin"]
|
||||
|
||||
[assign.adhoc_groups]
|
||||
compiler-team = [
|
||||
|
Loading…
Reference in New Issue
Block a user