Skip to content

Commit a49b736

Browse files
committed
Lint now-unnecessary associated type bounds
1 parent ca581f9 commit a49b736

File tree

6 files changed

+102
-4
lines changed

6 files changed

+102
-4
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ hir_analysis_unrecognized_intrinsic_function =
288288
unrecognized intrinsic function: `{$name}`
289289
.label = unrecognized intrinsic
290290
291+
hir_analysis_unused_associated_type_bounds =
292+
unnecessary associated type bound for not object safe associated type
293+
.note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
294+
.suggestion = remove this bound
295+
291296
hir_analysis_value_of_associated_struct_already_specified =
292297
the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
293298
.label = re-bound here

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_hir::intravisit::{walk_generics, Visitor as _};
2929
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
3030
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
3131
use rustc_infer::traits::ObligationCause;
32+
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
3233
use rustc_middle::middle::stability::AllowUnstable;
3334
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
3435
use rustc_middle::ty::DynKind;
@@ -929,6 +930,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
929930
fn conv_object_ty_poly_trait_ref(
930931
&self,
931932
span: Span,
933+
hir_id: hir::HirId,
932934
hir_trait_bounds: &[hir::PolyTraitRef<'_>],
933935
lifetime: &hir::Lifetime,
934936
borrowed: bool,
@@ -1125,9 +1127,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11251127
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
11261128
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
11271129
// corresponding `Projection` clause
1128-
for (projection_bound, _) in &projection_bounds {
1130+
for (projection_bound, span) in &projection_bounds {
11291131
for def_ids in associated_types.values_mut() {
1130-
def_ids.remove(&projection_bound.projection_def_id());
1132+
let def_id = projection_bound.projection_def_id();
1133+
def_ids.remove(&def_id);
1134+
if tcx.generics_require_sized_self(def_id) {
1135+
tcx.emit_spanned_lint(
1136+
UNUSED_ASSOCIATED_TYPE_BOUNDS,
1137+
hir_id,
1138+
*span,
1139+
crate::errors::UnusedAssociatedTypeBounds { span: *span },
1140+
);
1141+
}
11311142
}
11321143
}
11331144

@@ -2812,7 +2823,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
28122823
TraitObjectSyntax::DynStar => ty::DynStar,
28132824
};
28142825

2815-
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)
2826+
self.conv_object_ty_poly_trait_ref(
2827+
ast_ty.span,
2828+
ast_ty.hir_id,
2829+
bounds,
2830+
lifetime,
2831+
borrowed,
2832+
repr,
2833+
)
28162834
}
28172835
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
28182836
debug!(?maybe_qself, ?path);

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_errors::{
55
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
66
MultiSpan,
77
};
8-
use rustc_macros::{Diagnostic, Subdiagnostic};
8+
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
99
use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty};
1010
use rustc_span::{symbol::Ident, Span, Symbol};
1111

@@ -900,3 +900,11 @@ pub(crate) enum LateBoundInApit {
900900
param_span: Span,
901901
},
902902
}
903+
904+
#[derive(LintDiagnostic)]
905+
#[diag(hir_analysis_unused_associated_type_bounds)]
906+
#[note]
907+
pub struct UnusedAssociatedTypeBounds {
908+
#[suggestion(code = "")]
909+
pub span: Span,
910+
}

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3468,6 +3468,32 @@ declare_lint! {
34683468
report_in_external_macro
34693469
}
34703470

3471+
declare_lint! {
3472+
/// The `unused_associated_type_bounds` lint is emitted when an
3473+
/// associated type bound is added to a trait object, but the associated
3474+
/// type has a `where Self: Sized` bound, and is thus unavailable on the
3475+
/// trait object anyway.
3476+
///
3477+
/// ### Example
3478+
///
3479+
/// ```rust
3480+
/// trait Foo {
3481+
/// type Bar where Self: Sized;
3482+
/// }
3483+
/// type Mop = dyn Foo<Bar = ()>;
3484+
/// ```
3485+
///
3486+
/// {{produces}}
3487+
///
3488+
/// ### Explanation
3489+
///
3490+
/// Just like methods with `Self: Sized` bounds are unavailable on trait
3491+
/// objects, associated types can be removed from the trait object.
3492+
pub UNUSED_ASSOCIATED_TYPE_BOUNDS,
3493+
Warn,
3494+
"detects unused `Foo = Bar` bounds in `dyn Trait<Foo = Bar>`"
3495+
}
3496+
34713497
declare_lint! {
34723498
/// The `unused_doc_comments` lint detects doc comments that aren't used
34733499
/// by `rustdoc`.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
trait Foo {
4+
type Bar
5+
where
6+
Self: Sized;
7+
}
8+
9+
fn foo(_: &dyn Foo<Bar = ()>) {}
10+
//~^ WARN: unnecessary associated type bound for not object safe associated type
11+
//~| WARN: unnecessary associated type bound for not object safe associated type
12+
//~| WARN: unnecessary associated type bound for not object safe associated type
13+
14+
fn main() {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
warning: unnecessary associated type bound for not object safe associated type
2+
--> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20
3+
|
4+
LL | fn foo(_: &dyn Foo<Bar = ()>) {}
5+
| ^^^^^^^^ help: remove this bound
6+
|
7+
= note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
8+
= note: `#[warn(unused_associated_type_bounds)]` on by default
9+
10+
warning: unnecessary associated type bound for not object safe associated type
11+
--> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20
12+
|
13+
LL | fn foo(_: &dyn Foo<Bar = ()>) {}
14+
| ^^^^^^^^ help: remove this bound
15+
|
16+
= note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
17+
18+
warning: unnecessary associated type bound for not object safe associated type
19+
--> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20
20+
|
21+
LL | fn foo(_: &dyn Foo<Bar = ()>) {}
22+
| ^^^^^^^^ help: remove this bound
23+
|
24+
= note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
25+
26+
warning: 3 warnings emitted
27+

0 commit comments

Comments
 (0)