From 2bba98b1216e21fcb18e2242c491ae7205af8308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Fiala?= Date: Mon, 16 Oct 2023 14:29:36 +0200 Subject: [PATCH 01/38] Avoid unnecessary renumbering --- compiler/rustc_borrowck/src/renumber.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 5d6f5cc896782..ec0131c5349a1 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -81,6 +81,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> { #[instrument(skip(self), level = "debug")] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { + if matches!(ty_context, TyContext::ReturnTy(_)) { + // We will renumber the return ty when called again with `TyContext::LocalDecl` + return; + } *ty = self.renumber_regions(*ty, || RegionCtxt::TyContext(ty_context)); debug!(?ty); From eb31d7e7f8f0432017af3f7aa6789602a23ce3ed Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:10:30 -0700 Subject: [PATCH 02/38] FileCheck asm_unwind --- tests/mir-opt/inline/asm_unwind.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs index 0cf21fda72fac..596a4592f25ff 100644 --- a/tests/mir-opt/inline/asm_unwind.rs +++ b/tests/mir-opt/inline/asm_unwind.rs @@ -1,4 +1,3 @@ -// skip-filecheck // Tests inlining of `may_unwind` inline assembly. // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -20,5 +19,7 @@ fn foo() { // EMIT_MIR asm_unwind.main.Inline.diff pub fn main() { + // CHECK-LABEL: fn main( + // CHECK: (inlined foo) foo(); } From 07bb2d529674f5a2f0ab6795332dc89b4cfa1561 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:11:06 -0700 Subject: [PATCH 03/38] FileCheck caller_with_trivial_bound --- tests/mir-opt/inline/caller_with_trivial_bound.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.rs b/tests/mir-opt/inline/caller_with_trivial_bound.rs index 3829cbdd30240..722c7f6724efd 100644 --- a/tests/mir-opt/inline/caller_with_trivial_bound.rs +++ b/tests/mir-opt/inline/caller_with_trivial_bound.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // needs-unwind @@ -18,6 +17,8 @@ pub fn foo() where IntFactory: Factory, { + // CHECK-LABEL: fn foo( + // CHECK-NOT: (inlined bar::) let mut x: >::Item = bar::(); } From d9205cdf0ab06bcd00fcd495428436356fc35fce Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:11:22 -0700 Subject: [PATCH 04/38] FileCheck cycle --- tests/mir-opt/inline/cycle.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index 3e4f06834358e..8716b44b3dc02 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -1,20 +1,27 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -Zinline-mir-hint-threshold=1000 // EMIT_MIR cycle.f.Inline.diff #[inline(always)] fn f(g: impl Fn()) { + // CHECK-LABEL: fn f( + // CHECK-NOT: inlined g(); } // EMIT_MIR cycle.g.Inline.diff #[inline(always)] fn g() { + // CHECK-LABEL: fn g( + // CHECK: (inlined f::) + // CHECK-NOT: inlined f(main); } // EMIT_MIR cycle.main.Inline.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: (inlined f::) + // CHECK-NOT: inlined f(g); } From 820e791dbebe96d3e2510f689d00eb252e3208d1 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:11:37 -0700 Subject: [PATCH 05/38] FileCheck dont_ice_on_generic_rust_call --- tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs index 4147325ec44b9..3307a1408fb56 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -Zmir-enable-passes=+Inline --crate-type=lib @@ -8,5 +7,7 @@ use std::marker::Tuple; // EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff pub fn call(mut mock: Box>, input: I) { + // CHECK-LABEL: fn call( + // CHECK-NOT: (inlined > as FnMut>::call_mut) mock.call_mut(input) } From 2e9a7c2cf169c942ee549630931bdcfc385019b0 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:11:50 -0700 Subject: [PATCH 06/38] FileCheck dyn_trait --- tests/mir-opt/inline/dyn_trait.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs index 7b41b1e1171e2..005cf155fdb93 100644 --- a/tests/mir-opt/inline/dyn_trait.rs +++ b/tests/mir-opt/inline/dyn_trait.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] @@ -20,18 +19,26 @@ pub trait Query { // EMIT_MIR dyn_trait.mk_cycle.Inline.diff #[inline(always)] pub fn mk_cycle(c: &dyn Cache) { + // CHECK-LABEL: fn mk_cycle( + // CHECK-NOT: (inlined as Cache>::store_nocache) c.store_nocache() } // EMIT_MIR dyn_trait.try_execute_query.Inline.diff #[inline(always)] pub fn try_execute_query(c: &C) { + // CHECK-LABEL: fn try_execute_query( + // CHECK: (inlined mk_cycle::<::V>) mk_cycle(c) } // EMIT_MIR dyn_trait.get_query.Inline.diff #[inline(always)] pub fn get_query(t: &T) { + // CHECK-LABEL: fn get_query( + // CHECK-NOT: (inlined ::cache::) let c = Q::cache(t); + // CHECK: (inlined try_execute_query::<::C>) + // CHECK: (inlined mk_cycle::<::V>) try_execute_query(c) } From dfe047c42d1381db0012d6c60872780f07275e79 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:12:05 -0700 Subject: [PATCH 07/38] FileCheck exponential_runtime --- tests/mir-opt/inline/exponential_runtime.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs index 6d3af8b9c572a..499bec33ffc9b 100644 --- a/tests/mir-opt/inline/exponential_runtime.rs +++ b/tests/mir-opt/inline/exponential_runtime.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // Checks that code with exponential runtime does not have exponential behavior in inlining. @@ -85,5 +84,13 @@ impl A for () { // EMIT_MIR exponential_runtime.main.Inline.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: (inlined <() as G>::call) + // CHECK: (inlined <() as F>::call) + // CHECK: (inlined <() as E>::call) + // CHECK: (inlined <() as D>::call) + // CHECK: (inlined <() as C>::call) + // CHECK: (inlined <() as B>::call) + // CHECK-NOT: inlined <() as G>::call(); } From 8436a4611242f3bebc0946e8afcc4e61675c6a9a Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:12:17 -0700 Subject: [PATCH 08/38] FileCheck inline_any_operand --- tests/mir-opt/inline/inline_any_operand.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_any_operand.rs b/tests/mir-opt/inline/inline_any_operand.rs index e131cd6ef7ee8..659b7c3a0a1f5 100644 --- a/tests/mir-opt/inline/inline_any_operand.rs +++ b/tests/mir-opt/inline/inline_any_operand.rs @@ -1,4 +1,3 @@ -// skip-filecheck // compile-flags: -Z span_free_formats // Tests that MIR inliner works for any operand @@ -9,6 +8,8 @@ fn main() { // EMIT_MIR inline_any_operand.bar.Inline.after.mir fn bar() -> bool { + // CHECK-LABEL: fn bar( + // CHECK: (inlined foo) let f = foo; f(1, -1) } From 359d2ab55ea970f88ea751dd9b286603ea06dc6d Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:24:38 -0700 Subject: [PATCH 09/38] FileCheck inline_box_fn --- tests/mir-opt/inline/inline_box_fn.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_box_fn.rs b/tests/mir-opt/inline/inline_box_fn.rs index f6a90b92c9118..7686477c291a3 100644 --- a/tests/mir-opt/inline/inline_box_fn.rs +++ b/tests/mir-opt/inline/inline_box_fn.rs @@ -1,9 +1,10 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: Inline // compile-flags: --crate-type=lib // EMIT_MIR inline_box_fn.call.Inline.diff fn call(x: Box) { + // CHECK-LABEL: fn call( + // CHECK-NOT: (inlined as Fn<(i32,)>>::call) x(1); } From d67e934bd1f3f42ddf7b4df3d846f0785b7bf8e0 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:28:38 -0700 Subject: [PATCH 10/38] FileCheck inline_closure_borrows_arg --- tests/mir-opt/inline/inline_closure_borrows_arg.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.rs b/tests/mir-opt/inline/inline_closure_borrows_arg.rs index a5cc7d1036530..1570ab057c728 100644 --- a/tests/mir-opt/inline/inline_closure_borrows_arg.rs +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.rs @@ -1,4 +1,3 @@ -// skip-filecheck // compile-flags: -Z span_free_formats -Zunsound-mir-opts // Tests that MIR inliner can handle closure arguments, @@ -14,5 +13,8 @@ fn foo(_t: T, q: &i32) -> i32 { let variable = &*r; *variable }; + + // CHECK-LABEL: fn foo( + // CHECK: (inlined foo::::{closure#0}) x(q, q) } From b9015534134cb21eadd97e698a51fca0ccf017db Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:30:04 -0700 Subject: [PATCH 11/38] FileCheck inline_closure_captures --- tests/mir-opt/inline/inline_closure_captures.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_closure_captures.rs b/tests/mir-opt/inline/inline_closure_captures.rs index 0d95564e5ddee..2b08b10688728 100644 --- a/tests/mir-opt/inline/inline_closure_captures.rs +++ b/tests/mir-opt/inline/inline_closure_captures.rs @@ -1,4 +1,3 @@ -// skip-filecheck // compile-flags: -Z span_free_formats // Tests that MIR inliner can handle closure captures. @@ -10,5 +9,8 @@ fn main() { // EMIT_MIR inline_closure_captures.foo.Inline.after.mir fn foo(t: T, q: i32) -> (i32, T) { let x = |_q| (q, t); + + // CHECK-LABEL: fn foo( + // CHECK: (inlined foo::::{closure#0}) x(q) } From 149b8822bd7e02cffd7064461288aae0543cc7ad Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 11:31:05 -0700 Subject: [PATCH 12/38] FileCheck inline_closure --- tests/mir-opt/inline/inline_closure.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_closure.rs b/tests/mir-opt/inline/inline_closure.rs index bd4c84ff0ca29..65f55d49a806e 100644 --- a/tests/mir-opt/inline/inline_closure.rs +++ b/tests/mir-opt/inline/inline_closure.rs @@ -1,4 +1,3 @@ -// skip-filecheck // compile-flags: -Z span_free_formats // Tests that MIR inliner can handle closure arguments. (#45894) @@ -10,5 +9,8 @@ fn main() { // EMIT_MIR inline_closure.foo.Inline.after.mir fn foo(_t: T, q: i32) -> i32 { let x = |_t, _q| _t; + + // CHECK-LABEL: fn foo( + // CHECK: (inlined foo::::{closure#0}) x(q, q) } From 82a9ff0356a2bab2f0f5dd4e3e0d97cc41b1962a Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 14:04:52 -0700 Subject: [PATCH 13/38] FileCheck inline_compatibility --- tests/mir-opt/inline/inline_compatibility.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_compatibility.rs b/tests/mir-opt/inline/inline_compatibility.rs index 52f4debf5dbad..17bc91c6752be 100644 --- a/tests/mir-opt/inline/inline_compatibility.rs +++ b/tests/mir-opt/inline/inline_compatibility.rs @@ -1,4 +1,3 @@ -// skip-filecheck // Checks that only functions with compatible attributes are inlined. // // only-x86_64 @@ -12,22 +11,30 @@ // EMIT_MIR inline_compatibility.inlined_target_feature.Inline.diff #[target_feature(enable = "sse2")] pub unsafe fn inlined_target_feature() { + // CHECK-LABEL: fn inlined_target_feature( + // CHECK: (inlined target_feature) target_feature(); } // EMIT_MIR inline_compatibility.not_inlined_target_feature.Inline.diff pub unsafe fn not_inlined_target_feature() { + // CHECK-LABEL: fn not_inlined_target_feature( + // CHECK-NOT: (inlined target_feature) target_feature(); } // EMIT_MIR inline_compatibility.inlined_no_sanitize.Inline.diff #[no_sanitize(address)] pub unsafe fn inlined_no_sanitize() { + // CHECK-LABEL: fn inlined_no_sanitize( + // CHECK: (inlined no_sanitize) no_sanitize(); } // EMIT_MIR inline_compatibility.not_inlined_no_sanitize.Inline.diff pub unsafe fn not_inlined_no_sanitize() { + // CHECK-LABEL: fn not_inlined_no_sanitize( + // CHECK-NOT: (inlined no_sanitize) no_sanitize(); } @@ -41,6 +48,8 @@ pub unsafe fn no_sanitize() {} // EMIT_MIR inline_compatibility.not_inlined_c_variadic.Inline.diff pub unsafe fn not_inlined_c_variadic() { + // CHECK-LABEL: fn not_inlined_c_variadic( + // CHECK-NOT: (inlined sum) let s = sum(4u32, 4u32, 30u32, 200u32, 1000u32); } From 196c9ef30aa8480c934594082265c80b8bf59208 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 18:03:13 -0700 Subject: [PATCH 14/38] FileCheck inline_diverging --- tests/mir-opt/inline/inline_diverging.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs index 9e50b1ead2bc0..25a5b9c5c5e72 100644 --- a/tests/mir-opt/inline/inline_diverging.rs +++ b/tests/mir-opt/inline/inline_diverging.rs @@ -1,4 +1,3 @@ -// skip-filecheck // Tests inlining of diverging calls. // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -7,6 +6,8 @@ // EMIT_MIR inline_diverging.f.Inline.diff pub fn f() { + // CHECK-LABEL: fn f( + // CHECK: (inlined sleep) sleep(); } @@ -15,12 +16,17 @@ pub fn g(i: i32) -> u32 { if i > 0 { i as u32 } else { + // CHECK-LABEL: fn g( + // CHECK: (inlined panic) panic(); } } // EMIT_MIR inline_diverging.h.Inline.diff pub fn h() { + // CHECK-LABEL: fn h( + // CHECK: (inlined call_twice:: ! {sleep}>) + // CHECK-NOT: inlined call_twice(sleep); } From ac2278b79a9419b623c0ff4efed55953f695dd2f Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 18:15:32 -0700 Subject: [PATCH 15/38] FileCheck inline_coroutine --- ...ne_coroutine.main.Inline.panic-unwind.diff | 22 +++++++++---------- tests/mir-opt/inline/inline_coroutine.rs | 4 +++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index e7d020968389f..fdb42bf3d8a0e 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -4,26 +4,26 @@ fn main() -> () { let mut _0: (); let _1: std::ops::CoroutineState; - let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>; - let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}; - let mut _4: {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}; + let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>; + let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new) { ++ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}; ++ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _7: u32; + let mut _8: i32; + } @@ -37,20 +37,20 @@ - } - - bb1: { -+ _4 = {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8 (#0)}; ++ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; _3 = &mut _4; -- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}>::new(move _3) -> [return: bb2, unwind: bb5]; +- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5]; - } - - bb2: { -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}> { pointer: move _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: move _3 }; StorageDead(_3); -- _1 = <{coroutine@$DIR/inline_coroutine.rs:17:5: 17:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; +- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; + StorageLive(_5); + _5 = const false; + StorageLive(_6); + StorageLive(_7); -+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:17:5: 17:8}); ++ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } diff --git a/tests/mir-opt/inline/inline_coroutine.rs b/tests/mir-opt/inline/inline_coroutine.rs index d021cdac28efa..a82586bf2bfac 100644 --- a/tests/mir-opt/inline/inline_coroutine.rs +++ b/tests/mir-opt/inline/inline_coroutine.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -Zinline-mir-hint-threshold=1000 #![feature(coroutines, coroutine_trait)] @@ -8,6 +7,9 @@ use std::pin::Pin; // EMIT_MIR inline_coroutine.main.Inline.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: (inlined g) + // CHECK: (inlined g::{closure#0}) let _r = Pin::new(&mut g()).resume(false); } From 13138662fdeeb8557d9d32a8c2e717b6013fbb7f Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 18:21:41 -0700 Subject: [PATCH 16/38] FileCheck inline_instruction_set --- tests/mir-opt/inline/inline_instruction_set.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_instruction_set.rs b/tests/mir-opt/inline/inline_instruction_set.rs index 4ac4d462f82de..7cb59645587b6 100644 --- a/tests/mir-opt/inline/inline_instruction_set.rs +++ b/tests/mir-opt/inline/inline_instruction_set.rs @@ -1,4 +1,3 @@ -// skip-filecheck // Checks that only functions with the compatible instruction_set attributes are inlined. // // A function is "compatible" when the *callee* has the same attribute or no attribute. @@ -47,16 +46,26 @@ fn inline_always_and_using_inline_asm() { // EMIT_MIR inline_instruction_set.t32.Inline.diff #[instruction_set(arm::t32)] pub fn t32() { + // CHECK-LABEL: fn t32( + // CHECK-NOT: (inlined instruction_set_a32) instruction_set_a32(); + // CHECK: (inlined instruction_set_t32) instruction_set_t32(); + // CHECK: (inlined instruction_set_default) instruction_set_default(); + // CHECK-NOT: (inlined inline_always_and_using_inline_asm) inline_always_and_using_inline_asm(); } // EMIT_MIR inline_instruction_set.default.Inline.diff pub fn default() { + // CHECK-LABEL: fn default( + // CHECK-NOT: (inlined instruction_set_a32) instruction_set_a32(); + // CHECK-NOT: (inlined instruction_set_t32) instruction_set_t32(); + // CHECK: (inlined instruction_set_default) instruction_set_default(); + // CHECK: (inlined inline_always_and_using_inline_asm) inline_always_and_using_inline_asm(); } From 6e01ab9650173a18759c767d1deab95fd66986cc Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 20:33:22 -0700 Subject: [PATCH 17/38] FileCheck inline_into_box_place --- tests/mir-opt/inline/inline_into_box_place.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs index b755692afc214..65f8e2916b630 100644 --- a/tests/mir-opt/inline/inline_into_box_place.rs +++ b/tests/mir-opt/inline/inline_into_box_place.rs @@ -1,4 +1,3 @@ -// skip-filecheck // ignore-endian-big // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug MIR alignment checks in std alter the diff, breaking the test @@ -6,5 +5,7 @@ // EMIT_MIR inline_into_box_place.main.Inline.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: (inlined Box::>::new) let _x: Box> = Box::new(Vec::new()); } From 0764c8bdb3c04948c212a7bc0ae7f04e6acd2192 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 20:34:41 -0700 Subject: [PATCH 18/38] FileCheck inline_options --- tests/mir-opt/inline/inline_options.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs index 394a8c4945cdd..b940c64f0b886 100644 --- a/tests/mir-opt/inline/inline_options.rs +++ b/tests/mir-opt/inline/inline_options.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // Checks that inlining threshold can be controlled with // inline-mir-threshold and inline-hint-threshold options. @@ -8,7 +7,10 @@ // EMIT_MIR inline_options.main.Inline.after.mir fn main() { + // CHECK-LABEL: fn main( + // CHECK-NOT: (inlined not_inlined) not_inlined(); + // CHECK: (inlined inlined::) inlined::(); } From 0a8a0132aced59a217b2fa757fa8383a69a29419 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 20:38:15 -0700 Subject: [PATCH 19/38] FileCheck inline_retag --- tests/mir-opt/inline/inline_retag.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_retag.rs b/tests/mir-opt/inline/inline_retag.rs index f695b9f22e616..c90c0b819b7ba 100644 --- a/tests/mir-opt/inline/inline_retag.rs +++ b/tests/mir-opt/inline/inline_retag.rs @@ -1,4 +1,3 @@ -// skip-filecheck // compile-flags: -Z span_free_formats -Z mir-emit-retag // Tests that MIR inliner fixes up `Retag`'s `fn_entry` flag @@ -9,6 +8,8 @@ fn main() { // EMIT_MIR inline_retag.bar.Inline.after.mir fn bar() -> bool { + // CHECK-LABEL: fn bar( + // CHECK: (inlined foo) let f = foo; f(&1, &-1) } From af6b86ee381f7699ec84bfb94c4461ce1c5319b9 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 20:40:20 -0700 Subject: [PATCH 20/38] FileCheck inline_specialization --- tests/mir-opt/inline/inline_specialization.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs index eb0cf891dad01..6453abc008129 100644 --- a/tests/mir-opt/inline/inline_specialization.rs +++ b/tests/mir-opt/inline/inline_specialization.rs @@ -1,9 +1,10 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![feature(specialization)] // EMIT_MIR inline_specialization.main.Inline.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: (inlined as Foo>::bar) let x = as Foo>::bar(); } From ac19ff31082ef743b6c306cda68d957dbc84e2db Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 20:41:43 -0700 Subject: [PATCH 21/38] FileCheck inline_trait_method_2 --- tests/mir-opt/inline/inline_trait_method_2.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_trait_method_2.rs b/tests/mir-opt/inline/inline_trait_method_2.rs index e87609a8c7e00..b0b6a7b9b01de 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.rs +++ b/tests/mir-opt/inline/inline_trait_method_2.rs @@ -1,9 +1,11 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -Z span_free_formats -Z mir-opt-level=4 // EMIT_MIR inline_trait_method_2.test2.Inline.after.mir fn test2(x: &dyn X) -> bool { + // CHECK-LABEL: fn test2( + // CHECK: (inlined test) + // CHECK-NOT: (inlined ::y) test(x) } From 6eedec5f0e4b272127730c34d953ec4640332555 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 21:32:56 -0700 Subject: [PATCH 22/38] FileCheck inline_trait_method --- tests/mir-opt/inline/inline_trait_method.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs index 8a95adf3713e2..ea09966a2aa94 100644 --- a/tests/mir-opt/inline/inline_trait_method.rs +++ b/tests/mir-opt/inline/inline_trait_method.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -Z span_free_formats @@ -8,6 +7,8 @@ fn main() { // EMIT_MIR inline_trait_method.test.Inline.after.mir fn test(x: &dyn X) -> u32 { + // CHECK-LABEL: fn test( + // CHECK-NOT: (inlined ::y) x.y() } From 2846971ce578d20ee8cd85db1354765e8194ee5e Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 21:41:07 -0700 Subject: [PATCH 23/38] FileCheck inline_as_ref_as_mut --- tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs index da779fed76fb5..4517c88d71340 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs @@ -1,21 +1,28 @@ -// skip-filecheck // EMIT_MIR issue_58867_inline_as_ref_as_mut.a.Inline.after.mir pub fn a(x: &mut [T]) -> &mut [T] { + // CHECK-LABEL: fn a( + // CHECK: (inlined <[T] as AsMut<[T]>>::as_mut) x.as_mut() } // EMIT_MIR issue_58867_inline_as_ref_as_mut.b.Inline.after.mir pub fn b(x: &mut Box) -> &mut T { + // CHECK-LABEL: fn b( + // CHECK: (inlined as AsMut>::as_mut) x.as_mut() } // EMIT_MIR issue_58867_inline_as_ref_as_mut.c.Inline.after.mir pub fn c(x: &[T]) -> &[T] { + // CHECK-LABEL: fn c( + // CHECK: (inlined <[T] as AsRef<[T]>>::as_ref) x.as_ref() } // EMIT_MIR issue_58867_inline_as_ref_as_mut.d.Inline.after.mir pub fn d(x: &Box) -> &T { + // CHECK-LABEL: fn d( + // CHECK: (inlined as AsRef>::as_ref) x.as_ref() } From 13fe05c2725ad8a19e9fc4b08ae49a908b068d6b Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 21:57:08 -0700 Subject: [PATCH 24/38] FileCheck inline_scopes_parenting --- ...ssue_76997_inline_scopes_parenting.main.Inline.after.mir | 6 +++--- tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index d28c0441f63c3..ba5eb757cf977 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -2,8 +2,8 @@ fn main() -> () { let mut _0: (); - let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:6:13: 6:16}; - let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:6:13: 6:16}; + let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16}; + let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16}; let mut _3: ((),); let mut _4: (); let mut _5: (); @@ -19,7 +19,7 @@ fn main() -> () { bb0: { StorageLive(_1); - _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:6:13: 6:16}; + _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16}; StorageLive(_2); _2 = &_1; StorageLive(_3); diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs index c7147d42df996..2a7c931a659ee 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs @@ -1,8 +1,12 @@ -// skip-filecheck // Tests that MIR inliner can handle `SourceScopeData` parenting correctly. (#76997) // EMIT_MIR issue_76997_inline_scopes_parenting.main.Inline.after.mir fn main() { + // CHECK-LABEL: fn main( + // CHECK: scope 2 + // CHECK-NEXT: debug x + // CHECK-NEXT: scope 3 + // CHECK-NEXT: debug y let f = |x| { let y = x; y }; f(()) } From 1950f290f4f90507a99e7486bb7085360fcafd62 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 22:06:38 -0700 Subject: [PATCH 25/38] FileCheck issue_78442 --- tests/mir-opt/inline/issue_78442.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/issue_78442.rs b/tests/mir-opt/inline/issue_78442.rs index f83ed70d0db32..f9a5234283a03 100644 --- a/tests/mir-opt/inline/issue_78442.rs +++ b/tests/mir-opt/inline/issue_78442.rs @@ -1,4 +1,3 @@ -// skip-filecheck // compile-flags: -Z mir-opt-level=3 -Z inline-mir // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] @@ -9,6 +8,11 @@ pub fn bar

( // Error won't happen if "bar" is not generic _baz: P, ) { + // CHECK-LABEL: fn bar( + // CHECK: let mut {{.*}}: &fn() {foo}; + // CHECK: let {{.*}}: fn() {foo}; + // CHECK: (inlined hide_foo) + // CHECK-NOT: inlined hide_foo()(); } From 587926c12426c0b37f18b7ca4b0b42ceec069167 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 22:18:02 -0700 Subject: [PATCH 26/38] FileCheck unchecked_shifts --- tests/mir-opt/inline/unchecked_shifts.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs index 67666f2f713f2..805195dd8b375 100644 --- a/tests/mir-opt/inline/unchecked_shifts.rs +++ b/tests/mir-opt/inline/unchecked_shifts.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] #![feature(unchecked_math)] @@ -9,23 +8,31 @@ // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { + // CHECK-LABEL: fn unchecked_shl_unsigned_smaller( + // CHECK: (inlined core::num::::unchecked_shl) a.unchecked_shl(b) } // EMIT_MIR unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff // EMIT_MIR unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { + // CHECK-LABEL: fn unchecked_shr_signed_smaller( + // CHECK: (inlined core::num::::unchecked_shr) a.unchecked_shr(b) } // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.diff // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.mir pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { + // CHECK-LABEL: fn unchecked_shl_unsigned_bigger( + // CHECK: (inlined core::num::::unchecked_shl) a.unchecked_shl(b) } // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.Inline.diff // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.mir pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { + // CHECK-LABEL: fn unchecked_shr_signed_bigger( + // CHECK: (inlined core::num::::unchecked_shr) a.unchecked_shr(b) } From 1fa26012887e6f272165bac952a0564536409f11 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 22:21:03 -0700 Subject: [PATCH 27/38] FileCheck unsized_argument --- tests/mir-opt/inline/unsized_argument.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/unsized_argument.rs b/tests/mir-opt/inline/unsized_argument.rs index 22c88b83f9b1b..e8c2bc10be220 100644 --- a/tests/mir-opt/inline/unsized_argument.rs +++ b/tests/mir-opt/inline/unsized_argument.rs @@ -1,4 +1,3 @@ -// skip-filecheck // needs-unwind #![feature(unsized_fn_params)] @@ -7,6 +6,8 @@ fn callee(y: [i32]) {} // EMIT_MIR unsized_argument.caller.Inline.diff fn caller(x: Box<[i32]>) { + // CHECK-LABEL: fn caller( + // CHECK-NOT: (inlined callee) callee(*x); } From f474cf4de596c54f7cee73749a0b54137e9635bd Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Fri, 20 Oct 2023 22:22:32 -0700 Subject: [PATCH 28/38] FileCheck unwrap_unchecked --- tests/mir-opt/inline/unwrap_unchecked.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs index f8964eba227a4..be133706e5c22 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.rs +++ b/tests/mir-opt/inline/unwrap_unchecked.rs @@ -1,4 +1,3 @@ -// skip-filecheck #![crate_type = "lib"] // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -8,5 +7,7 @@ // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir pub unsafe fn unwrap_unchecked(slf: Option) -> T { + // CHECK-LABEL: fn unwrap_unchecked( + // CHECK: (inlined #[track_caller] Option::::unwrap_unchecked) slf.unwrap_unchecked() } From 1f35769f994ebd00d5a93125f5e1f7856a90d1e5 Mon Sep 17 00:00:00 2001 From: Ryan Mehri Date: Sun, 22 Oct 2023 09:27:43 -0700 Subject: [PATCH 29/38] address review comments --- tests/mir-opt/inline/asm_unwind.rs | 3 + .../inline/caller_with_trivial_bound.rs | 3 + tests/mir-opt/inline/cycle.rs | 2 + .../inline/dont_ice_on_generic_rust_call.rs | 2 +- tests/mir-opt/inline/dyn_trait.rs | 4 +- tests/mir-opt/inline/exponential_runtime.rs | 1 + tests/mir-opt/inline/inline_box_fn.rs | 2 +- .../inline/inline_retag.bar.Inline.after.mir | 59 ----------------- .../inline/inline_retag.bar.Inline.diff | 65 +++++++++++++++++++ tests/mir-opt/inline/inline_retag.rs | 11 +++- tests/mir-opt/inline/inline_trait_method.rs | 3 +- ...ine_scopes_parenting.main.Inline.after.mir | 6 +- .../issue_76997_inline_scopes_parenting.rs | 9 ++- 13 files changed, 100 insertions(+), 70 deletions(-) delete mode 100644 tests/mir-opt/inline/inline_retag.bar.Inline.after.mir create mode 100644 tests/mir-opt/inline/inline_retag.bar.Inline.diff diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs index 596a4592f25ff..0ae20e5221110 100644 --- a/tests/mir-opt/inline/asm_unwind.rs +++ b/tests/mir-opt/inline/asm_unwind.rs @@ -2,6 +2,7 @@ // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // needs-asm-support +// needs-unwind // compile-flags: -Zinline-mir-hint-threshold=1000 #![feature(asm_unwind)] @@ -21,5 +22,7 @@ fn foo() { pub fn main() { // CHECK-LABEL: fn main( // CHECK: (inlined foo) + // CHECK: asm!("", options(MAY_UNWIND)) -> [return: {{bb.*}}, unwind: [[unwind:bb.*]]]; + // CHECK: [[unwind]] (cleanup) foo(); } diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.rs b/tests/mir-opt/inline/caller_with_trivial_bound.rs index 722c7f6724efd..40f7f4bbab2f7 100644 --- a/tests/mir-opt/inline/caller_with_trivial_bound.rs +++ b/tests/mir-opt/inline/caller_with_trivial_bound.rs @@ -15,6 +15,9 @@ impl Factory for IntFactory { // EMIT_MIR caller_with_trivial_bound.foo.Inline.diff pub fn foo() where + // Because of this trivial bound, the inliner fails to normalize + // `>::Item`. + // Verify that we do not inline anything, which would cause validation ICEs. IntFactory: Factory, { // CHECK-LABEL: fn foo( diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index 8716b44b3dc02..350724235ba04 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -13,6 +13,7 @@ fn f(g: impl Fn()) { #[inline(always)] fn g() { // CHECK-LABEL: fn g( + // CHECK-NOT: inlined // CHECK: (inlined f::) // CHECK-NOT: inlined f(main); @@ -21,6 +22,7 @@ fn g() { // EMIT_MIR cycle.main.Inline.diff fn main() { // CHECK-LABEL: fn main( + // CHECK-NOT: inlined // CHECK: (inlined f::) // CHECK-NOT: inlined f(g); diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs index 3307a1408fb56..ce5e1855a716b 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs @@ -8,6 +8,6 @@ use std::marker::Tuple; // EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff pub fn call(mut mock: Box>, input: I) { // CHECK-LABEL: fn call( - // CHECK-NOT: (inlined > as FnMut>::call_mut) + // CHECK-NOT: inlined mock.call_mut(input) } diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs index 005cf155fdb93..ecf220a85e6a3 100644 --- a/tests/mir-opt/inline/dyn_trait.rs +++ b/tests/mir-opt/inline/dyn_trait.rs @@ -20,7 +20,7 @@ pub trait Query { #[inline(always)] pub fn mk_cycle(c: &dyn Cache) { // CHECK-LABEL: fn mk_cycle( - // CHECK-NOT: (inlined as Cache>::store_nocache) + // CHECK-NOT: inlined c.store_nocache() } @@ -36,7 +36,7 @@ pub fn try_execute_query(c: &C) { #[inline(always)] pub fn get_query(t: &T) { // CHECK-LABEL: fn get_query( - // CHECK-NOT: (inlined ::cache::) + // CHECK-NOT: inlined let c = Q::cache(t); // CHECK: (inlined try_execute_query::<::C>) // CHECK: (inlined mk_cycle::<::V>) diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs index 499bec33ffc9b..1199ce4e5588e 100644 --- a/tests/mir-opt/inline/exponential_runtime.rs +++ b/tests/mir-opt/inline/exponential_runtime.rs @@ -85,6 +85,7 @@ impl A for () { // EMIT_MIR exponential_runtime.main.Inline.diff fn main() { // CHECK-LABEL: fn main( + // CHECK-NOT: inlined // CHECK: (inlined <() as G>::call) // CHECK: (inlined <() as F>::call) // CHECK: (inlined <() as E>::call) diff --git a/tests/mir-opt/inline/inline_box_fn.rs b/tests/mir-opt/inline/inline_box_fn.rs index 7686477c291a3..d2da239399235 100644 --- a/tests/mir-opt/inline/inline_box_fn.rs +++ b/tests/mir-opt/inline/inline_box_fn.rs @@ -5,6 +5,6 @@ // EMIT_MIR inline_box_fn.call.Inline.diff fn call(x: Box) { // CHECK-LABEL: fn call( - // CHECK-NOT: (inlined as Fn<(i32,)>>::call) + // CHECK-NOT: inlined x(1); } diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir deleted file mode 100644 index 8c3f3a4589e63..0000000000000 --- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ /dev/null @@ -1,59 +0,0 @@ -// MIR for `bar` after Inline - -fn bar() -> bool { - let mut _0: bool; - let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; - let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; - let mut _3: &i32; - let _4: &i32; - let _5: i32; - let mut _6: &i32; - let _7: &i32; - let _8: i32; - scope 1 { - debug f => _1; - let mut _9: &i32; - let mut _10: &i32; - scope 2 (inlined foo) { - debug x => _3; - debug y => _6; - let mut _11: i32; - let mut _12: i32; - } - } - - bb0: { - StorageLive(_1); - _1 = foo; - StorageLive(_2); - _2 = _1; - StorageLive(_3); - StorageLive(_4); - _10 = const _; - Retag(_10); - _4 = &(*_10); - _3 = &(*_4); - StorageLive(_6); - StorageLive(_7); - _9 = const _; - Retag(_9); - _7 = &(*_9); - _6 = &(*_7); - Retag(_3); - Retag(_6); - StorageLive(_11); - _11 = (*_3); - StorageLive(_12); - _12 = (*_6); - _0 = Eq(move _11, move _12); - StorageDead(_12); - StorageDead(_11); - StorageDead(_6); - StorageDead(_3); - StorageDead(_2); - StorageDead(_1); - StorageDead(_7); - StorageDead(_4); - return; - } -} diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.diff b/tests/mir-opt/inline/inline_retag.bar.Inline.diff new file mode 100644 index 0000000000000..8f53f6342ec6d --- /dev/null +++ b/tests/mir-opt/inline/inline_retag.bar.Inline.diff @@ -0,0 +1,65 @@ +- // MIR for `bar` before Inline ++ // MIR for `bar` after Inline + + fn bar() -> bool { + let mut _0: bool; + let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; + let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; + let mut _3: &i32; + let _4: &i32; + let _5: i32; + let mut _6: &i32; + let _7: &i32; + let _8: i32; + scope 1 { + debug f => _1; + let mut _9: &i32; + let mut _10: &i32; ++ scope 2 (inlined foo) { ++ debug x => _3; ++ debug y => _6; ++ let mut _11: i32; ++ let mut _12: i32; ++ } + } + + bb0: { + StorageLive(_1); + _1 = foo; + StorageLive(_2); + _2 = _1; + StorageLive(_3); + StorageLive(_4); + _10 = const _; + Retag(_10); + _4 = &(*_10); + _3 = &(*_4); + StorageLive(_6); + StorageLive(_7); + _9 = const _; + Retag(_9); + _7 = &(*_9); + _6 = &(*_7); +- _0 = move _2(move _3, move _6) -> [return: bb1, unwind continue]; +- } +- +- bb1: { ++ Retag(_3); ++ Retag(_6); ++ StorageLive(_11); ++ _11 = (*_3); ++ StorageLive(_12); ++ _12 = (*_6); ++ _0 = Eq(move _11, move _12); ++ StorageDead(_12); ++ StorageDead(_11); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); + StorageDead(_7); + StorageDead(_4); + return; + } + } + diff --git a/tests/mir-opt/inline/inline_retag.rs b/tests/mir-opt/inline/inline_retag.rs index c90c0b819b7ba..b9058905892bf 100644 --- a/tests/mir-opt/inline/inline_retag.rs +++ b/tests/mir-opt/inline/inline_retag.rs @@ -6,10 +6,19 @@ fn main() { println!("{}", bar()); } -// EMIT_MIR inline_retag.bar.Inline.after.mir +// EMIT_MIR inline_retag.bar.Inline.diff fn bar() -> bool { // CHECK-LABEL: fn bar( // CHECK: (inlined foo) + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: bb0: { + // CHECK: Retag + // CHECK: Retag + // CHECK: Retag([[x]]); + // CHECK: Retag([[y]]); + // CHECK: return; + // CHECK-NEXT: } let f = foo; f(&1, &-1) } diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs index ea09966a2aa94..b39355637a1c5 100644 --- a/tests/mir-opt/inline/inline_trait_method.rs +++ b/tests/mir-opt/inline/inline_trait_method.rs @@ -1,3 +1,4 @@ +// Verify that we do not inline the default impl in a trait object. // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -Z span_free_formats @@ -8,7 +9,7 @@ fn main() { // EMIT_MIR inline_trait_method.test.Inline.after.mir fn test(x: &dyn X) -> u32 { // CHECK-LABEL: fn test( - // CHECK-NOT: (inlined ::y) + // CHECK-NOT: inlined x.y() } diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir index ba5eb757cf977..ba4f91b28d536 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -2,8 +2,8 @@ fn main() -> () { let mut _0: (); - let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16}; - let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16}; + let _1: {closure@$DIR/issue_76997_inline_scopes_parenting.rs:15:13: 15:16}; + let mut _2: &{closure@$DIR/issue_76997_inline_scopes_parenting.rs:15:13: 15:16}; let mut _3: ((),); let mut _4: (); let mut _5: (); @@ -19,7 +19,7 @@ fn main() -> () { bb0: { StorageLive(_1); - _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:10:13: 10:16}; + _1 = {closure@$DIR/issue_76997_inline_scopes_parenting.rs:15:13: 15:16}; StorageLive(_2); _2 = &_1; StorageLive(_3); diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs index 2a7c931a659ee..2fb363c19044d 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs @@ -3,10 +3,15 @@ // EMIT_MIR issue_76997_inline_scopes_parenting.main.Inline.after.mir fn main() { // CHECK-LABEL: fn main( - // CHECK: scope 2 + // CHECK: scope 1 { + // CHECK-NEXT: debug f + // CHECK-NEXT: scope 2 (inlined main::{closure#0}) { // CHECK-NEXT: debug x - // CHECK-NEXT: scope 3 + // CHECK-NEXT: scope 3 { // CHECK-NEXT: debug y + // CHECK-NEXT: } + // CHECK-NEXT: } + // CHECK-NEXT: } let f = |x| { let y = x; y }; f(()) } From 66a554b04539a1319c68b3d52c7c3e027208dfec Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Fri, 20 Oct 2023 23:05:38 -0700 Subject: [PATCH 30/38] Add method to convert internal to stable constructs --- Cargo.lock | 1 + compiler/rustc_smir/Cargo.toml | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 58 ++++- compiler/rustc_smir/src/rustc_smir/mod.rs | 206 +++++++++++------- compiler/stable_mir/src/lib.rs | 52 ++--- 5 files changed, 197 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f8d566c2d156..d0422340c5258 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4524,6 +4524,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_target", + "scoped-tls", "stable_mir", "tracing", ] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 41c7d3a859437..47dd7372f3d18 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -9,6 +9,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } +scoped-tls = "1.0" stable_mir = {path = "../stable_mir" } tracing = "0.1" diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index f7e519570fa56..7bec946788b31 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,7 +3,7 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. -use crate::rustc_smir::Tables; +use crate::rustc_smir::{Stable, Tables, TablesWrapper}; use rustc_data_structures::fx; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::mir::interpret::AllocId; @@ -11,13 +11,21 @@ use rustc_middle::ty; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; +use scoped_tls::scoped_thread_local; use stable_mir::ty::IndexedVal; +use std::cell::Cell; +use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; +use std::rc::Rc; mod internal; +pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { + with_tables(|tables| item.stable(tables)) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -125,18 +133,44 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { item.id.into() } +// A thread local variable that stores a pointer to the tables mapping between TyCtxt +// datastructures and stable MIR datastructures +scoped_thread_local! (static TLV: Cell<*const ()>); + +pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) { + assert!(!TLV.is_set()); + fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) { + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); + } + g(&tables, f); +} + +/// Loads the current context and calls a function with it. +/// Do not nest these, as that will ICE. +pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R { + assert!(TLV.is_set()); + TLV.with(|tlv| { + let ptr = tlv.get(); + assert!(!ptr.is_null()); + let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) }; + let mut tables = wrapper.0.borrow_mut(); + f(&mut *tables) + }) +} + pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - stable_mir::run( - Tables { - tcx, - def_ids: IndexMap::default(), - alloc_ids: IndexMap::default(), - spans: IndexMap::default(), - types: vec![], - instances: IndexMap::default(), - }, - f, - ); + let tables = Rc::new(RefCell::new(Tables { + tcx, + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), + types: vec![], + instances: IndexMap::default(), + })); + stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f)); } #[macro_export] diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index d5379797f1c6b..19ad9898db168 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -23,27 +23,31 @@ use stable_mir::ty::{ FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, }; use stable_mir::{self, opaque, Context, Filename}; +use std::cell::RefCell; use tracing::debug; mod alloc; mod builder; -impl<'tcx> Context for Tables<'tcx> { +impl<'tcx> Context for TablesWrapper<'tcx> { fn local_crate(&self) -> stable_mir::Crate { - smir_crate(self.tcx, LOCAL_CRATE) + let tables = self.0.borrow(); + smir_crate(tables.tcx, LOCAL_CRATE) } fn external_crates(&self) -> Vec { - self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect() + let tables = self.0.borrow(); + tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect() } fn find_crates(&self, name: &str) -> Vec { + let tables = self.0.borrow(); let crates: Vec = [LOCAL_CRATE] .iter() - .chain(self.tcx.crates(()).iter()) + .chain(tables.tcx.crates(()).iter()) .map(|crate_num| { - let crate_name = self.tcx.crate_name(*crate_num).to_string(); - (name == crate_name).then(|| smir_crate(self.tcx, *crate_num)) + let crate_name = tables.tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) }) .into_iter() .filter_map(|c| c) @@ -52,163 +56,197 @@ impl<'tcx> Context for Tables<'tcx> { } fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String { - self.tcx.def_path_str(self[def_id]) + let tables = self.0.borrow(); + tables.tcx.def_path_str(tables[def_id]) } fn span_to_string(&self, span: stable_mir::ty::Span) -> String { - self.tcx.sess.source_map().span_to_diagnostic_string(self[span]) + let tables = self.0.borrow(); + tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span]) } fn get_filename(&self, span: &Span) -> Filename { + let tables = self.0.borrow(); opaque( - &self + &tables .tcx .sess .source_map() - .span_to_filename(self[*span]) + .span_to_filename(tables[*span]) .display(rustc_span::FileNameDisplayPreference::Local) .to_string(), ) } fn get_lines(&self, span: &Span) -> LineInfo { - let lines = &self.tcx.sess.source_map().span_to_location_info(self[*span]); + let tables = self.0.borrow(); + let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]); LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 } } - fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind { - self.tcx.def_kind(self[def_id]).stable(self) + fn def_kind(&self, def_id: stable_mir::DefId) -> stable_mir::DefKind { + let mut tables = self.0.borrow_mut(); + tables.tcx.def_kind(tables[def_id]).stable(&mut *tables) } - fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span { - self.tcx.def_span(self[def_id]).stable(self) + fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { + let mut tables = self.0.borrow_mut(); + tables.tcx.def_span(tables[def_id]).stable(&mut *tables) } - fn all_local_items(&mut self) -> stable_mir::CrateItems { - self.tcx.mir_keys(()).iter().map(|item| self.crate_item(item.to_def_id())).collect() + fn all_local_items(&self) -> stable_mir::CrateItems { + let mut tables = self.0.borrow_mut(); + tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect() } - fn entry_fn(&mut self) -> Option { - Some(self.crate_item(self.tcx.entry_fn(())?.0)) + fn entry_fn(&self) -> Option { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + Some(tables.crate_item(tcx.entry_fn(())?.0)) } - fn all_trait_decls(&mut self) -> stable_mir::TraitDecls { - self.tcx + fn all_trait_decls(&self) -> stable_mir::TraitDecls { + let mut tables = self.0.borrow_mut(); + tables + .tcx .traits(LOCAL_CRATE) .iter() - .map(|trait_def_id| self.trait_def(*trait_def_id)) + .map(|trait_def_id| tables.trait_def(*trait_def_id)) .collect() } - fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { - let def_id = self[trait_def.0]; - let trait_def = self.tcx.trait_def(def_id); - trait_def.stable(self) + fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { + let mut tables = self.0.borrow_mut(); + let def_id = tables[trait_def.0]; + let trait_def = tables.tcx.trait_def(def_id); + trait_def.stable(&mut *tables) } - fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls { - self.tcx + fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls { + let mut tables = self.0.borrow_mut(); + tables + .tcx .trait_impls_in_crate(LOCAL_CRATE) .iter() - .map(|impl_def_id| self.impl_def(*impl_def_id)) + .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() } - fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { - let def_id = self[impl_def.0]; - let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap(); - impl_trait.stable(self) + fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { + let mut tables = self.0.borrow_mut(); + let def_id = tables[impl_def.0]; + let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap(); + impl_trait.stable(&mut *tables) } - fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body { - let def_id = self[item]; - self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self) + fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body { + let mut tables = self.0.borrow_mut(); + let def_id = tables[item]; + tables.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(&mut tables) } - fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { - self.types[ty.0].clone().stable(self) + fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind { + let mut tables = self.0.borrow_mut(); + tables.types[ty.0].clone().stable(&mut *tables) } - fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty { - let n = self.types.len(); - self.types.push(MaybeStable::Stable(kind)); + fn mk_ty(&self, kind: TyKind) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let n = tables.types.len(); + tables.types.push(MaybeStable::Stable(kind)); stable_mir::ty::Ty(n) } - fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { - let def_id = self[def_id]; - let generics = self.tcx.generics_of(def_id); - generics.stable(self) + fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let generics = tables.tcx.generics_of(def_id); + generics.stable(&mut *tables) } - fn predicates_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { - let def_id = self[def_id]; - let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id); + fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let ty::GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id); stable_mir::ty::GenericPredicates { - parent: parent.map(|did| self.trait_def(did)), + parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() .map(|(clause, span)| { - (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + ( + clause.as_predicate().kind().skip_binder().stable(&mut *tables), + span.stable(&mut *tables), + ) }) .collect(), } } fn explicit_predicates_of( - &mut self, + &self, def_id: stable_mir::DefId, ) -> stable_mir::ty::GenericPredicates { - let def_id = self[def_id]; - let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id); + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let ty::GenericPredicates { parent, predicates } = + tables.tcx.explicit_predicates_of(def_id); stable_mir::ty::GenericPredicates { - parent: parent.map(|did| self.trait_def(did)), + parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() .map(|(clause, span)| { - (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + ( + clause.as_predicate().kind().skip_binder().stable(&mut *tables), + span.stable(&mut *tables), + ) }) .collect(), } } - fn instance_body(&mut self, def: InstanceDef) -> Body { - let instance = self.instances[def]; - builder::BodyBuilder::new(self.tcx, instance).build(self) + fn instance_body(&self, def: InstanceDef) -> Body { + let mut tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables) } - fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty { - let instance = self.instances[def]; - let ty = instance.ty(self.tcx, ParamEnv::empty()); - self.intern_ty(ty) + fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + let ty = instance.ty(tables.tcx, ParamEnv::empty()); + tables.intern_ty(ty) } - fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId { - let def_id = self.instances[def].def_id(); - self.create_def_id(def_id) + fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId { + let mut tables = self.0.borrow_mut(); + let def_id = tables.instances[def].def_id(); + tables.create_def_id(def_id) } - fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { - let def_id = self[item.0]; - Instance::mono(self.tcx, def_id).stable(self) + fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { + let mut tables = self.0.borrow_mut(); + let def_id = tables[item.0]; + Instance::mono(tables.tcx, def_id).stable(&mut *tables) } fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool { - let def_id = self[def_id]; - let generics = self.tcx.generics_of(def_id); - let result = generics.requires_monomorphization(self.tcx); + let tables = self.0.borrow(); + let def_id = tables[def_id]; + let generics = tables.tcx.generics_of(def_id); + let result = generics.requires_monomorphization(tables.tcx); result } fn resolve_instance( - &mut self, + &self, def: stable_mir::ty::FnDef, args: &stable_mir::ty::GenericArgs, ) -> Option { - let def_id = def.0.internal(self); - let args_ref = args.internal(self); - match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) { - Ok(Some(instance)) => Some(instance.stable(self)), + let mut tables = self.0.borrow_mut(); + let def_id = def.0.internal(&mut *tables); + let args_ref = args.internal(&mut *tables); + match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) { + Ok(Some(instance)) => Some(instance.stable(&mut *tables)), Ok(None) | Err(_) => None, } } @@ -241,13 +279,15 @@ impl PartialEq for MaybeStable { } } +pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc>>); + pub struct Tables<'tcx> { - pub tcx: TyCtxt<'tcx>, - pub def_ids: IndexMap, - pub alloc_ids: IndexMap, - pub spans: IndexMap, - pub types: Vec>>, - pub instances: IndexMap, InstanceDef>, + pub(crate) tcx: TyCtxt<'tcx>, + pub(crate) def_ids: IndexMap, + pub(crate) alloc_ids: IndexMap, + pub(crate) spans: IndexMap, + pub(crate) types: Vec>>, + pub(crate) instances: IndexMap, InstanceDef>, } impl<'tcx> Tables<'tcx> { @@ -270,7 +310,7 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { } /// Trait used to convert between an internal MIR type to a Stable MIR type. -pub(crate) trait Stable<'tcx> { +pub trait Stable<'tcx> { /// The stable representation of the type implementing Stable. type T; /// Converts an object to the equivalent Stable MIR representation. diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index be5ccac78c7c6..512c3fc629645 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -175,17 +175,17 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { } pub trait Context { - fn entry_fn(&mut self) -> Option; + fn entry_fn(&self) -> Option; /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&mut self) -> CrateItems; - fn mir_body(&mut self, item: DefId) -> mir::Body; - fn all_trait_decls(&mut self) -> TraitDecls; - fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl; - fn all_trait_impls(&mut self) -> ImplTraitDecls; - fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; - fn generics_of(&mut self, def_id: DefId) -> Generics; - fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates; - fn explicit_predicates_of(&mut self, def_id: DefId) -> GenericPredicates; + fn all_local_items(&self) -> CrateItems; + fn mir_body(&self, item: DefId) -> mir::Body; + fn all_trait_decls(&self) -> TraitDecls; + fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; + fn all_trait_impls(&self) -> ImplTraitDecls; + fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; + fn generics_of(&self, def_id: DefId) -> Generics; + fn predicates_of(&self, def_id: DefId) -> GenericPredicates; + fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. @@ -207,61 +207,61 @@ pub trait Context { fn get_lines(&self, span: &Span) -> LineInfo; /// Returns the `kind` of given `DefId` - fn def_kind(&mut self, def_id: DefId) -> DefKind; + fn def_kind(&self, def_id: DefId) -> DefKind; /// `Span` of an item - fn span_of_an_item(&mut self, def_id: DefId) -> Span; + fn span_of_an_item(&self, def_id: DefId) -> Span; /// Obtain the representation of a type. - fn ty_kind(&mut self, ty: Ty) -> TyKind; + fn ty_kind(&self, ty: Ty) -> TyKind; /// Create a new `Ty` from scratch without information from rustc. - fn mk_ty(&mut self, kind: TyKind) -> Ty; + fn mk_ty(&self, kind: TyKind) -> Ty; /// Get the body of an Instance. /// FIXME: Monomorphize the body. - fn instance_body(&mut self, instance: InstanceDef) -> Body; + fn instance_body(&self, instance: InstanceDef) -> Body; /// Get the instance type with generic substitutions applied and lifetimes erased. - fn instance_ty(&mut self, instance: InstanceDef) -> Ty; + fn instance_ty(&self, instance: InstanceDef) -> Ty; /// Get the instance. - fn instance_def_id(&mut self, instance: InstanceDef) -> DefId; + fn instance_def_id(&self, instance: InstanceDef) -> DefId; /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. - fn mono_instance(&mut self, item: CrateItem) -> Instance; + fn mono_instance(&self, item: CrateItem) -> Instance; /// Item requires monomorphization. fn requires_monomorphization(&self, def_id: DefId) -> bool; /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&mut self, def: FnDef, args: &GenericArgs) -> Option; + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt // datastructures and stable MIR datastructures -scoped_thread_local! (static TLV: Cell<*mut ()>); +scoped_thread_local! (static TLV: Cell<*const ()>); -pub fn run(mut context: impl Context, f: impl FnOnce()) { +pub fn run(context: impl Context, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) { - let ptr: *mut () = &mut context as *mut &mut _ as _; + fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) { + let ptr: *const () = &context as *const &_ as _; TLV.set(&Cell::new(ptr), || { f(); }); } - g(&mut context, f); + g(&context, f); } /// Loads the current context and calls a function with it. /// Do not nest these, as that will ICE. -pub fn with(f: impl FnOnce(&mut dyn Context) -> R) -> R { +pub fn with(f: impl FnOnce(&dyn Context) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - f(unsafe { *(ptr as *mut &mut dyn Context) }) + f(unsafe { *(ptr as *const &dyn Context) }) }) } From f613b26cfbfea5d7b1afbbad57be8e5774669775 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 12:02:17 -0700 Subject: [PATCH 31/38] Add `internal()` method counterpart to `stable()` Note: We do not expect to provide internalizing methods for all StableMIR constructs. They exist only to help migrating efforts to allow users to mix StableMIR and internal constructs. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 7bec946788b31..58cdcd49087e5 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -26,6 +26,10 @@ pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.stable(tables)) } +pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { + with_tables(|tables| item.internal(tables)) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -285,7 +289,7 @@ impl Index { +pub trait RustcInternal<'tcx> { type T; fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T; } From 421631a3a1fb4fe5f12d3212c070f95ea501471e Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 14:21:24 -0700 Subject: [PATCH 32/38] Remove unsafe and `Rc` --- compiler/rustc_smir/src/rustc_internal/mod.rs | 22 ++++++++----------- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- compiler/stable_mir/src/lib.rs | 13 +++++------ 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 58cdcd49087e5..efbf9eba04c34 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -18,15 +18,14 @@ use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; -use std::rc::Rc; mod internal; -pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { +pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.stable(tables)) } -pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { +pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.internal(tables)) } @@ -141,15 +140,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { // datastructures and stable MIR datastructures scoped_thread_local! (static TLV: Cell<*const ()>); -pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) { +pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) { - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); - } - g(&tables, f); + let ptr: *const () = &tables as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } /// Loads the current context and calls a function with it. @@ -166,7 +162,7 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R } pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - let tables = Rc::new(RefCell::new(Tables { + let tables = TablesWrapper(RefCell::new(Tables { tcx, def_ids: IndexMap::default(), alloc_ids: IndexMap::default(), @@ -174,7 +170,7 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { types: vec![], instances: IndexMap::default(), })); - stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f)); + stable_mir::run(&tables, || init(&tables, f)); } #[macro_export] diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 19ad9898db168..d5a5f800a40c0 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -279,7 +279,7 @@ impl PartialEq for MaybeStable { } } -pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc>>); +pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell>); pub struct Tables<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 512c3fc629645..8cacbdbda487f 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -243,15 +243,12 @@ pub trait Context { // datastructures and stable MIR datastructures scoped_thread_local! (static TLV: Cell<*const ()>); -pub fn run(context: impl Context, f: impl FnOnce()) { +pub fn run(context: &dyn Context, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) { - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); - } - g(&context, f); + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } /// Loads the current context and calls a function with it. From cb618162b138be0e0472d0f5540e6fc0d5a11210 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Thu, 19 Oct 2023 21:12:19 +0800 Subject: [PATCH 33/38] compiler: Add target features for LoongArch --- .../rustc_codegen_ssa/src/target_features.rs | 16 ++++++++++++++++ compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + 3 files changed, 18 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index baf6b19d3f97e..13a3f432b0398 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -342,6 +342,19 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("hard-float-abi", Some(sym::csky_target_feature)), // tidy-alphabetical-end ]; + +const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // tidy-alphabetical-start + ("d", Some(sym::loongarch_target_feature)), + ("f", Some(sym::loongarch_target_feature)), + ("lasx", Some(sym::loongarch_target_feature)), + ("lbt", Some(sym::loongarch_target_feature)), + ("lsx", Some(sym::loongarch_target_feature)), + ("lvz", Some(sym::loongarch_target_feature)), + ("ual", Some(sym::loongarch_target_feature)), + // tidy-alphabetical-end +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -358,6 +371,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Opt "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, "bpf" => BPF_ALLOWED_FEATURES, "csky" => CSKY_ALLOWED_FEATURES, + "loongarch64" => LOONGARCH_ALLOWED_FEATURES, _ => &[], } } @@ -445,6 +460,7 @@ pub fn from_target_feature( Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, Some(sym::csky_target_feature) => rust_features.csky_target_feature, + Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8185a8a3e437d..695de54eefa0a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -288,6 +288,7 @@ declare_features! ( (unstable, csky_target_feature, "1.73.0", Some(44839), None), (unstable, ermsb_target_feature, "1.49.0", Some(44839), None), (unstable, hexagon_target_feature, "1.27.0", Some(44839), None), + (unstable, loongarch_target_feature, "1.73.0", Some(44839), None), (unstable, mips_target_feature, "1.27.0", Some(44839), None), (unstable, powerpc_target_feature, "1.27.0", Some(44839), None), (unstable, riscv_target_feature, "1.45.0", Some(44839), None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5b58cf8b6d629..50d969890419b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -957,6 +957,7 @@ symbols! { log_syntax, logf32, logf64, + loongarch_target_feature, loop_break_value, lt, macro_at_most_once_rep, From 6cf9423770437bd6f7b4f8ab0fb81dc2ae722ac0 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Thu, 19 Oct 2023 21:13:52 +0800 Subject: [PATCH 34/38] tests: Add features-gate for LoongArch --- tests/ui/target-feature/gate.rs | 1 + tests/ui/target-feature/gate.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 782444417a8fc..971a4654b4cec 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -18,6 +18,7 @@ // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature // gate-test-csky_target_feature +// gate-test-loongarch_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index f56efb3bb831e..0ec7427c3c456 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:22:18 + --> $DIR/gate.rs:23:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From 300d04dc70a28188bf34e4476eb85ecd96f6a99b Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 24 Oct 2023 11:43:46 +0800 Subject: [PATCH 35/38] tests/ui/abi/compatibility: Set min-llvm-version to 17 for LoongArch64 --- tests/ui/abi/compatibility.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 1f049b1785a62..0cdf229711ad0 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -30,6 +30,7 @@ // revisions: loongarch64 //[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //[loongarch64] needs-llvm-components: loongarch +//[loongarch64] min-llvm-version: 17 // revisions: wasm //[wasm] compile-flags: --target wasm32-unknown-unknown //[wasm] needs-llvm-components: webassembly From ae86f59cc9dd7d4be3c47d9ecbc3b98ca1f514a8 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 21:35:30 -0700 Subject: [PATCH 36/38] Add test and remove double ref --- compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +- .../ui-fulldeps/stable-mir/check_instance.rs | 33 +++++----- tests/ui-fulldeps/stable-mir/smir_internal.rs | 64 +++++++++++++++++++ 3 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/smir_internal.rs diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index efbf9eba04c34..d3ea8cdc699a0 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -142,7 +142,7 @@ scoped_thread_local! (static TLV: Cell<*const ()>); pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { assert!(!TLV.is_set()); - let ptr: *const () = &tables as *const &_ as _; + let ptr = tables as *const _ as *const (); TLV.set(&Cell::new(ptr), || { f(); }); @@ -155,8 +155,8 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) }; - let mut tables = wrapper.0.borrow_mut(); + let wrapper = ptr as *const TablesWrapper<'tcx>; + let mut tables = unsafe { (*wrapper).0.borrow_mut() }; f(&mut *tables) }) } diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index c6a9e08ed0260..ee82bc77aedae 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -1,5 +1,5 @@ // run-pass -// Test that users are able to use stable mir APIs to retrieve monomorphized instances +//! Test that users are able to use stable mir APIs to retrieve monomorphized instances // ignore-stage1 // ignore-cross-compile @@ -14,15 +14,15 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_smir; -extern crate stable_mir; extern crate rustc_driver; extern crate rustc_interface; +extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use mir::{mono::Instance, TerminatorKind::*}; -use stable_mir::ty::{TyKind, RigidTy}; -use stable_mir::*; +use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; +use stable_mir::ty::{RigidTy, TyKind}; +use stable_mir::*; use std::io::Write; use std::ops::ControlFlow; @@ -33,16 +33,16 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let items = stable_mir::all_local_items(); // Get all items and split generic vs monomorphic items. - let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| { - item.requires_monomorphization() - }); + let (generic, mono): (Vec<_>, Vec<_>) = + items.into_iter().partition(|item| item.requires_monomorphization()); assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. - let instances = mono.iter().filter_map(|item| { - mir::mono::Instance::try_from(*item).ok() - }).collect::>(); + let instances = mono + .iter() + .filter_map(|item| mir::mono::Instance::try_from(*item).ok()) + .collect::>(); assert_eq!(instances.len(), mono.len()); // For all generic items, try_from should fail. @@ -58,19 +58,22 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { fn test_body(body: mir::Body) { for term in body.blocks.iter().map(|bb| &bb.terminator) { match &term.kind { - Call{ func, .. } => { + Call { func, .. } => { let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; let result = Instance::resolve(def, &args); assert!(result.is_ok()); } - Goto {..} | Assert{..} | SwitchInt{..} | Return | Drop {..} => { /* Do nothing */} - _ => { unreachable!("Unexpected terminator {term:?}") } + Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => { + /* Do nothing */ + } + _ => { + unreachable!("Unexpected terminator {term:?}") + } } } } - /// This test will generate and analyze a dummy crate using the stable mir. /// For that, it will first write the dummy crate into a file. /// Then it will create a `StableMir` using custom arguments and then diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs new file mode 100644 index 0000000000000..5ad05559cb4bb --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -0,0 +1,64 @@ +// run-pass +//! Test that users are able to use retrieve internal constructs from stable ones to help with +//! the migration. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let main_fn = stable_mir::entry_fn().unwrap(); + let body = main_fn.body(); + let orig_ty = body.locals[0].ty; + let rustc_ty = rustc_internal::internal(&orig_ty); + assert!(rustc_ty.is_unit()); + ControlFlow::Continue(()) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "internal_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_translation(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub fn main() {{ + }} + "# + )?; + Ok(()) +} From 2b36547e9cf3ff0331953571201e9ce451782c44 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Aug 2023 10:54:37 +0200 Subject: [PATCH 37/38] Introduce `-C instrument-coverage=branch` to gate branch coverage This flag has to be used in combination with `-Zunstable-options`, and is added in advance of adding branch coverage instrumentation. --- compiler/rustc_session/src/config.rs | 8 +++++++- compiler/rustc_session/src/options.rs | 5 ++++- compiler/rustc_session/src/session.rs | 4 ++++ tests/ui/instrument-coverage/bad-value.bad.stderr | 2 +- tests/ui/instrument-coverage/bad-value.blank.stderr | 2 +- .../ui/instrument-coverage/except-unused-functions.stderr | 2 +- .../ui/instrument-coverage/except-unused-generics.stderr | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 462e7e85c65ac..84933588f17fe 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -169,6 +169,9 @@ pub enum MirSpanview { pub enum InstrumentCoverage { /// Default `-C instrument-coverage` or `-C instrument-coverage=statement` All, + /// Additionally, instrument branches and output branch coverage. + /// `-Zunstable-options -C instrument-coverage=branch` + Branch, /// `-Zunstable-options -C instrument-coverage=except-unused-generics` ExceptUnusedGenerics, /// `-Zunstable-options -C instrument-coverage=except-unused-functions` @@ -2747,7 +2750,10 @@ pub fn build_session_options( } (Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {} (Some(_), _) if !unstable_opts.unstable_options => { - handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`"); + handler.early_error( + "`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \ + require `-Z unstable-options`", + ); } (None, None) => {} (None, ic) => { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c090bcaf9d8e2..77aaf951f0db0 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -389,7 +389,7 @@ mod desc { pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = - "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; + "`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; @@ -931,6 +931,7 @@ mod parse { *slot = Some(match v { "all" => InstrumentCoverage::All, + "branch" => InstrumentCoverage::Branch, "except-unused-generics" | "except_unused_generics" => { InstrumentCoverage::ExceptUnusedGenerics } @@ -1356,6 +1357,7 @@ options! { reports (note, the compiler build config must include `profiler = true`); \ implies `-C symbol-mangling-version=v0`. Optional values are: `=all` (implicit value) + `=branch` `=except-unused-generics` `=except-unused-functions` `=off` (default)"), @@ -1597,6 +1599,7 @@ options! { reports (note, the compiler build config must include `profiler = true`); \ implies `-C symbol-mangling-version=v0`. Optional values are: `=all` (implicit value) + `=branch` `=except-unused-generics` `=except-unused-functions` `=off` (default)"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 793074981654c..94fe38b72ad16 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -702,6 +702,10 @@ impl Session { self.opts.cg.instrument_coverage() != InstrumentCoverage::Off } + pub fn instrument_coverage_branch(&self) -> bool { + self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch + } + pub fn instrument_coverage_except_unused_generics(&self) -> bool { self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics } diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr index 246c4f31a4bac..b867d169dae5b 100644 --- a/tests/ui/instrument-coverage/bad-value.bad.stderr +++ b/tests/ui/instrument-coverage/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected +error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr index b539c558d9ba7..e7122fb61cdfc 100644 --- a/tests/ui/instrument-coverage/bad-value.blank.stderr +++ b/tests/ui/instrument-coverage/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected +error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected diff --git a/tests/ui/instrument-coverage/except-unused-functions.stderr b/tests/ui/instrument-coverage/except-unused-functions.stderr index 82c1c630cbf23..acc633a2a6d2f 100644 --- a/tests/ui/instrument-coverage/except-unused-functions.stderr +++ b/tests/ui/instrument-coverage/except-unused-functions.stderr @@ -1,2 +1,2 @@ -error: `-C instrument-coverage=except-*` requires `-Z unstable-options` +error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` diff --git a/tests/ui/instrument-coverage/except-unused-generics.stderr b/tests/ui/instrument-coverage/except-unused-generics.stderr index 82c1c630cbf23..acc633a2a6d2f 100644 --- a/tests/ui/instrument-coverage/except-unused-generics.stderr +++ b/tests/ui/instrument-coverage/except-unused-generics.stderr @@ -1,2 +1,2 @@ -error: `-C instrument-coverage=except-*` requires `-Z unstable-options` +error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` From 68f5536667ca2d60ac8275fe3bf5b6549f96d2f2 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Tue, 3 Oct 2023 20:17:40 +0300 Subject: [PATCH 38/38] Migrate diagnostics in `rustc_hir_analysis/src/coherence/orphan.rs` --- compiler/rustc_hir_analysis/messages.ftl | 41 +++ .../src/coherence/orphan.rs | 291 ++++++++---------- compiler/rustc_hir_analysis/src/errors.rs | 172 ++++++++++- 3 files changed, 341 insertions(+), 163 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 6bf6650986a67..e8d9918be22d2 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -72,6 +72,12 @@ hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors +hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` + .label = can't implement cross-crate trait with a default impl for non-struct/enum type + +hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate + .label = can't implement cross-crate trait for type in another crate + hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions .note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced .coercions_note = currently, {$number} fields need coercions: {$coercions} @@ -237,6 +243,28 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types + +hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait + +hir_analysis_only_current_traits_label = impl doesn't use only types from inside the current crate + +hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign + +hir_analysis_only_current_traits_note = define and implement a trait or new type instead + +hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + +hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate + +hir_analysis_only_current_traits_pointer = `{$pointer}` is not defined in the current crate because raw pointers are always foreign + +hir_analysis_only_current_traits_pointer_sugg = consider introducing a new wrapper type + +hir_analysis_only_current_traits_primitive = only traits defined in the current crate can be implemented for primitive types + +hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate + hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it @@ -326,6 +354,9 @@ hir_analysis_trait_object_declared_with_no_traits = at least one trait is required for an object type .alias_span = this alias does not contain a trait +hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}` + .note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds + hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number} .label = needs exactly one variant, but has {$number} .many_label = too many variants in `{$path}` @@ -339,6 +370,16 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de .label = needs at most one field with non-trivial size or alignment, but has {$field_count} .labels = this field has non-zero size or requires alignment +hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`) + .label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`) + .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + .case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +hir_analysis_ty_param_some = type parameter `{$param_ty}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param_ty}>`) + .label = type parameter `{$param_ty}` must be used as the type parameter for some local type + .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + .only_note = only traits defined in the current crate can be implemented for a type parameter + hir_analysis_type_of = {$type_of} hir_analysis_typeof_reserved_keyword_used = diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index faddb0c38298c..7eeb7837467fd 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -2,8 +2,7 @@ //! crate or pertains to a type defined in this crate. use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, DelayDm}; -use rustc_errors::{Diagnostic, ErrorGuaranteed}; +use rustc_errors::{DelayDm, ErrorGuaranteed}; use rustc_hir as hir; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::GenericArgs; @@ -17,6 +16,8 @@ use rustc_span::Span; use rustc_trait_selection::traits; use std::ops::ControlFlow; +use crate::errors; + #[instrument(skip(tcx), level = "debug")] pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, @@ -259,49 +260,30 @@ fn do_orphan_check_impl<'tcx>( match local_impl { LocalImpl::Allow => {} LocalImpl::Disallow { problematic_kind } => { - let msg = format!( - "traits with a default impl, like `{trait}`, \ - cannot be implemented for {problematic_kind} `{self_ty}`", - trait = tcx.def_path_str(trait_def_id), - ); - let label = format!( - "a trait object implements `{trait}` if and only if `{trait}` \ - is one of the trait object's trait bounds", - trait = tcx.def_path_str(trait_def_id), - ); - let sp = tcx.def_span(def_id); - let reported = - struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit(); - return Err(reported); + return Err(tcx.sess.emit_err(errors::TraitsWithDefaultImpl { + span: tcx.def_span(def_id), + traits: tcx.def_path_str(trait_def_id), + problematic_kind, + self_ty, + })); } } } else { - if let Some((msg, label)) = match nonlocal_impl { - NonlocalImpl::Allow => None, - NonlocalImpl::DisallowBecauseNonlocal => Some(( - format!( - "cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - tcx.def_path_str(trait_def_id) - ), - "can't implement cross-crate trait for type in another crate", - )), - NonlocalImpl::DisallowOther => Some(( - format!( - "cross-crate traits with a default impl, like `{}`, can \ - only be implemented for a struct/enum type, not `{}`", - tcx.def_path_str(trait_def_id), - self_ty - ), - "can't implement cross-crate trait with a default impl for \ - non-struct/enum type", - )), - } { - let sp = tcx.def_span(def_id); - let reported = - struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit(); - return Err(reported); + match nonlocal_impl { + NonlocalImpl::Allow => {} + NonlocalImpl::DisallowBecauseNonlocal => { + return Err(tcx.sess.emit_err(errors::CrossCrateTraitsDefined { + span: tcx.def_span(def_id), + traits: tcx.def_path_str(trait_def_id), + })); + } + NonlocalImpl::DisallowOther => { + return Err(tcx.sess.emit_err(errors::CrossCrateTraits { + span: tcx.def_span(def_id), + traits: tcx.def_path_str(trait_def_id), + self_ty, + })); + } } } } @@ -322,19 +304,18 @@ fn emit_orphan_check_error<'tcx>( let self_ty = trait_ref.self_ty(); Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { - let msg = match self_ty.kind() { - ty::Adt(..) => "can be implemented for types defined outside of the crate", - _ if self_ty.is_primitive() => "can be implemented for primitive types", - _ => "can be implemented for arbitrary types", - }; - let mut err = struct_span_err!( - tcx.sess, - sp, - E0117, - "only traits defined in the current crate {msg}" - ); - err.span_label(sp, "impl doesn't use only types from inside the current crate"); + let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) = + (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()); + let mut sugg = None; for &(mut ty, is_target_ty) in &tys { + let span = if is_target_ty { + // Point at `D` in `impl for C in D` + self_ty_span + } else { + // Point at `C` in `impl for C in D` + trait_span + }; + ty = tcx.erase_regions(ty); ty = match ty.kind() { // Remove the type arguments from the output, as they are not relevant. @@ -345,50 +326,103 @@ fn emit_orphan_check_error<'tcx>( ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()), _ => ty, }; - let msg = |ty: &str, postfix: &str| { - format!("{ty} is not defined in the current crate{postfix}") - }; - let this = |name: &str| { - if !trait_ref.def_id.is_local() && !is_target_ty { - msg("this", " because this is a foreign trait") + fn push_to_foreign_or_name<'tcx>( + is_foreign: bool, + foreign: &mut Vec, + name: &mut Vec>, + span: Span, + sname: &'tcx str, + ) { + if is_foreign { + foreign.push(errors::OnlyCurrentTraitsForeign { span }) } else { - msg("this", &format!(" because {name} are always foreign")) + name.push(errors::OnlyCurrentTraitsName { span, name: sname }); + } + } + + let is_foreign = !trait_ref.def_id.is_local() && !is_target_ty; + + match &ty.kind() { + ty::Slice(_) => { + push_to_foreign_or_name( + is_foreign, + &mut foreign, + &mut name, + span, + "slices", + ); + } + ty::Array(..) => { + push_to_foreign_or_name( + is_foreign, + &mut foreign, + &mut name, + span, + "arrays", + ); + } + ty::Tuple(..) => { + push_to_foreign_or_name( + is_foreign, + &mut foreign, + &mut name, + span, + "tuples", + ); } - }; - let msg = match &ty.kind() { - ty::Slice(_) => this("slices"), - ty::Array(..) => this("arrays"), - ty::Tuple(..) => this("tuples"), ty::Alias(ty::Opaque, ..) => { - "type alias impl trait is treated as if it were foreign, \ - because its hidden type could be from a foreign crate" - .to_string() + opaque.push(errors::OnlyCurrentTraitsOpaque { span }) } ty::RawPtr(ptr_ty) => { - emit_newtype_suggestion_for_raw_ptr( - full_impl_span, - self_ty, - self_ty_span, - ptr_ty, - &mut err, - ); - - msg(&format!("`{ty}`"), " because raw pointers are always foreign") + if !self_ty.has_param() { + let mut_key = ptr_ty.mutbl.prefix_str(); + sugg = Some(errors::OnlyCurrentTraitsPointerSugg { + wrapper_span: self_ty_span, + struct_span: full_impl_span.shrink_to_lo(), + mut_key, + ptr_ty: ptr_ty.ty, + }); + } + pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty }); } - _ => msg(&format!("`{ty}`"), ""), - }; - - if is_target_ty { - // Point at `D` in `impl for C in D` - err.span_label(self_ty_span, msg); - } else { - // Point at `C` in `impl for C in D` - err.span_label(trait_span, msg); + _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }), } } - err.note("define and implement a trait or new type instead"); - err.emit() + + let err_struct = match self_ty.kind() { + ty::Adt(..) => errors::OnlyCurrentTraits::Outside { + span: sp, + note: (), + opaque, + foreign, + name, + pointer, + ty: ty_diag, + sugg, + }, + _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive { + span: sp, + note: (), + opaque, + foreign, + name, + pointer, + ty: ty_diag, + sugg, + }, + _ => errors::OnlyCurrentTraits::Arbitrary { + span: sp, + note: (), + opaque, + foreign, + name, + pointer, + ty: ty_diag, + sugg, + }, + }; + tcx.sess.emit_err(err_struct) } traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => { let mut sp = sp; @@ -399,85 +433,18 @@ fn emit_orphan_check_error<'tcx>( } match local_type { - Some(local_type) => struct_span_err!( - tcx.sess, - sp, - E0210, - "type parameter `{}` must be covered by another type \ - when it appears before the first local type (`{}`)", - param_ty, - local_type - ) - .span_label( - sp, - format!( - "type parameter `{param_ty}` must be covered by another type \ - when it appears before the first local type (`{local_type}`)" - ), - ) - .note( - "implementing a foreign trait is only possible if at \ - least one of the types for which it is implemented is local, \ - and no uncovered type parameters appear before that first \ - local type", - ) - .note( - "in this case, 'before' refers to the following order: \ - `impl<..> ForeignTrait for T0`, \ - where `T0` is the first and `Tn` is the last", - ) - .emit(), - None => struct_span_err!( - tcx.sess, - sp, - E0210, - "type parameter `{}` must be used as the type parameter for some \ - local type (e.g., `MyStruct<{}>`)", + Some(local_type) => tcx.sess.emit_err(errors::TyParamFirstLocal { + span: sp, + note: (), param_ty, - param_ty - ) - .span_label( - sp, - format!( - "type parameter `{param_ty}` must be used as the type parameter for some \ - local type", - ), - ) - .note( - "implementing a foreign trait is only possible if at \ - least one of the types for which it is implemented is local", - ) - .note( - "only traits defined in the current crate can be \ - implemented for a type parameter", - ) - .emit(), + local_type, + }), + None => tcx.sess.emit_err(errors::TyParamSome { span: sp, note: (), param_ty }), } } }) } -fn emit_newtype_suggestion_for_raw_ptr( - full_impl_span: Span, - self_ty: Ty<'_>, - self_ty_span: Span, - ptr_ty: &ty::TypeAndMut<'_>, - diag: &mut Diagnostic, -) { - if !self_ty.has_param() { - let mut_key = ptr_ty.mutbl.prefix_str(); - let msg_sugg = "consider introducing a new wrapper type".to_owned(); - let sugg = vec![ - ( - full_impl_span.shrink_to_lo(), - format!("struct WrapperType(*{}{});\n\n", mut_key, ptr_ty.ty), - ), - (self_ty_span, "WrapperType".to_owned()), - ]; - diag.multipart_suggestion(msg_sugg, sugg, rustc_errors::Applicability::MaybeIncorrect); - } -} - /// Lint impls of auto traits if they are likely to have /// unsound or surprising effects on auto impls. fn lint_auto_trait_impl<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 189564d4e3392..6a2db1d06276c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -683,7 +683,6 @@ pub(crate) struct SIMDFFIHighlyExperimental { } #[derive(Diagnostic)] - pub enum ImplNotMarkedDefault { #[diag(hir_analysis_impl_not_marked_default, code = "E0520")] #[note] @@ -1159,3 +1158,174 @@ pub struct ImplForTyRequires { pub trait_name: String, pub ty: String, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")] +#[note] +pub struct TraitsWithDefaultImpl<'a> { + #[primary_span] + pub span: Span, + pub traits: String, + pub problematic_kind: &'a str, + pub self_ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cross_crate_traits, code = "E0321")] +pub struct CrossCrateTraits<'a> { + #[primary_span] + #[label] + pub span: Span, + pub traits: String, + pub self_ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")] +pub struct CrossCrateTraitsDefined { + #[primary_span] + #[label] + pub span: Span, + pub traits: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_ty_param_first_local, code = "E0210")] +#[note] +pub struct TyParamFirstLocal<'a> { + #[primary_span] + #[label] + pub span: Span, + #[note(hir_analysis_case_note)] + pub note: (), + pub param_ty: Ty<'a>, + pub local_type: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_ty_param_some, code = "E0210")] +#[note] +pub struct TyParamSome<'a> { + #[primary_span] + #[label] + pub span: Span, + #[note(hir_analysis_only_note)] + pub note: (), + pub param_ty: Ty<'a>, +} + +#[derive(Diagnostic)] +pub enum OnlyCurrentTraits<'a> { + #[diag(hir_analysis_only_current_traits_outside, code = "E0117")] + Outside { + #[primary_span] + #[label(hir_analysis_only_current_traits_label)] + span: Span, + #[note(hir_analysis_only_current_traits_note)] + note: (), + #[subdiagnostic] + opaque: Vec, + #[subdiagnostic] + foreign: Vec, + #[subdiagnostic] + name: Vec>, + #[subdiagnostic] + pointer: Vec>, + #[subdiagnostic] + ty: Vec>, + #[subdiagnostic] + sugg: Option>, + }, + #[diag(hir_analysis_only_current_traits_primitive, code = "E0117")] + Primitive { + #[primary_span] + #[label(hir_analysis_only_current_traits_label)] + span: Span, + #[note(hir_analysis_only_current_traits_note)] + note: (), + #[subdiagnostic] + opaque: Vec, + #[subdiagnostic] + foreign: Vec, + #[subdiagnostic] + name: Vec>, + #[subdiagnostic] + pointer: Vec>, + #[subdiagnostic] + ty: Vec>, + #[subdiagnostic] + sugg: Option>, + }, + #[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")] + Arbitrary { + #[primary_span] + #[label(hir_analysis_only_current_traits_label)] + span: Span, + #[note(hir_analysis_only_current_traits_note)] + note: (), + #[subdiagnostic] + opaque: Vec, + #[subdiagnostic] + foreign: Vec, + #[subdiagnostic] + name: Vec>, + #[subdiagnostic] + pointer: Vec>, + #[subdiagnostic] + ty: Vec>, + #[subdiagnostic] + sugg: Option>, + }, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_opaque)] +pub struct OnlyCurrentTraitsOpaque { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_foreign)] +pub struct OnlyCurrentTraitsForeign { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_name)] +pub struct OnlyCurrentTraitsName<'a> { + #[primary_span] + pub span: Span, + pub name: &'a str, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_pointer)] +pub struct OnlyCurrentTraitsPointer<'a> { + #[primary_span] + pub span: Span, + pub pointer: Ty<'a>, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_ty)] +pub struct OnlyCurrentTraitsTy<'a> { + #[primary_span] + pub span: Span, + pub ty: Ty<'a>, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + hir_analysis_only_current_traits_pointer_sugg, + applicability = "maybe-incorrect" +)] +pub struct OnlyCurrentTraitsPointerSugg<'a> { + #[suggestion_part(code = "WrapperType")] + pub wrapper_span: Span, + #[suggestion_part(code = "struct WrapperType(*{mut_key}{ptr_ty});\n\n")] + pub struct_span: Span, + pub mut_key: &'a str, + pub ptr_ty: Ty<'a>, +}