Skip to content

Commit 4db5daa

Browse files
committed
Auto merge of rust-lang#133365 - compiler-errors:compare-impl-item, r=lcnr
Make `compare_impl_item` into a query Turns `compare_impl_item` into a query (generalizing the existing query for `compare_impl_const`), and uses that in `Instance::resolve` to fail resolution when an implementation is incompatible with the trait it comes from. Fixes rust-lang#119701 Fixes rust-lang#121127 Fixes rust-lang#121411 Fixes rust-lang#129075 Fixes rust-lang#129127 Fixes rust-lang#129214 Fixes rust-lang#131294
2 parents f2abf82 + a1d9da3 commit 4db5daa

File tree

16 files changed

+84
-228
lines changed

16 files changed

+84
-228
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+3-15
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use tracing::{debug, instrument};
3333
use ty::TypingMode;
3434
use {rustc_attr as attr, rustc_hir as hir};
3535

36-
use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
36+
use super::compare_impl_item::check_type_bounds;
3737
use super::*;
3838
use crate::check::intrinsicck::InlineAsmCtxt;
3939

@@ -1036,20 +1036,8 @@ fn check_impl_items_against_trait<'tcx>(
10361036
tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
10371037
continue;
10381038
};
1039-
match ty_impl_item.kind {
1040-
ty::AssocKind::Const => {
1041-
tcx.ensure().compare_impl_const((
1042-
impl_item.expect_local(),
1043-
ty_impl_item.trait_item_def_id.unwrap(),
1044-
));
1045-
}
1046-
ty::AssocKind::Fn => {
1047-
compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref);
1048-
}
1049-
ty::AssocKind::Type => {
1050-
compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref);
1051-
}
1052-
}
1039+
1040+
let _ = tcx.ensure().compare_impl_item(impl_item.expect_local());
10531041

10541042
check_specialization_validity(
10551043
tcx,

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+41-31
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@ use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
3535

3636
mod refine;
3737

38+
/// Call the query `tcx.compare_impl_item()` directly instead.
39+
pub(super) fn compare_impl_item(
40+
tcx: TyCtxt<'_>,
41+
impl_item_def_id: LocalDefId,
42+
) -> Result<(), ErrorGuaranteed> {
43+
let impl_item = tcx.associated_item(impl_item_def_id);
44+
let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap());
45+
let impl_trait_ref =
46+
tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity();
47+
debug!(?impl_trait_ref);
48+
49+
match impl_item.kind {
50+
ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
51+
ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
52+
ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
53+
}
54+
}
55+
3856
/// Checks that a method from an impl conforms to the signature of
3957
/// the same method as declared in the trait.
4058
///
@@ -44,22 +62,21 @@ mod refine;
4462
/// - `trait_m`: the method in the trait
4563
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
4664
#[instrument(level = "debug", skip(tcx))]
47-
pub(super) fn compare_impl_method<'tcx>(
65+
fn compare_impl_method<'tcx>(
4866
tcx: TyCtxt<'tcx>,
4967
impl_m: ty::AssocItem,
5068
trait_m: ty::AssocItem,
5169
impl_trait_ref: ty::TraitRef<'tcx>,
52-
) {
53-
let _: Result<_, ErrorGuaranteed> = try {
54-
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
55-
compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
56-
refine::check_refining_return_position_impl_trait_in_trait(
57-
tcx,
58-
impl_m,
59-
trait_m,
60-
impl_trait_ref,
61-
);
62-
};
70+
) -> Result<(), ErrorGuaranteed> {
71+
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
72+
compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?;
73+
refine::check_refining_return_position_impl_trait_in_trait(
74+
tcx,
75+
impl_m,
76+
trait_m,
77+
impl_trait_ref,
78+
);
79+
Ok(())
6380
}
6481

6582
/// Checks a bunch of different properties of the impl/trait methods for
@@ -1727,17 +1744,12 @@ fn compare_generic_param_kinds<'tcx>(
17271744
Ok(())
17281745
}
17291746

1730-
/// Use `tcx.compare_impl_const` instead
1731-
pub(super) fn compare_impl_const_raw(
1732-
tcx: TyCtxt<'_>,
1733-
(impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
1747+
fn compare_impl_const<'tcx>(
1748+
tcx: TyCtxt<'tcx>,
1749+
impl_const_item: ty::AssocItem,
1750+
trait_const_item: ty::AssocItem,
1751+
impl_trait_ref: ty::TraitRef<'tcx>,
17341752
) -> Result<(), ErrorGuaranteed> {
1735-
let impl_const_item = tcx.associated_item(impl_const_item_def);
1736-
let trait_const_item = tcx.associated_item(trait_const_item_def);
1737-
let impl_trait_ref =
1738-
tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
1739-
debug!(?impl_trait_ref);
1740-
17411753
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
17421754
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
17431755
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
@@ -1868,19 +1880,17 @@ fn compare_const_predicate_entailment<'tcx>(
18681880
}
18691881

18701882
#[instrument(level = "debug", skip(tcx))]
1871-
pub(super) fn compare_impl_ty<'tcx>(
1883+
fn compare_impl_ty<'tcx>(
18721884
tcx: TyCtxt<'tcx>,
18731885
impl_ty: ty::AssocItem,
18741886
trait_ty: ty::AssocItem,
18751887
impl_trait_ref: ty::TraitRef<'tcx>,
1876-
) {
1877-
let _: Result<(), ErrorGuaranteed> = try {
1878-
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
1879-
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
1880-
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
1881-
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
1882-
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
1883-
};
1888+
) -> Result<(), ErrorGuaranteed> {
1889+
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
1890+
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
1891+
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
1892+
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
1893+
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)
18841894
}
18851895

18861896
/// The equivalent of [compare_method_predicate_entailment], but for associated types

compiler/rustc_hir_analysis/src/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub fn provide(providers: &mut Providers) {
108108
adt_async_destructor,
109109
region_scope_tree,
110110
collect_return_position_impl_trait_in_trait_tys,
111-
compare_impl_const: compare_impl_item::compare_impl_const_raw,
111+
compare_impl_item: compare_impl_item::compare_impl_item,
112112
check_coroutine_obligations: check::check_coroutine_obligations,
113113
..*providers
114114
};

compiler/rustc_middle/src/query/mod.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -2311,10 +2311,13 @@ rustc_queries! {
23112311
desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
23122312
}
23132313

2314-
query compare_impl_const(
2315-
key: (LocalDefId, DefId)
2316-
) -> Result<(), ErrorGuaranteed> {
2317-
desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0) }
2314+
/// This takes the def-id of an associated item from a impl of a trait,
2315+
/// and checks its validity against the trait item it corresponds to.
2316+
///
2317+
/// Any other def id will ICE.
2318+
query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
2319+
desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) }
2320+
ensure_forwards_result_if_red
23182321
}
23192322

23202323
query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] {

compiler/rustc_ty_utils/src/instance.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,13 @@ fn resolve_associated_item<'tcx>(
215215

216216
let args = tcx.erase_regions(args);
217217

218-
// Check if we just resolved an associated `const` declaration from
219-
// a `trait` to an associated `const` definition in an `impl`, where
220-
// the definition in the `impl` has the wrong type (for which an
221-
// error has already been/will be emitted elsewhere).
222-
if leaf_def.item.kind == ty::AssocKind::Const
223-
&& trait_item_id != leaf_def.item.def_id
218+
// We check that the impl item is compatible with the trait item
219+
// because otherwise we may ICE in const eval due to type mismatches,
220+
// signature incompatibilities, etc.
221+
if trait_item_id != leaf_def.item.def_id
224222
&& let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
225223
{
226-
tcx.compare_impl_const((leaf_def_item, trait_item_id))?;
224+
tcx.ensure().compare_impl_item(leaf_def_item)?;
227225
}
228226

229227
Some(ty::Instance::new(leaf_def.item.def_id, args))

tests/crashes/119701.rs

-21
This file was deleted.

tests/crashes/121127.rs

-23
This file was deleted.

tests/crashes/121411.rs

-13
This file was deleted.

tests/crashes/129075.rs

-16
This file was deleted.

tests/crashes/129127.rs

-21
This file was deleted.

tests/crashes/129214.rs

-30
This file was deleted.

tests/crashes/131294-2.rs

-25
This file was deleted.

tests/crashes/131294.rs

-16
This file was deleted.

tests/ui/const-generics/issues/issue-83765.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ note: ...which requires computing candidate for `<LazyUpdim<'_, T, <T as TensorD
2929
LL | trait TensorDimension {
3030
| ^^^^^^^^^^^^^^^^^^^^^
3131
= note: ...which again requires resolving instance `<LazyUpdim<'_, T, <T as TensorDimension>::DIM, DIM> as TensorDimension>::DIM`, completing the cycle
32-
note: cycle used when checking that `<impl at $DIR/issue-83765.rs:56:1: 56:97>` is well-formed
33-
--> $DIR/issue-83765.rs:56:1
32+
note: cycle used when checking assoc item `<impl at $DIR/issue-83765.rs:56:1: 56:97>::bget` is compatible with trait definition
33+
--> $DIR/issue-83765.rs:58:5
3434
|
35-
LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> {
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35+
LL | fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
36+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3737
= 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
3838

3939
error[E0308]: method not compatible with trait

tests/crashes/112623.rs tests/ui/traits/const-traits/eval-bad-signature.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@ known-bug: #112623
1+
// Make sure we don't ICE when evaluating a trait whose impl has a bad signature.
22

33
#![feature(const_trait_impl)]
44

@@ -15,6 +15,7 @@ struct FortyTwo;
1515

1616
impl const Value for FortyTwo {
1717
fn value() -> i64 {
18+
//~^ ERROR method `value` has an incompatible type for trait
1819
42
1920
}
2021
}

0 commit comments

Comments
 (0)