summaryrefslogtreecommitdiffstats
path: root/src/test/ui/mir
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/mir
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/mir')
-rw-r--r--src/test/ui/mir/auxiliary/issue_76375_aux.rs20
-rw-r--r--src/test/ui/mir/auxiliary/mir_external_refs.rs17
-rw-r--r--src/test/ui/mir/drop-elaboration-after-borrowck-error.rs25
-rw-r--r--src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr60
-rw-r--r--src/test/ui/mir/issue-100476-recursion-check-blewup.rs42
-rw-r--r--src/test/ui/mir/issue-60390.rs8
-rw-r--r--src/test/ui/mir/issue-66851.rs20
-rw-r--r--src/test/ui/mir/issue-66930.rs11
-rw-r--r--src/test/ui/mir/issue-67639-normalization-ice.rs34
-rw-r--r--src/test/ui/mir/issue-67710-inline-projection.rs17
-rw-r--r--src/test/ui/mir/issue-67947.rs7
-rw-r--r--src/test/ui/mir/issue-67947.stderr16
-rw-r--r--src/test/ui/mir/issue-68841.rs15
-rw-r--r--src/test/ui/mir/issue-71793-inline-args-storage.rs16
-rw-r--r--src/test/ui/mir/issue-73914.rs30
-rw-r--r--src/test/ui/mir/issue-74739.rs14
-rw-r--r--src/test/ui/mir/issue-75053.rs49
-rw-r--r--src/test/ui/mir/issue-75053.stderr8
-rw-r--r--src/test/ui/mir/issue-75419-validation-impl-trait.rs13
-rw-r--r--src/test/ui/mir/issue-76248.rs29
-rw-r--r--src/test/ui/mir/issue-76375.rs27
-rw-r--r--src/test/ui/mir/issue-76740-copy-propagation.rs30
-rw-r--r--src/test/ui/mir/issue-76803-branches-not-same.rs19
-rw-r--r--src/test/ui/mir/issue-77359-simplify-arm-identity.rs35
-rw-r--r--src/test/ui/mir/issue-77911.rs15
-rw-r--r--src/test/ui/mir/issue-78496.rs16
-rw-r--r--src/test/ui/mir/issue-80949.rs34
-rw-r--r--src/test/ui/mir/issue-83499-input-output-iteration-ice.rs10
-rw-r--r--src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr21
-rw-r--r--src/test/ui/mir/issue-89485.rs18
-rw-r--r--src/test/ui/mir/issue-91745.rs21
-rw-r--r--src/test/ui/mir/issue-92893.rs8
-rw-r--r--src/test/ui/mir/issue-92893.stderr26
-rw-r--r--src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs10
-rw-r--r--src/test/ui/mir/issue66339.rs13
-rw-r--r--src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs11
-rw-r--r--src/test/ui/mir/mir-inlining/ice-issue-45493.rs17
-rw-r--r--src/test/ui/mir/mir-inlining/ice-issue-45885.rs29
-rw-r--r--src/test/ui/mir/mir-inlining/ice-issue-68347.rs28
-rw-r--r--src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs17
-rw-r--r--src/test/ui/mir/mir-inlining/ice-issue-77306-2.rs32
-rw-r--r--src/test/ui/mir/mir-inlining/ice-issue-77564.rs38
-rw-r--r--src/test/ui/mir/mir-inlining/no-trait-method-issue-40473.rs16
-rw-r--r--src/test/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs11
-rw-r--r--src/test/ui/mir/mir-typeck-normalize-fn-sig.rs30
-rw-r--r--src/test/ui/mir/mir_adt_construction.rs92
-rw-r--r--src/test/ui/mir/mir_ascription_coercion.rs10
-rw-r--r--src/test/ui/mir/mir_assign_eval_order.rs67
-rw-r--r--src/test/ui/mir/mir_augmented_assignments.rs160
-rw-r--r--src/test/ui/mir/mir_autoderef.rs28
-rw-r--r--src/test/ui/mir/mir_boxing.rs10
-rw-r--r--src/test/ui/mir/mir_build_match_comparisons.rs59
-rw-r--r--src/test/ui/mir/mir_call_with_associated_type.rs16
-rw-r--r--src/test/ui/mir/mir_calls_to_shims.rs50
-rw-r--r--src/test/ui/mir/mir_cast_fn_ret.rs23
-rw-r--r--src/test/ui/mir/mir_codegen_array.rs11
-rw-r--r--src/test/ui/mir/mir_codegen_array_2.rs9
-rw-r--r--src/test/ui/mir/mir_codegen_call_converging.rs17
-rw-r--r--src/test/ui/mir/mir_codegen_calls.rs192
-rw-r--r--src/test/ui/mir/mir_codegen_calls_converging_drops.rs26
-rw-r--r--src/test/ui/mir/mir_codegen_calls_converging_drops_2.rs30
-rw-r--r--src/test/ui/mir/mir_codegen_calls_diverging.rs15
-rw-r--r--src/test/ui/mir/mir_codegen_calls_diverging_drops.rs24
-rw-r--r--src/test/ui/mir/mir_codegen_critical_edge.rs44
-rw-r--r--src/test/ui/mir/mir_codegen_spike1.rs12
-rw-r--r--src/test/ui/mir/mir_codegen_switch.rs35
-rw-r--r--src/test/ui/mir/mir_codegen_switchint.rs12
-rw-r--r--src/test/ui/mir/mir_coercion_casts.rs10
-rw-r--r--src/test/ui/mir/mir_coercions.rs71
-rw-r--r--src/test/ui/mir/mir_const_prop_identity.rs12
-rw-r--r--src/test/ui/mir/mir_const_prop_tuple_field_reorder.rs27
-rw-r--r--src/test/ui/mir/mir_constval_adts.rs34
-rw-r--r--src/test/ui/mir/mir_detects_invalid_ops.rs24
-rw-r--r--src/test/ui/mir/mir_detects_invalid_ops.stderr16
-rw-r--r--src/test/ui/mir/mir_drop_order.rs49
-rw-r--r--src/test/ui/mir/mir_drop_panics.rs25
-rw-r--r--src/test/ui/mir/mir_dynamic_drops_1.rs31
-rw-r--r--src/test/ui/mir/mir_dynamic_drops_2.rs29
-rw-r--r--src/test/ui/mir/mir_dynamic_drops_3.rs35
-rw-r--r--src/test/ui/mir/mir_early_return_scope.rs29
-rw-r--r--src/test/ui/mir/mir_fat_ptr.rs52
-rw-r--r--src/test/ui/mir/mir_fat_ptr_drop.rs32
-rw-r--r--src/test/ui/mir/mir_heavy_promoted.rs11
-rw-r--r--src/test/ui/mir/mir_indexing_oob_1.rs14
-rw-r--r--src/test/ui/mir/mir_indexing_oob_2.rs14
-rw-r--r--src/test/ui/mir/mir_indexing_oob_3.rs14
-rw-r--r--src/test/ui/mir/mir_let_chains_drop_order.rs94
-rw-r--r--src/test/ui/mir/mir_match_arm_guard.rs16
-rw-r--r--src/test/ui/mir/mir_match_test.rs83
-rw-r--r--src/test/ui/mir/mir_misc_casts.rs320
-rw-r--r--src/test/ui/mir/mir_overflow_off.rs17
-rw-r--r--src/test/ui/mir/mir_raw_fat_ptr.rs216
-rw-r--r--src/test/ui/mir/mir_refs_correct.rs209
-rw-r--r--src/test/ui/mir/mir_small_agg_arg.rs8
-rw-r--r--src/test/ui/mir/mir_static_subtype.rs9
-rw-r--r--src/test/ui/mir/mir_struct_with_assoc_ty.rs29
-rw-r--r--src/test/ui/mir/mir_temp_promotions.rs10
-rw-r--r--src/test/ui/mir/mir_void_return.rs12
-rw-r--r--src/test/ui/mir/mir_void_return_2.rs10
-rw-r--r--src/test/ui/mir/remove-zsts-query-cycle.rs16
-rw-r--r--src/test/ui/mir/simplify-branch-same.rs21
-rw-r--r--src/test/ui/mir/ssa-analysis-regression-50041.rs36
-rw-r--r--src/test/ui/mir/thir-constparam-temp.rs20
-rw-r--r--src/test/ui/mir/thir-constparam-temp.stderr22
104 files changed, 3602 insertions, 0 deletions
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>([T; 1]);
+
+impl<T> B<T> {
+ 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<T>`, 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<const N: usize, T: Tr>() {
+ inner::<N, T>();
+ }
+
+ #[inline(always)]
+ fn inner<const N: usize, T: Tr>() {
+ inner::<N, T::Next>();
+ }
+ }
+)*}
+
+// 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::<u32>();
+}
+
+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<I>()
+where I: Foo,
+ I::Item: Bar
+{
+ Vec::<<I::Item as Bar>::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<Output = u8> {
+ (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::<String>::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<T>(std::marker::PhantomData<T>);
+
+impl<T> std::ops::Deref for S<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ todo!()
+ }
+}
+impl<T> std::ops::DerefMut for S<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ todo!()
+ }
+}
+
+async fn new() -> S<u64> {
+ 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<T> {
+ type O;
+ fn my_index(self) -> Self::O;
+}
+trait MyFrom<T>: Sized {
+ type Error;
+ fn my_from(value: T) -> Result<Self, Self::Error>;
+}
+
+trait F {}
+impl F for () {}
+type DummyT<T> = impl F;
+fn _dummy_t<T>() -> DummyT<T> {}
+
+struct Phantom1<T>(PhantomData<T>);
+struct Phantom2<T>(PhantomData<T>);
+struct Scope<T>(Phantom2<DummyT<T>>);
+
+impl<T> Scope<T> {
+ fn new() -> Self {
+ unimplemented!()
+ }
+}
+
+impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
+ type Error = ();
+ fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> {
+ unimplemented!()
+ }
+}
+
+impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<Phantom1<T>> for Scope<U> {
+ type O = T;
+ fn my_index(self) -> Self::O {
+ MyFrom::my_from(self.0).ok().unwrap()
+ }
+}
+
+#[rustc_error]
+fn main() {
+ //~^ ERROR
+ let _pos: Phantom1<DummyT<()>> = 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<Item = &'a T> {
+ 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<M> {
+ pub x: [usize; N],
+ pub m: M,
+}
+
+pub fn f() -> Elem<()> {
+ g(())
+}
+
+#[inline]
+pub fn g<M>(m: M) -> Elem<M> {
+ 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<u8>),
+ 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<MyEnum>);
+
+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<Item = String> {
+ 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<X> {
+ type Item = &'a X;
+}
+
+impl<X> Trait for Box<dyn Trait<Item = X>> {
+ type Item = X;
+}
+
+fn make_dyn_trait(_: &()) -> Box<dyn Trait<Item = &()>> {
+ todo!()
+}
+
+fn diff<'a, M, N, S>(_: N, _: S)
+where
+ M: 'a,
+ N: Trait<Item = &'a M>,
+ S: Trait<Item = &'a M>,
+{
+ todo!()
+}
+
+fn may_panic<X>(_: 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<T> Broken for T {
+ type Assoc = ();
+ fn broken(&self) where Self::Assoc: Foo {
+ let _x: <Self::Assoc as Foo>::Bar;
+ }
+}
+
+fn main() {
+ let _m: &dyn Broken<Assoc=()> = &();
+}
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<A = [(); (let a = (), 1).1]> {
+ //~^ `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<A = [(); (let a = (), 1).1]> {
+ | ^^^
+
+error: `let` expressions are not supported here
+ --> $DIR/issue-92893.rs:1:22
+ |
+LL | struct Bug<A = [(); (let a = (), 1).1]> {
+ | ^^^^^^^^^^
+ |
+ = 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<A = [(); (let a = (), 1).1]> {
+ | ^^^^^^^^^^
+ |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/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, const N: usize>([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<A: Array>() {
+ let _: *mut A::Item = std::ptr::null_mut();
+}
+
+struct Foo;
+impl Array for Foo { type Item = i32; }
+
+fn main() {
+ foo::<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: SliceIndex>(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<TokenTree> {
+ None
+ }
+}
+
+fn tokenstream_probably_equal_for_proc_macro() {
+ fn break_tokens(_tree: TokenTree) -> impl Iterator<Item = TokenTree> {
+ let token_trees: Vec<TokenTree> = 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<A>: Iterator<Item = A> {
+ 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<A, I: ?Sized> CollectArray<A> for I
+where
+ I: Iterator<Item = A>,
+{
+ fn inner_array(&mut self) -> [A; N] {
+ let mut result: [MaybeUninit<A>; N] = unsafe { MaybeUninit::uninit().assume_init() };
+ for (dest, item) in result.iter_mut().zip(self) {
+ *dest = MaybeUninit::new(item);
+ }
+ let temp_ptr: *const [MaybeUninit<A>; 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 `<u32 as Foo<'x>>::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) -> <u32 as Foo<'x>>::Value,
+}
+
+fn foo<'y, 'x: 'x>(x: &'x u32, y: &'y u32) -> <u32 as Foo<'x>>::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<u32>) -> (Option<u32>, Option<u32>) {
+ 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<u8> for Int {
+ fn shl_assign(&mut self, rhs: u8) {
+ self.0 <<= rhs;
+ }
+}
+
+impl ShlAssign<u16> for Int {
+ fn shl_assign(&mut self, rhs: u16) {
+ self.0 <<= rhs;
+ }
+}
+
+impl ShrAssign<u8> for Int {
+ fn shr_assign(&mut self, rhs: u8) {
+ self.0 >>= rhs;
+ }
+}
+
+impl ShrAssign<u16> 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<i32> 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<i32> {
+ 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<i8> = 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<T> {
+ 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<T>(mut t: T)
+ where T: Fn(u32, u32) -> u32,
+{
+ let as_fn = <T as Fn<(u32, u32)>>::call;
+ assert_eq!(as_fn(&t, (9, 3)), 3);
+ let as_fn_mut = <T as FnMut<(u32, u32)>>::call_mut;
+ assert_eq!(as_fn_mut(&mut t, (18, 3)), 6);
+ let as_fn_once = <T as FnOnce<(u32, u32)>>::call_once;
+ assert_eq!(as_fn_once(t, (24, 3)), 8);
+}
+
+fn assert_panics<F>(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<T>(mut t: T)
+ where T: Fn() -> !
+{
+ let as_fn = <T as Fn<()>>::call;
+ assert_panics(|| as_fn(&t, ()));
+ let as_fn_mut = <T as FnMut<()>>::call_mut;
+ assert_panics(|| as_fn_mut(&mut t, ()));
+ let as_fn_once = <T as FnOnce<()>>::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<T: Bar>(x: &T, a: isize) -> isize {
+ // Test calling extension method on generic callee
+ x.extension_method(a)
+}
+
+trait One<T = Self> {
+ fn one() -> T;
+}
+impl One for isize {
+ fn one() -> isize { 1 }
+}
+
+fn test7() -> isize {
+ // Test calling trait static method
+ <isize as One>::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: &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: &F, x: i32, y: i32) -> i32
+ where F: Fn(i32, i32) -> i32
+{
+ f.call((x, y))
+}
+
+fn test_fn_const_call<F>(f: &F) -> i32
+ where F: Fn(i32, i32) -> i32
+{
+ f.call((100, -1))
+}
+
+fn test_fn_nil_call<F>(f: &F) -> i32
+ where F: Fn() -> i32
+{
+ f()
+}
+
+fn test_fn_transmute_zst(x: ()) -> [(); 1] {
+ fn id<T>(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<T>(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<A: Iterator, B: Iterator> {
+ state: State,
+ a: A,
+ b: B
+}
+
+impl<A, B> Foo<A, B>
+where A: Iterator, B: Iterator<Item=A::Item>
+{
+ // This is the function we care about
+ fn next(&mut self) -> Option<A::Item> {
+ 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<dyn Iterator<Item=u32>>, Box<dyn Iterator<Item=u32>>>) {
+ 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>, U: ?Sized>
+ CoerceUnsized<PtrWrapper<'a, U>> for PtrWrapper<'a, T> {}
+
+struct TrivPtrWrapper<'a, T: 'a+?Sized>(&'a T);
+impl<'a, T: ?Sized+Unsize<U>, U: ?Sized>
+ CoerceUnsized<TrivPtrWrapper<'a, U>> 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<dyn Fn(u32) -> u32+Send>)
+ -> PtrWrapper<dyn Fn(u32) -> u32> {
+ p
+}
+
+fn coerce_ptr_wrapper_poly<'a, T, Trait: ?Sized>(p: PtrWrapper<'a, T>)
+ -> PtrWrapper<'a, Trait>
+ where PtrWrapper<'a, T>: CoerceUnsized<PtrWrapper<'a, Trait>>
+{
+ 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<dyn Fn(u32) -> 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<T>(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>(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<i32>, Newtype<i32>) = (Newtype(42), Newtype(42));
+
+fn mir() -> (Point, (i32, i32), (&'static str, &'static str), (Newtype<i32>, Newtype<i32>)) {
+ 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<RefCell<Vec<usize>>>
+}
+
+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<T: ?Sized>(#[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<RefCell<Vec<usize>>>
+}
+
+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>) -> 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<T: Copy>(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<T> Foo for T {
+ fn foo(&self) -> usize {
+ mem::size_of::<T>()
+ }
+}
+
+#[allow(unused_tuple_struct_fields)]
+struct S<T:?Sized>(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<U> {
+ fn f(self, other: U) -> u64;
+}
+
+impl F<u32> for u32 {
+ fn f(self, other: u32) -> u64 { self as u64 + other as u64 }
+}
+
+impl F<u64> for u32 {
+ fn f(self, other: u64) -> u64 { self as u64 - other }
+}
+
+impl F<u64> for u64 {
+ fn f(self, other: u64) -> u64 { self * other }
+}
+
+impl F<u32> for u64 {
+ fn f(self, other: u32) -> u64 { self ^ other as u64 }
+}
+
+trait T<I, O> {
+ fn staticmeth(i: I, o: O) -> (I, O) { (i, o) }
+}
+
+impl<I, O> T<I, O> 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<T>(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 {
+ <S as X>::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 {
+ <ext::S as ext::X>::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 {
+ <S as X>::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) {
+ <u32 as T<_, _>>::staticmeth
+}
+
+fn t21() -> Unit {
+ Unit
+}
+
+fn t22() -> Option<u8> {
+ 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), <S as X>::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), <ext::S as ext::X>::hoy(&sext));
+
+ let p = parametric::<u8>;
+ assert_eq!(t11() as *mut (), p as *mut ());
+
+ assert_eq!(t12(), C);
+ assert_eq!(t13(), C2);
+ assert_eq!(t13_2(), C3);
+
+ assert_eq!(t14()(), <S as X>::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), <u32 as T<_, _>>::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<T> DataBind for Global<T> {
+ type Data = T;
+}
+
+pub struct Global<T>(PhantomData<T>);
+
+pub struct Data {
+ pub offsets: <Global<[u32; 2]> 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<T: ?Sized>(*const T);
+
+struct Unique<T: ?Sized>(NonNull<T>);
+
+#[lang = "owned_box"]
+pub struct Box<T: ?Sized>(Unique<T>);
+
+impl<T: ?Sized> Drop for Box<T> {
+ fn drop(&mut self) {}
+}
+
+#[lang = "box_free"]
+#[inline(always)]
+unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
+ dealloc(ptr.0.0)
+}
+
+#[inline(never)]
+fn dealloc<T: ?Sized>(_: *const T) {}
+
+pub struct Foo<T>(T);
+
+pub fn foo(a: Option<Box<Foo<usize>>>) -> 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<const YIKES: Yikes>() {
+ 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<const YIKES: Yikes>() {
+ | ^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+