Skip to content

Commit 66f3ab9

Browse files
committed
Reintroduce multiple_supertrait_upcastable lint
1 parent 94e59cb commit 66f3ab9

File tree

13 files changed

+173
-0
lines changed

13 files changed

+173
-0
lines changed

compiler/rustc_error_messages/locales/en-US/lint.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ lint_cstring_ptr = getting the inner pointer of a temporary `CString`
100100
.note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
101101
.help = for more information, see https://doc.rust-lang.org/reference/destructors.html
102102
103+
lint_multple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
104+
103105
lint_identifier_non_ascii_char = identifier contains non-ASCII characters
104106
105107
lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ declare_features! (
160160
(active, intrinsics, "1.0.0", None, None),
161161
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
162162
(active, lang_items, "1.0.0", None, None),
163+
/// Allows the `multiple_supertrait_upcastable` lint.
164+
(active, multiple_supertrait_upcastable, "CURRENT_RUSTC_VERSION", None, None),
163165
/// Allows using `#[omit_gdb_pretty_printer_section]`.
164166
(active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
165167
/// Allows using `#[prelude_import]` on glob `use` items.

compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ mod let_underscore;
6464
mod levels;
6565
mod lints;
6666
mod methods;
67+
mod multiple_supertrait_upcastable;
6768
mod non_ascii_idents;
6869
mod non_fmt_panic;
6970
mod nonstandard_style;
@@ -98,6 +99,7 @@ use hidden_unicode_codepoints::*;
9899
use internal::*;
99100
use let_underscore::*;
100101
use methods::*;
102+
use multiple_supertrait_upcastable::*;
101103
use non_ascii_idents::*;
102104
use non_fmt_panic::NonPanicFmt;
103105
use nonstandard_style::*;
@@ -232,6 +234,7 @@ late_lint_methods!(
232234
InvalidAtomicOrdering: InvalidAtomicOrdering,
233235
NamedAsmLabels: NamedAsmLabels,
234236
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
237+
MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
235238
]
236239
]
237240
);

compiler/rustc_lint/src/lints.rs

+7
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,13 @@ pub struct CStringPtr {
917917
pub unwrap: Span,
918918
}
919919

920+
// multiple_supertrait_upcastable.rs
921+
#[derive(LintDiagnostic)]
922+
#[diag(lint_multple_supertrait_upcastable)]
923+
pub struct MultipleSupertraitUpcastable {
924+
pub ident: Ident,
925+
}
926+
920927
// non_ascii_idents.rs
921928
#[derive(LintDiagnostic)]
922929
#[diag(lint_identifier_non_ascii_char)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::{LateContext, LateLintPass, LintContext};
2+
3+
use rustc_hir as hir;
4+
use rustc_span::sym;
5+
6+
declare_lint! {
7+
/// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
8+
/// supertraits.
9+
///
10+
/// ### Example
11+
///
12+
/// ```rust
13+
/// trait A {}
14+
/// trait B {}
15+
///
16+
/// #[warn(multiple_supertrait_upcastable)]
17+
/// trait C: A + B {}
18+
/// ```
19+
///
20+
/// {{produces}}
21+
///
22+
/// ### Explanation
23+
///
24+
/// To support upcasting with multiple supertraits, we need to store multiple vtables and this
25+
/// can result in extra space overhead, even if no code actually uses upcasting.
26+
/// This lint allows users to identify when such scenarios occur and to decide whether the
27+
/// additional overhead is justified.
28+
pub MULTIPLE_SUPERTRAIT_UPCASTABLE,
29+
Allow,
30+
"detect when an object-safe trait has multiple supertraits",
31+
@feature_gate = sym::multiple_supertrait_upcastable;
32+
}
33+
34+
declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTABLE]);
35+
36+
impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
37+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
38+
let def_id = item.owner_id.to_def_id();
39+
// NOTE(nbdd0121): use `object_safety_violations` instead of `check_is_object_safe` because
40+
// the latter will report `where_clause_object_safety` lint.
41+
if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
42+
&& cx.tcx.object_safety_violations(def_id).is_empty()
43+
{
44+
let direct_super_traits_iter = cx.tcx
45+
.super_predicates_of(def_id)
46+
.predicates
47+
.into_iter()
48+
.filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
49+
if direct_super_traits_iter.count() > 1 {
50+
cx.emit_spanned_lint(
51+
MULTIPLE_SUPERTRAIT_UPCASTABLE,
52+
cx.tcx.def_span(def_id),
53+
crate::lints::MultipleSupertraitUpcastable {
54+
ident: item.ident
55+
},
56+
);
57+
}
58+
}
59+
}
60+
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,7 @@ symbols! {
955955
mul,
956956
mul_assign,
957957
mul_with_overflow,
958+
multiple_supertrait_upcastable,
958959
must_not_suspend,
959960
must_use,
960961
naked,

library/alloc/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
#![warn(missing_debug_implementations)]
8888
#![warn(missing_docs)]
8989
#![allow(explicit_outlives_requirements)]
90+
#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
9091
//
9192
// Library features:
9293
#![feature(alloc_layout_extra)]
@@ -195,6 +196,7 @@
195196
#![feature(c_unwind)]
196197
#![feature(with_negative_coherence)]
197198
#![cfg_attr(test, feature(panic_update_hook))]
199+
#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
198200
//
199201
// Rustdoc features:
200202
#![feature(doc_cfg)]

library/core/src/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::fmt::{Debug, Display};
2828
#[stable(feature = "rust1", since = "1.0.0")]
2929
#[cfg_attr(not(test), rustc_diagnostic_item = "Error")]
3030
#[rustc_has_incoherent_inherent_impls]
31+
#[cfg_attr(not(bootstrap), allow(multiple_supertrait_upcastable))]
3132
pub trait Error: Debug + Display {
3233
/// The lower-level source of this error, if any.
3334
///

library/core/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#![warn(missing_docs)]
9696
#![allow(explicit_outlives_requirements)]
9797
#![allow(incomplete_features)]
98+
#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
9899
//
99100
// Library features:
100101
#![feature(const_align_offset)]
@@ -235,6 +236,7 @@
235236
#![feature(unsized_fn_params)]
236237
#![feature(asm_const)]
237238
#![feature(const_transmute_copy)]
239+
#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
238240
//
239241
// Target features:
240242
#![feature(arm_target_feature)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
3+
#![deny(multiple_supertrait_upcastable)]
4+
//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
5+
//~| WARNING unknown lint: `multiple_supertrait_upcastable`
6+
//~| WARNING unknown lint: `multiple_supertrait_upcastable`
7+
#![warn(multiple_supertrait_upcastable)]
8+
//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
9+
//~| WARNING unknown lint: `multiple_supertrait_upcastable`
10+
//~| WARNING unknown lint: `multiple_supertrait_upcastable`
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
warning: unknown lint: `multiple_supertrait_upcastable`
2+
--> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
3+
|
4+
LL | #![deny(multiple_supertrait_upcastable)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: the `multiple_supertrait_upcastable` lint is unstable
8+
= help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
9+
= note: `#[warn(unknown_lints)]` on by default
10+
11+
warning: unknown lint: `multiple_supertrait_upcastable`
12+
--> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
13+
|
14+
LL | #![warn(multiple_supertrait_upcastable)]
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: the `multiple_supertrait_upcastable` lint is unstable
18+
= help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
19+
20+
warning: unknown lint: `multiple_supertrait_upcastable`
21+
--> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
22+
|
23+
LL | #![deny(multiple_supertrait_upcastable)]
24+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
|
26+
= note: the `multiple_supertrait_upcastable` lint is unstable
27+
= help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
28+
29+
warning: unknown lint: `multiple_supertrait_upcastable`
30+
--> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
31+
|
32+
LL | #![warn(multiple_supertrait_upcastable)]
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
|
35+
= note: the `multiple_supertrait_upcastable` lint is unstable
36+
= help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
37+
38+
warning: unknown lint: `multiple_supertrait_upcastable`
39+
--> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
40+
|
41+
LL | #![deny(multiple_supertrait_upcastable)]
42+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43+
|
44+
= note: the `multiple_supertrait_upcastable` lint is unstable
45+
= help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
46+
47+
warning: unknown lint: `multiple_supertrait_upcastable`
48+
--> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
49+
|
50+
LL | #![warn(multiple_supertrait_upcastable)]
51+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
|
53+
= note: the `multiple_supertrait_upcastable` lint is unstable
54+
= help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
55+
56+
warning: 6 warnings emitted
57+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(multiple_supertrait_upcastable)]
2+
#![deny(multiple_supertrait_upcastable)]
3+
4+
trait A {}
5+
trait B {}
6+
7+
trait C: A + B {}
8+
//~^ ERROR `C` is object-safe and has multiple supertraits
9+
10+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `C` is object-safe and has multiple supertraits
2+
--> $DIR/multiple_supertrait_upcastable.rs:7:1
3+
|
4+
LL | trait C: A + B {}
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/multiple_supertrait_upcastable.rs:2:9
9+
|
10+
LL | #![deny(multiple_supertrait_upcastable)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)