Don't require method impls for methods with Self:Sized
bounds for impls for unsized types
This commit is contained in:
parent
f5729cfed3
commit
ffc955bcfb
11 changed files with 107 additions and 21 deletions
|
@ -605,6 +605,8 @@ hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =
|
||||||
hir_analysis_unused_generic_parameter_ty_alias_help =
|
hir_analysis_unused_generic_parameter_ty_alias_help =
|
||||||
consider removing `{$param_name}` or referring to it in the body of the type alias
|
consider removing `{$param_name}` or referring to it in the body of the type alias
|
||||||
|
|
||||||
|
hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type
|
||||||
|
|
||||||
hir_analysis_value_of_associated_struct_already_specified =
|
hir_analysis_value_of_associated_struct_already_specified =
|
||||||
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
|
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
|
||||||
.label = re-bound here
|
.label = re-bound here
|
||||||
|
|
|
@ -992,6 +992,32 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
|
|
||||||
let trait_def = tcx.trait_def(trait_ref.def_id);
|
let trait_def = tcx.trait_def(trait_ref.def_id);
|
||||||
|
|
||||||
|
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
|
||||||
|
|
||||||
|
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||||
|
let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id);
|
||||||
|
let param_env = tcx.param_env(impl_id);
|
||||||
|
|
||||||
|
let self_is_guaranteed_unsized = match tcx
|
||||||
|
.struct_tail_raw(
|
||||||
|
trait_ref.self_ty(),
|
||||||
|
|ty| {
|
||||||
|
ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| {
|
||||||
|
Ty::new_error_with_message(
|
||||||
|
tcx,
|
||||||
|
tcx.def_span(impl_id),
|
||||||
|
"struct tail should be computable",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|| (),
|
||||||
|
)
|
||||||
|
.kind()
|
||||||
|
{
|
||||||
|
ty::Dynamic(_, _, ty::DynKind::Dyn) | ty::Slice(_) | ty::Str => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
for &impl_item in impl_item_refs {
|
for &impl_item in impl_item_refs {
|
||||||
let ty_impl_item = tcx.associated_item(impl_item);
|
let ty_impl_item = tcx.associated_item(impl_item);
|
||||||
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
|
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
|
||||||
|
@ -1021,6 +1047,15 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self_is_guaranteed_unsized && tcx.generics_require_sized_self(ty_trait_item.def_id) {
|
||||||
|
tcx.emit_node_span_lint(
|
||||||
|
rustc_lint_defs::builtin::DEAD_CODE,
|
||||||
|
tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()),
|
||||||
|
tcx.def_span(ty_impl_item.def_id),
|
||||||
|
errors::UselessImplItem,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
check_specialization_validity(
|
check_specialization_validity(
|
||||||
tcx,
|
tcx,
|
||||||
trait_def,
|
trait_def,
|
||||||
|
@ -1044,7 +1079,11 @@ fn check_impl_items_against_trait<'tcx>(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
|
.is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
|
||||||
|
|
||||||
if !is_implemented && tcx.defaultness(impl_id).is_final() {
|
if !is_implemented
|
||||||
|
&& tcx.defaultness(impl_id).is_final()
|
||||||
|
// unsized types don't need to implement methods that have `Self: Sized` bounds.
|
||||||
|
&& !(self_is_guaranteed_unsized && tcx.generics_require_sized_self(trait_item_id))
|
||||||
|
{
|
||||||
missing_items.push(tcx.associated_item(trait_item_id));
|
missing_items.push(tcx.associated_item(trait_item_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -908,6 +908,10 @@ pub(crate) enum ImplNotMarkedDefault {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(hir_analysis_useless_impl_item)]
|
||||||
|
pub(crate) struct UselessImplItem;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_missing_trait_item, code = E0046)]
|
#[diag(hir_analysis_missing_trait_item, code = E0046)]
|
||||||
pub(crate) struct MissingTraitItem {
|
pub(crate) struct MissingTraitItem {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
error: reached the recursion limit finding the struct tail for `K`
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
|
||||||
|
|
||||||
error: reached the recursion limit finding the struct tail for `Bottom`
|
error: reached the recursion limit finding the struct tail for `Bottom`
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
|
||||||
|
@ -21,7 +25,7 @@ LL | let x: &Bottom = &t;
|
||||||
= note: expected reference `&Bottom`
|
= note: expected reference `&Bottom`
|
||||||
found reference `&Top`
|
found reference `&Top`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0055, E0308.
|
Some errors have detailed explanations: E0055, E0308.
|
||||||
For more information about an error, try `rustc --explain E0055`.
|
For more information about an error, try `rustc --explain E0055`.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@ build-fail
|
//@ check-fail
|
||||||
//@ compile-flags: --crate-type lib -Cdebuginfo=2
|
//@ compile-flags: --crate-type lib -Cdebuginfo=2
|
||||||
//@ error-pattern: the type has an unknown layout
|
//@ error-pattern: recursion limit
|
||||||
|
|
||||||
#![recursion_limit = "10"]
|
#![recursion_limit = "10"]
|
||||||
macro_rules! link {
|
macro_rules! link {
|
||||||
|
@ -28,7 +28,6 @@ impl Bottom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
link!(A, B);
|
link!(A, B);
|
||||||
link!(B, C);
|
link!(B, C);
|
||||||
link!(C, D);
|
link!(C, D);
|
||||||
|
|
|
@ -2,7 +2,5 @@ error: reached the recursion limit finding the struct tail for `Bottom`
|
||||||
|
|
|
|
||||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]`
|
||||||
|
|
||||||
error: the type has an unknown layout
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc`
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Regression test for #129541
|
// Regression test for #129541
|
||||||
|
|
||||||
//@ revisions: unique multiple
|
//@ revisions: unique multiple
|
||||||
//@ check-pass
|
//@ error-pattern: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc`
|
||||||
|
|
||||||
trait Bound {}
|
trait Bound {}
|
||||||
trait Normalize {
|
trait Normalize {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc`
|
||||||
|
|
|
||||||
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! This test checks that we currently need to implement
|
//! This test checks that we do not need to implement
|
||||||
//! members, even if their where bounds don't hold for the impl type.
|
//! members, whose `where Self: Sized` bounds don't hold for the impl type.
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn foo()
|
fn foo()
|
||||||
|
@ -15,12 +15,28 @@ impl Foo for () {
|
||||||
impl Foo for i32 {}
|
impl Foo for i32 {}
|
||||||
//~^ ERROR: not all trait items implemented, missing: `foo`
|
//~^ ERROR: not all trait items implemented, missing: `foo`
|
||||||
|
|
||||||
// Should be allowed
|
|
||||||
impl Foo for dyn std::fmt::Debug {}
|
impl Foo for dyn std::fmt::Debug {}
|
||||||
//~^ ERROR: not all trait items implemented, missing: `foo`
|
|
||||||
|
|
||||||
|
#[deny(dead_code)]
|
||||||
impl Foo for dyn std::fmt::Display {
|
impl Foo for dyn std::fmt::Display {
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
|
//~^ ERROR this item cannot be used as its where bounds are not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Struct {
|
||||||
|
i: i32,
|
||||||
|
tail: [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for Struct {}
|
||||||
|
|
||||||
|
// Ensure we only allow known-unsized types to be skipped
|
||||||
|
trait Trait {
|
||||||
|
fn foo(self)
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
impl<T: ?Sized> Trait for T {}
|
||||||
|
//~^ ERROR: not all trait items implemented, missing: `foo`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -9,17 +9,29 @@ LL | | Self: Sized;
|
||||||
LL | impl Foo for i32 {}
|
LL | impl Foo for i32 {}
|
||||||
| ^^^^^^^^^^^^^^^^ missing `foo` in implementation
|
| ^^^^^^^^^^^^^^^^ missing `foo` in implementation
|
||||||
|
|
||||||
error[E0046]: not all trait items implemented, missing: `foo`
|
error: this item cannot be used as its where bounds are not satisfied for the `Self` type
|
||||||
--> $DIR/trivial_impl_sized.rs:19:1
|
--> $DIR/trivial_impl_sized.rs:22:5
|
||||||
|
|
|
|
||||||
LL | / fn foo()
|
LL | fn foo() {}
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/trivial_impl_sized.rs:20:8
|
||||||
|
|
|
||||||
|
LL | #[deny(dead_code)]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0046]: not all trait items implemented, missing: `foo`
|
||||||
|
--> $DIR/trivial_impl_sized.rs:39:1
|
||||||
|
|
|
||||||
|
LL | / fn foo(self)
|
||||||
LL | | where
|
LL | | where
|
||||||
LL | | Self: Sized;
|
LL | | Self: Sized;
|
||||||
| |____________________- `foo` from trait
|
| |____________________- `foo` from trait
|
||||||
...
|
LL | }
|
||||||
LL | impl Foo for dyn std::fmt::Debug {}
|
LL | impl<T: ?Sized> Trait for T {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0046`.
|
For more information about this error, try `rustc --explain E0046`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue