about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-05-15 22:28:51 +0200
committerGitHub <noreply@github.com>2025-05-15 22:28:51 +0200
commitd0ea3424406c4ca5e61746359a4f87fef5868efb (patch)
tree151812c6ee6c24d260b4bfe8309560c47a953fd9
parentf5fb0d3ea0599cb75065b9ad3103c860e83734c2 (diff)
parenta508011b1f0ae84930e2bcd0f6261f7e8843db6d (diff)
downloadrust-d0ea3424406c4ca5e61746359a4f87fef5868efb.tar.gz
rust-d0ea3424406c4ca5e61746359a4f87fef5868efb.zip
Rollup merge of #140947 - compiler-errors:pending-norm, r=lcnr
Flush errors before deep normalize in `dropck_outlives`

Deep normalization doesn't allow the ocx to have pending obligations, so process them before deeply normalizing.

Fixes https://github.com/rust-lang/rust/issues/140931
Fixes https://github.com/rust-lang/rust/issues/140462
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs28
-rw-r--r--tests/ui/drop/dropck-normalize-errors.rs31
-rw-r--r--tests/ui/drop/dropck-normalize-errors.stderr76
4 files changed, 132 insertions, 11 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 7718644b9a9..512288a0f7d 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -621,13 +621,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
                         &ocx, op, span,
                     ) {
                         Ok(_) => ocx.select_all_or_error(),
-                        Err(e) => {
-                            if e.is_empty() {
-                                ocx.select_all_or_error()
-                            } else {
-                                e
-                            }
-                        }
+                        Err(e) => e,
                     };
 
                     // Could have no errors if a type lowering error, say, caused the query
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index f04a5feba30..38cfdcdc22d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -196,11 +196,31 @@ where
                 debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
                 ty
             } else {
-                ocx.deeply_normalize(&cause, param_env, ty)?;
+                // Flush errors b/c `deeply_normalize` doesn't expect pending
+                // obligations, and we may have pending obligations from the
+                // branch above (from other types).
+                let errors = ocx.select_all_or_error();
+                if !errors.is_empty() {
+                    return Err(errors);
+                }
 
-                let errors = ocx.select_where_possible();
-                debug!("normalize errors: {ty} ~> {errors:#?}");
-                return Err(errors);
+                // When query normalization fails, we don't get back an interesting
+                // reason that we could use to report an error in borrowck. In order to turn
+                // this into a reportable error, we deeply normalize again. We don't expect
+                // this to succeed, so delay a bug if it does.
+                match ocx.deeply_normalize(&cause, param_env, ty) {
+                    Ok(_) => {
+                        tcx.dcx().span_delayed_bug(
+                            span,
+                            format!(
+                                "query normalize succeeded of {ty}, \
+                                but deep normalize failed",
+                            ),
+                        );
+                        ty
+                    }
+                    Err(errors) => return Err(errors),
+                }
             };
 
             match ty.kind() {
diff --git a/tests/ui/drop/dropck-normalize-errors.rs b/tests/ui/drop/dropck-normalize-errors.rs
new file mode 100644
index 00000000000..793122bd33d
--- /dev/null
+++ b/tests/ui/drop/dropck-normalize-errors.rs
@@ -0,0 +1,31 @@
+// Test that we don't ICE when computing the drop types for
+
+trait Decode<'a> {
+    type Decoder;
+}
+
+trait NonImplementedTrait {
+    type Assoc;
+}
+struct NonImplementedStruct;
+
+pub struct ADecoder<'a> {
+    b: <B as Decode<'a>>::Decoder,
+}
+fn make_a_decoder<'a>() -> ADecoder<'a> {
+    //~^ ERROR the trait bound
+    //~| ERROR the trait bound
+    panic!()
+}
+
+struct B;
+impl<'a> Decode<'a> for B {
+    type Decoder = BDecoder;
+    //~^ ERROR the trait bound
+}
+pub struct BDecoder {
+    non_implemented: <NonImplementedStruct as NonImplementedTrait>::Assoc,
+    //~^ ERROR the trait bound
+}
+
+fn main() {}
diff --git a/tests/ui/drop/dropck-normalize-errors.stderr b/tests/ui/drop/dropck-normalize-errors.stderr
new file mode 100644
index 00000000000..2bb5909c6b2
--- /dev/null
+++ b/tests/ui/drop/dropck-normalize-errors.stderr
@@ -0,0 +1,76 @@
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `ADecoder<'a>`
+  --> $DIR/dropck-normalize-errors.rs:15:28
+   |
+LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
+   |                            ^^^^^^^^^^^^ within `ADecoder<'a>`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:7:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:26:12
+   |
+LL | pub struct BDecoder {
+   |            ^^^^^^^^
+note: required because it appears within the type `ADecoder<'a>`
+  --> $DIR/dropck-normalize-errors.rs:12:12
+   |
+LL | pub struct ADecoder<'a> {
+   |            ^^^^^^^^
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:23:20
+   |
+LL |     type Decoder = BDecoder;
+   |                    ^^^^^^^^ within `BDecoder`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:7:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:26:12
+   |
+LL | pub struct BDecoder {
+   |            ^^^^^^^^
+note: required by a bound in `Decode::Decoder`
+  --> $DIR/dropck-normalize-errors.rs:4:5
+   |
+LL |     type Decoder;
+   |     ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Decoder: ?Sized;
+   |                 ++++++++
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
+  --> $DIR/dropck-normalize-errors.rs:27:22
+   |
+LL |     non_implemented: <NonImplementedStruct as NonImplementedTrait>::Assoc,
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:7:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
+  --> $DIR/dropck-normalize-errors.rs:15:28
+   |
+LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
+   |                            ^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:7:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.