about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs68
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs11
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs14
-rw-r--r--tests/crashes/119701.rs21
-rw-r--r--tests/crashes/121127.rs23
-rw-r--r--tests/crashes/121411.rs13
-rw-r--r--tests/crashes/129075.rs16
-rw-r--r--tests/crashes/129127.rs21
-rw-r--r--tests/crashes/129214.rs30
-rw-r--r--tests/crashes/131294-2.rs25
-rw-r--r--tests/crashes/131294.rs16
-rw-r--r--tests/ui/const-generics/issues/issue-83765.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/refine-cycle.rs26
-rw-r--r--tests/ui/traits/const-traits/eval-bad-signature.rs (renamed from tests/crashes/112623.rs)3
-rw-r--r--tests/ui/traits/const-traits/eval-bad-signature.stderr21
18 files changed, 123 insertions, 228 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 192dc1b4d22..e1f4ccca97e 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -33,7 +33,7 @@ use tracing::{debug, instrument};
 use ty::TypingMode;
 use {rustc_attr as attr, rustc_hir as hir};
 
-use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
+use super::compare_impl_item::check_type_bounds;
 use super::*;
 use crate::check::intrinsicck::InlineAsmCtxt;
 
@@ -1044,18 +1044,23 @@ fn check_impl_items_against_trait<'tcx>(
             tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
             continue;
         };
-        match ty_impl_item.kind {
-            ty::AssocKind::Const => {
-                tcx.ensure().compare_impl_const((
-                    impl_item.expect_local(),
-                    ty_impl_item.trait_item_def_id.unwrap(),
-                ));
-            }
-            ty::AssocKind::Fn => {
-                compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref);
-            }
-            ty::AssocKind::Type => {
-                compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref);
+
+        let res = tcx.ensure().compare_impl_item(impl_item.expect_local());
+
+        if res.is_ok() {
+            match ty_impl_item.kind {
+                ty::AssocKind::Fn => {
+                    compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait(
+                        tcx,
+                        ty_impl_item,
+                        ty_trait_item,
+                        tcx.impl_trait_ref(ty_impl_item.container_id(tcx))
+                            .unwrap()
+                            .instantiate_identity(),
+                    );
+                }
+                ty::AssocKind::Const => {}
+                ty::AssocKind::Type => {}
             }
         }
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 06dee6bda54..e176fc58999 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -33,7 +33,25 @@ use tracing::{debug, instrument};
 use super::potentially_plural_count;
 use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
 
-mod refine;
+pub(super) mod refine;
+
+/// Call the query `tcx.compare_impl_item()` directly instead.
+pub(super) fn compare_impl_item(
+    tcx: TyCtxt<'_>,
+    impl_item_def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
+    let impl_item = tcx.associated_item(impl_item_def_id);
+    let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
+    let impl_trait_ref =
+        tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
+    debug!(?impl_trait_ref);
+
+    match impl_item.kind {
+        ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
+        ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
+        ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
+    }
+}
 
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
@@ -44,22 +62,15 @@ mod refine;
 /// - `trait_m`: the method in the trait
 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
 #[instrument(level = "debug", skip(tcx))]
-pub(super) fn compare_impl_method<'tcx>(
+fn compare_impl_method<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: ty::AssocItem,
     trait_m: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
-) {
-    let _: Result<_, ErrorGuaranteed> = try {
-        check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
-        compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
-        refine::check_refining_return_position_impl_trait_in_trait(
-            tcx,
-            impl_m,
-            trait_m,
-            impl_trait_ref,
-        );
-    };
+) -> Result<(), ErrorGuaranteed> {
+    check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
+    compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
+    Ok(())
 }
 
 /// Checks a bunch of different properties of the impl/trait methods for
@@ -1721,17 +1732,12 @@ fn compare_generic_param_kinds<'tcx>(
     Ok(())
 }
 
-/// Use `tcx.compare_impl_const` instead
-pub(super) fn compare_impl_const_raw(
-    tcx: TyCtxt<'_>,
-    (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
+fn compare_impl_const<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_const_item: ty::AssocItem,
+    trait_const_item: ty::AssocItem,
+    impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
-    let impl_const_item = tcx.associated_item(impl_const_item_def);
-    let trait_const_item = tcx.associated_item(trait_const_item_def);
-    let impl_trait_ref =
-        tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
-    debug!(?impl_trait_ref);
-
     compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
     compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
     check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
@@ -1862,19 +1868,17 @@ fn compare_const_predicate_entailment<'tcx>(
 }
 
 #[instrument(level = "debug", skip(tcx))]
-pub(super) fn compare_impl_ty<'tcx>(
+fn compare_impl_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_ty: ty::AssocItem,
     trait_ty: ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
-) {
-    let _: Result<(), ErrorGuaranteed> = try {
-        compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
-        compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
-        check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
-        compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
-        check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
-    };
+) -> Result<(), ErrorGuaranteed> {
+    compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
+    compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
+    check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
+    compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
+    check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)
 }
 
 /// The equivalent of [compare_method_predicate_entailment], but for associated types
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 67cbcc1566a..6eac4ac3baf 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -17,7 +17,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
 use rustc_trait_selection::traits::{ObligationCtxt, elaborate, normalize_param_env_or_error};
 
 /// Check that an implementation does not refine an RPITIT from a trait method signature.
-pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
+pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: ty::AssocItem,
     trait_m: ty::AssocItem,
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 375cbfd1c4f..61e203a1ff6 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -108,7 +108,7 @@ pub fn provide(providers: &mut Providers) {
         adt_async_destructor,
         region_scope_tree,
         collect_return_position_impl_trait_in_trait_tys,
-        compare_impl_const: compare_impl_item::compare_impl_const_raw,
+        compare_impl_item: compare_impl_item::compare_impl_item,
         check_coroutine_obligations: check::check_coroutine_obligations,
         ..*providers
     };
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0f2a6d598a0..a17aa9ecc04 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2311,10 +2311,13 @@ rustc_queries! {
         desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
     }
 
-    query compare_impl_const(
-        key: (LocalDefId, DefId)
-    ) -> Result<(), ErrorGuaranteed> {
-        desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0) }
+    /// This takes the def-id of an associated item from a impl of a trait,
+    /// and checks its validity against the trait item it corresponds to.
+    ///
+    /// Any other def id will ICE.
+    query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
+        desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) }
+        ensure_forwards_result_if_red
     }
 
     query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 1a98c85bee9..eb30169a7d9 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -216,15 +216,15 @@ fn resolve_associated_item<'tcx>(
 
             let args = tcx.erase_regions(args);
 
-            // Check if we just resolved an associated `const` declaration from
-            // a `trait` to an associated `const` definition in an `impl`, where
-            // the definition in the `impl` has the wrong type (for which an
-            // error has already been/will be emitted elsewhere).
-            if leaf_def.item.kind == ty::AssocKind::Const
-                && trait_item_id != leaf_def.item.def_id
+            // We check that the impl item is compatible with the trait item
+            // because otherwise we may ICE in const eval due to type mismatches,
+            // signature incompatibilities, etc.
+            // NOTE: We could also only enforce this in `PostAnalysis`, which
+            // is what CTFE and MIR inlining would care about anyways.
+            if trait_item_id != leaf_def.item.def_id
                 && let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
             {
-                tcx.compare_impl_const((leaf_def_item, trait_item_id))?;
+                tcx.ensure().compare_impl_item(leaf_def_item)?;
             }
 
             Some(ty::Instance::new(leaf_def.item.def_id, args))
diff --git a/tests/crashes/119701.rs b/tests/crashes/119701.rs
deleted file mode 100644
index bdb326ea76b..00000000000
--- a/tests/crashes/119701.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ known-bug: #119701
-#![feature(const_trait_impl, generic_const_exprs)]
-
-fn main() {
-    let _ = process::<()>([()]);
-}
-
-fn process<T: const Trait>() -> [(); T::make(2)] {
-    input
-}
-
-#[const_trait]
-trait Trait {
-    fn make(input: u8) -> usize;
-}
-
-impl const Trait for () {
-    fn make(input: usize) -> usize {
-        input / 2
-    }
-}
diff --git a/tests/crashes/121127.rs b/tests/crashes/121127.rs
deleted file mode 100644
index e50dc7763fc..00000000000
--- a/tests/crashes/121127.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//@ known-bug: #121127
-//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes -C debuginfo=2
-// Note that as of PR#123949 this only crashes with debuginfo enabled
-
-#![feature(specialization)]
-
-pub trait Foo {
-    fn abc() -> u32;
-}
-
-pub trait Marker {}
-
-impl<T> Foo for T {
-    default fn abc(f: fn(&T), t: &T) -> u32 {
-        16
-    }
-}
-
-impl<T: Marker> Foo for T {
-    fn def() -> u32 {
-        Self::abc()
-    }
-}
diff --git a/tests/crashes/121411.rs b/tests/crashes/121411.rs
deleted file mode 100644
index 2456910e6fa..00000000000
--- a/tests/crashes/121411.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ known-bug: #121411
-#![feature(const_trait_impl)]
-
-#[const_trait]
-trait Foo {
-    fn into_iter(&self) {}
-}
-
-impl const Foo for () {
-    fn into_iter(a: u32, b: u32) {}
-}
-
-const _: () = Foo::into_iter(&());
diff --git a/tests/crashes/129075.rs b/tests/crashes/129075.rs
deleted file mode 100644
index 4a0e920914c..00000000000
--- a/tests/crashes/129075.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ known-bug: rust-lang/rust#129075
-//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
-
-struct Foo<T>([T; 2]);
-
-impl<T: Default + Copy> Default for Foo<T> {
-    fn default(&mut self) -> Self {
-        Foo([Default::default(); 2])
-    }
-}
-
-fn field_array() {
-    let a: i32;
-    let b;
-    Foo([a, b]) = Default::default();
-}
diff --git a/tests/crashes/129127.rs b/tests/crashes/129127.rs
deleted file mode 100644
index 8ec848dbd05..00000000000
--- a/tests/crashes/129127.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ known-bug: rust-lang/rust#129127
-//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always
-
-
-
-
-pub struct Rows<'a>();
-
-impl<'a> Iterator for Rows<'a> {
-    type Item = ();
-
-    fn next() -> Option<Self::Item> {
-        let mut rows = Rows();
-        rows.map(|row| row).next()
-    }
-}
-
-fn main() {
-    let mut rows = Rows();
-    rows.next();
-}
diff --git a/tests/crashes/129214.rs b/tests/crashes/129214.rs
deleted file mode 100644
index e14b9f379d6..00000000000
--- a/tests/crashes/129214.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ known-bug: rust-lang/rust#129214
-//@ compile-flags: -Zvalidate-mir -Copt-level=3 --crate-type=lib
-
-trait to_str {}
-
-trait map<T> {
-    fn map<U, F>(&self, f: F) -> Vec<U>
-    where
-        F: FnMut(&Box<usize>) -> U;
-}
-impl<T> map<T> for Vec<T> {
-    fn map<U, F>(&self, mut f: F) -> Vec<U>
-    where
-        F: FnMut(&T) -> U,
-    {
-        let mut r = Vec::new();
-        for i in self {
-            r.push(f(i));
-        }
-        r
-    }
-}
-
-fn foo<U, T: map<U>>(x: T) -> Vec<String> {
-    x.map(|_e| "hi".to_string())
-}
-
-pub fn main() {
-    assert_eq!(foo(vec![1]), ["hi".to_string()]);
-}
diff --git a/tests/crashes/131294-2.rs b/tests/crashes/131294-2.rs
deleted file mode 100644
index 130a8b10fb7..00000000000
--- a/tests/crashes/131294-2.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #131294
-//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always
-
-// https://github.com/rust-lang/rust/issues/131294#issuecomment-2395088049 second comment
-struct Rows;
-
-impl Iterator for Rows {
-    type Item = String;
-
-    fn next() -> Option<String> {
-        let args = format_args!("Hello world");
-
-        {
-            match args.as_str() {
-                Some(t) => t.to_owned(),
-                None => String::new(),
-            }
-        }
-            .into()
-    }
-}
-
-fn main() {
-    Rows.next();
-}
diff --git a/tests/crashes/131294.rs b/tests/crashes/131294.rs
deleted file mode 100644
index ec6c9567467..00000000000
--- a/tests/crashes/131294.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ known-bug: #131294
-//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always
-
-struct Rows;
-
-impl Iterator for Rows {
-    type Item = String;
-
-    fn next() -> Option<Self::Item> {
-        std::fmt::format(format_args!("Hello world")).into()
-    }
-}
-
-fn main() {
-    Rows.next();
-}
diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr
index c3292314f23..cce62749912 100644
--- a/tests/ui/const-generics/issues/issue-83765.stderr
+++ b/tests/ui/const-generics/issues/issue-83765.stderr
@@ -29,11 +29,11 @@ note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorD
 LL | trait TensorDimension {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
-note: cycle used when checking that `<impl at $DIR/issue-83765.rs:56:1: 56:97>` is well-formed
-  --> $DIR/issue-83765.rs:56:1
+note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:56:1: 56:97>::bget` is compatible with trait definition
+  --> $DIR/issue-83765.rs:58:5
    |
-LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error[E0308]: method not compatible with trait
diff --git a/tests/ui/impl-trait/in-trait/refine-cycle.rs b/tests/ui/impl-trait/in-trait/refine-cycle.rs
new file mode 100644
index 00000000000..78d672a7ed6
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/refine-cycle.rs
@@ -0,0 +1,26 @@
+//@ check-pass
+
+// Make sure that refinement checking doesn't cause a cycle in `Instance::resolve`
+// which calls `compare_impl_item`.
+
+trait Foo {
+    fn test() -> impl IntoIterator<Item = ()> + Send;
+}
+
+struct A;
+impl Foo for A {
+    fn test() -> impl IntoIterator<Item = ()> + Send {
+        B::test()
+    }
+}
+
+struct B;
+impl Foo for B {
+    fn test() -> impl IntoIterator<Item = ()> + Send {
+        for () in A::test() {}
+
+        []
+    }
+}
+
+fn main() {}
diff --git a/tests/crashes/112623.rs b/tests/ui/traits/const-traits/eval-bad-signature.rs
index 592ad742e5f..97c573ea652 100644
--- a/tests/crashes/112623.rs
+++ b/tests/ui/traits/const-traits/eval-bad-signature.rs
@@ -1,4 +1,4 @@
-//@ known-bug: #112623
+// Make sure we don't ICE when evaluating a trait whose impl has a bad signature.
 
 #![feature(const_trait_impl)]
 
@@ -15,6 +15,7 @@ struct FortyTwo;
 
 impl const Value for FortyTwo {
     fn value() -> i64 {
+        //~^ ERROR method `value` has an incompatible type for trait
         42
     }
 }
diff --git a/tests/ui/traits/const-traits/eval-bad-signature.stderr b/tests/ui/traits/const-traits/eval-bad-signature.stderr
new file mode 100644
index 00000000000..a64cf631743
--- /dev/null
+++ b/tests/ui/traits/const-traits/eval-bad-signature.stderr
@@ -0,0 +1,21 @@
+error[E0053]: method `value` has an incompatible type for trait
+  --> $DIR/eval-bad-signature.rs:17:19
+   |
+LL |     fn value() -> i64 {
+   |                   ^^^ expected `u32`, found `i64`
+   |
+note: type in trait
+  --> $DIR/eval-bad-signature.rs:7:19
+   |
+LL |     fn value() -> u32;
+   |                   ^^^
+   = note: expected signature `fn() -> u32`
+              found signature `fn() -> i64`
+help: change the output type to match the trait
+   |
+LL |     fn value() -> u32 {
+   |                   ~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0053`.