Skip to content

Commit fa00d7b

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

File tree

5 files changed

+38
-14
lines changed

5 files changed

+38
-14
lines changed

compiler/rustc_hir_analysis/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ hir_analysis_missing_one_of_trait_item = not all trait items implemented, missin
321321
.label = missing one of `{$missing_items_msg}` in implementation
322322
.note = required because of this annotation
323323
324+
hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type
325+
324326
hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}`
325327
.label = missing `{$missing_items_msg}` in implementation
326328

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-3
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()
@@ -17,10 +17,11 @@ impl Foo for i32 {}
1717

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

21+
#[deny(dead_code)]
2222
impl Foo for dyn std::fmt::Display {
2323
fn foo() {}
24+
//~^ ERROR this item cannot be used as its where bounds are not satisfied
2425
}
2526

2627
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:23: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:21:8
20+
|
21+
LL | #[deny(dead_code)]
22+
| ^^^^^^^^^
2223

2324
error: aborting due to 2 previous errors
2425

0 commit comments

Comments
 (0)