From 0fa27efad79eb6ba496c0ea8542e225d60469dcb Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 9 May 2022 18:43:16 +0200 Subject: [PATCH 1/2] Add tests. --- .../associated-consts/issue-88599-ref-self.rs | 24 +++++++ src/test/ui/issues/issue-37725.rs | 2 + ...ssue-73021-impossible-inline.inline.stderr | 46 ++++++++++++ ...ssue-73021-impossible-inline.no-opt.stderr | 46 ++++++++++++ .../issue-73021-impossible-inline.rs | 71 +++++++++++++++++++ 5 files changed, 189 insertions(+) create mode 100644 src/test/ui/associated-consts/issue-88599-ref-self.rs create mode 100644 src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr create mode 100644 src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr create mode 100644 src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs diff --git a/src/test/ui/associated-consts/issue-88599-ref-self.rs b/src/test/ui/associated-consts/issue-88599-ref-self.rs new file mode 100644 index 00000000000..f1144db44ca --- /dev/null +++ b/src/test/ui/associated-consts/issue-88599-ref-self.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait First { + const CONST: usize; +} +pub trait Second {} + +impl<'a> First for dyn Second +where + &'a Self: First, +{ + const CONST: usize = <&Self>::CONST; +} + +trait Third: First +where + [u8; Self::CONST]: +{ + const VAL: [u8; Self::CONST] = [0; Self::CONST]; +} + +fn main() {} diff --git a/src/test/ui/issues/issue-37725.rs b/src/test/ui/issues/issue-37725.rs index 965ecde6f3c..1c6df0da60c 100644 --- a/src/test/ui/issues/issue-37725.rs +++ b/src/test/ui/issues/issue-37725.rs @@ -1,4 +1,6 @@ // build-pass +// compiler-opts: -Zmir-opt-level=2 + #![allow(dead_code)] trait Foo { fn foo(&self); diff --git a/src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr new file mode 100644 index 00000000000..40829f53709 --- /dev/null +++ b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr @@ -0,0 +1,46 @@ +warning: trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:20:29 + | +LL | for<'any> &'any mut (): Clone, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:28:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:31:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:40:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:48:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:57:13 + | +LL | String: ::std::ops::Neg, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:65:10 + | +LL | i32: Iterator, + | ^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr new file mode 100644 index 00000000000..40829f53709 --- /dev/null +++ b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr @@ -0,0 +1,46 @@ +warning: trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:20:29 + | +LL | for<'any> &'any mut (): Clone, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:28:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:31:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:40:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:48:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:57:13 + | +LL | String: ::std::ops::Neg, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:65:10 + | +LL | i32: Iterator, + | ^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs new file mode 100644 index 00000000000..ab6677e911b --- /dev/null +++ b/src/test/ui/trivial-bounds/issue-73021-impossible-inline.rs @@ -0,0 +1,71 @@ +// build-pass +// revisions: no-opt inline +// [inline]compile-flags: -Zmir-opt-level=3 --emit=mir +#![feature(trivial_bounds)] +#![allow(unused)] + +trait Foo { + fn test(&self); +} + +fn foo<'a>(s: &'a mut ()) +where + &'a mut (): Foo, +{ + s.test(); +} + +fn clone(it: &mut ()) -> &mut () +where + for<'any> &'any mut (): Clone, + //~^ WARN trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters +{ + it.clone() +} + +fn generic_function(x: X) {} + +struct S where i32: Foo; +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + +impl Foo for () where i32: Foo { +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + fn test(&self) { + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); + } +} + +fn f() where i32: Foo { +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + let s = S; + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn g() where &'static str: Foo { +//~^ WARN trait bound &'static str: Foo does not depend on any type or lifetime parameters + "Foo".test(); + Foo::test(&"Foo"); + generic_function("Foo"); +} + +fn use_op(s: String) -> String +where + String: ::std::ops::Neg, +//~^ WARN trait bound String: Neg does not depend on any type or lifetime parameters +{ + -s +} + +fn use_for() +where + i32: Iterator, +//~^ WARN trait bound i32: Iterator does not depend on any type or lifetime parameters +{ + for _ in 2i32 {} +} + +fn main() {} From bd41874eeadba20870f49e837babc56e67292b10 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 12 May 2022 12:46:28 +0200 Subject: [PATCH 2/2] Add mir-opt test. --- src/test/mir-opt/inline/dyn-trait.rs | 35 +++++++++++ .../inline/dyn_trait.get_query.Inline.diff | 62 +++++++++++++++++++ .../inline/dyn_trait.mk_cycle.Inline.diff | 23 +++++++ .../dyn_trait.try_execute_query.Inline.diff | 37 +++++++++++ 4 files changed, 157 insertions(+) create mode 100644 src/test/mir-opt/inline/dyn-trait.rs create mode 100644 src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff create mode 100644 src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff create mode 100644 src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff diff --git a/src/test/mir-opt/inline/dyn-trait.rs b/src/test/mir-opt/inline/dyn-trait.rs new file mode 100644 index 00000000000..6a46e1e07b1 --- /dev/null +++ b/src/test/mir-opt/inline/dyn-trait.rs @@ -0,0 +1,35 @@ +#![crate_type = "lib"] + +use std::fmt::Debug; + +pub trait Cache { + type V: Debug; + + fn store_nocache(&self); +} + +pub trait Query { + type V; + type C: Cache; + + fn cache(s: &T) -> &Self::C; +} + +// EMIT_MIR dyn_trait.mk_cycle.Inline.diff +#[inline(always)] +pub fn mk_cycle(c: &dyn Cache) { + c.store_nocache() +} + +// EMIT_MIR dyn_trait.try_execute_query.Inline.diff +#[inline(always)] +pub fn try_execute_query(c: &C) { + mk_cycle(c) +} + +// EMIT_MIR dyn_trait.get_query.Inline.diff +#[inline(always)] +pub fn get_query(t: &T) { + let c = Q::cache(t); + try_execute_query(c) +} diff --git a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff new file mode 100644 index 00000000000..953d7b85c5b --- /dev/null +++ b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff @@ -0,0 +1,62 @@ +- // MIR for `get_query` before Inline ++ // MIR for `get_query` after Inline + + fn get_query(_1: &T) -> () { + debug t => _1; // in scope 0 at $DIR/dyn-trait.rs:32:31: 32:32 + let mut _0: (); // return place in scope 0 at $DIR/dyn-trait.rs:32:38: 32:38 + let _2: &::C; // in scope 0 at $DIR/dyn-trait.rs:33:9: 33:10 + let mut _3: &T; // in scope 0 at $DIR/dyn-trait.rs:33:22: 33:23 + let mut _4: &::C; // in scope 0 at $DIR/dyn-trait.rs:34:23: 34:24 + scope 1 { + debug c => _2; // in scope 1 at $DIR/dyn-trait.rs:33:9: 33:10 ++ scope 2 (inlined try_execute_query::<::C>) { // at $DIR/dyn-trait.rs:34:5: 34:25 ++ debug c => _4; // in scope 2 at $DIR/dyn-trait.rs:26:36: 26:37 ++ let mut _5: &dyn Cache::V>; // in scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ let mut _6: &::C; // in scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ scope 3 (inlined mk_cycle::<::V>) { // at $DIR/dyn-trait.rs:27:5: 27:16 ++ debug c => _5; // in scope 3 at $DIR/dyn-trait.rs:20:27: 20:28 ++ let mut _7: &dyn Cache::V>; // in scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 ++ } ++ } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/dyn-trait.rs:33:9: 33:10 + StorageLive(_3); // scope 0 at $DIR/dyn-trait.rs:33:22: 33:23 + _3 = &(*_1); // scope 0 at $DIR/dyn-trait.rs:33:22: 33:23 + _2 = ::cache::(move _3) -> bb1; // scope 0 at $DIR/dyn-trait.rs:33:13: 33:24 + // mir::Constant + // + span: $DIR/dyn-trait.rs:33:13: 33:21 + // + user_ty: UserType(0) + // + literal: Const { ty: for<'r> fn(&'r T) -> &'r ::C {::cache::}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/dyn-trait.rs:33:23: 33:24 + StorageLive(_4); // scope 1 at $DIR/dyn-trait.rs:34:23: 34:24 + _4 = &(*_2); // scope 1 at $DIR/dyn-trait.rs:34:23: 34:24 +- _0 = try_execute_query::<::C>(move _4) -> bb2; // scope 1 at $DIR/dyn-trait.rs:34:5: 34:25 ++ StorageLive(_5); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ StorageLive(_6); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ _6 = _4; // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ _5 = move _6 as &dyn Cache::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ StorageDead(_6); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15 ++ StorageLive(_7); // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 ++ _7 = _5; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 ++ _0 = ::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22 + // mir::Constant +- // + span: $DIR/dyn-trait.rs:34:5: 34:22 +- // + literal: Const { ty: for<'r> fn(&'r ::C) {try_execute_query::<::C>}, val: Value(Scalar()) } ++ // + span: $DIR/dyn-trait.rs:21:7: 21:20 ++ // + literal: Const { ty: for<'r> fn(&'r dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value(Scalar()) } + } + + bb2: { ++ StorageDead(_7); // scope 3 at $DIR/dyn-trait.rs:21:21: 21:22 ++ StorageDead(_5); // scope 2 at $DIR/dyn-trait.rs:27:15: 27:16 + StorageDead(_4); // scope 1 at $DIR/dyn-trait.rs:34:24: 34:25 + StorageDead(_2); // scope 0 at $DIR/dyn-trait.rs:35:1: 35:2 + return; // scope 0 at $DIR/dyn-trait.rs:35:2: 35:2 + } + } + diff --git a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff new file mode 100644 index 00000000000..27309328052 --- /dev/null +++ b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff @@ -0,0 +1,23 @@ +- // MIR for `mk_cycle` before Inline ++ // MIR for `mk_cycle` after Inline + + fn mk_cycle(_1: &dyn Cache) -> () { + debug c => _1; // in scope 0 at $DIR/dyn-trait.rs:20:27: 20:28 + let mut _0: (); // return place in scope 0 at $DIR/dyn-trait.rs:20:49: 20:49 + let mut _2: &dyn Cache; // in scope 0 at $DIR/dyn-trait.rs:21:5: 21:22 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/dyn-trait.rs:21:5: 21:22 + _2 = &(*_1); // scope 0 at $DIR/dyn-trait.rs:21:5: 21:22 + _0 = as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:21:5: 21:22 + // mir::Constant + // + span: $DIR/dyn-trait.rs:21:7: 21:20 + // + literal: Const { ty: for<'r> fn(&'r dyn Cache) { as Cache>::store_nocache}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/dyn-trait.rs:21:21: 21:22 + return; // scope 0 at $DIR/dyn-trait.rs:22:2: 22:2 + } + } + diff --git a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff new file mode 100644 index 00000000000..93bba58825d --- /dev/null +++ b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff @@ -0,0 +1,37 @@ +- // MIR for `try_execute_query` before Inline ++ // MIR for `try_execute_query` after Inline + + fn try_execute_query(_1: &C) -> () { + debug c => _1; // in scope 0 at $DIR/dyn-trait.rs:26:36: 26:37 + let mut _0: (); // return place in scope 0 at $DIR/dyn-trait.rs:26:43: 26:43 + let mut _2: &dyn Cache::V>; // in scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 + let mut _3: &C; // in scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 ++ scope 1 (inlined mk_cycle::<::V>) { // at $DIR/dyn-trait.rs:27:5: 27:16 ++ debug c => _2; // in scope 1 at $DIR/dyn-trait.rs:20:27: 20:28 ++ let mut _4: &dyn Cache::V>; // in scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 + StorageLive(_3); // scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 + _3 = &(*_1); // scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 + _2 = move _3 as &dyn Cache::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 + StorageDead(_3); // scope 0 at $DIR/dyn-trait.rs:27:14: 27:15 +- _0 = mk_cycle::<::V>(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:27:5: 27:16 ++ StorageLive(_4); // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 ++ _4 = _2; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 ++ _0 = ::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22 + // mir::Constant +- // + span: $DIR/dyn-trait.rs:27:5: 27:13 +- // + literal: Const { ty: for<'r> fn(&'r (dyn Cache::V> + 'r)) {mk_cycle::<::V>}, val: Value(Scalar()) } ++ // + span: $DIR/dyn-trait.rs:21:7: 21:20 ++ // + literal: Const { ty: for<'r> fn(&'r dyn Cache::V>) {::V> as Cache>::store_nocache}, val: Value(Scalar()) } + } + + bb1: { ++ StorageDead(_4); // scope 1 at $DIR/dyn-trait.rs:21:21: 21:22 + StorageDead(_2); // scope 0 at $DIR/dyn-trait.rs:27:15: 27:16 + return; // scope 0 at $DIR/dyn-trait.rs:28:2: 28:2 + } + } +