From a1d9da343ddcd27585f59349e286b50081704365 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 04:48:01 +0000 Subject: [PATCH] Make compare_impl_item into a query --- .../rustc_hir_analysis/src/check/check.rs | 18 +---- .../src/check/compare_impl_item.rs | 72 +++++++++++-------- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 11 +-- compiler/rustc_ty_utils/src/instance.rs | 12 ++-- tests/crashes/119701.rs | 21 ------ tests/crashes/121127.rs | 23 ------ tests/crashes/121411.rs | 13 ---- tests/crashes/129075.rs | 16 ----- tests/crashes/129127.rs | 21 ------ tests/crashes/129214.rs | 30 -------- tests/crashes/131294-2.rs | 25 ------- tests/crashes/131294.rs | 16 ----- .../const-generics/issues/issue-83765.stderr | 8 +-- .../const-traits/eval-bad-signature.rs} | 3 +- .../const-traits/eval-bad-signature.stderr | 21 ++++++ 16 files changed, 84 insertions(+), 228 deletions(-) delete mode 100644 tests/crashes/119701.rs delete mode 100644 tests/crashes/121127.rs delete mode 100644 tests/crashes/121411.rs delete mode 100644 tests/crashes/129075.rs delete mode 100644 tests/crashes/129127.rs delete mode 100644 tests/crashes/129214.rs delete mode 100644 tests/crashes/131294-2.rs delete mode 100644 tests/crashes/131294.rs rename tests/{crashes/112623.rs => ui/traits/const-traits/eval-bad-signature.rs} (69%) create mode 100644 tests/ui/traits/const-traits/eval-bad-signature.stderr diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c66572a937726..032e8c3365a3a 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; @@ -1036,20 +1036,8 @@ 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 _ = tcx.ensure().compare_impl_item(impl_item.expect_local()); check_specialization_validity( tcx, 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 f86ca95a954b2..086a1898400d8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -35,6 +35,24 @@ use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; 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,21 @@ 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)?; + refine::check_refining_return_position_impl_trait_in_trait( + tcx, + impl_m, + trait_m, + impl_trait_ref, + ); + Ok(()) } /// Checks a bunch of different properties of the impl/trait methods for @@ -1727,17 +1744,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)?; @@ -1868,19 +1880,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/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 375cbfd1c4fb8..61e203a1ff668 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 0f2a6d598a0fd..a17aa9ecc0446 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 8798772e398d7..17183f7f8a68c 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -215,15 +215,13 @@ 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. + 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 bdb326ea76b19..0000000000000 --- 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::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 e50dc7763fc65..0000000000000 --- 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 Foo for T { - default fn abc(f: fn(&T), t: &T) -> u32 { - 16 - } -} - -impl 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 2456910e6fa62..0000000000000 --- 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 4a0e920914cc5..0000000000000 --- 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; 2]); - -impl Default for Foo { - 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 8ec848dbd0578..0000000000000 --- 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 { - 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 e14b9f379d62a..0000000000000 --- 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 { - fn map(&self, f: F) -> Vec - where - F: FnMut(&Box) -> U; -} -impl map for Vec { - fn map(&self, mut f: F) -> Vec - where - F: FnMut(&T) -> U, - { - let mut r = Vec::new(); - for i in self { - r.push(f(i)); - } - r - } -} - -fn foo>(x: T) -> Vec { - 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 130a8b10fb78e..0000000000000 --- 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 { - 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 ec6c95674677e..0000000000000 --- 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 { - 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 c3292314f23b3..cce627499125b 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 `::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when checking that `` is well-formed - --> $DIR/issue-83765.rs:56:1 +note: cycle used when checking assoc item `::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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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/crashes/112623.rs b/tests/ui/traits/const-traits/eval-bad-signature.rs similarity index 69% rename from tests/crashes/112623.rs rename to tests/ui/traits/const-traits/eval-bad-signature.rs index 592ad742e5ffb..97c573ea6528d 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 0000000000000..a64cf631743d5 --- /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`.