about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-03-15 06:20:24 +0000
committerbors <bors@rust-lang.org>2021-03-15 06:20:24 +0000
commit3963c3da02d17b9c52feaf0e05271db2ec51c29f (patch)
tree095c951a8acac61930a9ed114bf63612e0dcec0d
parentd6eaea1c8860adb5302d2fbaad409e36585ab217 (diff)
parent18f89790dacad42d11f7fbd5d9cb09ce5dd8ff2f (diff)
downloadrust-3963c3da02d17b9c52feaf0e05271db2ec51c29f.tar.gz
rust-3963c3da02d17b9c52feaf0e05271db2ec51c29f.zip
Auto merge of #83074 - Aaron1011:new-sort-fix, r=jackh726
Avoid sorting predicates by `DefId`

Fixes issue #82920

Even if an item does not change between compilation sessions, it may end
up with a different `DefId`, since inserting/deleting an item affects
the `DefId`s of all subsequent items. Therefore, we use a `DefPathHash`
in the incremental compilation system, which is stable in the face of
changes to unrelated items.

In particular, the query system will consider the inputs to a query to
be unchanged if any `DefId`s in the inputs have their `DefPathHash`es
unchanged. Queries are pure functions, so the query result should be
unchanged if the query inputs are unchanged.

Unfortunately, it's possible to inadvertantly make a query result
incorrectly change across compilations, by relying on the specific value
of a `DefId`. Specifically, if the query result is a slice that gets
sorted by `DefId`, the precise order will depend on how the `DefId`s got
assigned in a particular compilation session. If some definitions end up
with different `DefId`s (but the same `DefPathHash`es) in a subsequent
compilation session, we will end up re-computing a *different* value for
the query, even though the query system expects the result to unchanged
due to the unchanged inputs.

It turns out that we have been sorting the predicates computed during
`astconv` by their `DefId`. These predicates make their way into the
`super_predicates_that_define_assoc_type`, which ends up getting used to
compute the vtables of trait objects. This, re-ordering these predicates
between compilation sessions can lead to undefined behavior at runtime -
the query system will re-use code built with a *differently ordered*
vtable, resulting in the wrong method being invoked at runtime.

This PR avoids sorting by `DefId` in `astconv`, fixing the
miscompilation. However, it's possible that other instances of this
issue exist - they could also be easily introduced in the future.

To fully fix this issue, we should
1. Turn on `-Z incremental-verify-ich` by default. This will cause the
   compiler to ICE whenver an 'unchanged' query result changes between
   compilation sessions, instead of causing a miscompilation.
2. Remove the `Ord` impls for `CrateNum` and `DefId`. This will make it
   difficult to introduce ICEs in the first place.
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs7
-rw-r--r--src/test/incremental/issue-82920-predicate-order-miscompile.rs31
-rw-r--r--src/test/rustdoc/inline_cross/impl_trait.rs2
-rw-r--r--src/test/rustdoc/unit-return.rs4
-rw-r--r--src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr29
-rw-r--r--src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr20
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-1.stderr28
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-2.stderr28
-rw-r--r--src/test/ui/issues/issue-40827.stderr12
-rw-r--r--src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr4
-rw-r--r--src/test/ui/traits/inductive-overflow/simultaneous.stderr2
14 files changed, 105 insertions, 65 deletions
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 1017b23e567..a46a5502b24 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -11,6 +11,7 @@
 #![feature(or_patterns)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
+#![recursion_limit = "256"]
 
 extern crate proc_macro;
 
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index cea4de72df5..001b52b56fc 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(or_patterns)]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
+#![recursion_limit = "256"]
 
 use rustc_ast as ast;
 use rustc_ast::token::{self, Nonterminal};
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index d002f597391..7eaeae504eb 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,6 +1,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(once_cell)]
 #![feature(or_patterns)]
+#![recursion_limit = "256"]
 
 #[macro_use]
 extern crate bitflags;
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 947363fc3ed..89501d9ce97 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -942,7 +942,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let mut bounds = Bounds::default();
 
         self.add_bounds(param_ty, ast_bounds, &mut bounds);
-        bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id());
 
         bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
             if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
@@ -1318,8 +1317,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
         // `dyn Trait + Send`.
-        auto_traits.sort_by_key(|i| i.trait_ref().def_id());
-        auto_traits.dedup_by_key(|i| i.trait_ref().def_id());
+        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
+        // the bounds
+        let mut duplicates = FxHashSet::default();
+        auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id()));
         debug!("regular_traits: {:?}", regular_traits);
         debug!("auto_traits: {:?}", auto_traits);
 
diff --git a/src/test/incremental/issue-82920-predicate-order-miscompile.rs b/src/test/incremental/issue-82920-predicate-order-miscompile.rs
new file mode 100644
index 00000000000..793af679c9f
--- /dev/null
+++ b/src/test/incremental/issue-82920-predicate-order-miscompile.rs
@@ -0,0 +1,31 @@
+// revisions: rpass1 rpass2
+
+trait MyTrait: One + Two {}
+impl<T> One for T {
+    fn method_one(&self) -> usize {
+        1
+    }
+}
+impl<T> Two for T {
+    fn method_two(&self) -> usize {
+        2
+    }
+}
+impl<T: One + Two> MyTrait for T {}
+
+fn main() {
+    let a: &dyn MyTrait = &true;
+    assert_eq!(a.method_one(), 1);
+    assert_eq!(a.method_two(), 2);
+}
+
+// Re-order traits 'One' and 'Two' between compilation
+// sessions
+
+#[cfg(rpass1)]
+trait One { fn method_one(&self) -> usize; }
+
+trait Two { fn method_two(&self) -> usize; }
+
+#[cfg(rpass2)]
+trait One { fn method_one(&self) -> usize; }
diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs
index 0ab2fa99f87..44e2c4d3fb2 100644
--- a/src/test/rustdoc/inline_cross/impl_trait.rs
+++ b/src/test/rustdoc/inline_cross/impl_trait.rs
@@ -18,7 +18,7 @@ pub use impl_trait_aux::func2;
 
 // @has impl_trait/fn.func3.html
 // @has - '//pre[@class="rust fn"]' "func3("
-// @has - '//pre[@class="rust fn"]' "_x: impl Clone + Iterator<Item = impl Iterator<Item = u8>>)"
+// @has - '//pre[@class="rust fn"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
 // @!has - '//pre[@class="rust fn"]' 'where'
 pub use impl_trait_aux::func3;
 
diff --git a/src/test/rustdoc/unit-return.rs b/src/test/rustdoc/unit-return.rs
index b1f251dae6e..ae3a6031519 100644
--- a/src/test/rustdoc/unit-return.rs
+++ b/src/test/rustdoc/unit-return.rs
@@ -10,8 +10,8 @@ pub fn f0<F: FnMut(u8) + Clone>(f: F) {}
 // @has 'foo/fn.f1.html' '//*[@class="rust fn"]' 'F: FnMut(u16) + Clone'
 pub fn f1<F: FnMut(u16) -> () + Clone>(f: F) {}
 
-// @has 'foo/fn.f2.html' '//*[@class="rust fn"]' 'F: Clone + FnMut(u32)'
+// @has 'foo/fn.f2.html' '//*[@class="rust fn"]' 'F: FnMut(u32) + Clone'
 pub use unit_return::f2;
 
-// @has 'foo/fn.f3.html' '//*[@class="rust fn"]' 'F: Clone + FnMut(u64)'
+// @has 'foo/fn.f3.html' '//*[@class="rust fn"]' 'F: FnMut(u64) + Clone'
 pub use unit_return::f3;
diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
index 1c493581bc9..a5ebb80c836 100644
--- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
+++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
@@ -1,15 +1,3 @@
-error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:5
-   |
-LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
-help: consider further restricting the associated type
-   |
-LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
   --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:36
    |
@@ -27,6 +15,23 @@ help: consider further restricting the associated type
 LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:43
+   |
+LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator
+   | 
+  ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL | pub trait Iterator {
+   | ------------------ required by this bound in `Iterator`
+   |
+   = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item`
+help: consider further restricting the associated type
+   |
+LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
   --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:93
    |
diff --git a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
index b6a88179c1f..cd7c0dc4a44 100644
--- a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
+++ b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
@@ -20,12 +20,12 @@ LL | fn dent<C:BoxCar>(c: C, color: C::Color) {
    |
 help: use fully qualified syntax to disambiguate
    |
-LL | fn dent<C:BoxCar>(c: C, color: <C as Box>::Color) {
-   |                                ^^^^^^^^^^^^^^^^^
-help: use fully qualified syntax to disambiguate
-   |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Vehicle>::Color) {
    |                                ^^^^^^^^^^^^^^^^^^^^^
+help: use fully qualified syntax to disambiguate
+   |
+LL | fn dent<C:BoxCar>(c: C, color: <C as Box>::Color) {
+   |                                ^^^^^^^^^^^^^^^^^
 
 error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar`
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37
@@ -42,8 +42,8 @@ LL | fn dent_object<COLOR>(c: dyn BoxCar<Color=COLOR>) {
    = help: consider introducing a new type parameter `T` and adding `where` constraints:
                where
                    T: BoxCar,
-                   T: Box::Color = COLOR,
-                   T: Vehicle::Color = COLOR
+                   T: Vehicle::Color = COLOR,
+                   T: Box::Color = COLOR
 
 error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:30
@@ -73,12 +73,12 @@ LL | fn paint<C:BoxCar>(c: C, d: C::Color) {
    |
 help: use fully qualified syntax to disambiguate
    |
-LL | fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) {
-   |                             ^^^^^^^^^^^^^^^^^
-help: use fully qualified syntax to disambiguate
-   |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Vehicle>::Color) {
    |                             ^^^^^^^^^^^^^^^^^^^^^
+help: use fully qualified syntax to disambiguate
+   |
+LL | fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) {
+   |                             ^^^^^^^^^^^^^^^^^
 
 error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
index 8e446cf051f..bcdb50aa312 100644
--- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
+++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
@@ -13,20 +13,6 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + std::fmt::Display {
    |                            ^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `Self: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:20:5
-   |
-LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |     ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |                   |
-   |     |                   required by this bound in `UncheckedCopy::Output`
-   |     the trait `Deref` is not implemented for `Self`
-   |
-help: consider further restricting `Self`
-   |
-LL | trait UncheckedCopy: Sized + Deref {
-   |                            ^^^^^^^
-
 error[E0277]: cannot add-assign `&'static str` to `Self`
   --> $DIR/defaults-unsound-62211-1.rs:20:5
    |
@@ -41,6 +27,20 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0277]: the trait bound `Self: Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:20:5
+   |
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                   |
+   |     |                   required by this bound in `UncheckedCopy::Output`
+   |     the trait `Deref` is not implemented for `Self`
+   |
+help: consider further restricting `Self`
+   |
+LL | trait UncheckedCopy: Sized + Deref {
+   |                            ^^^^^^^
+
 error[E0277]: the trait bound `Self: Copy` is not satisfied
   --> $DIR/defaults-unsound-62211-1.rs:20:5
    |
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
index 93f4f497b38..fa5cf9196ed 100644
--- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
+++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
@@ -13,20 +13,6 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + std::fmt::Display {
    |                            ^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `Self: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:20:5
-   |
-LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-   |     ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |                   |
-   |     |                   required by this bound in `UncheckedCopy::Output`
-   |     the trait `Deref` is not implemented for `Self`
-   |
-help: consider further restricting `Self`
-   |
-LL | trait UncheckedCopy: Sized + Deref {
-   |                            ^^^^^^^
-
 error[E0277]: cannot add-assign `&'static str` to `Self`
   --> $DIR/defaults-unsound-62211-2.rs:20:5
    |
@@ -41,6 +27,20 @@ help: consider further restricting `Self`
 LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0277]: the trait bound `Self: Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:20:5
+   |
+LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |                   |
+   |     |                   required by this bound in `UncheckedCopy::Output`
+   |     the trait `Deref` is not implemented for `Self`
+   |
+help: consider further restricting `Self`
+   |
+LL | trait UncheckedCopy: Sized + Deref {
+   |                            ^^^^^^^
+
 error[E0277]: the trait bound `Self: Copy` is not satisfied
   --> $DIR/defaults-unsound-62211-2.rs:20:5
    |
diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr
index 5ea795d1397..95cacbc32ab 100644
--- a/src/test/ui/issues/issue-40827.stderr
+++ b/src/test/ui/issues/issue-40827.stderr
@@ -1,27 +1,27 @@
-error[E0277]: `Rc<Foo>` cannot be sent between threads safely
+error[E0277]: `Rc<Foo>` cannot be shared between threads safely
   --> $DIR/issue-40827.rs:14:5
    |
 LL | fn f<T: Send>(_: T) {}
    |         ---- required by this bound in `f`
 ...
 LL |     f(Foo(Arc::new(Bar::B(None))));
-   |     ^ `Rc<Foo>` cannot be sent between threads safely
+   |     ^ `Rc<Foo>` cannot be shared between threads safely
    |
-   = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>`
+   = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>`
    = note: required because it appears within the type `Bar`
    = note: required because of the requirements on the impl of `Send` for `Arc<Bar>`
    = note: required because it appears within the type `Foo`
 
-error[E0277]: `Rc<Foo>` cannot be shared between threads safely
+error[E0277]: `Rc<Foo>` cannot be sent between threads safely
   --> $DIR/issue-40827.rs:14:5
    |
 LL | fn f<T: Send>(_: T) {}
    |         ---- required by this bound in `f`
 ...
 LL |     f(Foo(Arc::new(Bar::B(None))));
-   |     ^ `Rc<Foo>` cannot be shared between threads safely
+   |     ^ `Rc<Foo>` cannot be sent between threads safely
    |
-   = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>`
+   = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>`
    = note: required because it appears within the type `Bar`
    = note: required because of the requirements on the impl of `Send` for `Arc<Bar>`
    = note: required because it appears within the type `Foo`
diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr
index c7376b0007f..0a64a0d7d5e 100644
--- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr
+++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr
@@ -8,10 +8,10 @@ LL |         self.foo();
    |              ^^^ method cannot be called on `&Foo<T>` due to unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
-           `T: Bar`
-           which is required by `Foo<T>: Bar`
            `T: Default`
            which is required by `Foo<T>: Bar`
+           `T: Bar`
+           which is required by `Foo<T>: Bar`
 help: consider restricting the type parameters to satisfy the trait bounds
    |
 LL | struct Foo<T> where T: Bar, T: Default {
diff --git a/src/test/ui/traits/inductive-overflow/simultaneous.stderr b/src/test/ui/traits/inductive-overflow/simultaneous.stderr
index 484ac851179..88e0631eeb2 100644
--- a/src/test/ui/traits/inductive-overflow/simultaneous.stderr
+++ b/src/test/ui/traits/inductive-overflow/simultaneous.stderr
@@ -1,4 +1,4 @@
-error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum`
+error[E0275]: overflow evaluating the requirement `{integer}: Tweedledee`
   --> $DIR/simultaneous.rs:18:5
    |
 LL | fn is_ee<T: Combo>(t: T) {