From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- src/test/ui/mir/auxiliary/issue_76375_aux.rs | 20 ++ src/test/ui/mir/auxiliary/mir_external_refs.rs | 17 ++ .../mir/drop-elaboration-after-borrowck-error.rs | 25 ++ .../drop-elaboration-after-borrowck-error.stderr | 60 ++++ .../ui/mir/issue-100476-recursion-check-blewup.rs | 42 +++ src/test/ui/mir/issue-60390.rs | 8 + src/test/ui/mir/issue-66851.rs | 20 ++ src/test/ui/mir/issue-66930.rs | 11 + src/test/ui/mir/issue-67639-normalization-ice.rs | 34 +++ src/test/ui/mir/issue-67710-inline-projection.rs | 17 ++ src/test/ui/mir/issue-67947.rs | 7 + src/test/ui/mir/issue-67947.stderr | 16 ++ src/test/ui/mir/issue-68841.rs | 15 + src/test/ui/mir/issue-71793-inline-args-storage.rs | 16 ++ src/test/ui/mir/issue-73914.rs | 30 ++ src/test/ui/mir/issue-74739.rs | 14 + src/test/ui/mir/issue-75053.rs | 49 ++++ src/test/ui/mir/issue-75053.stderr | 8 + .../ui/mir/issue-75419-validation-impl-trait.rs | 13 + src/test/ui/mir/issue-76248.rs | 29 ++ src/test/ui/mir/issue-76375.rs | 27 ++ src/test/ui/mir/issue-76740-copy-propagation.rs | 30 ++ src/test/ui/mir/issue-76803-branches-not-same.rs | 19 ++ .../ui/mir/issue-77359-simplify-arm-identity.rs | 35 +++ src/test/ui/mir/issue-77911.rs | 15 + src/test/ui/mir/issue-78496.rs | 16 ++ src/test/ui/mir/issue-80949.rs | 34 +++ .../mir/issue-83499-input-output-iteration-ice.rs | 10 + .../issue-83499-input-output-iteration-ice.stderr | 21 ++ src/test/ui/mir/issue-89485.rs | 18 ++ src/test/ui/mir/issue-91745.rs | 21 ++ src/test/ui/mir/issue-92893.rs | 8 + src/test/ui/mir/issue-92893.stderr | 26 ++ .../issue-95978-validator-lifetime-comparison.rs | 10 + src/test/ui/mir/issue66339.rs | 13 + .../mir-inlining/array-clone-with-generic-size.rs | 11 + src/test/ui/mir/mir-inlining/ice-issue-45493.rs | 17 ++ src/test/ui/mir/mir-inlining/ice-issue-45885.rs | 29 ++ src/test/ui/mir/mir-inlining/ice-issue-68347.rs | 28 ++ src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs | 17 ++ src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs | 32 +++ src/test/ui/mir/mir-inlining/ice-issue-77564.rs | 38 +++ .../mir-inlining/no-trait-method-issue-40473.rs | 16 ++ .../mir/mir-inlining/var-debuginfo-issue-67586.rs | 11 + src/test/ui/mir/mir-typeck-normalize-fn-sig.rs | 30 ++ src/test/ui/mir/mir_adt_construction.rs | 92 ++++++ src/test/ui/mir/mir_ascription_coercion.rs | 10 + src/test/ui/mir/mir_assign_eval_order.rs | 67 +++++ src/test/ui/mir/mir_augmented_assignments.rs | 160 +++++++++++ src/test/ui/mir/mir_autoderef.rs | 28 ++ src/test/ui/mir/mir_boxing.rs | 10 + src/test/ui/mir/mir_build_match_comparisons.rs | 59 ++++ src/test/ui/mir/mir_call_with_associated_type.rs | 16 ++ src/test/ui/mir/mir_calls_to_shims.rs | 50 ++++ src/test/ui/mir/mir_cast_fn_ret.rs | 23 ++ src/test/ui/mir/mir_codegen_array.rs | 11 + src/test/ui/mir/mir_codegen_array_2.rs | 9 + src/test/ui/mir/mir_codegen_call_converging.rs | 17 ++ src/test/ui/mir/mir_codegen_calls.rs | 192 +++++++++++++ .../ui/mir/mir_codegen_calls_converging_drops.rs | 26 ++ .../ui/mir/mir_codegen_calls_converging_drops_2.rs | 30 ++ src/test/ui/mir/mir_codegen_calls_diverging.rs | 15 + .../ui/mir/mir_codegen_calls_diverging_drops.rs | 24 ++ src/test/ui/mir/mir_codegen_critical_edge.rs | 44 +++ src/test/ui/mir/mir_codegen_spike1.rs | 12 + src/test/ui/mir/mir_codegen_switch.rs | 35 +++ src/test/ui/mir/mir_codegen_switchint.rs | 12 + src/test/ui/mir/mir_coercion_casts.rs | 10 + src/test/ui/mir/mir_coercions.rs | 71 +++++ src/test/ui/mir/mir_const_prop_identity.rs | 12 + .../ui/mir/mir_const_prop_tuple_field_reorder.rs | 27 ++ src/test/ui/mir/mir_constval_adts.rs | 34 +++ src/test/ui/mir/mir_detects_invalid_ops.rs | 24 ++ src/test/ui/mir/mir_detects_invalid_ops.stderr | 16 ++ src/test/ui/mir/mir_drop_order.rs | 49 ++++ src/test/ui/mir/mir_drop_panics.rs | 25 ++ src/test/ui/mir/mir_dynamic_drops_1.rs | 31 ++ src/test/ui/mir/mir_dynamic_drops_2.rs | 29 ++ src/test/ui/mir/mir_dynamic_drops_3.rs | 35 +++ src/test/ui/mir/mir_early_return_scope.rs | 29 ++ src/test/ui/mir/mir_fat_ptr.rs | 52 ++++ src/test/ui/mir/mir_fat_ptr_drop.rs | 32 +++ src/test/ui/mir/mir_heavy_promoted.rs | 11 + src/test/ui/mir/mir_indexing_oob_1.rs | 14 + src/test/ui/mir/mir_indexing_oob_2.rs | 14 + src/test/ui/mir/mir_indexing_oob_3.rs | 14 + src/test/ui/mir/mir_let_chains_drop_order.rs | 94 ++++++ src/test/ui/mir/mir_match_arm_guard.rs | 16 ++ src/test/ui/mir/mir_match_test.rs | 83 ++++++ src/test/ui/mir/mir_misc_casts.rs | 320 +++++++++++++++++++++ src/test/ui/mir/mir_overflow_off.rs | 17 ++ src/test/ui/mir/mir_raw_fat_ptr.rs | 216 ++++++++++++++ src/test/ui/mir/mir_refs_correct.rs | 209 ++++++++++++++ src/test/ui/mir/mir_small_agg_arg.rs | 8 + src/test/ui/mir/mir_static_subtype.rs | 9 + src/test/ui/mir/mir_struct_with_assoc_ty.rs | 29 ++ src/test/ui/mir/mir_temp_promotions.rs | 10 + src/test/ui/mir/mir_void_return.rs | 12 + src/test/ui/mir/mir_void_return_2.rs | 10 + src/test/ui/mir/remove-zsts-query-cycle.rs | 16 ++ src/test/ui/mir/simplify-branch-same.rs | 21 ++ src/test/ui/mir/ssa-analysis-regression-50041.rs | 36 +++ src/test/ui/mir/thir-constparam-temp.rs | 20 ++ src/test/ui/mir/thir-constparam-temp.stderr | 22 ++ 104 files changed, 3602 insertions(+) create mode 100644 src/test/ui/mir/auxiliary/issue_76375_aux.rs create mode 100644 src/test/ui/mir/auxiliary/mir_external_refs.rs create mode 100644 src/test/ui/mir/drop-elaboration-after-borrowck-error.rs create mode 100644 src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr create mode 100644 src/test/ui/mir/issue-100476-recursion-check-blewup.rs create mode 100644 src/test/ui/mir/issue-60390.rs create mode 100644 src/test/ui/mir/issue-66851.rs create mode 100644 src/test/ui/mir/issue-66930.rs create mode 100644 src/test/ui/mir/issue-67639-normalization-ice.rs create mode 100644 src/test/ui/mir/issue-67710-inline-projection.rs create mode 100644 src/test/ui/mir/issue-67947.rs create mode 100644 src/test/ui/mir/issue-67947.stderr create mode 100644 src/test/ui/mir/issue-68841.rs create mode 100644 src/test/ui/mir/issue-71793-inline-args-storage.rs create mode 100644 src/test/ui/mir/issue-73914.rs create mode 100644 src/test/ui/mir/issue-74739.rs create mode 100644 src/test/ui/mir/issue-75053.rs create mode 100644 src/test/ui/mir/issue-75053.stderr create mode 100644 src/test/ui/mir/issue-75419-validation-impl-trait.rs create mode 100644 src/test/ui/mir/issue-76248.rs create mode 100644 src/test/ui/mir/issue-76375.rs create mode 100644 src/test/ui/mir/issue-76740-copy-propagation.rs create mode 100644 src/test/ui/mir/issue-76803-branches-not-same.rs create mode 100644 src/test/ui/mir/issue-77359-simplify-arm-identity.rs create mode 100644 src/test/ui/mir/issue-77911.rs create mode 100644 src/test/ui/mir/issue-78496.rs create mode 100644 src/test/ui/mir/issue-80949.rs create mode 100644 src/test/ui/mir/issue-83499-input-output-iteration-ice.rs create mode 100644 src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr create mode 100644 src/test/ui/mir/issue-89485.rs create mode 100644 src/test/ui/mir/issue-91745.rs create mode 100644 src/test/ui/mir/issue-92893.rs create mode 100644 src/test/ui/mir/issue-92893.stderr create mode 100644 src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs create mode 100644 src/test/ui/mir/issue66339.rs create mode 100644 src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-45493.rs create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-45885.rs create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-68347.rs create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs create mode 100644 src/test/ui/mir/mir-inlining/ice-issue-77564.rs create mode 100644 src/test/ui/mir/mir-inlining/no-trait-method-issue-40473.rs create mode 100644 src/test/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs create mode 100644 src/test/ui/mir/mir-typeck-normalize-fn-sig.rs create mode 100644 src/test/ui/mir/mir_adt_construction.rs create mode 100644 src/test/ui/mir/mir_ascription_coercion.rs create mode 100644 src/test/ui/mir/mir_assign_eval_order.rs create mode 100644 src/test/ui/mir/mir_augmented_assignments.rs create mode 100644 src/test/ui/mir/mir_autoderef.rs create mode 100644 src/test/ui/mir/mir_boxing.rs create mode 100644 src/test/ui/mir/mir_build_match_comparisons.rs create mode 100644 src/test/ui/mir/mir_call_with_associated_type.rs create mode 100644 src/test/ui/mir/mir_calls_to_shims.rs create mode 100644 src/test/ui/mir/mir_cast_fn_ret.rs create mode 100644 src/test/ui/mir/mir_codegen_array.rs create mode 100644 src/test/ui/mir/mir_codegen_array_2.rs create mode 100644 src/test/ui/mir/mir_codegen_call_converging.rs create mode 100644 src/test/ui/mir/mir_codegen_calls.rs create mode 100644 src/test/ui/mir/mir_codegen_calls_converging_drops.rs create mode 100644 src/test/ui/mir/mir_codegen_calls_converging_drops_2.rs create mode 100644 src/test/ui/mir/mir_codegen_calls_diverging.rs create mode 100644 src/test/ui/mir/mir_codegen_calls_diverging_drops.rs create mode 100644 src/test/ui/mir/mir_codegen_critical_edge.rs create mode 100644 src/test/ui/mir/mir_codegen_spike1.rs create mode 100644 src/test/ui/mir/mir_codegen_switch.rs create mode 100644 src/test/ui/mir/mir_codegen_switchint.rs create mode 100644 src/test/ui/mir/mir_coercion_casts.rs create mode 100644 src/test/ui/mir/mir_coercions.rs create mode 100644 src/test/ui/mir/mir_const_prop_identity.rs create mode 100644 src/test/ui/mir/mir_const_prop_tuple_field_reorder.rs create mode 100644 src/test/ui/mir/mir_constval_adts.rs create mode 100644 src/test/ui/mir/mir_detects_invalid_ops.rs create mode 100644 src/test/ui/mir/mir_detects_invalid_ops.stderr create mode 100644 src/test/ui/mir/mir_drop_order.rs create mode 100644 src/test/ui/mir/mir_drop_panics.rs create mode 100644 src/test/ui/mir/mir_dynamic_drops_1.rs create mode 100644 src/test/ui/mir/mir_dynamic_drops_2.rs create mode 100644 src/test/ui/mir/mir_dynamic_drops_3.rs create mode 100644 src/test/ui/mir/mir_early_return_scope.rs create mode 100644 src/test/ui/mir/mir_fat_ptr.rs create mode 100644 src/test/ui/mir/mir_fat_ptr_drop.rs create mode 100644 src/test/ui/mir/mir_heavy_promoted.rs create mode 100644 src/test/ui/mir/mir_indexing_oob_1.rs create mode 100644 src/test/ui/mir/mir_indexing_oob_2.rs create mode 100644 src/test/ui/mir/mir_indexing_oob_3.rs create mode 100644 src/test/ui/mir/mir_let_chains_drop_order.rs create mode 100644 src/test/ui/mir/mir_match_arm_guard.rs create mode 100644 src/test/ui/mir/mir_match_test.rs create mode 100644 src/test/ui/mir/mir_misc_casts.rs create mode 100644 src/test/ui/mir/mir_overflow_off.rs create mode 100644 src/test/ui/mir/mir_raw_fat_ptr.rs create mode 100644 src/test/ui/mir/mir_refs_correct.rs create mode 100644 src/test/ui/mir/mir_small_agg_arg.rs create mode 100644 src/test/ui/mir/mir_static_subtype.rs create mode 100644 src/test/ui/mir/mir_struct_with_assoc_ty.rs create mode 100644 src/test/ui/mir/mir_temp_promotions.rs create mode 100644 src/test/ui/mir/mir_void_return.rs create mode 100644 src/test/ui/mir/mir_void_return_2.rs create mode 100644 src/test/ui/mir/remove-zsts-query-cycle.rs create mode 100644 src/test/ui/mir/simplify-branch-same.rs create mode 100644 src/test/ui/mir/ssa-analysis-regression-50041.rs create mode 100644 src/test/ui/mir/thir-constparam-temp.rs create mode 100644 src/test/ui/mir/thir-constparam-temp.stderr (limited to 'src/test/ui/mir') diff --git a/src/test/ui/mir/auxiliary/issue_76375_aux.rs b/src/test/ui/mir/auxiliary/issue_76375_aux.rs new file mode 100644 index 000000000..90f4df739 --- /dev/null +++ b/src/test/ui/mir/auxiliary/issue_76375_aux.rs @@ -0,0 +1,20 @@ +// edition:2018 +// compile-flags: -Z mir-opt-level=3 + +#[inline(always)] +pub fn copy_prop(s: bool) -> String { + let a = "Hello world!".to_string(); + let b = a; + let c = b; + if s { + c + } else { + String::new() + } +} + +#[inline(always)] +pub fn dest_prop(x: &[u8]) -> &[u8] { + let y = &x[..x.len()]; + y +} diff --git a/src/test/ui/mir/auxiliary/mir_external_refs.rs b/src/test/ui/mir/auxiliary/mir_external_refs.rs new file mode 100644 index 000000000..9fd58f1d7 --- /dev/null +++ b/src/test/ui/mir/auxiliary/mir_external_refs.rs @@ -0,0 +1,17 @@ +pub struct S(pub u8); + +impl S { + pub fn hey() -> u8 { 24 } +} + +pub trait X { + fn hoy(&self) -> u8 { 25 } +} + +impl X for S {} + +pub enum E { + U(u8) +} + +pub fn regular_fn() -> u8 { 12 } diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs new file mode 100644 index 000000000..fc7341a56 --- /dev/null +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -0,0 +1,25 @@ +// Regression test for issue 81708 and issue 91816 where running a drop +// elaboration on a MIR which failed borrowck lead to an ICE. + +static A: () = { + let a: [String; 1]; + //~^ ERROR destructors cannot be evaluated at compile-time + a[0] = String::new(); + //~^ ERROR destructors cannot be evaluated at compile-time + //~| ERROR binding `a` isn't initialized +}; + +struct B([T; 1]); + +impl B { + pub const fn f(mut self, other: T) -> Self { + let _this = self; + //~^ ERROR destructors cannot be evaluated at compile-time + self.0[0] = other; + //~^ ERROR destructors cannot be evaluated at compile-time + //~| ERROR use of moved value + self + } +} + +fn main() {} diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr new file mode 100644 index 000000000..d8154f8d2 --- /dev/null +++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -0,0 +1,60 @@ +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 + | +LL | a[0] = String::new(); + | ^^^^ + | | + | statics cannot evaluate destructors + | value is dropped here + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:5:9 + | +LL | let a: [String; 1]; + | ^ statics cannot evaluate destructors +... +LL | }; + | - value is dropped here + +error[E0381]: used binding `a` isn't initialized + --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 + | +LL | let a: [String; 1]; + | - binding declared here but left uninitialized +LL | +LL | a[0] = String::new(); + | ^^^^ `a` used here but it isn't initialized + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + | +LL | self.0[0] = other; + | ^^^^^^^^^ + | | + | constant functions cannot evaluate destructors + | value is dropped here + +error[E0493]: destructors cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 + | +LL | let _this = self; + | ^^^^^ constant functions cannot evaluate destructors +... +LL | } + | - value is dropped here + +error[E0382]: use of moved value: `self.0` + --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + | +LL | pub const fn f(mut self, other: T) -> Self { + | -------- move occurs because `self` has type `B`, which does not implement the `Copy` trait +LL | let _this = self; + | ---- value moved here +LL | +LL | self.0[0] = other; + | ^^^^^^^^^ value used here after move + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0381, E0382, E0493. +For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/mir/issue-100476-recursion-check-blewup.rs b/src/test/ui/mir/issue-100476-recursion-check-blewup.rs new file mode 100644 index 000000000..bc2f32f4c --- /dev/null +++ b/src/test/ui/mir/issue-100476-recursion-check-blewup.rs @@ -0,0 +1,42 @@ +// check-pass + +// compile-flags: --emit=mir,link -O + +// At one point the MIR inlining, when guarding against infinitely (or even just +// excessive) recursion, was using `ty::Instance` as the basis for its history +// check. The problem is that when you have polymorphic recursion, you can have +// distinct instances of the same code (because you're inlining the same code +// with differing substitutions), causing the amount of inlining to blow up +// exponentially. +// +// This test illustrates an example of that filed in issue rust#100476. + +#![allow(unconditional_recursion)] +#![feature(decl_macro)] + +macro emit($($m:ident)*) {$( + // Randomize `def_path_hash` by defining them under a module with + // different names + pub mod $m { + pub trait Tr { + type Next: Tr; + } + + pub fn hoge() { + inner::(); + } + + #[inline(always)] + fn inner() { + inner::(); + } + } +)*} + +// Increase the chance of triggering the bug +emit!( + m00 m01 m02 m03 m04 m05 m06 m07 m08 m09 + m10 m11 m12 m13 m14 m15 m16 m17 m18 m19 +); + +fn main() { } diff --git a/src/test/ui/mir/issue-60390.rs b/src/test/ui/mir/issue-60390.rs new file mode 100644 index 000000000..fd9d6b46d --- /dev/null +++ b/src/test/ui/mir/issue-60390.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for #60390, this ICE requires `--emit=mir` flag. + +fn main() { + enum Inner { Member(u32) }; + Inner::Member(0); +} diff --git a/src/test/ui/mir/issue-66851.rs b/src/test/ui/mir/issue-66851.rs new file mode 100644 index 000000000..878ad4e47 --- /dev/null +++ b/src/test/ui/mir/issue-66851.rs @@ -0,0 +1,20 @@ +// This used to mis-compile because the mir-opt `SimplifyArmIdentity` +// did not check that the types matched up in the `Ok(r)` branch. +// +// run-pass +// compile-flags: -Zmir-opt-level=3 + +#[derive(Debug, PartialEq, Eq)] +enum SpecialsRes { Res(u64) } + +fn e103() -> SpecialsRes { + if let Ok(r) = "1".parse() { + SpecialsRes::Res(r) + } else { + SpecialsRes::Res(42) + } +} + +fn main() { + assert_eq!(e103(), SpecialsRes::Res(1)); +} diff --git a/src/test/ui/mir/issue-66930.rs b/src/test/ui/mir/issue-66930.rs new file mode 100644 index 000000000..5f9eb2bf4 --- /dev/null +++ b/src/test/ui/mir/issue-66930.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for #66930, this ICE requires `--emit=mir` flag. + +static UTF8_CHAR_WIDTH: [u8; 0] = []; + +pub fn utf8_char_width(b: u8) -> usize { + UTF8_CHAR_WIDTH[b as usize] as usize +} + +fn main() {} diff --git a/src/test/ui/mir/issue-67639-normalization-ice.rs b/src/test/ui/mir/issue-67639-normalization-ice.rs new file mode 100644 index 000000000..71150a80b --- /dev/null +++ b/src/test/ui/mir/issue-67639-normalization-ice.rs @@ -0,0 +1,34 @@ +// compile-flags: -Z mir-opt-level=4 +// build-pass + +// This used to ICE in const-prop due +// to an empty ParamEnv being used during normalization +// of a generic type + + +fn main() { + join_all::(); +} + +trait Foo { + type Item; +} + +impl Foo for u32 { + type Item = u8; +} + +trait Bar { + type Item2; +} + +impl Bar for u8 { + type Item2 = u64; +} + +fn join_all() +where I: Foo, + I::Item: Bar +{ + Vec::<::Item2>::new(); // ICE occurs processing this line +} diff --git a/src/test/ui/mir/issue-67710-inline-projection.rs b/src/test/ui/mir/issue-67710-inline-projection.rs new file mode 100644 index 000000000..1ff6b4d62 --- /dev/null +++ b/src/test/ui/mir/issue-67710-inline-projection.rs @@ -0,0 +1,17 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass + +// This used to ICE due to the inling pass not examining projections +// for references to locals + +pub fn parse(version: ()) { + p(&b'.', b"0"); +} +#[inline(always)] +fn p(byte: &u8, s: &[u8]) { + !(s[0] == *byte); +} + +fn main() { + parse(()); +} diff --git a/src/test/ui/mir/issue-67947.rs b/src/test/ui/mir/issue-67947.rs new file mode 100644 index 000000000..f73d38f80 --- /dev/null +++ b/src/test/ui/mir/issue-67947.rs @@ -0,0 +1,7 @@ +struct Bug { + A: [(); { *"" }.len()], + //~^ ERROR: cannot move a value of type `str` + //~| ERROR: cannot move out of a shared reference +} + +fn main() {} diff --git a/src/test/ui/mir/issue-67947.stderr b/src/test/ui/mir/issue-67947.stderr new file mode 100644 index 000000000..7697a411e --- /dev/null +++ b/src/test/ui/mir/issue-67947.stderr @@ -0,0 +1,16 @@ +error[E0161]: cannot move a value of type `str` + --> $DIR/issue-67947.rs:2:13 + | +LL | A: [(); { *"" }.len()], + | ^^^^^^^ the size of `str` cannot be statically determined + +error[E0507]: cannot move out of a shared reference + --> $DIR/issue-67947.rs:2:15 + | +LL | A: [(); { *"" }.len()], + | ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0161, E0507. +For more information about an error, try `rustc --explain E0161`. diff --git a/src/test/ui/mir/issue-68841.rs b/src/test/ui/mir/issue-68841.rs new file mode 100644 index 000000000..550bd452a --- /dev/null +++ b/src/test/ui/mir/issue-68841.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z mir-opt-level=3 +// edition:2018 +// build-pass + +#![feature(async_closure)] + +use std::future::Future; + +fn async_closure() -> impl Future { + (async move || -> u8 { 42 })() +} + +fn main() { + let _fut = async_closure(); +} diff --git a/src/test/ui/mir/issue-71793-inline-args-storage.rs b/src/test/ui/mir/issue-71793-inline-args-storage.rs new file mode 100644 index 000000000..18f2e38d1 --- /dev/null +++ b/src/test/ui/mir/issue-71793-inline-args-storage.rs @@ -0,0 +1,16 @@ +// Verifies that inliner emits StorageLive & StorageDead when introducing +// temporaries for arguments, so that they don't become part of the generator. +// Regression test for #71793. +// +// check-pass +// edition:2018 +// compile-args: -Zmir-opt-level=3 + +#![crate_type = "lib"] + +pub async fn connect() {} + +pub async fn connect_many() { + Vec::::new().first().ok_or("").unwrap(); + connect().await; +} diff --git a/src/test/ui/mir/issue-73914.rs b/src/test/ui/mir/issue-73914.rs new file mode 100644 index 000000000..1e99faade --- /dev/null +++ b/src/test/ui/mir/issue-73914.rs @@ -0,0 +1,30 @@ +// build-pass +// compile-flags:-Copt-level=0 +// edition:2018 + +struct S(std::marker::PhantomData); + +impl std::ops::Deref for S { + type Target = T; + + fn deref(&self) -> &Self::Target { + todo!() + } +} +impl std::ops::DerefMut for S { + fn deref_mut(&mut self) -> &mut Self::Target { + todo!() + } +} + +async fn new() -> S { + todo!() +} + +async fn crash() { + *new().await = 1 + 1; +} + +fn main() { + let _ = crash(); +} diff --git a/src/test/ui/mir/issue-74739.rs b/src/test/ui/mir/issue-74739.rs new file mode 100644 index 000000000..03622358a --- /dev/null +++ b/src/test/ui/mir/issue-74739.rs @@ -0,0 +1,14 @@ +// compile-flags: -O +// run-pass + +struct Foo { + x: i32, +} + +pub fn main() { + let mut foo = Foo { x: 42 }; + let x = &mut foo.x; + *x = 13; + let y = foo; + assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug +} diff --git a/src/test/ui/mir/issue-75053.rs b/src/test/ui/mir/issue-75053.rs new file mode 100644 index 000000000..cb56eaa0b --- /dev/null +++ b/src/test/ui/mir/issue-75053.rs @@ -0,0 +1,49 @@ +// compile-flags: -Z mir-opt-level=3 + +#![feature(type_alias_impl_trait, rustc_attrs)] + +use std::marker::PhantomData; + +trait MyIndex { + type O; + fn my_index(self) -> Self::O; +} +trait MyFrom: Sized { + type Error; + fn my_from(value: T) -> Result; +} + +trait F {} +impl F for () {} +type DummyT = impl F; +fn _dummy_t() -> DummyT {} + +struct Phantom1(PhantomData); +struct Phantom2(PhantomData); +struct Scope(Phantom2>); + +impl Scope { + fn new() -> Self { + unimplemented!() + } +} + +impl MyFrom> for Phantom1 { + type Error = (); + fn my_from(_: Phantom2) -> Result { + unimplemented!() + } +} + +impl>>, U> MyIndex> for Scope { + type O = T; + fn my_index(self) -> Self::O { + MyFrom::my_from(self.0).ok().unwrap() + } +} + +#[rustc_error] +fn main() { + //~^ ERROR + let _pos: Phantom1> = Scope::new().my_index(); +} diff --git a/src/test/ui/mir/issue-75053.stderr b/src/test/ui/mir/issue-75053.stderr new file mode 100644 index 000000000..64e59e6c4 --- /dev/null +++ b/src/test/ui/mir/issue-75053.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-75053.rs:46:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/mir/issue-75419-validation-impl-trait.rs b/src/test/ui/mir/issue-75419-validation-impl-trait.rs new file mode 100644 index 000000000..a8741befb --- /dev/null +++ b/src/test/ui/mir/issue-75419-validation-impl-trait.rs @@ -0,0 +1,13 @@ +// build-pass + +// This used to fail MIR validation due to the types on both sides of +// an assignment not being equal. +// The failure doesn't occur with a check-only build. + +fn iter_slice<'a, T>(xs: &'a [T]) -> impl Iterator { + xs.iter() +} + +fn main() { + iter_slice::<()> as fn(_) -> _; +} diff --git a/src/test/ui/mir/issue-76248.rs b/src/test/ui/mir/issue-76248.rs new file mode 100644 index 000000000..18473e79e --- /dev/null +++ b/src/test/ui/mir/issue-76248.rs @@ -0,0 +1,29 @@ +// This used to ICE during codegen after MIR inlining of g into f. +// The root cause was a missing fold of length constant in Rvalue::Repeat. +// Regression test for #76248. +// +// build-pass +// compile-flags: -Zmir-opt-level=3 + +const N: usize = 1; + +pub struct Elem { + pub x: [usize; N], + pub m: M, +} + +pub fn f() -> Elem<()> { + g(()) +} + +#[inline] +pub fn g(m: M) -> Elem { + Elem { + x: [0; N], + m, + } +} + +pub fn main() { + f(); +} diff --git a/src/test/ui/mir/issue-76375.rs b/src/test/ui/mir/issue-76375.rs new file mode 100644 index 000000000..e635caca9 --- /dev/null +++ b/src/test/ui/mir/issue-76375.rs @@ -0,0 +1,27 @@ +// Regression test for issue #76375. +// +// edition:2018 +// build-pass +// compile-flags: -Z mir-opt-level=3 +// aux-build:issue_76375_aux.rs + +#![crate_type = "lib"] + +extern crate issue_76375_aux; + +pub async fn g() { + issue_76375_aux::copy_prop(true); + h().await; +} + +pub async fn u() { + let b = [0u8; 32]; + let mut i = 0; + while i != 10 { + issue_76375_aux::dest_prop(&b); + h().await; + i += 1; + } +} + +pub async fn h() {} diff --git a/src/test/ui/mir/issue-76740-copy-propagation.rs b/src/test/ui/mir/issue-76740-copy-propagation.rs new file mode 100644 index 000000000..1d4ec1176 --- /dev/null +++ b/src/test/ui/mir/issue-76740-copy-propagation.rs @@ -0,0 +1,30 @@ +// Regression test for issue #76740. +// run-pass +// compile-flags: -Zmir-opt-level=4 + +#[derive(Copy, Clone)] +pub struct V([usize; 4]); + +impl V { + fn new() -> Self { + V([0; 4]) + } + + #[inline(never)] + fn check(mut self) { + assert_eq!(self.0[0], 0); + self.0[0] = 1; + } +} + +fn main() { + let v = V::new(); + let mut i = 0; + while i != 10 { + // Copy propagation incorrectly assumed that Operand::Move does not + // mutate the local, and used the same v for each V::check call, + // rather than a copy. + v.check(); + i += 1; + } +} diff --git a/src/test/ui/mir/issue-76803-branches-not-same.rs b/src/test/ui/mir/issue-76803-branches-not-same.rs new file mode 100644 index 000000000..a6a576220 --- /dev/null +++ b/src/test/ui/mir/issue-76803-branches-not-same.rs @@ -0,0 +1,19 @@ +// run-pass + +#[derive(Debug, Eq, PartialEq)] +pub enum Type { + A, + B, +} + + +pub fn encode(v: Type) -> Type { + match v { + Type::A => Type::B, + _ => v, + } +} + +fn main() { + assert_eq!(Type::B, encode(Type::A)); +} diff --git a/src/test/ui/mir/issue-77359-simplify-arm-identity.rs b/src/test/ui/mir/issue-77359-simplify-arm-identity.rs new file mode 100644 index 000000000..e58ba50a9 --- /dev/null +++ b/src/test/ui/mir/issue-77359-simplify-arm-identity.rs @@ -0,0 +1,35 @@ +// run-pass + +#![allow(dead_code)] + +#[derive(Debug)] +enum MyEnum { + Variant1(Vec), + Variant2, + Variant3, + Variant4, +} + +fn f(arg1: &bool, arg2: &bool, arg3: bool) -> MyStruct { + if *arg1 { + println!("{:?}", f(&arg2, arg2, arg3)); + MyStruct(None) + } else { + match if arg3 { Some(MyEnum::Variant3) } else { None } { + Some(t) => { + let ah = t; + return MyStruct(Some(ah)); + } + _ => MyStruct(None) + } + } +} + +#[derive(Debug)] +struct MyStruct(Option); + +fn main() { + let arg1 = true; + let arg2 = false; + f(&arg1, &arg2, true); +} diff --git a/src/test/ui/mir/issue-77911.rs b/src/test/ui/mir/issue-77911.rs new file mode 100644 index 000000000..acf4c2054 --- /dev/null +++ b/src/test/ui/mir/issue-77911.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass + +use std::fs::File; +use std::io::{BufRead, BufReader}; + +fn file_lines() -> impl Iterator { + BufReader::new(File::open("").unwrap()) + .lines() + .map(Result::unwrap) +} + +fn main() { + for _ in file_lines() {} +} diff --git a/src/test/ui/mir/issue-78496.rs b/src/test/ui/mir/issue-78496.rs new file mode 100644 index 000000000..a0d1f5a78 --- /dev/null +++ b/src/test/ui/mir/issue-78496.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -Z mir-opt-level=3 -C opt-level=0 + +// example from #78496 +pub enum E<'a> { + Empty, + Some(&'a E<'a>), +} + +fn f(e: &E) -> u32 { + if let E::Some(E::Some(_)) = e { 1 } else { 2 } +} + +fn main() { + assert_eq!(f(&E::Empty), 2); +} diff --git a/src/test/ui/mir/issue-80949.rs b/src/test/ui/mir/issue-80949.rs new file mode 100644 index 000000000..7e34a4f5c --- /dev/null +++ b/src/test/ui/mir/issue-80949.rs @@ -0,0 +1,34 @@ +// build-pass + +trait Trait { type Item; } + +impl<'a, X> Trait for &'a Vec { + type Item = &'a X; +} + +impl Trait for Box> { + type Item = X; +} + +fn make_dyn_trait(_: &()) -> Box> { + todo!() +} + +fn diff<'a, M, N, S>(_: N, _: S) +where + M: 'a, + N: Trait, + S: Trait, +{ + todo!() +} + +fn may_panic(_: X) { } + +fn main() { + let dyn_trait = make_dyn_trait(&()); + let storage = vec![()]; + let _x = may_panic(()); + let storage_ref = &storage; + diff(dyn_trait, storage_ref); +} diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs new file mode 100644 index 000000000..0086d2ec1 --- /dev/null +++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -0,0 +1,10 @@ +// Test that when in MIR the amount of local_decls and amount of normalized_input_tys don't match +// that an out-of-bounds access does not occur. +#![feature(c_variadic)] + +fn main() {} + +fn foo(_: Bar, ...) -> impl {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR cannot find type `Bar` in this scope +//~| ERROR at least one trait must be specified diff --git a/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr new file mode 100644 index 000000000..4eb3adc8b --- /dev/null +++ b/src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -0,0 +1,21 @@ +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^ + +error: at least one trait must be specified + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:24 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^^ + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:11 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/mir/issue-89485.rs b/src/test/ui/mir/issue-89485.rs new file mode 100644 index 000000000..cb507eefe --- /dev/null +++ b/src/test/ui/mir/issue-89485.rs @@ -0,0 +1,18 @@ +// Regression test for issue #89485. + +// run-pass + +#[derive(Debug, Eq, PartialEq)] +pub enum Type { + A = 1, + B = 2, +} +pub fn encode(v: Type) -> Type { + match v { + Type::A => Type::B, + _ => v, + } +} +fn main() { + assert_eq!(Type::B, encode(Type::A)); +} diff --git a/src/test/ui/mir/issue-91745.rs b/src/test/ui/mir/issue-91745.rs new file mode 100644 index 000000000..ca3d66b1c --- /dev/null +++ b/src/test/ui/mir/issue-91745.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Foo { + type Bar; +} + +pub trait Broken { + type Assoc; + fn broken(&self) where Self::Assoc: Foo; +} + +impl Broken for T { + type Assoc = (); + fn broken(&self) where Self::Assoc: Foo { + let _x: ::Bar; + } +} + +fn main() { + let _m: &dyn Broken = &(); +} diff --git a/src/test/ui/mir/issue-92893.rs b/src/test/ui/mir/issue-92893.rs new file mode 100644 index 000000000..635050f37 --- /dev/null +++ b/src/test/ui/mir/issue-92893.rs @@ -0,0 +1,8 @@ +struct Bug { + //~^ `let` expressions are not supported here + //~| `let` expressions in this position are unstable [E0658] + //~| expected expression, found `let` statement + a: A +} + +fn main() {} diff --git a/src/test/ui/mir/issue-92893.stderr b/src/test/ui/mir/issue-92893.stderr new file mode 100644 index 000000000..4a0fcce31 --- /dev/null +++ b/src/test/ui/mir/issue-92893.stderr @@ -0,0 +1,26 @@ +error: expected expression, found `let` statement + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^ + +error: `let` expressions are not supported here + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs b/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs new file mode 100644 index 000000000..cd6c5bf27 --- /dev/null +++ b/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Zvalidate-mir + +fn foo(_a: &str) {} + +fn main() { + let x = foo as fn(&'static str); + + let _ = x == foo; +} diff --git a/src/test/ui/mir/issue66339.rs b/src/test/ui/mir/issue66339.rs new file mode 100644 index 000000000..2507af38c --- /dev/null +++ b/src/test/ui/mir/issue66339.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass + +// This used to ICE in const-prop + +fn foo() { + let bar = |_| { }; + let _ = bar("a"); +} + +fn main() { + foo(); +} diff --git a/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs new file mode 100644 index 000000000..e36e8bd74 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs @@ -0,0 +1,11 @@ +// Checks that we can build a clone shim for array with generic size. +// Regression test for issue #79269. +// +// build-pass +// compile-flags: -Zmir-opt-level=3 -Zvalidate-mir +#[derive(Clone)] +struct Array([T; N]); + +fn main() { + let _ = Array([0u32, 1u32, 2u32]).clone(); +} diff --git a/src/test/ui/mir/mir-inlining/ice-issue-45493.rs b/src/test/ui/mir/mir-inlining/ice-issue-45493.rs new file mode 100644 index 000000000..04a23212e --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-45493.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +trait Array { + type Item; +} + +fn foo() { + let _: *mut A::Item = std::ptr::null_mut(); +} + +struct Foo; +impl Array for Foo { type Item = i32; } + +fn main() { + foo::(); +} diff --git a/src/test/ui/mir/mir-inlining/ice-issue-45885.rs b/src/test/ui/mir/mir-inlining/ice-issue-45885.rs new file mode 100644 index 000000000..09b1279ef --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-45885.rs @@ -0,0 +1,29 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +pub enum Enum { + A, + B, +} + +trait SliceIndex { + type Output; + fn get(&self) -> &Self::Output; +} + +impl SliceIndex for usize { + type Output = Enum; + #[inline(never)] + fn get(&self) -> &Enum { + &Enum::A + } +} + +#[inline(always)] +fn index(t: &T) -> &T::Output { + t.get() +} + +fn main() { + match *index(&0) { Enum::A => true, _ => false }; +} diff --git a/src/test/ui/mir/mir-inlining/ice-issue-68347.rs b/src/test/ui/mir/mir-inlining/ice-issue-68347.rs new file mode 100644 index 000000000..7c1352509 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-68347.rs @@ -0,0 +1,28 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 +pub fn main() { + let _x: fn() = handle_debug_column; +} + +fn handle_debug_column() { + let sampler = sample_columns(); + + let foo = || { + sampler.get(17); + }; + foo(); +} + +fn sample_columns() -> impl Sampler { + ColumnGen {} +} + +struct ColumnGen {} + +trait Sampler { + fn get(&self, index: i32); +} + +impl Sampler for ColumnGen { + fn get(&self, _index: i32) {} +} diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs b/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs new file mode 100644 index 000000000..ef05ff9ce --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +// Previously ICEd because we did not normalize during inlining, +// see https://github.com/rust-lang/rust/pull/77306 for more discussion. + +pub fn write() { + create()() +} + +pub fn create() -> impl FnOnce() { + || () +} + +fn main() { + write(); +} diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs b/src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs new file mode 100644 index 000000000..cb2084013 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs @@ -0,0 +1,32 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +struct Cursor {} +struct TokenTree {} + +impl Iterator for Cursor { + type Item = TokenTree; + + fn next(&mut self) -> Option { + None + } +} + +fn tokenstream_probably_equal_for_proc_macro() { + fn break_tokens(_tree: TokenTree) -> impl Iterator { + let token_trees: Vec = vec![]; + token_trees.into_iter() + } + + let c1 = Cursor {}; + let c2 = Cursor {}; + + let mut t1 = c1.flat_map(break_tokens); + let mut t2 = c2.flat_map(break_tokens); + + for (_t1, _t2) in t1.by_ref().zip(t2.by_ref()) {} +} + +fn main() { + tokenstream_probably_equal_for_proc_macro(); +} diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77564.rs b/src/test/ui/mir/mir-inlining/ice-issue-77564.rs new file mode 100644 index 000000000..0d3fbfe5d --- /dev/null +++ b/src/test/ui/mir/mir-inlining/ice-issue-77564.rs @@ -0,0 +1,38 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +use std::mem::MaybeUninit; +const N: usize = 2; + +trait CollectArray: Iterator { + fn inner_array(&mut self) -> [A; N]; + fn collect_array(&mut self) -> [A; N] { + let result = self.inner_array(); + assert!(self.next().is_none()); + result + } +} + +impl CollectArray for I +where + I: Iterator, +{ + fn inner_array(&mut self) -> [A; N] { + let mut result: [MaybeUninit; N] = unsafe { MaybeUninit::uninit().assume_init() }; + for (dest, item) in result.iter_mut().zip(self) { + *dest = MaybeUninit::new(item); + } + let temp_ptr: *const [MaybeUninit; N] = &result; + unsafe { std::ptr::read(temp_ptr as *const [A; N]) } + } +} + +fn main() { + assert_eq!( + [[1, 2], [3, 4]] + .iter() + .map(|row| row.iter().collect_array()) + .collect_array(), + [[&1, &2], [&3, &4]] + ); +} diff --git a/src/test/ui/mir/mir-inlining/no-trait-method-issue-40473.rs b/src/test/ui/mir/mir-inlining/no-trait-method-issue-40473.rs new file mode 100644 index 000000000..8b3cb703d --- /dev/null +++ b/src/test/ui/mir/mir-inlining/no-trait-method-issue-40473.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 +pub trait Foo { + fn bar(&self) -> usize { 2 } +} + +impl Foo for () { + fn bar(&self) -> usize { 3 } +} + +// Test a case where MIR would inline the default trait method +// instead of bailing out. Issue #40473. +fn main() { + let result = ().bar(); + assert_eq!(result, 3); +} diff --git a/src/test/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs b/src/test/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs new file mode 100644 index 000000000..e26206826 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags: -Z mir-opt-level=3 -C opt-level=0 -C debuginfo=2 + +#[inline(never)] +pub fn foo(bar: usize) -> usize { + std::convert::identity(bar) +} + +fn main() { + foo(0); +} diff --git a/src/test/ui/mir/mir-typeck-normalize-fn-sig.rs b/src/test/ui/mir/mir-typeck-normalize-fn-sig.rs new file mode 100644 index 000000000..bdd9321af --- /dev/null +++ b/src/test/ui/mir/mir-typeck-normalize-fn-sig.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_variables)] +// This code was creating an ICE in the MIR type checker. The reason +// is that we are reifying a reference to a function (`foo::<'x>`), +// which involves extracting its signature, but we were not +// normalizing the signature afterwards. As a result, we sometimes got +// errors around the `>::Value`, which can be +// normalized to `f64`. + +#![allow(dead_code)] + +trait Foo<'x> { + type Value; +} + +impl<'x> Foo<'x> for u32 { + type Value = f64; +} + +struct Providers<'x> { + foo: for<'y> fn(x: &'x u32, y: &'y u32) -> >::Value, +} + +fn foo<'y, 'x: 'x>(x: &'x u32, y: &'y u32) -> >::Value { + *x as f64 +} + +fn main() { + Providers { foo }; +} diff --git a/src/test/ui/mir/mir_adt_construction.rs b/src/test/ui/mir/mir_adt_construction.rs new file mode 100644 index 000000000..9fb5896de --- /dev/null +++ b/src/test/ui/mir/mir_adt_construction.rs @@ -0,0 +1,92 @@ +// run-pass +use std::fmt; + +#[repr(C)] +enum CEnum { + Hello = 30, + World = 60 +} + +fn test1(c: CEnum) -> i32 { + let c2 = CEnum::Hello; + match (c, c2) { + (CEnum::Hello, CEnum::Hello) => 42, + (CEnum::World, CEnum::Hello) => 0, + _ => 1 + } +} + +#[repr(packed)] +struct Pakd { + a: u64, + b: u32, + c: u16, + d: u8, + e: () +} + +// It is unsafe to use #[derive(Debug)] on a packed struct because the code generated by the derive +// macro takes references to the fields instead of accessing them directly. +impl fmt::Debug for Pakd { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // It's important that we load the fields into locals by-value here. This will do safe + // unaligned loads into the locals, then pass references to the properly-aligned locals to + // the formatting code. + let Pakd { a, b, c, d, e } = *self; + f.debug_struct("Pakd") + .field("a", &a) + .field("b", &b) + .field("c", &c) + .field("d", &d) + .field("e", &e) + .finish() + } +} + +// It is unsafe to use #[derive(PartialEq)] on a packed struct because the code generated by the +// derive macro takes references to the fields instead of accessing them directly. +impl PartialEq for Pakd { + fn eq(&self, other: &Pakd) -> bool { + self.a == other.a && + self.b == other.b && + self.c == other.c && + self.d == other.d && + self.e == other.e + } +} + +impl Drop for Pakd { + fn drop(&mut self) {} +} + +fn test2() -> Pakd { + Pakd { a: 42, b: 42, c: 42, d: 42, e: () } +} + +#[derive(PartialEq, Debug)] +struct TupleLike(u64, u32); + +fn test3() -> TupleLike { + TupleLike(42, 42) +} + +fn test4(x: fn(u64, u32) -> TupleLike) -> (TupleLike, TupleLike) { + let y = TupleLike; + (x(42, 84), y(42, 84)) +} + +fn test5(x: fn(u32) -> Option) -> (Option, Option) { + let y = Some; + (x(42), y(42)) +} + +fn main() { + assert_eq!(test1(CEnum::Hello), 42); + assert_eq!(test1(CEnum::World), 0); + assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () }); + assert_eq!(test3(), TupleLike(42, 42)); + let t4 = test4(TupleLike); + assert_eq!(t4.0, t4.1); + let t5 = test5(Some); + assert_eq!(t5.0, t5.1); +} diff --git a/src/test/ui/mir/mir_ascription_coercion.rs b/src/test/ui/mir/mir_ascription_coercion.rs new file mode 100644 index 000000000..0ebd20e97 --- /dev/null +++ b/src/test/ui/mir/mir_ascription_coercion.rs @@ -0,0 +1,10 @@ +// run-pass +// Tests that the result of type ascription has adjustments applied + +#![feature(type_ascription)] + +fn main() { + let x = [1, 2, 3]; + // The RHS should coerce to &[i32] + let _y : &[i32] = &x : &[i32; 3]; +} diff --git a/src/test/ui/mir/mir_assign_eval_order.rs b/src/test/ui/mir/mir_assign_eval_order.rs new file mode 100644 index 000000000..799bf7f3a --- /dev/null +++ b/src/test/ui/mir/mir_assign_eval_order.rs @@ -0,0 +1,67 @@ +// Test evaluation order of assignment expressions is right to left. + +// run-pass + +// We would previously not finish evaluating borrow and FRU expressions before +// starting on the LHS + +struct S(i32); + +fn evaluate_reborrow_before_assign() { + let mut x = &1; + let y = &mut &2; + let z = &3; + // There's an implicit reborrow of `x` on the right-hand side of the + // assignment. Note that writing an explicit reborrow would not show this + // bug, as now there would be two reborrows on the right-hand side and at + // least one of them would happen before the left-hand side is evaluated. + *{ x = z; &mut *y } = x; + assert_eq!(*x, 3); + assert_eq!(**y, 1); // y should be assigned the original value of `x`. +} + +fn evaluate_mut_reborrow_before_assign() { + let mut x = &mut 1; + let y = &mut &mut 2; + let z = &mut 3; + *{ x = z; &mut *y } = x; + assert_eq!(*x, 3); + assert_eq!(**y, 1); // y should be assigned the original value of `x`. +} + +// We should evaluate `x[2]` and borrow the value out *before* evaluating the +// LHS and changing its value. +fn evaluate_ref_to_temp_before_assign_slice() { + let mut x = &[S(0), S(1), S(2)][..]; + let y = &mut &S(7); + *{ x = &[S(3), S(4), S(5)]; &mut *y } = &x[2]; + assert_eq!(2, y.0); + assert_eq!(5, x[2].0); +} + +// We should evaluate `x[2]` and copy the value out *before* evaluating the LHS +// and changing its value. +fn evaluate_fru_to_temp_before_assign_slice() { + let mut x = &[S(0), S(1), S(2)][..]; + let y = &mut S(7); + *{ x = &[S(3), S(4), S(5)]; &mut *y } = S { ..x[2] }; + assert_eq!(2, y.0); + assert_eq!(5, x[2].0); +} + +// We should evaluate `*x` and copy the value out *before* evaluating the LHS +// and dropping `x`. +fn evaluate_fru_to_temp_before_assign_box() { + let x = Box::new(S(0)); + let y = &mut S(1); + *{ drop(x); &mut *y } = S { ..*x }; + assert_eq!(0, y.0); +} + +fn main() { + evaluate_reborrow_before_assign(); + evaluate_mut_reborrow_before_assign(); + evaluate_ref_to_temp_before_assign_slice(); + evaluate_fru_to_temp_before_assign_slice(); + evaluate_fru_to_temp_before_assign_box(); +} diff --git a/src/test/ui/mir/mir_augmented_assignments.rs b/src/test/ui/mir/mir_augmented_assignments.rs new file mode 100644 index 000000000..44454f8f4 --- /dev/null +++ b/src/test/ui/mir/mir_augmented_assignments.rs @@ -0,0 +1,160 @@ +// run-pass +use std::mem; +use std::ops::{ + AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, RemAssign, + ShlAssign, ShrAssign, SubAssign, +}; + +#[derive(Debug, PartialEq)] +struct Int(i32); + +struct Slice([i32]); + +impl Slice { + fn new(slice: &mut [i32]) -> &mut Slice { + unsafe { + mem::transmute(slice) + } + } +} + +fn main() { + main_mir(); +} + +fn main_mir() { + let mut x = Int(1); + + x += Int(2); + assert_eq!(x, Int(0b11)); + + x &= Int(0b01); + assert_eq!(x, Int(0b01)); + + x |= Int(0b10); + assert_eq!(x, Int(0b11)); + + x ^= Int(0b01); + assert_eq!(x, Int(0b10)); + + x /= Int(2); + assert_eq!(x, Int(1)); + + x *= Int(3); + assert_eq!(x, Int(3)); + + x %= Int(2); + assert_eq!(x, Int(1)); + + // overloaded RHS + x <<= 1u8; + assert_eq!(x, Int(2)); + + x <<= 1u16; + assert_eq!(x, Int(4)); + + x >>= 1u8; + assert_eq!(x, Int(2)); + + x >>= 1u16; + assert_eq!(x, Int(1)); + + x -= Int(1); + assert_eq!(x, Int(0)); + + // indexed LHS + // FIXME(mir-drop): use the vec![..] macro + let mut v = Vec::new(); + v.push(Int(1)); + v.push(Int(2)); + v[0] += Int(2); + assert_eq!(v[0], Int(3)); + + // unsized RHS + let mut array = [0, 1, 2]; + *Slice::new(&mut array) += 1; + assert_eq!(array[0], 1); + assert_eq!(array[1], 2); + assert_eq!(array[2], 3); + +} + +impl AddAssign for Int { + fn add_assign(&mut self, rhs: Int) { + self.0 += rhs.0; + } +} + +impl BitAndAssign for Int { + fn bitand_assign(&mut self, rhs: Int) { + self.0 &= rhs.0; + } +} + +impl BitOrAssign for Int { + fn bitor_assign(&mut self, rhs: Int) { + self.0 |= rhs.0; + } +} + +impl BitXorAssign for Int { + fn bitxor_assign(&mut self, rhs: Int) { + self.0 ^= rhs.0; + } +} + +impl DivAssign for Int { + fn div_assign(&mut self, rhs: Int) { + self.0 /= rhs.0; + } +} + +impl MulAssign for Int { + fn mul_assign(&mut self, rhs: Int) { + self.0 *= rhs.0; + } +} + +impl RemAssign for Int { + fn rem_assign(&mut self, rhs: Int) { + self.0 %= rhs.0; + } +} + +impl ShlAssign for Int { + fn shl_assign(&mut self, rhs: u8) { + self.0 <<= rhs; + } +} + +impl ShlAssign for Int { + fn shl_assign(&mut self, rhs: u16) { + self.0 <<= rhs; + } +} + +impl ShrAssign for Int { + fn shr_assign(&mut self, rhs: u8) { + self.0 >>= rhs; + } +} + +impl ShrAssign for Int { + fn shr_assign(&mut self, rhs: u16) { + self.0 >>= rhs; + } +} + +impl SubAssign for Int { + fn sub_assign(&mut self, rhs: Int) { + self.0 -= rhs.0; + } +} + +impl AddAssign for Slice { + fn add_assign(&mut self, rhs: i32) { + for lhs in &mut self.0 { + *lhs += rhs; + } + } +} diff --git a/src/test/ui/mir/mir_autoderef.rs b/src/test/ui/mir/mir_autoderef.rs new file mode 100644 index 000000000..a0e615a73 --- /dev/null +++ b/src/test/ui/mir/mir_autoderef.rs @@ -0,0 +1,28 @@ +// run-pass +use std::ops::{Deref, DerefMut}; + +pub struct MyRef(u32); + +impl Deref for MyRef { + type Target = u32; + fn deref(&self) -> &u32 { &self.0 } +} + +impl DerefMut for MyRef { + fn deref_mut(&mut self) -> &mut u32 { &mut self.0 } +} + + +fn deref(x: &MyRef) -> &u32 { + x +} + +fn deref_mut(x: &mut MyRef) -> &mut u32 { + x +} + +fn main() { + let mut r = MyRef(2); + assert_eq!(deref(&r) as *const _, &r.0 as *const _); + assert_eq!(deref_mut(&mut r) as *mut _, &mut r.0 as *mut _); +} diff --git a/src/test/ui/mir/mir_boxing.rs b/src/test/ui/mir/mir_boxing.rs new file mode 100644 index 000000000..83e1cfb64 --- /dev/null +++ b/src/test/ui/mir/mir_boxing.rs @@ -0,0 +1,10 @@ +// run-pass +#![feature(box_syntax)] + +fn test() -> Box { + box 42 +} + +fn main() { + assert_eq!(*test(), 42); +} diff --git a/src/test/ui/mir/mir_build_match_comparisons.rs b/src/test/ui/mir/mir_build_match_comparisons.rs new file mode 100644 index 000000000..045700557 --- /dev/null +++ b/src/test/ui/mir/mir_build_match_comparisons.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(dead_code)] +fn test1(x: i8) -> i32 { + match x { + 1..=10 => 0, + _ => 1, + } +} + +const U: Option = Some(10); +const S: &'static str = "hello"; + +fn test2(x: i8) -> i32 { + match Some(x) { + U => 0, + _ => 1, + } +} + +fn test3(x: &'static str) -> i32 { + match x { + S => 0, + _ => 1, + } +} + +enum Opt { + Some { v: T }, + None +} + +fn test4(x: u64) -> i32 { + let opt = Opt::Some{ v: x }; + match opt { + Opt::Some { v: 10 } => 0, + _ => 1, + } +} + + +fn main() { + assert_eq!(test1(0), 1); + assert_eq!(test1(1), 0); + assert_eq!(test1(2), 0); + assert_eq!(test1(5), 0); + assert_eq!(test1(9), 0); + assert_eq!(test1(10), 0); + assert_eq!(test1(11), 1); + assert_eq!(test1(20), 1); + assert_eq!(test2(10), 0); + assert_eq!(test2(0), 1); + assert_eq!(test2(20), 1); + assert_eq!(test3("hello"), 0); + assert_eq!(test3(""), 1); + assert_eq!(test3("world"), 1); + assert_eq!(test4(10), 0); + assert_eq!(test4(0), 1); + assert_eq!(test4(20), 1); +} diff --git a/src/test/ui/mir/mir_call_with_associated_type.rs b/src/test/ui/mir/mir_call_with_associated_type.rs new file mode 100644 index 000000000..7103533e1 --- /dev/null +++ b/src/test/ui/mir/mir_call_with_associated_type.rs @@ -0,0 +1,16 @@ +// run-pass +trait Trait { + type Type; +} + +impl<'a> Trait for &'a () { + type Type = u32; +} + +fn foo<'a>(t: <&'a () as Trait>::Type) -> <&'a () as Trait>::Type { + t +} + +fn main() { + assert_eq!(foo(4), 4); +} diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs new file mode 100644 index 000000000..42eaab77d --- /dev/null +++ b/src/test/ui/mir/mir_calls_to_shims.rs @@ -0,0 +1,50 @@ +// run-pass +// needs-unwind +// ignore-wasm32-bare compiled with panic=abort by default + +#![feature(fn_traits)] +#![feature(never_type)] + +use std::panic; + +fn foo(x: u32, y: u32) -> u32 { x/y } +fn foo_diverges() -> ! { panic!() } + +fn test_fn_ptr(mut t: T) + where T: Fn(u32, u32) -> u32, +{ + let as_fn = >::call; + assert_eq!(as_fn(&t, (9, 3)), 3); + let as_fn_mut = >::call_mut; + assert_eq!(as_fn_mut(&mut t, (18, 3)), 6); + let as_fn_once = >::call_once; + assert_eq!(as_fn_once(t, (24, 3)), 8); +} + +fn assert_panics(f: F) where F: FnOnce() { + let f = panic::AssertUnwindSafe(f); + let result = panic::catch_unwind(move || { + f.0() + }); + if let Ok(..) = result { + panic!("diverging function returned"); + } +} + +fn test_fn_ptr_panic(mut t: T) + where T: Fn() -> ! +{ + let as_fn = >::call; + assert_panics(|| as_fn(&t, ())); + let as_fn_mut = >::call_mut; + assert_panics(|| as_fn_mut(&mut t, ())); + let as_fn_once = >::call_once; + assert_panics(|| as_fn_once(t, ())); +} + +fn main() { + test_fn_ptr(foo); + test_fn_ptr(foo as fn(u32, u32) -> u32); + test_fn_ptr_panic(foo_diverges); + test_fn_ptr_panic(foo_diverges as fn() -> !); +} diff --git a/src/test/ui/mir/mir_cast_fn_ret.rs b/src/test/ui/mir/mir_cast_fn_ret.rs new file mode 100644 index 000000000..4574dbd85 --- /dev/null +++ b/src/test/ui/mir/mir_cast_fn_ret.rs @@ -0,0 +1,23 @@ +// run-pass +#[allow(improper_ctypes_definitions)] +pub extern "C" fn tuple2() -> (u16, u8) { + (1, 2) +} + +#[allow(improper_ctypes_definitions)] +pub extern "C" fn tuple3() -> (u8, u8, u8) { + (1, 2, 3) +} + +pub fn test2() -> u8 { + tuple2().1 +} + +pub fn test3() -> u8 { + tuple3().2 +} + +fn main() { + assert_eq!(test2(), 2); + assert_eq!(test3(), 3); +} diff --git a/src/test/ui/mir/mir_codegen_array.rs b/src/test/ui/mir/mir_codegen_array.rs new file mode 100644 index 000000000..38e443d8e --- /dev/null +++ b/src/test/ui/mir/mir_codegen_array.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_mut)] +fn into_inner() -> [u64; 1024] { + let mut x = 10 + 20; + [x; 1024] +} + +fn main(){ + let x: &[u64] = &[30; 1024]; + assert_eq!(&into_inner()[..], x); +} diff --git a/src/test/ui/mir/mir_codegen_array_2.rs b/src/test/ui/mir/mir_codegen_array_2.rs new file mode 100644 index 000000000..03d3aa5ad --- /dev/null +++ b/src/test/ui/mir/mir_codegen_array_2.rs @@ -0,0 +1,9 @@ +// run-pass +fn into_inner(x: u64) -> [u64; 1024] { + [x; 2*4*8*16] +} + +fn main(){ + let x: &[u64] = &[42; 1024]; + assert_eq!(&into_inner(42)[..], x); +} diff --git a/src/test/ui/mir/mir_codegen_call_converging.rs b/src/test/ui/mir/mir_codegen_call_converging.rs new file mode 100644 index 000000000..9c340e4e0 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_call_converging.rs @@ -0,0 +1,17 @@ +// run-pass +fn converging_fn() -> u64 { + 43 +} + +fn mir() -> u64 { + let x; + loop { + x = converging_fn(); + break; + } + x +} + +fn main() { + assert_eq!(mir(), 43); +} diff --git a/src/test/ui/mir/mir_codegen_calls.rs b/src/test/ui/mir/mir_codegen_calls.rs new file mode 100644 index 000000000..6a5a4dace --- /dev/null +++ b/src/test/ui/mir/mir_codegen_calls.rs @@ -0,0 +1,192 @@ +// run-pass +#![feature(fn_traits, test)] + +extern crate test; + +fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) { + // Test passing a number of arguments including a fat pointer. + // Also returning via an out pointer + fn callee(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) { + (a, b, c) + } + callee(a, b, c) +} + +fn test2(a: isize) -> isize { + // Test passing a single argument. + // Not using out pointer. + fn callee(a: isize) -> isize { + a + } + callee(a) +} + +#[derive(PartialEq, Eq, Debug)] +struct Foo; +impl Foo { + fn inherent_method(&self, a: isize) -> isize { a } +} + +fn test3(x: &Foo, a: isize) -> isize { + // Test calling inherent method + x.inherent_method(a) +} + +trait Bar { + fn extension_method(&self, a: isize) -> isize { a } +} +impl Bar for Foo {} + +fn test4(x: &Foo, a: isize) -> isize { + // Test calling extension method + x.extension_method(a) +} + +fn test5(x: &dyn Bar, a: isize) -> isize { + // Test calling method on trait object + x.extension_method(a) +} + +fn test6(x: &T, a: isize) -> isize { + // Test calling extension method on generic callee + x.extension_method(a) +} + +trait One { + fn one() -> T; +} +impl One for isize { + fn one() -> isize { 1 } +} + +fn test7() -> isize { + // Test calling trait static method + ::one() +} + +struct Two; +impl Two { + fn two() -> isize { 2 } +} + +fn test8() -> isize { + // Test calling impl static method + Two::two() +} + +#[allow(improper_ctypes_definitions)] +extern "C" fn simple_extern(x: u32, y: (u32, u32)) -> u32 { + x + y.0 * y.1 +} + +fn test9() -> u32 { + simple_extern(41, (42, 43)) +} + +fn test_closure(f: &F, x: i32, y: i32) -> i32 + where F: Fn(i32, i32) -> i32 +{ + f(x, y) +} + +fn test_fn_object(f: &dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 { + f(x, y) +} + +fn test_fn_impl(f: &&dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 { + // This call goes through the Fn implementation for &Fn provided in + // core::ops::impls. It expands to a static Fn::call() that calls the + // Fn::call() implementation of the object shim underneath. + f(x, y) +} + +fn test_fn_direct_call(f: &F, x: i32, y: i32) -> i32 + where F: Fn(i32, i32) -> i32 +{ + f.call((x, y)) +} + +fn test_fn_const_call(f: &F) -> i32 + where F: Fn(i32, i32) -> i32 +{ + f.call((100, -1)) +} + +fn test_fn_nil_call(f: &F) -> i32 + where F: Fn() -> i32 +{ + f() +} + +fn test_fn_transmute_zst(x: ()) -> [(); 1] { + fn id(x: T) -> T {x} + + id(unsafe { + std::mem::transmute(x) + }) +} + +fn test_fn_ignored_pair() -> ((), ()) { + ((), ()) +} + +fn test_fn_ignored_pair_0() { + test_fn_ignored_pair().0 +} + +fn id(x: T) -> T { x } + +fn ignored_pair_named() -> (Foo, Foo) { + (Foo, Foo) +} + +fn test_fn_ignored_pair_named() -> (Foo, Foo) { + id(ignored_pair_named()) +} + +fn test_fn_nested_pair(x: &((f32, f32), u32)) -> (f32, f32) { + let y = *x; + let z = y.0; + (z.0, z.1) +} + +fn test_fn_const_arg_by_ref(mut a: [u64; 4]) -> u64 { + // Mutate the by-reference argument, which won't work with + // a non-immediate constant unless it's copied to the stack. + let a = test::black_box(&mut a); + a[0] += a[1]; + a[0] += a[2]; + a[0] += a[3]; + a[0] +} + +fn main() { + assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..])); + assert_eq!(test2(98), 98); + assert_eq!(test3(&Foo, 42), 42); + assert_eq!(test4(&Foo, 970), 970); + assert_eq!(test5(&Foo, 8576), 8576); + assert_eq!(test6(&Foo, 12367), 12367); + assert_eq!(test7(), 1); + assert_eq!(test8(), 2); + assert_eq!(test9(), 41 + 42 * 43); + + let r = 3; + let closure = |x: i32, y: i32| { r*(x + (y*2)) }; + assert_eq!(test_fn_const_call(&closure), 294); + assert_eq!(test_closure(&closure, 100, 1), 306); + let function_object = &closure as &dyn Fn(i32, i32) -> i32; + assert_eq!(test_fn_object(function_object, 100, 2), 312); + assert_eq!(test_fn_impl(&function_object, 100, 3), 318); + assert_eq!(test_fn_direct_call(&closure, 100, 4), 324); + + assert_eq!(test_fn_nil_call(&(|| 42)), 42); + assert_eq!(test_fn_transmute_zst(()), [()]); + + assert_eq!(test_fn_ignored_pair_0(), ()); + assert_eq!(test_fn_ignored_pair_named(), (Foo, Foo)); + assert_eq!(test_fn_nested_pair(&((1.0, 2.0), 0)), (1.0, 2.0)); + + const ARRAY: [u64; 4] = [1, 2, 3, 4]; + assert_eq!(test_fn_const_arg_by_ref(ARRAY), 1 + 2 + 3 + 4); +} diff --git a/src/test/ui/mir/mir_codegen_calls_converging_drops.rs b/src/test/ui/mir/mir_codegen_calls_converging_drops.rs new file mode 100644 index 000000000..b562f9308 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_calls_converging_drops.rs @@ -0,0 +1,26 @@ +// run-fail +// error-pattern:converging_fn called +// error-pattern:0 dropped +// error-pattern:exit +// ignore-emscripten no processes + +struct Droppable(u8); +impl Drop for Droppable { + fn drop(&mut self) { + eprintln!("{} dropped", self.0); + } +} + +fn converging_fn() { + eprintln!("converging_fn called"); +} + +fn mir(d: Droppable) { + converging_fn(); +} + +fn main() { + let d = Droppable(0); + mir(d); + panic!("exit"); +} diff --git a/src/test/ui/mir/mir_codegen_calls_converging_drops_2.rs b/src/test/ui/mir/mir_codegen_calls_converging_drops_2.rs new file mode 100644 index 000000000..e9446da9e --- /dev/null +++ b/src/test/ui/mir/mir_codegen_calls_converging_drops_2.rs @@ -0,0 +1,30 @@ +// run-fail +// error-pattern:complex called +// error-pattern:dropped +// error-pattern:exit +// ignore-emscripten no processes + +struct Droppable; +impl Drop for Droppable { + fn drop(&mut self) { + eprintln!("dropped"); + } +} + +// return value of this function is copied into the return slot +fn complex() -> u64 { + eprintln!("complex called"); + 42 +} + + +fn mir() -> u64 { + let x = Droppable; + return complex(); + drop(x); +} + +pub fn main() { + assert_eq!(mir(), 42); + panic!("exit"); +} diff --git a/src/test/ui/mir/mir_codegen_calls_diverging.rs b/src/test/ui/mir/mir_codegen_calls_diverging.rs new file mode 100644 index 000000000..736d580e2 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_calls_diverging.rs @@ -0,0 +1,15 @@ +// run-fail +// error-pattern:diverging_fn called +// ignore-emscripten no processes + +fn diverging_fn() -> ! { + panic!("diverging_fn called") +} + +fn mir() { + diverging_fn(); +} + +fn main() { + mir(); +} diff --git a/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs b/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs new file mode 100644 index 000000000..796d74477 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs @@ -0,0 +1,24 @@ +// run-fail +// error-pattern:diverging_fn called +// error-pattern:0 dropped +// ignore-emscripten no processes + +struct Droppable(u8); +impl Drop for Droppable { + fn drop(&mut self) { + eprintln!("{} dropped", self.0); + } +} + +fn diverging_fn() -> ! { + panic!("diverging_fn called") +} + +fn mir(d: Droppable) { + diverging_fn(); +} + +fn main() { + let d = Droppable(0); + mir(d); +} diff --git a/src/test/ui/mir/mir_codegen_critical_edge.rs b/src/test/ui/mir/mir_codegen_critical_edge.rs new file mode 100644 index 000000000..5c1f1c3b7 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_critical_edge.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code)] +// This code produces a CFG with critical edges that, if we don't +// handle properly, will cause invalid codegen. + +#![feature(rustc_attrs)] + +enum State { + Both, + Front, + Back +} + +pub struct Foo { + state: State, + a: A, + b: B +} + +impl Foo +where A: Iterator, B: Iterator +{ + // This is the function we care about + fn next(&mut self) -> Option { + match self.state { + State::Both => match self.a.next() { + elt @ Some(..) => elt, + None => { + self.state = State::Back; + self.b.next() + } + }, + State::Front => self.a.next(), + State::Back => self.b.next(), + } + } +} + +// Make sure we actually codegen a version of the function +pub fn do_stuff(mut f: Foo>, Box>>) { + let _x = f.next(); +} + +fn main() {} diff --git a/src/test/ui/mir/mir_codegen_spike1.rs b/src/test/ui/mir/mir_codegen_spike1.rs new file mode 100644 index 000000000..90bdd6b4b --- /dev/null +++ b/src/test/ui/mir/mir_codegen_spike1.rs @@ -0,0 +1,12 @@ +// run-pass +// A simple spike test for MIR version of codegen. + +fn sum(x: i32, y: i32) -> i32 { + x + y +} + +fn main() { + let x = sum(22, 44); + assert_eq!(x, 66); + println!("sum()={:?}", x); +} diff --git a/src/test/ui/mir/mir_codegen_switch.rs b/src/test/ui/mir/mir_codegen_switch.rs new file mode 100644 index 000000000..9c93499d9 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_switch.rs @@ -0,0 +1,35 @@ +// run-pass +enum Abc { + A(#[allow(unused_tuple_struct_fields)] u8), + B(#[allow(unused_tuple_struct_fields)] i8), + C, + D, +} + +fn foo(x: Abc) -> i32 { + match x { + Abc::C => 3, + Abc::D => 4, + Abc::B(_) => 2, + Abc::A(_) => 1, + } +} + +fn foo2(x: Abc) -> bool { + match x { + Abc::D => true, + _ => false + } +} + +fn main() { + assert_eq!(1, foo(Abc::A(42))); + assert_eq!(2, foo(Abc::B(-100))); + assert_eq!(3, foo(Abc::C)); + assert_eq!(4, foo(Abc::D)); + + assert_eq!(false, foo2(Abc::A(1))); + assert_eq!(false, foo2(Abc::B(2))); + assert_eq!(false, foo2(Abc::C)); + assert_eq!(true, foo2(Abc::D)); +} diff --git a/src/test/ui/mir/mir_codegen_switchint.rs b/src/test/ui/mir/mir_codegen_switchint.rs new file mode 100644 index 000000000..c092a6c31 --- /dev/null +++ b/src/test/ui/mir/mir_codegen_switchint.rs @@ -0,0 +1,12 @@ +// run-pass +pub fn foo(x: i8) -> i32 { + match x { + 1 => 0, + _ => 1, + } +} + +fn main() { + assert_eq!(foo(0), 1); + assert_eq!(foo(1), 0); +} diff --git a/src/test/ui/mir/mir_coercion_casts.rs b/src/test/ui/mir/mir_coercion_casts.rs new file mode 100644 index 000000000..7d761181d --- /dev/null +++ b/src/test/ui/mir/mir_coercion_casts.rs @@ -0,0 +1,10 @@ +// run-pass +// Tests the coercion casts are handled properly + +fn main() { + // This should produce only a reification of f, + // not a fn -> fn cast as well + let _ = f as fn(&()); +} + +fn f<'a>(_: &'a ()) { } diff --git a/src/test/ui/mir/mir_coercions.rs b/src/test/ui/mir/mir_coercions.rs new file mode 100644 index 000000000..f3dcc6b85 --- /dev/null +++ b/src/test/ui/mir/mir_coercions.rs @@ -0,0 +1,71 @@ +// run-pass +#![feature(coerce_unsized, unsize)] + +use std::ops::CoerceUnsized; +use std::marker::Unsize; + +fn identity_coercion(x: &(dyn Fn(u32)->u32 + Send)) -> &dyn Fn(u32)->u32 { + x +} +fn fn_coercions(f: &fn(u32) -> u32) -> + (unsafe fn(u32) -> u32, + &(dyn Fn(u32) -> u32+Send)) +{ + (*f, f) +} + +fn simple_array_coercion(x: &[u8; 3]) -> &[u8] { x } + +fn square(a: u32) -> u32 { a * a } + +#[derive(PartialEq,Eq)] +struct PtrWrapper<'a, T: 'a+?Sized>(u32, u32, (), &'a T); +impl<'a, T: ?Sized+Unsize, U: ?Sized> + CoerceUnsized> for PtrWrapper<'a, T> {} + +struct TrivPtrWrapper<'a, T: 'a+?Sized>(&'a T); +impl<'a, T: ?Sized+Unsize, U: ?Sized> + CoerceUnsized> for TrivPtrWrapper<'a, T> {} + +fn coerce_ptr_wrapper(p: PtrWrapper<[u8; 3]>) -> PtrWrapper<[u8]> { + p +} + +fn coerce_triv_ptr_wrapper(p: TrivPtrWrapper<[u8; 3]>) -> TrivPtrWrapper<[u8]> { + p +} + +fn coerce_fat_ptr_wrapper(p: PtrWrapper u32+Send>) + -> PtrWrapper u32> { + p +} + +fn coerce_ptr_wrapper_poly<'a, T, Trait: ?Sized>(p: PtrWrapper<'a, T>) + -> PtrWrapper<'a, Trait> + where PtrWrapper<'a, T>: CoerceUnsized> +{ + p +} + +fn main() { + let a = [0,1,2]; + let square_local : fn(u32) -> u32 = square; + let (f,g) = fn_coercions(&square_local); + assert_eq!(f as usize, square as usize); + assert_eq!(g(4), 16); + assert_eq!(identity_coercion(g)(5), 25); + + assert_eq!(simple_array_coercion(&a), &a); + let w = coerce_ptr_wrapper(PtrWrapper(2,3,(),&a)); + assert!(w == PtrWrapper(2,3,(),&a) as PtrWrapper<[u8]>); + + let w = coerce_triv_ptr_wrapper(TrivPtrWrapper(&a)); + assert_eq!(&w.0, &a); + + let z = coerce_fat_ptr_wrapper(PtrWrapper(2,3,(),&square_local)); + assert_eq!((z.3)(6), 36); + + let z: PtrWrapper u32> = + coerce_ptr_wrapper_poly(PtrWrapper(2,3,(),&square_local)); + assert_eq!((z.3)(6), 36); +} diff --git a/src/test/ui/mir/mir_const_prop_identity.rs b/src/test/ui/mir/mir_const_prop_identity.rs new file mode 100644 index 000000000..25d2202b9 --- /dev/null +++ b/src/test/ui/mir/mir_const_prop_identity.rs @@ -0,0 +1,12 @@ +// Regression test for issue #91725. +// +// run-pass +// compile-flags: -Zmir-opt-level=4 + +fn main() { + let a = true; + let _ = &a; + let mut b = false; + b |= a; + assert!(b); +} diff --git a/src/test/ui/mir/mir_const_prop_tuple_field_reorder.rs b/src/test/ui/mir/mir_const_prop_tuple_field_reorder.rs new file mode 100644 index 000000000..b66a85d07 --- /dev/null +++ b/src/test/ui/mir/mir_const_prop_tuple_field_reorder.rs @@ -0,0 +1,27 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass +#![crate_type="lib"] + +// This used to ICE: const-prop did not account for field reordering of scalar pairs, +// and would generate a tuple like `(0x1337, VariantBar): (FooEnum, isize)`, +// causing assertion failures in codegen when trying to read 0x1337 at the wrong type. + +pub enum FooEnum { + VariantBar, + VariantBaz, + VariantBuz, +} + +pub fn wrong_index() -> isize { + let (_, b) = id((FooEnum::VariantBar, 0x1337)); + b +} + +pub fn wrong_index_two() -> isize { + let (_, (_, b)) = id(((), (FooEnum::VariantBar, 0x1338))); + b +} + +fn id(x: T) -> T { + x +} diff --git a/src/test/ui/mir/mir_constval_adts.rs b/src/test/ui/mir/mir_constval_adts.rs new file mode 100644 index 000000000..ee9d73451 --- /dev/null +++ b/src/test/ui/mir/mir_constval_adts.rs @@ -0,0 +1,34 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Point { + _x: i32, + _y: i32, +} + +#[derive(PartialEq, Eq, Debug)] +struct Newtype(T); + +const STRUCT: Point = Point { _x: 42, _y: 42 }; +const TUPLE1: (i32, i32) = (42, 42); +const TUPLE2: (&'static str, &'static str) = ("hello","world"); +const PAIR_NEWTYPE: (Newtype, Newtype) = (Newtype(42), Newtype(42)); + +fn mir() -> (Point, (i32, i32), (&'static str, &'static str), (Newtype, Newtype)) { + let struct1 = STRUCT; + let tuple1 = TUPLE1; + let tuple2 = TUPLE2; + let pair_newtype = PAIR_NEWTYPE; + (struct1, tuple1, tuple2, pair_newtype) +} + +const NEWTYPE: Newtype<&'static str> = Newtype("foobar"); + +fn test_promoted_newtype_str_ref() { + let x = &NEWTYPE; + assert_eq!(x, &Newtype("foobar")); +} + +fn main(){ + assert_eq!(mir(), (STRUCT, TUPLE1, TUPLE2, PAIR_NEWTYPE)); + test_promoted_newtype_str_ref(); +} diff --git a/src/test/ui/mir/mir_detects_invalid_ops.rs b/src/test/ui/mir/mir_detects_invalid_ops.rs new file mode 100644 index 000000000..136c03cd9 --- /dev/null +++ b/src/test/ui/mir/mir_detects_invalid_ops.rs @@ -0,0 +1,24 @@ +// build-fail + +fn main() { + divide_by_zero(); + mod_by_zero(); + oob_error_for_slices(); +} + +fn divide_by_zero() { + let y = 0; + let _z = 1 / y; //~ ERROR this operation will panic at runtime [unconditional_panic] +} + +fn mod_by_zero() { + let y = 0; + let _z = 1 % y; //~ ERROR this operation will panic at runtime [unconditional_panic] +} + +fn oob_error_for_slices() { + let a: *const [_] = &[1, 2, 3]; + unsafe { + let _b = (*a)[3]; + } +} diff --git a/src/test/ui/mir/mir_detects_invalid_ops.stderr b/src/test/ui/mir/mir_detects_invalid_ops.stderr new file mode 100644 index 000000000..0fe56f417 --- /dev/null +++ b/src/test/ui/mir/mir_detects_invalid_ops.stderr @@ -0,0 +1,16 @@ +error: this operation will panic at runtime + --> $DIR/mir_detects_invalid_ops.rs:11:14 + | +LL | let _z = 1 / y; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/mir_detects_invalid_ops.rs:16:14 + | +LL | let _z = 1 % y; + | ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mir/mir_drop_order.rs b/src/test/ui/mir/mir_drop_order.rs new file mode 100644 index 000000000..853efb0fe --- /dev/null +++ b/src/test/ui/mir/mir_drop_order.rs @@ -0,0 +1,49 @@ +// run-pass +// needs-unwind +// ignore-wasm32-bare compiled with panic=abort by default + +use std::cell::RefCell; +use std::panic; + +pub struct DropLogger<'a> { + id: usize, + log: &'a panic::AssertUnwindSafe>> +} + +impl<'a> Drop for DropLogger<'a> { + fn drop(&mut self) { + self.log.0.borrow_mut().push(self.id); + } +} + +struct InjectedFailure; + +#[allow(unreachable_code)] +fn main() { + let log = panic::AssertUnwindSafe(RefCell::new(vec![])); + let d = |id| DropLogger { id: id, log: &log }; + let get = || -> Vec<_> { + let mut m = log.0.borrow_mut(); + let n = m.drain(..); + n.collect() + }; + + { + let _x = (d(0), &d(1), d(2), &d(3)); + // all borrows are extended - nothing has been dropped yet + assert_eq!(get(), vec![]); + } + // in a let-statement, extended places are dropped + // *after* the let result (tho they have the same scope + // as far as scope-based borrowck goes). + assert_eq!(get(), vec![0, 2, 3, 1]); + + let _ = std::panic::catch_unwind(|| { + (d(4), &d(5), d(6), &d(7), panic::panic_any(InjectedFailure)); + }); + + // here, the temporaries (5/7) live until the end of the + // containing statement, which is destroyed after the operands + // (4/6) on a panic. + assert_eq!(get(), vec![6, 4, 7, 5]); +} diff --git a/src/test/ui/mir/mir_drop_panics.rs b/src/test/ui/mir/mir_drop_panics.rs new file mode 100644 index 000000000..b4093d704 --- /dev/null +++ b/src/test/ui/mir/mir_drop_panics.rs @@ -0,0 +1,25 @@ +// run-fail +// needs-unwind +// error-pattern:panic 1 +// error-pattern:drop 2 +// ignore-emscripten no processes + +struct Droppable(u32); +impl Drop for Droppable { + fn drop(&mut self) { + if self.0 == 1 { + panic!("panic 1"); + } else { + eprintln!("drop {}", self.0); + } + } +} + +fn mir() { + let x = Droppable(2); + let y = Droppable(1); +} + +fn main() { + mir(); +} diff --git a/src/test/ui/mir/mir_dynamic_drops_1.rs b/src/test/ui/mir/mir_dynamic_drops_1.rs new file mode 100644 index 000000000..2b33b6166 --- /dev/null +++ b/src/test/ui/mir/mir_dynamic_drops_1.rs @@ -0,0 +1,31 @@ +// run-fail +// error-pattern:drop 1 +// error-pattern:drop 2 +// ignore-emscripten no processes + +/// Structure which will not allow to be dropped twice. +struct Droppable<'a>(&'a mut bool, u32); +impl<'a> Drop for Droppable<'a> { + fn drop(&mut self) { + if *self.0 { + eprintln!("{} dropped twice", self.1); + ::std::process::exit(1); + } + eprintln!("drop {}", self.1); + *self.0 = true; + } +} + +fn mir() { + let (mut xv, mut yv) = (false, false); + let x = Droppable(&mut xv, 1); + let y = Droppable(&mut yv, 2); + let mut z = x; + let k = y; + z = k; +} + +fn main() { + mir(); + panic!(); +} diff --git a/src/test/ui/mir/mir_dynamic_drops_2.rs b/src/test/ui/mir/mir_dynamic_drops_2.rs new file mode 100644 index 000000000..c883efdab --- /dev/null +++ b/src/test/ui/mir/mir_dynamic_drops_2.rs @@ -0,0 +1,29 @@ +// run-fail +// error-pattern:drop 1 +// ignore-emscripten no processes + +/// Structure which will not allow to be dropped twice. +struct Droppable<'a>(&'a mut bool, u32); +impl<'a> Drop for Droppable<'a> { + fn drop(&mut self) { + if *self.0 { + eprintln!("{} dropped twice", self.1); + ::std::process::exit(1); + } + eprintln!("drop {}", self.1); + *self.0 = true; + } +} + +fn mir<'a>(d: Droppable<'a>) { + loop { + let x = d; + break; + } +} + +fn main() { + let mut xv = false; + mir(Droppable(&mut xv, 1)); + panic!(); +} diff --git a/src/test/ui/mir/mir_dynamic_drops_3.rs b/src/test/ui/mir/mir_dynamic_drops_3.rs new file mode 100644 index 000000000..2bcd9fac5 --- /dev/null +++ b/src/test/ui/mir/mir_dynamic_drops_3.rs @@ -0,0 +1,35 @@ +// run-fail +// needs-unwind +// error-pattern:unwind happens +// error-pattern:drop 3 +// error-pattern:drop 2 +// error-pattern:drop 1 +// ignore-emscripten no processes + +/// Structure which will not allow to be dropped twice. +struct Droppable<'a>(&'a mut bool, u32); +impl<'a> Drop for Droppable<'a> { + fn drop(&mut self) { + if *self.0 { + eprintln!("{} dropped twice", self.1); + ::std::process::exit(1); + } + eprintln!("drop {}", self.1); + *self.0 = true; + } +} + +fn may_panic<'a>() -> Droppable<'a> { + panic!("unwind happens"); +} + +fn mir<'a>(d: Droppable<'a>) { + let (mut a, mut b) = (false, false); + let y = Droppable(&mut a, 2); + let x = [Droppable(&mut b, 1), y, d, may_panic()]; +} + +fn main() { + let mut c = false; + mir(Droppable(&mut c, 3)); +} diff --git a/src/test/ui/mir/mir_early_return_scope.rs b/src/test/ui/mir/mir_early_return_scope.rs new file mode 100644 index 000000000..a696471c3 --- /dev/null +++ b/src/test/ui/mir/mir_early_return_scope.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(unused_variables)] +static mut DROP: bool = false; + +struct ConnWrap(Conn); +impl ::std::ops::Deref for ConnWrap { + type Target=Conn; + fn deref(&self) -> &Conn { &self.0 } +} + +struct Conn; +impl Drop for Conn { + fn drop(&mut self) { unsafe { DROP = true; } } +} + +fn inner() { + let conn = &*match Some(ConnWrap(Conn)) { + Some(val) => val, + None => return, + }; + return; +} + +fn main() { + inner(); + unsafe { + assert_eq!(DROP, true); + } +} diff --git a/src/test/ui/mir/mir_fat_ptr.rs b/src/test/ui/mir/mir_fat_ptr.rs new file mode 100644 index 000000000..7c3e07c9e --- /dev/null +++ b/src/test/ui/mir/mir_fat_ptr.rs @@ -0,0 +1,52 @@ +// run-pass +// test that ordinary fat pointer operations work. + +struct Wrapper(#[allow(unused_tuple_struct_fields)] u32, T); + +struct FatPtrContainer<'a> { + ptr: &'a [u8] +} + +fn fat_ptr_project(a: &Wrapper<[u8]>) -> &[u8] { + &a.1 +} + +fn fat_ptr_simple(a: &[u8]) -> &[u8] { + a +} + +fn fat_ptr_via_local(a: &[u8]) -> &[u8] { + let x = a; + x +} + +fn fat_ptr_from_struct(s: FatPtrContainer) -> &[u8] { + s.ptr +} + +fn fat_ptr_to_struct(a: &[u8]) -> FatPtrContainer { + FatPtrContainer { ptr: a } +} + +fn fat_ptr_store_to<'a>(a: &'a [u8], b: &mut &'a [u8]) { + *b = a; +} + +fn fat_ptr_constant() -> &'static str { + "HELLO" +} + +fn main() { + let a = Wrapper(4, [7,6,5]); + + let p = fat_ptr_project(&a); + let p = fat_ptr_simple(p); + let p = fat_ptr_via_local(p); + let p = fat_ptr_from_struct(fat_ptr_to_struct(p)); + + let mut target : &[u8] = &[42]; + fat_ptr_store_to(p, &mut target); + assert_eq!(target, &a.1); + + assert_eq!(fat_ptr_constant(), "HELLO"); +} diff --git a/src/test/ui/mir/mir_fat_ptr_drop.rs b/src/test/ui/mir/mir_fat_ptr_drop.rs new file mode 100644 index 000000000..d865c3499 --- /dev/null +++ b/src/test/ui/mir/mir_fat_ptr_drop.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(unused_variables)] +#![allow(stable_features)] + +// test that ordinary fat pointer operations work. + +#![feature(braced_empty_structs)] +#![feature(rustc_attrs)] + +use std::sync::atomic; +use std::sync::atomic::Ordering::SeqCst; + +static COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0); + +struct DropMe { +} + +impl Drop for DropMe { + fn drop(&mut self) { + COUNTER.fetch_add(1, SeqCst); + } +} + +fn fat_ptr_move_then_drop(a: Box<[DropMe]>) { + let b = a; +} + +fn main() { + let a: Box<[DropMe]> = Box::new([DropMe { }]); + fat_ptr_move_then_drop(a); + assert_eq!(COUNTER.load(SeqCst), 1); +} diff --git a/src/test/ui/mir/mir_heavy_promoted.rs b/src/test/ui/mir/mir_heavy_promoted.rs new file mode 100644 index 000000000..092299880 --- /dev/null +++ b/src/test/ui/mir/mir_heavy_promoted.rs @@ -0,0 +1,11 @@ +// run-pass +// ignore-emscripten apparently only works in optimized mode + +const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024]; + +// Check that the promoted copy of TEST_DATA doesn't +// leave an alloca from an unused temp behind, which, +// without optimizations, can still blow the stack. +fn main() { + println!("{}", TEST_DATA.len()); +} diff --git a/src/test/ui/mir/mir_indexing_oob_1.rs b/src/test/ui/mir/mir_indexing_oob_1.rs new file mode 100644 index 000000000..6d769b6b2 --- /dev/null +++ b/src/test/ui/mir/mir_indexing_oob_1.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 10 +// ignore-emscripten no processes + +const C: [u32; 5] = [0; 5]; + +#[allow(unconditional_panic)] +fn test() -> u32 { + C[10] +} + +fn main() { + test(); +} diff --git a/src/test/ui/mir/mir_indexing_oob_2.rs b/src/test/ui/mir/mir_indexing_oob_2.rs new file mode 100644 index 000000000..a9e850570 --- /dev/null +++ b/src/test/ui/mir/mir_indexing_oob_2.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 10 +// ignore-emscripten no processes + +const C: &'static [u8; 5] = b"hello"; + +#[allow(unconditional_panic)] +fn test() -> u8 { + C[10] +} + +fn main() { + test(); +} diff --git a/src/test/ui/mir/mir_indexing_oob_3.rs b/src/test/ui/mir/mir_indexing_oob_3.rs new file mode 100644 index 000000000..4f5cab59b --- /dev/null +++ b/src/test/ui/mir/mir_indexing_oob_3.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 10 +// ignore-emscripten no processes + +const C: &'static [u8; 5] = b"hello"; + +#[allow(unconditional_panic)] +fn mir() -> u8 { + C[10] +} + +fn main() { + mir(); +} diff --git a/src/test/ui/mir/mir_let_chains_drop_order.rs b/src/test/ui/mir/mir_let_chains_drop_order.rs new file mode 100644 index 000000000..6498a5195 --- /dev/null +++ b/src/test/ui/mir/mir_let_chains_drop_order.rs @@ -0,0 +1,94 @@ +// run-pass +// needs-unwind +// ignore-wasm32-bare compiled with panic=abort by default + +// See `mir_drop_order.rs` for more information + +#![feature(let_chains)] +#![allow(irrefutable_let_patterns)] + +use std::cell::RefCell; +use std::panic; + +pub struct DropLogger<'a, T> { + extra: T, + id: usize, + log: &'a panic::AssertUnwindSafe>> +} + +impl<'a, T> Drop for DropLogger<'a, T> { + fn drop(&mut self) { + self.log.0.borrow_mut().push(self.id); + } +} + +struct InjectedFailure; + +#[allow(unreachable_code)] +fn main() { + let log = panic::AssertUnwindSafe(RefCell::new(vec![])); + let d = |id, extra| DropLogger { extra, id: id, log: &log }; + let get = || -> Vec<_> { + let mut m = log.0.borrow_mut(); + let n = m.drain(..); + n.collect() + }; + + { + let _x = ( + d( + 0, + d( + 1, + if let Some(_) = d(2, Some(true)).extra && let DropLogger { .. } = d(3, None) { + None + } else { + Some(true) + } + ).extra + ), + d(4, None), + &d(5, None), + d(6, None), + if let DropLogger { .. } = d(7, None) && let DropLogger { .. } = d(8, None) { + d(9, None) + } + else { + // 10 is not constructed + d(10, None) + } + ); + assert_eq!(get(), vec![3, 8, 7, 1, 2]); + } + assert_eq!(get(), vec![0, 4, 6, 9, 5]); + + let _ = std::panic::catch_unwind(|| { + ( + d( + 11, + d( + 12, + if let Some(_) = d(13, Some(true)).extra + && let DropLogger { .. } = d(14, None) + { + None + } else { + Some(true) + } + ).extra + ), + d(15, None), + &d(16, None), + d(17, None), + if let DropLogger { .. } = d(18, None) && let DropLogger { .. } = d(19, None) { + d(20, None) + } + else { + // 10 is not constructed + d(21, None) + }, + panic::panic_any(InjectedFailure) + ); + }); + assert_eq!(get(), vec![14, 19, 20, 17, 15, 11, 18, 16, 12, 13]); +} diff --git a/src/test/ui/mir/mir_match_arm_guard.rs b/src/test/ui/mir/mir_match_arm_guard.rs new file mode 100644 index 000000000..65e4ed041 --- /dev/null +++ b/src/test/ui/mir/mir_match_arm_guard.rs @@ -0,0 +1,16 @@ +// run-pass +// #30527 - We were not generating arms with guards in certain cases. + +fn match_with_guard(x: Option) -> i8 { + match x { + Some(xyz) if xyz > 100 => 0, + Some(_) => -1, + None => -2 + } +} + +fn main() { + assert_eq!(match_with_guard(Some(111)), 0); + assert_eq!(match_with_guard(Some(2)), -1); + assert_eq!(match_with_guard(None), -2); +} diff --git a/src/test/ui/mir/mir_match_test.rs b/src/test/ui/mir/mir_match_test.rs new file mode 100644 index 000000000..1f96d6737 --- /dev/null +++ b/src/test/ui/mir/mir_match_test.rs @@ -0,0 +1,83 @@ +#![feature(exclusive_range_pattern)] + +// run-pass + +fn main() { + let incl_range = |x, b| { + match x { + 0..=5 if b => 0, + 5..=10 if b => 1, + 1..=4 if !b => 2, + _ => 3, + } + }; + assert_eq!(incl_range(3, false), 2); + assert_eq!(incl_range(3, true), 0); + assert_eq!(incl_range(5, false), 3); + assert_eq!(incl_range(5, true), 0); + + let excl_range = |x, b| { + match x { + 0..5 if b => 0, + 5..10 if b => 1, + 1..4 if !b => 2, + _ => 3, + } + }; + assert_eq!(excl_range(3, false), 2); + assert_eq!(excl_range(3, true), 0); + assert_eq!(excl_range(5, false), 3); + assert_eq!(excl_range(5, true), 1); + + let incl_range_vs_const = |x, b| { + match x { + 0..=5 if b => 0, + 7 => 1, + 3 => 2, + _ => 3, + } + }; + assert_eq!(incl_range_vs_const(5, false), 3); + assert_eq!(incl_range_vs_const(5, true), 0); + assert_eq!(incl_range_vs_const(3, false), 2); + assert_eq!(incl_range_vs_const(3, true), 0); + assert_eq!(incl_range_vs_const(7, false), 1); + assert_eq!(incl_range_vs_const(7, true), 1); + + let excl_range_vs_const = |x, b| { + match x { + 0..5 if b => 0, + 7 => 1, + 3 => 2, + _ => 3, + } + }; + assert_eq!(excl_range_vs_const(5, false), 3); + assert_eq!(excl_range_vs_const(5, true), 3); + assert_eq!(excl_range_vs_const(3, false), 2); + assert_eq!(excl_range_vs_const(3, true), 0); + assert_eq!(excl_range_vs_const(7, false), 1); + assert_eq!(excl_range_vs_const(7, true), 1); + + let const_vs_incl_range = |x, b| { + match x { + 3 if b => 0, + 5..=7 => 2, + 1..=4 => 1, + _ => 3, + } + }; + assert_eq!(const_vs_incl_range(3, false), 1); + assert_eq!(const_vs_incl_range(3, true), 0); + + let const_vs_excl_range = |x, b| { + match x { + 3 if b => 0, + 5..7 => 2, + 1..4 => 1, + _ => 3, + } + }; + assert_eq!(const_vs_excl_range(3, false), 1); + assert_eq!(const_vs_excl_range(3, true), 0); +} diff --git a/src/test/ui/mir/mir_misc_casts.rs b/src/test/ui/mir/mir_misc_casts.rs new file mode 100644 index 000000000..2e7fbeee5 --- /dev/null +++ b/src/test/ui/mir/mir_misc_casts.rs @@ -0,0 +1,320 @@ +// run-pass +fn func(){} + +const STR: &'static str = "hello"; +const BSTR: &'static [u8; 5] = b"hello"; + +fn from_ptr() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, *const ()) { + let f = 1_usize as *const String; + let c1 = f as isize; + let c2 = f as usize; + let c3 = f as i8; + let c4 = f as i16; + let c5 = f as i32; + let c6 = f as i64; + let c7 = f as u8; + let c8 = f as u16; + let c9 = f as u32; + let c10 = f as u64; + let c11 = f as *const (); + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) +} + +fn from_1() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1 as isize; + let c2 = 1 as usize; + let c3 = 1 as i8; + let c4 = 1 as i16; + let c5 = 1 as i32; + let c6 = 1 as i64; + let c7 = 1 as u8; + let c8 = 1 as u16; + let c9 = 1 as u32; + let c10 = 1 as u64; + let c11 = 1 as f32; + let c12 = 1 as f64; + let c13 = 1 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1usize() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_usize as isize; + let c2 = 1_usize as usize; + let c3 = 1_usize as i8; + let c4 = 1_usize as i16; + let c5 = 1_usize as i32; + let c6 = 1_usize as i64; + let c7 = 1_usize as u8; + let c8 = 1_usize as u16; + let c9 = 1_usize as u32; + let c10 = 1_usize as u64; + let c11 = 1_usize as f32; + let c12 = 1_usize as f64; + let c13 = 1_usize as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1isize() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_isize as isize; + let c2 = 1_isize as usize; + let c3 = 1_isize as i8; + let c4 = 1_isize as i16; + let c5 = 1_isize as i32; + let c6 = 1_isize as i64; + let c7 = 1_isize as u8; + let c8 = 1_isize as u16; + let c9 = 1_isize as u32; + let c10 = 1_isize as u64; + let c11 = 1_isize as f32; + let c12 = 1_isize as f64; + let c13 = 1_isize as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u8() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u8 as isize; + let c2 = 1_u8 as usize; + let c3 = 1_u8 as i8; + let c4 = 1_u8 as i16; + let c5 = 1_u8 as i32; + let c6 = 1_u8 as i64; + let c7 = 1_u8 as u8; + let c8 = 1_u8 as u16; + let c9 = 1_u8 as u32; + let c10 = 1_u8 as u64; + let c11 = 1_u8 as f32; + let c12 = 1_u8 as f64; + let c13 = 1_u8 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i8() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i8 as isize; + let c2 = 1_i8 as usize; + let c3 = 1_i8 as i8; + let c4 = 1_i8 as i16; + let c5 = 1_i8 as i32; + let c6 = 1_i8 as i64; + let c7 = 1_i8 as u8; + let c8 = 1_i8 as u16; + let c9 = 1_i8 as u32; + let c10 = 1_i8 as u64; + let c11 = 1_i8 as f32; + let c12 = 1_i8 as f64; + let c13 = 1_i8 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u16() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u16 as isize; + let c2 = 1_u16 as usize; + let c3 = 1_u16 as i8; + let c4 = 1_u16 as i16; + let c5 = 1_u16 as i32; + let c6 = 1_u16 as i64; + let c7 = 1_u16 as u8; + let c8 = 1_u16 as u16; + let c9 = 1_u16 as u32; + let c10 = 1_u16 as u64; + let c11 = 1_u16 as f32; + let c12 = 1_u16 as f64; + let c13 = 1_u16 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i16() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i16 as isize; + let c2 = 1_i16 as usize; + let c3 = 1_i16 as i8; + let c4 = 1_i16 as i16; + let c5 = 1_i16 as i32; + let c6 = 1_i16 as i64; + let c7 = 1_i16 as u8; + let c8 = 1_i16 as u16; + let c9 = 1_i16 as u32; + let c10 = 1_i16 as u64; + let c11 = 1_i16 as f32; + let c12 = 1_i16 as f64; + let c13 = 1_i16 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u32() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u32 as isize; + let c2 = 1_u32 as usize; + let c3 = 1_u32 as i8; + let c4 = 1_u32 as i16; + let c5 = 1_u32 as i32; + let c6 = 1_u32 as i64; + let c7 = 1_u32 as u8; + let c8 = 1_u32 as u16; + let c9 = 1_u32 as u32; + let c10 = 1_u32 as u64; + let c11 = 1_u32 as f32; + let c12 = 1_u32 as f64; + let c13 = 1_u32 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i32() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i32 as isize; + let c2 = 1_i32 as usize; + let c3 = 1_i32 as i8; + let c4 = 1_i32 as i16; + let c5 = 1_i32 as i32; + let c6 = 1_i32 as i64; + let c7 = 1_i32 as u8; + let c8 = 1_i32 as u16; + let c9 = 1_i32 as u32; + let c10 = 1_i32 as u64; + let c11 = 1_i32 as f32; + let c12 = 1_i32 as f64; + let c13 = 1_i32 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u64() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u64 as isize; + let c2 = 1_u64 as usize; + let c3 = 1_u64 as i8; + let c4 = 1_u64 as i16; + let c5 = 1_u64 as i32; + let c6 = 1_u64 as i64; + let c7 = 1_u64 as u8; + let c8 = 1_u64 as u16; + let c9 = 1_u64 as u32; + let c10 = 1_u64 as u64; + let c11 = 1_u64 as f32; + let c12 = 1_u64 as f64; + let c13 = 1_u64 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i64() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i64 as isize; + let c2 = 1_i64 as usize; + let c3 = 1_i64 as i8; + let c4 = 1_i64 as i16; + let c5 = 1_i64 as i32; + let c6 = 1_i64 as i64; + let c7 = 1_i64 as u8; + let c8 = 1_i64 as u16; + let c9 = 1_i64 as u32; + let c10 = 1_i64 as u64; + let c11 = 1_i64 as f32; + let c12 = 1_i64 as f64; + let c13 = 1_i64 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_bool() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64) { + let c1 = true as isize; + let c2 = true as usize; + let c3 = true as i8; + let c4 = true as i16; + let c5 = true as i32; + let c6 = true as i64; + let c7 = true as u8; + let c8 = true as u16; + let c9 = true as u32; + let c10 = true as u64; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) +} + +fn from_1f32() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) { + let c1 = 1.0_f32 as isize; + let c2 = 1.0_f32 as usize; + let c3 = 1.0_f32 as i8; + let c4 = 1.0_f32 as i16; + let c5 = 1.0_f32 as i32; + let c6 = 1.0_f32 as i64; + let c7 = 1.0_f32 as u8; + let c8 = 1.0_f32 as u16; + let c9 = 1.0_f32 as u32; + let c10 = 1.0_f32 as u64; + let c11 = 1.0_f32 as f32; + let c12 = 1.0_f32 as f64; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12) +} + +fn from_1f64() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) { + let c1 = 1.0f64 as isize; + let c2 = 1.0f64 as usize; + let c3 = 1.0f64 as i8; + let c4 = 1.0f64 as i16; + let c5 = 1.0f64 as i32; + let c6 = 1.0f64 as i64; + let c7 = 1.0f64 as u8; + let c8 = 1.0f64 as u16; + let c9 = 1.0f64 as u32; + let c10 = 1.0f64 as u64; + let c11 = 1.0f64 as f32; + let c12 = 1.0f64 as f64; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12) +} + +fn other_casts() +-> (*const u8, *const isize, *const u8, *const u8) { + let c1 = func as *const u8; + let c2 = c1 as *const isize; + + let r = &42u32; + let _ = r as *const u32; + + // fat-ptr -> fat-ptr -> fat-raw-ptr -> thin-ptr + let c3 = STR as &str as *const str as *const u8; + + let c4 = BSTR as *const [u8] as *const [u16] as *const u8; + (c1, c2, c3, c4) +} + +pub fn assert_eq_13(l: (isize, usize, i8, i16, i32, i64, u8, + u16, u32, u64, f32, f64, *const String), + r: (isize, usize, i8, i16, i32, i64, u8, + u16, u32, u64, f32, f64, *const String)) -> bool { + let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13) = l; + let (r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13) = r; + l1 == r1 && l2 == r2 && l3 == r3 && l4 == r4 && l5 == r5 && l6 == r6 && l7 == r7 && + l8 == r8 && l9 == r9 && l10 == r10 && l11 == r11 && l12 == r12 && l13 == r13 +} + + +pub fn main() { + let f = 1_usize as *const String; + let t13 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0, f); + let t12 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0); + assert_eq_13(from_1(), t13); + assert_eq_13(from_1usize(), t13); + assert_eq_13(from_1isize(), t13); + assert_eq_13(from_1u8(), t13); + assert_eq_13(from_1i8(), t13); + assert_eq_13(from_1u16(), t13); + assert_eq_13(from_1i16(), t13); + assert_eq_13(from_1u32(), t13); + assert_eq_13(from_1i32(), t13); + assert_eq_13(from_1u64(), t13); + assert_eq_13(from_1i64(), t13); + assert_eq!(from_1f32(), t12); + assert_eq!(from_1f64(), t12); + + assert_eq!(from_ptr(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 as *const ())); + assert_eq!(from_bool(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + + assert_eq!(other_casts(), (func as *const u8, func as *const isize, + STR as *const str as *const u8, BSTR as *const [u8] as *const u8)); +} diff --git a/src/test/ui/mir/mir_overflow_off.rs b/src/test/ui/mir/mir_overflow_off.rs new file mode 100644 index 000000000..0098584dd --- /dev/null +++ b/src/test/ui/mir/mir_overflow_off.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags: -C overflow-checks=off + +// Test that with MIR codegen, overflow checks can be +// turned off, even when they're from core::ops::*. + +use std::ops::*; + +fn main() { + assert_eq!(i8::neg(-0x80), -0x80); + + assert_eq!(u8::add(0xff, 1), 0_u8); + assert_eq!(u8::sub(0, 1), 0xff_u8); + assert_eq!(u8::mul(0xff, 2), 0xfe_u8); + assert_eq!(u8::shl(1, 9), 2_u8); + assert_eq!(u8::shr(2, 9), 1_u8); +} diff --git a/src/test/ui/mir/mir_raw_fat_ptr.rs b/src/test/ui/mir/mir_raw_fat_ptr.rs new file mode 100644 index 000000000..6aceefbe7 --- /dev/null +++ b/src/test/ui/mir/mir_raw_fat_ptr.rs @@ -0,0 +1,216 @@ +// run-pass +// check raw fat pointer ops in mir +// FIXME: please improve this when we get monomorphization support +#![feature(raw_ref_op)] + +use std::mem; + +#[derive(Debug, PartialEq, Eq)] +struct ComparisonResults { + lt: bool, + le: bool, + gt: bool, + ge: bool, + eq: bool, + ne: bool +} + +const LT: ComparisonResults = ComparisonResults { + lt: true, + le: true, + gt: false, + ge: false, + eq: false, + ne: true +}; + +const EQ: ComparisonResults = ComparisonResults { + lt: false, + le: true, + gt: false, + ge: true, + eq: true, + ne: false +}; + +const GT: ComparisonResults = ComparisonResults { + lt: false, + le: false, + gt: true, + ge: true, + eq: false, + ne: true +}; + +fn compare_su8(a: *const S<[u8]>, b: *const S<[u8]>) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +fn compare_au8(a: *const [u8], b: *const [u8]) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +fn compare_foo<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +fn simple_eq<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> bool { + let result = a == b; + result +} + +fn assert_inorder(a: &[T], + compare: fn(T, T) -> ComparisonResults) { + for i in 0..a.len() { + for j in 0..a.len() { + let cres = compare(a[i], a[j]); + if i < j { + assert_eq!(cres, LT); + } else if i == j { + assert_eq!(cres, EQ); + } else { + assert_eq!(cres, GT); + } + } + } +} + +trait Foo { fn foo(&self) -> usize; } +impl Foo for T { + fn foo(&self) -> usize { + mem::size_of::() + } +} + +#[allow(unused_tuple_struct_fields)] +struct S(u32, T); + +fn main_ref() { + let array = [0,1,2,3,4]; + let array2 = [5,6,7,8,9]; + + // fat ptr comparison: addr then extra + + // check ordering for arrays + let mut ptrs: Vec<*const [u8]> = vec![ + &array[0..0], &array[0..1], &array, &array[1..] + ]; + + let array_addr = &array as *const [u8] as *const u8 as usize; + let array2_addr = &array2 as *const [u8] as *const u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &array2); + } else { + ptrs.push(&array2); + } + assert_inorder(&ptrs, compare_au8); + + let u8_ = (0u8, 1u8); + let u32_ = (4u32, 5u32); + + // check ordering for ptrs + let buf: &mut [*const dyn Foo] = &mut [ + &u8_, &u8_.0, + &u32_, &u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf, compare_foo); + + // check ordering for structs containing arrays + let ss: (S<[u8; 2]>, + S<[u8; 3]>, + S<[u8; 2]>) = ( + S(7, [8, 9]), + S(10, [11, 12, 13]), + S(4, [5, 6]) + ); + assert_inorder(&[ + &ss.0 as *const S<[u8]>, + &ss.1 as *const S<[u8]>, + &ss.2 as *const S<[u8]> + ], compare_su8); + + assert!(simple_eq(&0u8 as *const _, &0u8 as *const _)); + assert!(!simple_eq(&0u8 as *const _, &1u8 as *const _)); +} + +// similar to above, but using &raw +fn main_raw() { + let array = [0,1,2,3,4]; + let array2 = [5,6,7,8,9]; + + // fat ptr comparison: addr then extra + + // check ordering for arrays + let mut ptrs: Vec<*const [u8]> = vec![ + &raw const array[0..0], &raw const array[0..1], &raw const array, &raw const array[1..] + ]; + + let array_addr = &raw const array as *const u8 as usize; + let array2_addr = &raw const array2 as *const u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &raw const array2); + } else { + ptrs.push(&raw const array2); + } + assert_inorder(&ptrs, compare_au8); + + let u8_ = (0u8, 1u8); + let u32_ = (4u32, 5u32); + + // check ordering for ptrs + let buf: &mut [*const dyn Foo] = &mut [ + &raw const u8_, &raw const u8_.0, + &raw const u32_, &raw const u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf, compare_foo); + + // check ordering for structs containing arrays + let ss: (S<[u8; 2]>, + S<[u8; 3]>, + S<[u8; 2]>) = ( + S(7, [8, 9]), + S(10, [11, 12, 13]), + S(4, [5, 6]) + ); + assert_inorder(&[ + &raw const ss.0 as *const S<[u8]>, + &raw const ss.1 as *const S<[u8]>, + &raw const ss.2 as *const S<[u8]> + ], compare_su8); +} + +fn main() { + main_ref(); + main_raw(); +} diff --git a/src/test/ui/mir/mir_refs_correct.rs b/src/test/ui/mir/mir_refs_correct.rs new file mode 100644 index 000000000..6cd9526b7 --- /dev/null +++ b/src/test/ui/mir/mir_refs_correct.rs @@ -0,0 +1,209 @@ +// run-pass +// aux-build:mir_external_refs.rs + +extern crate mir_external_refs as ext; + +struct S(#[allow(unused_tuple_struct_fields)] u8); +#[derive(Debug, PartialEq, Eq)] +struct Unit; + +impl S { + fn hey() -> u8 { 42 } + fn hey2(&self) -> u8 { 44 } +} + +trait X { + fn hoy(&self) -> u8 { 43 } + fn hoy2() -> u8 { 45 } +} + +trait F { + fn f(self, other: U) -> u64; +} + +impl F for u32 { + fn f(self, other: u32) -> u64 { self as u64 + other as u64 } +} + +impl F for u32 { + fn f(self, other: u64) -> u64 { self as u64 - other } +} + +impl F for u64 { + fn f(self, other: u64) -> u64 { self * other } +} + +impl F for u64 { + fn f(self, other: u32) -> u64 { self ^ other as u64 } +} + +trait T { + fn staticmeth(i: I, o: O) -> (I, O) { (i, o) } +} + +impl T for O {} + +impl X for S {} + +enum E { + U(#[allow(unused_tuple_struct_fields)] u8) +} + +#[derive(PartialEq, Debug, Eq)] +enum CEnum { + A = 0x321, + B = 0x123 +} + +const C: u8 = 84; +const C2: [u8; 5] = [42; 5]; +const C3: [u8; 3] = [42, 41, 40]; +const C4: fn(u8) -> S = S; + +fn regular() -> u8 { + 21 +} + +fn parametric(u: T) -> T { + u +} + +fn t1() -> fn()->u8 { + regular +} + +fn t2() -> fn(u8)->E { + E::U +} + +fn t3() -> fn(u8)->S { + S +} + +fn t4() -> fn()->u8 { + S::hey +} + +fn t5() -> fn(&S)-> u8 { + ::hoy +} + + +fn t6() -> fn()->u8{ + ext::regular_fn +} + +fn t7() -> fn(u8)->ext::E { + ext::E::U +} + +fn t8() -> fn(u8)->ext::S { + ext::S +} + +fn t9() -> fn()->u8 { + ext::S::hey +} + +fn t10() -> fn(&ext::S)->u8 { + ::hoy +} + +fn t11() -> fn(u8)->u8 { + parametric +} + +fn t12() -> u8 { + C +} + +fn t13() -> [u8; 5] { + C2 +} + +fn t13_2() -> [u8; 3] { + C3 +} + +fn t14() -> fn()-> u8 { + ::hoy2 +} + +fn t15() -> fn(&S)-> u8 { + S::hey2 +} + +fn t16() -> fn(u32, u32)->u64 { + F::f +} + +fn t17() -> fn(u32, u64)->u64 { + F::f +} + +fn t18() -> fn(u64, u64)->u64 { + F::f +} + +fn t19() -> fn(u64, u32)->u64 { + F::f +} + +fn t20() -> fn(u64, u32)->(u64, u32) { + >::staticmeth +} + +fn t21() -> Unit { + Unit +} + +fn t22() -> Option { + None +} + +fn t23() -> (CEnum, CEnum) { + (CEnum::A, CEnum::B) +} + +fn t24() -> fn(u8) -> S { + C4 +} + +fn main() { + assert_eq!(t1()(), regular()); + + assert_eq!(t2() as *mut (), E::U as *mut ()); + assert_eq!(t3() as *mut (), S as *mut ()); + + assert_eq!(t4()(), S::hey()); + let s = S(42); + assert_eq!(t5()(&s), ::hoy(&s)); + + + assert_eq!(t6()(), ext::regular_fn()); + assert_eq!(t7() as *mut (), ext::E::U as *mut ()); + assert_eq!(t8() as *mut (), ext::S as *mut ()); + + assert_eq!(t9()(), ext::S::hey()); + let sext = ext::S(6); + assert_eq!(t10()(&sext), ::hoy(&sext)); + + let p = parametric::; + assert_eq!(t11() as *mut (), p as *mut ()); + + assert_eq!(t12(), C); + assert_eq!(t13(), C2); + assert_eq!(t13_2(), C3); + + assert_eq!(t14()(), ::hoy2()); + assert_eq!(t15()(&s), S::hey2(&s)); + assert_eq!(t16()(10u32, 20u32), F::f(10u32, 20u32)); + assert_eq!(t17()(30u32, 10u64), F::f(30u32, 10u64)); + assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64)); + assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32)); + assert_eq!(t20()(123u64, 38u32), >::staticmeth(123, 38)); + assert_eq!(t21(), Unit); + assert_eq!(t22(), None); + assert_eq!(t23(), (CEnum::A, CEnum::B)); + assert_eq!(t24(), C4); +} diff --git a/src/test/ui/mir/mir_small_agg_arg.rs b/src/test/ui/mir/mir_small_agg_arg.rs new file mode 100644 index 000000000..5a22a0420 --- /dev/null +++ b/src/test/ui/mir/mir_small_agg_arg.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_variables)] +fn foo((x, y): (i8, i8)) { +} + +fn main() { + foo((0, 1)); +} diff --git a/src/test/ui/mir/mir_static_subtype.rs b/src/test/ui/mir/mir_static_subtype.rs new file mode 100644 index 000000000..d471b8f14 --- /dev/null +++ b/src/test/ui/mir/mir_static_subtype.rs @@ -0,0 +1,9 @@ +// run-pass +// Test that subtyping the body of a static doesn't cause an ICE. + +fn foo(_ : &()) {} +static X: fn(&'static ()) = foo; + +fn main() { + let _ = X; +} diff --git a/src/test/ui/mir/mir_struct_with_assoc_ty.rs b/src/test/ui/mir/mir_struct_with_assoc_ty.rs new file mode 100644 index 000000000..26d026bdf --- /dev/null +++ b/src/test/ui/mir/mir_struct_with_assoc_ty.rs @@ -0,0 +1,29 @@ +// run-pass +use std::marker::PhantomData; + +pub trait DataBind { + type Data; +} + +impl DataBind for Global { + type Data = T; +} + +pub struct Global(PhantomData); + +pub struct Data { + pub offsets: as DataBind>::Data, +} + +fn create_data() -> Data { + let mut d = Data { offsets: [1, 2] }; + d.offsets[0] = 3; + d +} + + +fn main() { + let d = create_data(); + assert_eq!(d.offsets[0], 3); + assert_eq!(d.offsets[1], 2); +} diff --git a/src/test/ui/mir/mir_temp_promotions.rs b/src/test/ui/mir/mir_temp_promotions.rs new file mode 100644 index 000000000..845dc4c04 --- /dev/null +++ b/src/test/ui/mir/mir_temp_promotions.rs @@ -0,0 +1,10 @@ +// run-pass +fn test1(f: f32) -> bool { + // test that we properly promote temporaries to allocas when a temporary is assigned to + // multiple times (assignment is still happening once ∀ possible dataflows). + !(f.is_nan() || f.is_infinite()) +} + +fn main() { + assert_eq!(test1(0.0), true); +} diff --git a/src/test/ui/mir/mir_void_return.rs b/src/test/ui/mir/mir_void_return.rs new file mode 100644 index 000000000..d257affc2 --- /dev/null +++ b/src/test/ui/mir/mir_void_return.rs @@ -0,0 +1,12 @@ +// run-pass +fn mir() -> (){ + let x = 1; + let mut y = 0; + while y < x { + y += 1 + } +} + +pub fn main() { + mir(); +} diff --git a/src/test/ui/mir/mir_void_return_2.rs b/src/test/ui/mir/mir_void_return_2.rs new file mode 100644 index 000000000..a1fb0a7db --- /dev/null +++ b/src/test/ui/mir/mir_void_return_2.rs @@ -0,0 +1,10 @@ +// run-pass +fn nil() {} + +fn mir(){ + nil() +} + +pub fn main() { + mir(); +} diff --git a/src/test/ui/mir/remove-zsts-query-cycle.rs b/src/test/ui/mir/remove-zsts-query-cycle.rs new file mode 100644 index 000000000..be4d68f2d --- /dev/null +++ b/src/test/ui/mir/remove-zsts-query-cycle.rs @@ -0,0 +1,16 @@ +// Regression test for #88972. Used to cause a query cycle: +// optimized mir -> remove zsts -> layout of a generator -> optimized mir. +// +// edition:2018 +// compile-flags: --crate-type=lib -Zinline-mir=yes +// build-pass + +pub async fn listen() -> Result<(), std::io::Error> { + let f = do_async(); + std::mem::forget(f); + Ok(()) +} + +pub async fn do_async() { + listen().await.unwrap() +} diff --git a/src/test/ui/mir/simplify-branch-same.rs b/src/test/ui/mir/simplify-branch-same.rs new file mode 100644 index 000000000..d631c33d6 --- /dev/null +++ b/src/test/ui/mir/simplify-branch-same.rs @@ -0,0 +1,21 @@ +// Regression test for SimplifyBranchSame miscompilation. +// run-pass + +macro_rules! m { + ($a:expr, $b:expr, $c:block) => { + match $a { + Lto::Fat | Lto::Thin => { $b; (); $c } + Lto::No => { $b; () } + } + } +} + +pub enum Lto { No, Thin, Fat } + +fn f(mut cookie: u32, lto: Lto) -> u32 { + let mut _a = false; + m!(lto, _a = true, {cookie = 0}); + cookie +} + +fn main() { assert_eq!(f(42, Lto::Thin), 0) } diff --git a/src/test/ui/mir/ssa-analysis-regression-50041.rs b/src/test/ui/mir/ssa-analysis-regression-50041.rs new file mode 100644 index 000000000..ebc3e2f8c --- /dev/null +++ b/src/test/ui/mir/ssa-analysis-regression-50041.rs @@ -0,0 +1,36 @@ +// build-pass +// compile-flags: -Z mir-opt-level=4 + +#![crate_type = "lib"] +#![feature(lang_items)] +#![no_std] + +struct NonNull(*const T); + +struct Unique(NonNull); + +#[lang = "owned_box"] +pub struct Box(Unique); + +impl Drop for Box { + fn drop(&mut self) {} +} + +#[lang = "box_free"] +#[inline(always)] +unsafe fn box_free(ptr: Unique) { + dealloc(ptr.0.0) +} + +#[inline(never)] +fn dealloc(_: *const T) {} + +pub struct Foo(T); + +pub fn foo(a: Option>>) -> usize { + let f = match a { + None => Foo(0), + Some(vec) => *vec, + }; + f.0 +} diff --git a/src/test/ui/mir/thir-constparam-temp.rs b/src/test/ui/mir/thir-constparam-temp.rs new file mode 100644 index 000000000..cdc5910b3 --- /dev/null +++ b/src/test/ui/mir/thir-constparam-temp.rs @@ -0,0 +1,20 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +struct Yikes; + +impl Yikes { + fn mut_self(&mut self) {} +} + +fn foo() { + YIKES.mut_self() + //~^ WARNING taking a mutable reference +} + +fn main() { + foo::<{ Yikes }>() +} diff --git a/src/test/ui/mir/thir-constparam-temp.stderr b/src/test/ui/mir/thir-constparam-temp.stderr new file mode 100644 index 000000000..ed2766c00 --- /dev/null +++ b/src/test/ui/mir/thir-constparam-temp.stderr @@ -0,0 +1,22 @@ +warning: taking a mutable reference to a `const` item + --> $DIR/thir-constparam-temp.rs:14:5 + | +LL | YIKES.mut_self() + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(const_item_mutation)]` on by default + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: mutable reference created due to call to this method + --> $DIR/thir-constparam-temp.rs:10:5 + | +LL | fn mut_self(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^ +note: `const` item defined here + --> $DIR/thir-constparam-temp.rs:13:8 + | +LL | fn foo() { + | ^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + -- cgit v1.2.3