From 28fdc9796a431975cb7515b0a267fea4255bb20d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 12 Dec 2021 12:28:08 +0100 Subject: [PATCH] Do not ICE when failing to fulfill known obligations due to normalization. --- .../src/traits/codegen.rs | 8 +-- 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 +++++++++++ 5 files changed, 158 insertions(+), 7 deletions(-) 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/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 848aba7c91289..4d7b524dbf048 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -120,13 +120,7 @@ where // In principle, we only need to do this so long as `result` // contains unbound type parameters. It could be a slight // optimization to stop iterating early. - let errors = fulfill_cx.select_all_or_error(infcx); - if !errors.is_empty() { - infcx.tcx.sess.delay_span_bug( - rustc_span::DUMMY_SP, - &format!("Encountered errors `{:?}` resolving bounds after type-checking", errors), - ); - } + fulfill_cx.select_all_or_error(infcx); let result = infcx.resolve_vars_if_possible(result); infcx.tcx.erase_regions(result) 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 0000000000000..6a46e1e07b1a8 --- /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 0000000000000..70456475398fc --- /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:34:5: 34:25 ++ let mut _5: &dyn Cache::V>; // in scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 ++ let mut _6: &::C; // in scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 ++ scope 3 (inlined mk_cycle::<::V>) { // at $DIR/dyn-trait.rs:34:5: 34:25 ++ debug c => _5; // in scope 3 at $DIR/dyn-trait.rs:34:5: 34:25 ++ let mut _7: &dyn Cache::V>; // in scope 3 at $DIR/dyn-trait.rs:34:5: 34:25 ++ } ++ } + } + + 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:34:5: 34:25 ++ StorageLive(_6); // scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 ++ _6 = _4; // scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 ++ _5 = move _6 as &dyn Cache::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 ++ StorageDead(_6); // scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 ++ StorageLive(_7); // scope 3 at $DIR/dyn-trait.rs:34:5: 34:25 ++ _7 = _5; // scope 3 at $DIR/dyn-trait.rs:34:5: 34:25 ++ _0 = ::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:34:5: 34:25 + // 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:34:5: 34:25 ++ // + 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:34:5: 34:25 ++ StorageDead(_5); // scope 2 at $DIR/dyn-trait.rs:34:5: 34:25 + 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 0000000000000..27309328052c7 --- /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 0000000000000..3e94ff639a748 --- /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:27:5: 27:16 ++ let mut _4: &dyn Cache::V>; // in scope 1 at $DIR/dyn-trait.rs:27:5: 27:16 ++ } + + 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:27:5: 27:16 ++ _4 = _2; // scope 1 at $DIR/dyn-trait.rs:27:5: 27:16 ++ _0 = ::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:27:5: 27:16 + // 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:27:5: 27:16 ++ // + 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:27:5: 27:16 + 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 + } + } +