Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2025-04-25 05:01:33 +00:00
commit 65e76849ac
183 changed files with 2692 additions and 874 deletions

View file

@ -35,6 +35,7 @@ use minicore::*;
pub fn return_f32(x: f32) -> f32 {
// CHECK: movss {{.*}}(%ebp), %xmm0
// CHECK-NEXT: popl %ebp
// linux-NEXT: .cfi_def_cfa
// CHECK-NEXT: retl
x
}
@ -44,6 +45,7 @@ pub fn return_f32(x: f32) -> f32 {
pub fn return_f64(x: f64) -> f64 {
// CHECK: movsd {{.*}}(%ebp), %xmm0
// CHECK-NEXT: popl %ebp
// linux-NEXT: .cfi_def_cfa
// CHECK-NEXT: retl
x
}
@ -313,9 +315,13 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
#[no_mangle]
pub fn return_f16(x: f16) -> f16 {
// CHECK: pushl %ebp
// linux-NEXT: .cfi_def_cfa_offset
// linux-NEXT: .cfi_offset
// CHECK-NEXT: movl %esp, %ebp
// linux-NEXT: .cfi_def_cfa_register
// CHECK-NEXT: pinsrw $0, 8(%ebp), %xmm0
// CHECK-NEXT: popl %ebp
// linux-NEXT: .cfi_def_cfa
// CHECK-NEXT: retl
x
}
@ -324,10 +330,14 @@ pub fn return_f16(x: f16) -> f16 {
#[no_mangle]
pub fn return_f128(x: f128) -> f128 {
// CHECK: pushl %ebp
// linux-NEXT: .cfi_def_cfa_offset
// linux-NEXT: .cfi_offset
// CHECK-NEXT: movl %esp, %ebp
// linux-NEXT: .cfi_def_cfa_register
// linux-NEXT: movaps 8(%ebp), %xmm0
// win-NEXT: movups 8(%ebp), %xmm0
// CHECK-NEXT: popl %ebp
// linux-NEXT: .cfi_def_cfa
// CHECK-NEXT: retl
x
}

View file

@ -1,5 +1,7 @@
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
//
// 32bit MSVC does not align things properly so we suppress high alignment annotations (#112480)
//@ ignore-i686-pc-windows-msvc
//@ ignore-i686-pc-windows-gnu
#![crate_type = "lib"]

View file

@ -0,0 +1,45 @@
//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat
//@ no-prefer-dynamic
//@ needs-enzyme
//
// Each autodiff invocation creates a new placeholder function, which we will replace on llvm-ir
// level. If a user tries to differentiate two identical functions within the same compilation unit,
// then LLVM might merge them in release mode before AD. In that case we can't rewrite one of the
// merged placeholder function anymore, and compilation would fail. We prevent this by disabling
// LLVM's merge_function pass before AD. Here we implicetely test that our solution keeps working.
// We also explicetly test that we keep running merge_function after AD, by checking for two
// identical function calls in the LLVM-IR, while having two different calls in the Rust code.
#![feature(autodiff)]
use std::autodiff::autodiff;
#[autodiff(d_square, Reverse, Duplicated, Active)]
fn square(x: &f64) -> f64 {
x * x
}
#[autodiff(d_square2, Reverse, Duplicated, Active)]
fn square2(x: &f64) -> f64 {
x * x
}
// CHECK:; identical_fnc::main
// CHECK-NEXT:; Function Attrs:
// CHECK-NEXT:define internal void @_ZN13identical_fnc4main17hf4dbc69c8d2f9130E()
// CHECK-NEXT:start:
// CHECK-NOT:br
// CHECK-NOT:ret
// CHECK:; call identical_fnc::d_square
// CHECK-NEXT: call fastcc void @_ZN13identical_fnc8d_square17h4c364207a2f8e06dE(double %x.val, ptr noalias noundef nonnull align 8 dereferenceable(8) %dx1)
// CHECK-NEXT:; call identical_fnc::d_square
// CHECK-NEXT: call fastcc void @_ZN13identical_fnc8d_square17h4c364207a2f8e06dE(double %x.val, ptr noalias noundef nonnull align 8 dereferenceable(8) %dx2)
fn main() {
let x = std::hint::black_box(3.0);
let mut dx1 = std::hint::black_box(1.0);
let mut dx2 = std::hint::black_box(1.0);
let _ = d_square(&x, &mut dx1, 1.0);
let _ = d_square2(&x, &mut dx2, 1.0);
assert_eq!(dx1, 6.0);
assert_eq!(dx2, 6.0);
}

View file

@ -0,0 +1,23 @@
//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat -Zautodiff=NoPostopt
//@ no-prefer-dynamic
//@ needs-enzyme
#![feature(autodiff)]
use std::autodiff::autodiff;
#[autodiff(d_square, Reverse, Duplicated, Active)]
fn square(x: &f64) -> f64 {
x * x
}
// CHECK: ; inline::d_square
// CHECK-NEXT: ; Function Attrs: alwaysinline
// CHECK-NOT: noinline
// CHECK-NEXT: define internal fastcc void @_ZN6inline8d_square17h021c74e92c259cdeE
fn main() {
let x = std::hint::black_box(3.0);
let mut dx1 = std::hint::black_box(1.0);
let _ = d_square(&x, &mut dx1, 1.0);
assert_eq!(dx1, 6.0);
}

View file

@ -1,4 +1,7 @@
//@ compile-flags: -C no-prepopulate-passes
// 32bit MSVC does not align things properly so we suppress high alignment annotations (#112480)
//@ ignore-i686-pc-windows-msvc
//@ ignore-i686-pc-windows-gnu
#![crate_type = "rlib"]

View file

@ -145,7 +145,7 @@ fn get_item<'a>(
fn main() {
let path = "alloc_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -219,7 +219,7 @@ fn get_item<'a>(
fn main() {
let path = "alloc_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--edition=2021".to_string(),
"--crate-name".to_string(),

View file

@ -85,7 +85,7 @@ fn check_items<T: CrateDef>(items: &[T], expected: &[&str]) {
fn main() {
let path = "assoc_items.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -57,7 +57,7 @@ fn get_item<'a>(
fn main() {
let path = "attribute_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -81,7 +81,7 @@ impl<'a> MirVisitor for Visitor<'a> {
fn main() {
let path = "binop_input.rs";
generate_input(&path).unwrap();
let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
let args = &["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
run!(args, test_binops).unwrap();
}

View file

@ -84,7 +84,7 @@ fn contains<T: CrateDef + std::fmt::Debug>(items: &[T], expected: &[&str]) {
fn main() {
let path = "crate_definitions.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -76,7 +76,7 @@ fn check_fn_def(ty: Ty) {
fn main() {
let path = "defs_ty_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),

View file

@ -112,7 +112,7 @@ fn get_instances(body: mir::Body) -> Vec<Instance> {
fn main() {
let path = "defs_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),

View file

@ -58,7 +58,7 @@ fn test_foreign() -> ControlFlow<()> {
fn main() {
let path = "foreign_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),

View file

@ -87,7 +87,7 @@ fn test_body(body: mir::Body) {
fn main() {
let path = "instance_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),

View file

@ -115,7 +115,7 @@ impl<'a> MirVisitor for CallsVisitor<'a> {
fn main() {
let path = "binop_input.rs";
generate_input(&path).unwrap();
let args = vec!["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
let args = &["rustc".to_string(), "--crate-type=lib".to_string(), path.to_string()];
run!(args, test_intrinsics).unwrap();
}

View file

@ -47,7 +47,7 @@ fn test_item_kind() -> ControlFlow<()> {
fn main() {
let path = "item_kind_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),

View file

@ -61,7 +61,7 @@ fn check_ty(ty: Ty) {
fn main() {
let path = "normalization_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-type=lib".to_string(),

View file

@ -72,7 +72,7 @@ fn assert_impl(impl_names: &HashSet<String>, target: &str) {
fn main() {
let path = "trait_queries.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -120,7 +120,7 @@ fn get_item<'a>(
fn main() {
let path = "transform_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -78,7 +78,7 @@ impl<'a> MirVisitor for PlaceVisitor<'a> {
fn main() {
let path = "ty_fold_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),

View file

@ -25,40 +25,42 @@ use std::io::Write;
fn main() {
let path = "input_compilation_result_test.rs";
generate_input(&path).unwrap();
let args = vec!["rustc".to_string(), path.to_string()];
test_continue(args.clone());
test_break(args.clone());
test_failed(args.clone());
test_skipped(args.clone());
let args = &["rustc".to_string(), path.to_string()];
test_continue(args);
test_break(args);
test_failed(args);
test_skipped(args);
test_captured(args)
}
fn test_continue(args: Vec<String>) {
fn test_continue(args: &[String]) {
let result = run!(args, || ControlFlow::Continue::<(), bool>(true));
assert_eq!(result, Ok(true));
}
fn test_break(args: Vec<String>) {
fn test_break(args: &[String]) {
let result = run!(args, || ControlFlow::Break::<bool, i32>(false));
assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false)));
}
#[allow(unreachable_code)]
fn test_skipped(mut args: Vec<String>) {
fn test_skipped(args: &[String]) {
let mut args = args.to_vec();
args.push("--version".to_string());
let result = run!(args, || unreachable!() as ControlFlow<()>);
let result = run!(&args, || unreachable!() as ControlFlow<()>);
assert_eq!(result, Err(stable_mir::CompilerError::Skipped));
}
#[allow(unreachable_code)]
fn test_failed(mut args: Vec<String>) {
fn test_failed(args: &[String]) {
let mut args = args.to_vec();
args.push("--cfg=broken".to_string());
let result = run!(args, || unreachable!() as ControlFlow<()>);
let result = run!(&args, || unreachable!() as ControlFlow<()>);
assert_eq!(result, Err(stable_mir::CompilerError::Failed));
}
/// Test that we are able to pass a closure and set the return according to the captured value.
fn test_captured(args: Vec<String>) {
fn test_captured(args: &[String]) {
let captured = "10".to_string();
let result = run!(args, || ControlFlow::Continue::<(), usize>(captured.len()));
assert_eq!(result, Ok(captured.len()));

View file

@ -186,7 +186,7 @@ fn get_item<'a>(
fn main() {
let path = "input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -146,7 +146,7 @@ fn get_item<'a>(
fn main() {
let path = "input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),

View file

@ -40,7 +40,7 @@ fn test_translation(tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn main() {
let path = "internal_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),

View file

@ -46,7 +46,7 @@ fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn main() {
let path = "internal_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),

View file

@ -183,14 +183,14 @@ impl mir::MutMirVisitor for TestMutVisitor {
fn main() {
let path = "sim_visitor_input.rs";
generate_input(&path).unwrap();
let args = vec![
let args = &[
"rustc".to_string(),
"-Cpanic=abort".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
path.to_string(),
];
run!(args.clone(), test_visitor).unwrap();
run!(args, test_visitor).unwrap();
run!(args, test_mut_visitor).unwrap();
}

View file

@ -2,7 +2,7 @@
//@ ignore-endian-big
// ignore-tidy-linelength
//@ normalize-stderr: "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼" -> "╾ALLOC_ID$1╼"
#![allow(invalid_value)]
#![allow(invalid_value, unnecessary_transmutes)]
#![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)]
use std::mem;

View file

@ -1,3 +1,4 @@
#![allow(unnecessary_transmutes)]
use std::mem;
fn main() {

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/transmute-const-promotion.rs:4:37
--> $DIR/transmute-const-promotion.rs:5:37
|
LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use

View file

@ -1,3 +1,4 @@
#![allow(unnecessary_transmutes)]
use std::mem;
static FOO: bool = unsafe { mem::transmute(3u8) };

View file

@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/transmute-const.rs:3:1
--> $DIR/transmute-const.rs:4:1
|
LL | static FOO: bool = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean

View file

@ -3,7 +3,7 @@
//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
//@ normalize-stderr: "0x0+" -> "0x0"
#![feature(never_type)]
#![allow(invalid_value)]
#![allow(invalid_value, unnecessary_transmutes)]
use std::mem;

View file

@ -1,5 +1,5 @@
// ignore-tidy-linelength
#![allow(unused)]
#![allow(unused, unnecessary_transmutes)]
#![feature(ptr_metadata)]
use std::{ptr, mem};

View file

@ -2,6 +2,7 @@
//@ [no_flag] check-pass
//@ [with_flag] compile-flags: -Zextra-const-ub-checks
#![feature(never_type)]
#![allow(unnecessary_transmutes)]
use std::mem::transmute;
use std::ptr::addr_of;

View file

@ -1,11 +1,11 @@
error[E0080]: evaluation of constant value failed
--> $DIR/detect-extra-ub.rs:29:20
--> $DIR/detect-extra-ub.rs:30: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:35:21
--> $DIR/detect-extra-ub.rs:36:21
|
LL | let _x: usize = transmute(&3u8);
| ^^^^^^^^^^^^^^^ constructing invalid value: encountered a pointer, but expected an integer
@ -14,7 +14,7 @@ LL | let _x: usize = transmute(&3u8);
= 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:41:28
--> $DIR/detect-extra-ub.rs:42:28
|
LL | let _x: PtrSizedEnum = transmute(&3u8);
| ^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
@ -23,7 +23,7 @@ LL | let _x: PtrSizedEnum = transmute(&3u8);
= 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
--> $DIR/detect-extra-ub.rs:49:30
|
LL | let _x: (usize, usize) = transmute(x);
| ^^^^^^^^^^^^ constructing invalid value at .0: encountered a pointer, but expected an integer
@ -32,19 +32,19 @@ LL | let _x: (usize, usize) = transmute(x);
= 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:54:20
--> $DIR/detect-extra-ub.rs:55: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:62:13
--> $DIR/detect-extra-ub.rs:63:13
|
LL | let v = *addr_of!(data).cast::<UninhDiscriminant>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
error[E0080]: evaluation of constant value failed
--> $DIR/detect-extra-ub.rs:82:16
--> $DIR/detect-extra-ub.rs:83: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
@ -53,7 +53,7 @@ LL | let _val = *(&mem as *const Align as *const [*const u8; 2]);
= 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:97:16
--> $DIR/detect-extra-ub.rs:98:16
|
LL | let _val = &*slice;
| ^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object

View file

@ -1,8 +1,8 @@
//@ run-pass
const fn make_nans() -> (f64, f64, f32, f32) {
let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) };
let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) };
let nan1 = f64::from_bits(0x7FF0_0001_0000_0001);
let nan2 = f64::from_bits(0x7FF0_0000_0000_0001);
let nan1_32 = nan1 as f32;
let nan2_32 = nan2 as f32;

View file

@ -1,13 +1,15 @@
error: path separator must be a double colon
--> $DIR/single-colon-path-not-const-generics.rs:8:18
|
LL | pub struct Foo {
| --- while parsing this struct
LL | a: Vec<foo::bar:A>,
| ^
|
help: use a double colon instead
|
LL | a: Vec<foo::bar::A>,
| +
| +
error: aborting due to 1 previous error

View file

@ -1,4 +1,5 @@
//@ run-pass
#![allow(unnecessary_transmutes)]
use std::mem::transmute;
fn main() {

View file

@ -0,0 +1,20 @@
//@ only-apple
//@ build-fail
//@ dont-check-compiler-stderr
//@ dont-check-compiler-stdout
// Regression test for <https://github.com/rust-lang/rust/issues/139744>.
// Functions in the dynamic library marked with no_mangle should not be GC-ed.
#![crate_type = "cdylib"]
unsafe extern "C" {
unsafe static THIS_SYMBOL_SHOULD_BE_UNDEFINED: usize;
}
#[unsafe(no_mangle)]
pub unsafe fn function_marked_with_no_mangle() {
println!("FUNCTION_MARKED_WITH_NO_MANGLE = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED });
}
//~? ERROR linking

View file

@ -0,0 +1,27 @@
//@ run-pass
//@ ignore-windows-gnu: only statics marked with used can be GC-ed on windows-gnu
// Regression test for <https://github.com/rust-lang/rust/issues/139744>.
// Functions in the binary marked with no_mangle should be GC-ed if they
// are not indirectly referenced by main.
#![feature(used_with_arg)]
#[cfg_attr(windows, link(name = "this_lib_does_not_exist", kind = "raw-dylib"))]
unsafe extern "C" {
unsafe static THIS_SYMBOL_SHOULD_BE_UNDEFINED: usize;
}
#[unsafe(no_mangle)]
pub unsafe fn function_marked_with_no_mangle() {
println!("FUNCTION_MARKED_WITH_NO_MANGLE = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED });
}
#[used(compiler)]
pub static FUNCTION_MARKED_WITH_USED: unsafe fn() = || {
println!("FUNCTION_MARKED_WITH_USED = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED });
};
fn main() {
println!("MAIN");
}

View file

@ -1,19 +1,19 @@
// check-fail
// run-rustfix
#![allow(unnecessary_transmutes)]
use std::ptr;
use std::mem;
use std::{mem, ptr};
unsafe fn null_ptr() {
ptr::write(
//~^ ERROR calling this function with a null pointer is undefined behavior
//~^ ERROR calling this function with a null pointer is undefined behavior
ptr::null_mut() as *mut u32,
mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
);
let null_ptr = ptr::null_mut();
ptr::write(
//~^ ERROR calling this function with a null pointer is undefined behavior
//~^ ERROR calling this function with a null pointer is undefined behavior
null_ptr as *mut u32,
mem::transmute::<[u8; 4], _>([0, 0, 0, 255]),
);
@ -38,10 +38,10 @@ unsafe fn null_ptr() {
ptr::copy_nonoverlapping::<usize>(ptr::null(), ptr::NonNull::dangling().as_ptr(), 0);
//~^ ERROR calling this function with a null pointer is undefined behavior
ptr::copy_nonoverlapping::<usize>(
//~^ ERROR calling this function with a null pointer is undefined behavior
//~^ ERROR calling this function with a null pointer is undefined behavior
ptr::NonNull::dangling().as_ptr(),
ptr::null_mut(),
0
0,
);
#[derive(Copy, Clone)]

View file

@ -117,7 +117,7 @@ LL | |
LL | | ptr::NonNull::dangling().as_ptr(),
LL | | ptr::null_mut(),
| | --------------- null pointer originates from here
LL | | 0
LL | | 0,
LL | | );
| |_____^
|

View file

@ -2,6 +2,8 @@
#![deny(improper_ctypes)]
#![feature(ptr_internals)]
#![feature(transparent_unions)]
#![feature(repr128)]
#![allow(incomplete_features)]
use std::num;
@ -40,6 +42,20 @@ enum Isize {
C,
}
#[repr(u128)]
enum U128 {
A,
B,
C,
}
#[repr(i128)]
enum I128 {
A,
B,
C,
}
#[repr(transparent)]
struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
@ -71,6 +87,8 @@ extern "C" {
fn repr_c(x: ReprC);
fn repr_u8(x: U8);
fn repr_isize(x: Isize);
fn repr_u128(x: U128); //~ ERROR `extern` block uses type `U128`
fn repr_i128(x: I128); //~ ERROR `extern` block uses type `I128`
fn option_ref(x: Option<&'static u8>);
fn option_fn(x: Option<extern "C" fn()>);
fn option_nonnull(x: Option<std::ptr::NonNull<u8>>);

View file

@ -1,5 +1,5 @@
error: `extern` block uses type `U`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:68:14
--> $DIR/lint-ctypes-enum.rs:84:14
|
LL | fn uf(x: U);
| ^ not FFI-safe
@ -7,7 +7,7 @@ LL | fn uf(x: U);
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: the type is defined here
--> $DIR/lint-ctypes-enum.rs:9:1
--> $DIR/lint-ctypes-enum.rs:11:1
|
LL | enum U {
| ^^^^^^
@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
error: `extern` block uses type `B`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:69:14
--> $DIR/lint-ctypes-enum.rs:85:14
|
LL | fn bf(x: B);
| ^ not FFI-safe
@ -26,13 +26,13 @@ LL | fn bf(x: B);
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: the type is defined here
--> $DIR/lint-ctypes-enum.rs:12:1
--> $DIR/lint-ctypes-enum.rs:14:1
|
LL | enum B {
| ^^^^^^
error: `extern` block uses type `T`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:70:14
--> $DIR/lint-ctypes-enum.rs:86:14
|
LL | fn tf(x: T);
| ^ not FFI-safe
@ -40,13 +40,39 @@ LL | fn tf(x: T);
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: the type is defined here
--> $DIR/lint-ctypes-enum.rs:16:1
--> $DIR/lint-ctypes-enum.rs:18:1
|
LL | enum T {
| ^^^^^^
error: `extern` block uses type `U128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:90:21
|
LL | fn repr_u128(x: U128);
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
note: the type is defined here
--> $DIR/lint-ctypes-enum.rs:46:1
|
LL | enum U128 {
| ^^^^^^^^^
error: `extern` block uses type `I128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:91:21
|
LL | fn repr_i128(x: I128);
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
note: the type is defined here
--> $DIR/lint-ctypes-enum.rs:53:1
|
LL | enum I128 {
| ^^^^^^^^^
error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:82:31
--> $DIR/lint-ctypes-enum.rs:100:31
|
LL | fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -54,7 +80,7 @@ LL | fn option_nonzero_u128(x: Option<num::NonZero<u128>>);
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:89:31
--> $DIR/lint-ctypes-enum.rs:107:31
|
LL | fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -62,7 +88,7 @@ LL | fn option_nonzero_i128(x: Option<num::NonZero<i128>>);
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:94:36
--> $DIR/lint-ctypes-enum.rs:112:36
|
LL | fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -71,7 +97,7 @@ LL | fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>
= note: enum has no representation hint
error: `extern` block uses type `Option<Rust<NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:96:28
--> $DIR/lint-ctypes-enum.rs:114:28
|
LL | fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -80,7 +106,7 @@ LL | fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
= note: enum has no representation hint
error: `extern` block uses type `Option<u8>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:97:21
--> $DIR/lint-ctypes-enum.rs:115:21
|
LL | fn option_u8(x: Option<u8>);
| ^^^^^^^^^^ not FFI-safe
@ -89,7 +115,7 @@ LL | fn option_u8(x: Option<u8>);
= note: enum has no representation hint
error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:107:33
--> $DIR/lint-ctypes-enum.rs:125:33
|
LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -97,7 +123,7 @@ LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:114:33
--> $DIR/lint-ctypes-enum.rs:132:33
|
LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -105,7 +131,7 @@ LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:119:38
--> $DIR/lint-ctypes-enum.rs:137:38
|
LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -114,7 +140,7 @@ LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u
= note: enum has no representation hint
error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:121:30
--> $DIR/lint-ctypes-enum.rs:139:30
|
LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -123,7 +149,7 @@ LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
= note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:125:51
--> $DIR/lint-ctypes-enum.rs:143:51
|
LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -132,7 +158,7 @@ LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>,
= note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:127:53
--> $DIR/lint-ctypes-enum.rs:145:53
|
LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -141,7 +167,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>
= note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:129:51
--> $DIR/lint-ctypes-enum.rs:147:51
|
LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -150,7 +176,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>,
= note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:132:49
--> $DIR/lint-ctypes-enum.rs:150:49
|
LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -159,7 +185,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi
= note: enum has no representation hint
error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:134:30
--> $DIR/lint-ctypes-enum.rs:152:30
|
LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -168,7 +194,7 @@ LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
= note: enum has no representation hint
error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:145:33
--> $DIR/lint-ctypes-enum.rs:163:33
|
LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -176,7 +202,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:152:33
--> $DIR/lint-ctypes-enum.rs:170:33
|
LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -184,7 +210,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:157:38
--> $DIR/lint-ctypes-enum.rs:175:38
|
LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -193,7 +219,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe
= note: enum has no representation hint
error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:159:30
--> $DIR/lint-ctypes-enum.rs:177:30
|
LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -202,7 +228,7 @@ LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
= note: enum has no representation hint
error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:163:51
--> $DIR/lint-ctypes-enum.rs:181:51
|
LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -211,7 +237,7 @@ LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8
= note: enum has no representation hint
error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:165:53
--> $DIR/lint-ctypes-enum.rs:183:53
|
LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -220,7 +246,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<
= note: enum has no representation hint
error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:167:51
--> $DIR/lint-ctypes-enum.rs:185:51
|
LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -229,7 +255,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num
= note: enum has no representation hint
error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:170:49
--> $DIR/lint-ctypes-enum.rs:188:49
|
LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -238,7 +264,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<
= note: enum has no representation hint
error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:172:30
--> $DIR/lint-ctypes-enum.rs:190:30
|
LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -247,7 +273,7 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
= note: enum has no representation hint
error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:174:27
--> $DIR/lint-ctypes-enum.rs:192:27
|
LL | fn result_unit_t_e(x: Result<(), ()>);
| ^^^^^^^^^^^^^^ not FFI-safe
@ -255,5 +281,5 @@ LL | fn result_unit_t_e(x: Result<(), ()>);
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
error: aborting due to 27 previous errors
error: aborting due to 29 previous errors

View file

@ -0,0 +1,22 @@
// Paths in type contexts may be followed by single colons.
// This means we can't generally assume that the user typo'ed a double colon.
// issue: <https://github.com/rust-lang/rust/issues/140227>
//@ check-pass
#![crate_type = "lib"]
#![expect(non_camel_case_types)]
#[rustfmt::skip]
mod garden {
fn f<path>() where path:to::somewhere {} // OK!
fn g(_: impl Take<path:to::somewhere>) {} // OK!
#[cfg(any())] fn h() where a::path:to::nowhere {} // OK!
fn i(_: impl Take<path::<>:to::somewhere>) {} // OK!
mod to { pub(super) trait somewhere {} }
trait Take { type path; }
}

View file

@ -0,0 +1,19 @@
//! Byte string literal patterns use the mutability of the literal, rather than the mutability of
//! the pattern's scrutinee. Since byte string literals are always shared references, it's a
//! mismatch to use a byte string literal pattern to match on a mutable array or slice reference.
fn main() {
let mut val = [97u8, 10u8];
match &mut val {
b"a\n" => {},
//~^ ERROR mismatched types
//~| types differ in mutability
_ => {},
}
match &mut val[..] {
b"a\n" => {},
//~^ ERROR mismatched types
//~| types differ in mutability
_ => {},
}
}

View file

@ -0,0 +1,25 @@
error[E0308]: mismatched types
--> $DIR/byte-string-mutability-mismatch.rs:8:9
|
LL | match &mut val {
| -------- this expression has type `&mut [u8; 2]`
LL | b"a\n" => {},
| ^^^^^^ types differ in mutability
|
= note: expected mutable reference `&mut _`
found reference `&'static _`
error[E0308]: mismatched types
--> $DIR/byte-string-mutability-mismatch.rs:14:10
|
LL | match &mut val[..] {
| ------------ this expression has type `&mut [u8]`
LL | b"a\n" => {},
| ^^^^^^ types differ in mutability
|
= note: expected mutable reference `&mut _`
found reference `&'static _`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,34 @@
//! Test type errors for byte string literal patterns. `deref_patterns` allows byte string literal
//! patterns to have type `[u8]` or `[u8; N]` when matching on a slice or array; this can affect the
//! "found" type reported in error messages when matching on a slice or array of the wrong type.
#![feature(deref_patterns)]
#![expect(incomplete_features)]
fn main() {
// Baseline 1: under normal circumstances, byte string literal patterns have type `&[u8; N]`,
// the same as byte string literals.
if let b"test" = () {}
//~^ ERROR mismatched types
//~| expected `()`, found `&[u8; 4]`
// Baseline 2: there's a special case for byte string patterns in stable rust, allowing them to
// match on slice references. This affects the error when matching on a non-`&[u8]` slice ref,
// reporting the "found" type as `&[u8]`.
if let b"test" = &[] as &[i8] {}
//~^ ERROR mismatched types
//~| expected `&[i8]`, found `&[u8]`
// Test matching on a non-`[u8]` slice: the pattern has type `[u8]` if a slice is expected.
if let b"test" = *(&[] as &[i8]) {}
//~^ ERROR mismatched types
//~| expected `[i8]`, found `[u8]`
// Test matching on a non-`[u8;4]` array: the pattern has type `[u8;4]` if an array is expected.
if let b"test" = [()] {}
//~^ ERROR mismatched types
//~| expected `[(); 1]`, found `[u8; 4]`
if let b"test" = *b"this array is too long" {}
//~^ ERROR mismatched types
//~| expected an array with a size of 22, found one with a size of 4
}

View file

@ -0,0 +1,52 @@
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:11:12
|
LL | if let b"test" = () {}
| ^^^^^^^ -- this expression has type `()`
| |
| expected `()`, found `&[u8; 4]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:18:12
|
LL | if let b"test" = &[] as &[i8] {}
| ^^^^^^^ ------------ this expression has type `&[i8]`
| |
| expected `&[i8]`, found `&[u8]`
|
= note: expected reference `&[i8]`
found reference `&'static [u8]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:23:12
|
LL | if let b"test" = *(&[] as &[i8]) {}
| ^^^^^^^ --------------- this expression has type `[i8]`
| |
| expected `[i8]`, found `[u8]`
|
= note: expected slice `[i8]`
found slice `[u8]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:28:12
|
LL | if let b"test" = [()] {}
| ^^^^^^^ ---- this expression has type `[(); 1]`
| |
| expected `[(); 1]`, found `[u8; 4]`
|
= note: expected array `[(); 1]`
found array `[u8; 4]`
error[E0308]: mismatched types
--> $DIR/byte-string-type-errors.rs:31:12
|
LL | if let b"test" = *b"this array is too long" {}
| ^^^^^^^ -------------------------- this expression has type `[u8; 22]`
| |
| expected an array with a size of 22, found one with a size of 4
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -12,4 +12,21 @@ fn main() {
//~^ ERROR: mismatched types
_ => {}
}
// `deref_patterns` allows string and byte string literals to have non-ref types.
match *"test" {
"test" => {}
//~^ ERROR: mismatched types
_ => {}
}
match *b"test" {
b"test" => {}
//~^ ERROR: mismatched types
_ => {}
}
match *(b"test" as &[u8]) {
b"test" => {}
//~^ ERROR: mismatched types
_ => {}
}
}

View file

@ -23,7 +23,31 @@ help: consider dereferencing to access the inner value using the Deref trait
LL | match *Box::new(0) {
| +
error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:18:9
|
LL | match *"test" {
| ------- this expression has type `str`
LL | "test" => {}
| ^^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:23:9
|
LL | match *b"test" {
| -------- this expression has type `[u8; 4]`
LL | b"test" => {}
| ^^^^^^^ expected `[u8; 4]`, found `&[u8; 4]`
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:28:9
|
LL | match *(b"test" as &[u8]) {
| ------------------- this expression has type `[u8]`
LL | b"test" => {}
| ^^^^^^^ expected `[u8]`, found `&[u8; 4]`
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0308, E0658.
For more information about an error, try `rustc --explain E0308`.

View file

@ -0,0 +1,66 @@
//@ run-pass
//! Test deref patterns using string and bytestring literals.
#![feature(deref_patterns)]
#![allow(incomplete_features)]
fn main() {
for (test_in, test_expect) in [("zero", 0), ("one", 1), ("two", 2)] {
// Test string literal patterns having type `str`.
let test_actual = match *test_in {
"zero" => 0,
"one" => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test string literals in explicit `deref!(_)` patterns.
let test_actual = match test_in.to_string() {
deref!("zero") => 0,
deref!("one") => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
}
// Test that we can still mutate in the match arm after using a literal to test equality:
let mut test = "test".to_string();
if let deref!(s @ "test") = &mut test {
s.make_ascii_uppercase();
}
assert_eq!(test, "TEST");
for (test_in, test_expect) in [(b"0", 0), (b"1", 1), (b"2", 2)] {
// Test byte string literal patterns having type `[u8; N]`
let test_actual = match *test_in {
b"0" => 0,
b"1" => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test byte string literal patterns having type `[u8]`
let test_actual = match *(test_in as &[u8]) {
b"0" => 0,
b"1" => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test byte string literals used as arrays in explicit `deref!(_)` patterns.
let test_actual = match Box::new(*test_in) {
deref!(b"0") => 0,
deref!(b"1") => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
// Test byte string literals used as slices in explicit `deref!(_)` patterns.
let test_actual = match test_in.to_vec() {
deref!(b"0") => 0,
deref!(b"1") => 1,
_ => 2,
};
assert_eq!(test_actual, test_expect);
}
}

View file

@ -2,18 +2,14 @@
#![allow(incomplete_features)]
fn main() {
// FIXME(deref_patterns): fails to typecheck because `"foo"` has type &str but deref creates a
// place of type `str`.
// FIXME(deref_patterns): fails to typecheck because string literal patterns don't peel
// references from the scrutinee.
match "foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
"foo" => {}
//~^ ERROR: mismatched types
_ => {}
}
match &"foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
"foo" => {}
//~^ ERROR: mismatched types
_ => {}

View file

@ -1,34 +1,16 @@
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:8:16
--> $DIR/typeck_fail.rs:8:9
|
LL | match "foo".to_string() {
| ----------------- this expression has type `String`
LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:10:9
|
LL | match "foo".to_string() {
| ----------------- this expression has type `String`
...
LL | "foo" => {}
| ^^^^^ expected `String`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:15:16
--> $DIR/typeck_fail.rs:13:9
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:17:9
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
...
LL | "foo" => {}
| ^^^^^ expected `&String`, found `&str`
|
@ -36,7 +18,7 @@ LL | "foo" => {}
found reference `&'static str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:24:9
--> $DIR/typeck_fail.rs:20:9
|
LL | match Some(0) {
| ------- this expression has type `Option<{integer}>`
@ -46,6 +28,6 @@ LL | Ok(0) => {}
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
error: aborting due to 5 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,15 +0,0 @@
//@ run-rustfix
use std::fmt;
struct Hello;
impl fmt::Display for Hello {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
write!(f, "hello")
}
}
fn main() {
let _ = Hello;
}

View file

@ -1,15 +0,0 @@
//@ run-rustfix
use std::fmt;
struct Hello;
impl fmt::Display for Hello {
fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result { //~ ERROR path separator must be a double colon
write!(f, "hello")
}
}
fn main() {
let _ = Hello;
}

View file

@ -1,13 +0,0 @@
error: path separator must be a double colon
--> $DIR/argument-list-from-path-sep-error-129273.rs:8:30
|
LL | fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result {
| ^
|
help: use a double colon instead
|
LL | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
| +
error: aborting due to 1 previous error

View file

@ -7,14 +7,14 @@ mod foo {
struct Foo {
a: foo:A,
//~^ ERROR path separator must be a double colon
//~| ERROR struct `A` is private
//~^ ERROR found single colon in a struct field type path
//~| ERROR expected `,`, or `}`, found `:`
}
struct Bar {
b: foo::bar:B,
//~^ ERROR path separator must be a double colon
//~| ERROR module `bar` is private
//~^ ERROR found single colon in a struct field type path
//~| ERROR expected `,`, or `}`, found `:`
}
fn main() {}

View file

@ -1,51 +1,40 @@
error: path separator must be a double colon
error: found single colon in a struct field type path
--> $DIR/struct-field-type-including-single-colon.rs:9:11
|
LL | a: foo:A,
| ^
|
help: use a double colon instead
help: write a path separator here
|
LL | a: foo::A,
| +
error: path separator must be a double colon
error: expected `,`, or `}`, found `:`
--> $DIR/struct-field-type-including-single-colon.rs:9:11
|
LL | struct Foo {
| --- while parsing this struct
LL | a: foo:A,
| ^
error: found single colon in a struct field type path
--> $DIR/struct-field-type-including-single-colon.rs:15:16
|
LL | b: foo::bar:B,
| ^
|
help: use a double colon instead
help: write a path separator here
|
LL | b: foo::bar::B,
| +
error[E0603]: struct `A` is private
--> $DIR/struct-field-type-including-single-colon.rs:9:12
|
LL | a: foo:A,
| ^ private struct
|
note: the struct `A` is defined here
--> $DIR/struct-field-type-including-single-colon.rs:2:5
|
LL | struct A;
| ^^^^^^^^^
error[E0603]: module `bar` is private
--> $DIR/struct-field-type-including-single-colon.rs:15:13
error: expected `,`, or `}`, found `:`
--> $DIR/struct-field-type-including-single-colon.rs:15:16
|
LL | struct Bar {
| --- while parsing this struct
LL | b: foo::bar:B,
| ^^^ - struct `B` is not publicly re-exported
| |
| private module
|
note: the module `bar` is defined here
--> $DIR/struct-field-type-including-single-colon.rs:3:5
|
LL | mod bar {
| ^^^^^^^
| ^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0603`.

View file

@ -0,0 +1,85 @@
//@ run-rustfix
#![deny(unnecessary_transmutes)]
#![allow(unused_unsafe, unused_imports, unused_variables, unused_parens)]
use std::mem::transmute;
pub fn bytes_at_home(x: u32) -> [u8; 4] {
unsafe { u32::to_ne_bytes(x) }
//~^ ERROR
}
fn main() {
unsafe {
let x: u16 = u16::from_ne_bytes(*b"01");
//~^ ERROR
let x: [u8; 2] = u16::to_ne_bytes(x);
//~^ ERROR
let x: u32 = u32::from_ne_bytes(*b"0123");
//~^ ERROR
let x: [u8; 4] = u32::to_ne_bytes(x);
//~^ ERROR
let x: u64 = u64::from_ne_bytes(*b"feriscat");
//~^ ERROR
let x: [u8; 8] = u64::to_ne_bytes(x);
//~^ ERROR
let y: i16 = i16::from_ne_bytes(*b"01");
//~^ ERROR
let y: [u8; 2] = i16::to_ne_bytes(y);
//~^ ERROR
let y: i32 = i32::from_ne_bytes(*b"0123");
//~^ ERROR
let y: [u8; 4] = i32::to_ne_bytes(y);
//~^ ERROR
let y: i64 = i64::from_ne_bytes(*b"feriscat");
//~^ ERROR
let y: [u8; 8] = i64::to_ne_bytes(y);
//~^ ERROR
let z: f32 = f32::from_ne_bytes(*b"0123");
//~^ ERROR
let z: [u8; 4] = f32::to_ne_bytes(z);
//~^ ERROR
let z: f64 = f64::from_ne_bytes(*b"feriscat");
//~^ ERROR
let z: [u8; 8] = f64::to_ne_bytes(z);
//~^ ERROR
let y: u32 = u32::from('🦀');
//~^ ERROR
let y: char = char::from_u32_unchecked(y);
//~^ ERROR
let x: u16 = i16::cast_unsigned(8i16);
//~^ ERROR
let x: i16 = u16::cast_signed(x);
//~^ ERROR
let x: u32 = i32::cast_unsigned(4i32);
//~^ ERROR
let x: i32 = u32::cast_signed(x);
//~^ ERROR
let x: u64 = i64::cast_unsigned(7i64);
//~^ ERROR
let x: i64 = u64::cast_signed(x);
//~^ ERROR
let y: f32 = f32::from_bits(1u32);
//~^ ERROR
let y: u32 = f32::to_bits(y);
//~^ ERROR
let y: f64 = f64::from_bits(3u64);
//~^ ERROR
let y: u64 = f64::to_bits(2.0);
//~^ ERROR
let z: bool = (1u8 == 1);
//~^ ERROR
let z: u8 = (z) as u8;
//~^ ERROR
let z: bool = transmute(1i8);
// no error!
let z: i8 = (z) as i8;
//~^ ERROR
}
}

View file

@ -0,0 +1,85 @@
//@ run-rustfix
#![deny(unnecessary_transmutes)]
#![allow(unused_unsafe, unused_imports, unused_variables, unused_parens)]
use std::mem::transmute;
pub fn bytes_at_home(x: u32) -> [u8; 4] {
unsafe { transmute(x) }
//~^ ERROR
}
fn main() {
unsafe {
let x: u16 = transmute(*b"01");
//~^ ERROR
let x: [u8; 2] = transmute(x);
//~^ ERROR
let x: u32 = transmute(*b"0123");
//~^ ERROR
let x: [u8; 4] = transmute(x);
//~^ ERROR
let x: u64 = transmute(*b"feriscat");
//~^ ERROR
let x: [u8; 8] = transmute(x);
//~^ ERROR
let y: i16 = transmute(*b"01");
//~^ ERROR
let y: [u8; 2] = transmute(y);
//~^ ERROR
let y: i32 = transmute(*b"0123");
//~^ ERROR
let y: [u8; 4] = transmute(y);
//~^ ERROR
let y: i64 = transmute(*b"feriscat");
//~^ ERROR
let y: [u8; 8] = transmute(y);
//~^ ERROR
let z: f32 = transmute(*b"0123");
//~^ ERROR
let z: [u8; 4] = transmute(z);
//~^ ERROR
let z: f64 = transmute(*b"feriscat");
//~^ ERROR
let z: [u8; 8] = transmute(z);
//~^ ERROR
let y: u32 = transmute('🦀');
//~^ ERROR
let y: char = transmute(y);
//~^ ERROR
let x: u16 = transmute(8i16);
//~^ ERROR
let x: i16 = transmute(x);
//~^ ERROR
let x: u32 = transmute(4i32);
//~^ ERROR
let x: i32 = transmute(x);
//~^ ERROR
let x: u64 = transmute(7i64);
//~^ ERROR
let x: i64 = transmute(x);
//~^ ERROR
let y: f32 = transmute(1u32);
//~^ ERROR
let y: u32 = transmute(y);
//~^ ERROR
let y: f64 = transmute(3u64);
//~^ ERROR
let y: u64 = transmute(2.0);
//~^ ERROR
let z: bool = transmute(1u8);
//~^ ERROR
let z: u8 = transmute(z);
//~^ ERROR
let z: bool = transmute(1i8);
// no error!
let z: i8 = transmute(z);
//~^ ERROR
}
}

View file

@ -0,0 +1,235 @@
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:7:14
|
LL | unsafe { transmute(x) }
| ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
note: the lint level is defined here
--> $DIR/unnecessary-transmutation.rs:2:9
|
LL | #![deny(unnecessary_transmutes)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:13:22
|
LL | let x: u16 = transmute(*b"01");
| ^^^^^^^^^^^^^^^^^ help: replace this with: `u16::from_ne_bytes(*b"01")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:15:26
|
LL | let x: [u8; 2] = transmute(x);
| ^^^^^^^^^^^^ help: replace this with: `u16::to_ne_bytes(x)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:17:22
|
LL | let x: u32 = transmute(*b"0123");
| ^^^^^^^^^^^^^^^^^^^ help: replace this with: `u32::from_ne_bytes(*b"0123")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:19:26
|
LL | let x: [u8; 4] = transmute(x);
| ^^^^^^^^^^^^ help: replace this with: `u32::to_ne_bytes(x)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:21:22
|
LL | let x: u64 = transmute(*b"feriscat");
| ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `u64::from_ne_bytes(*b"feriscat")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:23:26
|
LL | let x: [u8; 8] = transmute(x);
| ^^^^^^^^^^^^ help: replace this with: `u64::to_ne_bytes(x)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:26:22
|
LL | let y: i16 = transmute(*b"01");
| ^^^^^^^^^^^^^^^^^ help: replace this with: `i16::from_ne_bytes(*b"01")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:28:26
|
LL | let y: [u8; 2] = transmute(y);
| ^^^^^^^^^^^^ help: replace this with: `i16::to_ne_bytes(y)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:30:22
|
LL | let y: i32 = transmute(*b"0123");
| ^^^^^^^^^^^^^^^^^^^ help: replace this with: `i32::from_ne_bytes(*b"0123")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:32:26
|
LL | let y: [u8; 4] = transmute(y);
| ^^^^^^^^^^^^ help: replace this with: `i32::to_ne_bytes(y)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:34:22
|
LL | let y: i64 = transmute(*b"feriscat");
| ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `i64::from_ne_bytes(*b"feriscat")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:36:26
|
LL | let y: [u8; 8] = transmute(y);
| ^^^^^^^^^^^^ help: replace this with: `i64::to_ne_bytes(y)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:39:22
|
LL | let z: f32 = transmute(*b"0123");
| ^^^^^^^^^^^^^^^^^^^ help: replace this with: `f32::from_ne_bytes(*b"0123")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:41:26
|
LL | let z: [u8; 4] = transmute(z);
| ^^^^^^^^^^^^ help: replace this with: `f32::to_ne_bytes(z)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:43:22
|
LL | let z: f64 = transmute(*b"feriscat");
| ^^^^^^^^^^^^^^^^^^^^^^^ help: replace this with: `f64::from_ne_bytes(*b"feriscat")`
|
= help: there's also `from_le_bytes` and `from_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:45:26
|
LL | let z: [u8; 8] = transmute(z);
| ^^^^^^^^^^^^ help: replace this with: `f64::to_ne_bytes(z)`
|
= help: there's also `to_le_bytes` and `to_be_bytes` if you expect a particular byte order
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:48:22
|
LL | let y: u32 = transmute('🦀');
| ^^^^^^^^^^^^^^^ help: replace this with: `u32::from('🦀')`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:50:23
|
LL | let y: char = transmute(y);
| ^^^^^^^^^^^^ help: replace this with: `char::from_u32_unchecked(y)`
|
= help: consider `char::from_u32(…).unwrap()`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:53:22
|
LL | let x: u16 = transmute(8i16);
| ^^^^^^^^^^^^^^^ help: replace this with: `i16::cast_unsigned(8i16)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:55:22
|
LL | let x: i16 = transmute(x);
| ^^^^^^^^^^^^ help: replace this with: `u16::cast_signed(x)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:57:22
|
LL | let x: u32 = transmute(4i32);
| ^^^^^^^^^^^^^^^ help: replace this with: `i32::cast_unsigned(4i32)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:59:22
|
LL | let x: i32 = transmute(x);
| ^^^^^^^^^^^^ help: replace this with: `u32::cast_signed(x)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:61:22
|
LL | let x: u64 = transmute(7i64);
| ^^^^^^^^^^^^^^^ help: replace this with: `i64::cast_unsigned(7i64)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:63:22
|
LL | let x: i64 = transmute(x);
| ^^^^^^^^^^^^ help: replace this with: `u64::cast_signed(x)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:66:22
|
LL | let y: f32 = transmute(1u32);
| ^^^^^^^^^^^^^^^ help: replace this with: `f32::from_bits(1u32)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:68:22
|
LL | let y: u32 = transmute(y);
| ^^^^^^^^^^^^ help: replace this with: `f32::to_bits(y)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:70:22
|
LL | let y: f64 = transmute(3u64);
| ^^^^^^^^^^^^^^^ help: replace this with: `f64::from_bits(3u64)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:72:22
|
LL | let y: u64 = transmute(2.0);
| ^^^^^^^^^^^^^^ help: replace this with: `f64::to_bits(2.0)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:75:23
|
LL | let z: bool = transmute(1u8);
| ^^^^^^^^^^^^^^ help: replace this with: `(1u8 == 1)`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:77:21
|
LL | let z: u8 = transmute(z);
| ^^^^^^^^^^^^ help: replace this with: `(z) as u8`
error: unnecessary transmute
--> $DIR/unnecessary-transmutation.rs:82:21
|
LL | let z: i8 = transmute(z);
| ^^^^^^^^^^^^ help: replace this with: `(z) as i8`
error: aborting due to 32 previous errors