Skip to content

Commit f049c41

Browse files
committed
Don't require method impls for methods with Self:Sized bounds for impls for unsized types
1 parent e491cae commit f049c41

File tree

5 files changed

+38
-15
lines changed

5 files changed

+38
-15
lines changed

compiler/rustc_hir_analysis/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,8 @@ hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =
597597
hir_analysis_unused_generic_parameter_ty_alias_help =
598598
consider removing `{$param_name}` or referring to it in the body of the type alias
599599
600+
hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type
601+
600602
hir_analysis_value_of_associated_struct_already_specified =
601603
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
602604
.label = re-bound here

compiler/rustc_hir_analysis/src/check/check.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_trait_selection::traits;
3030
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
3131
use rustc_type_ir::fold::TypeFoldable;
3232
use tracing::{debug, instrument};
33-
use ty::TypingMode;
33+
use ty::{TypingEnv, TypingMode};
3434
use {rustc_attr_parsing as attr, rustc_hir as hir};
3535

3636
use super::compare_impl_item::check_type_bounds;
@@ -1035,6 +1035,9 @@ fn check_impl_items_against_trait<'tcx>(
10351035

10361036
let trait_def = tcx.trait_def(trait_ref.def_id);
10371037

1038+
let self_is_sized =
1039+
trait_ref.self_ty().is_sized(tcx, TypingEnv::non_body_analysis(tcx, impl_id));
1040+
10381041
for &impl_item in impl_item_refs {
10391042
let ty_impl_item = tcx.associated_item(impl_item);
10401043
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
@@ -1064,6 +1067,15 @@ fn check_impl_items_against_trait<'tcx>(
10641067
}
10651068
}
10661069

1070+
if !self_is_sized && tcx.generics_require_sized_self(ty_trait_item.def_id) {
1071+
tcx.emit_node_span_lint(
1072+
rustc_lint_defs::builtin::DEAD_CODE,
1073+
tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()),
1074+
tcx.def_span(ty_impl_item.def_id),
1075+
errors::UselessImplItem,
1076+
)
1077+
}
1078+
10671079
check_specialization_validity(
10681080
tcx,
10691081
trait_def,
@@ -1087,7 +1099,11 @@ fn check_impl_items_against_trait<'tcx>(
10871099
.as_ref()
10881100
.is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
10891101

1090-
if !is_implemented && tcx.defaultness(impl_id).is_final() {
1102+
if !is_implemented
1103+
&& tcx.defaultness(impl_id).is_final()
1104+
// unsized types don't need to implement methods that have `Self: Sized` bounds.
1105+
&& (self_is_sized || !tcx.generics_require_sized_self(trait_item_id))
1106+
{
10911107
missing_items.push(tcx.associated_item(trait_item_id));
10921108
}
10931109

compiler/rustc_hir_analysis/src/errors.rs

+4
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,10 @@ pub(crate) enum ImplNotMarkedDefault {
947947
},
948948
}
949949

950+
#[derive(LintDiagnostic)]
951+
#[diag(hir_analysis_useless_impl_item)]
952+
pub(crate) struct UselessImplItem;
953+
950954
#[derive(Diagnostic)]
951955
#[diag(hir_analysis_missing_trait_item, code = E0046)]
952956
pub(crate) struct MissingTraitItem {

tests/ui/traits/trivial_impl_sized.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//! This test checks that we currently need to implement
2-
//! members, even if their where bounds don't hold for the impl type.
1+
//! This test checks that we do not need to implement
2+
//! members, whose `where Self: Sized` bounds don't hold for the impl type.
33
44
trait Foo {
55
fn foo()
@@ -15,12 +15,12 @@ impl Foo for () {
1515
impl Foo for i32 {}
1616
//~^ ERROR: not all trait items implemented, missing: `foo`
1717

18-
// Should be allowed
1918
impl Foo for dyn std::fmt::Debug {}
20-
//~^ ERROR: not all trait items implemented, missing: `foo`
2119

20+
#[deny(dead_code)]
2221
impl Foo for dyn std::fmt::Display {
2322
fn foo() {}
23+
//~^ ERROR this item cannot be used as its where bounds are not satisfied
2424
}
2525

2626
fn main() {}

tests/ui/traits/trivial_impl_sized.stderr

+10-9
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ LL | | Self: Sized;
99
LL | impl Foo for i32 {}
1010
| ^^^^^^^^^^^^^^^^ missing `foo` in implementation
1111

12-
error[E0046]: not all trait items implemented, missing: `foo`
13-
--> $DIR/trivial_impl_sized.rs:19:1
12+
error: this item cannot be used as its where bounds are not satisfied for the `Self` type
13+
--> $DIR/trivial_impl_sized.rs:22:5
1414
|
15-
LL | / fn foo()
16-
LL | | where
17-
LL | | Self: Sized;
18-
| |____________________- `foo` from trait
19-
...
20-
LL | impl Foo for dyn std::fmt::Debug {}
21-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
15+
LL | fn foo() {}
16+
| ^^^^^^^^
17+
|
18+
note: the lint level is defined here
19+
--> $DIR/trivial_impl_sized.rs:20:8
20+
|
21+
LL | #[deny(dead_code)]
22+
| ^^^^^^^^^
2223

2324
error: aborting due to 2 previous errors
2425

0 commit comments

Comments
 (0)