Skip to content

Commit 8b3d0c4

Browse files
authored
Rollup merge of #105484 - nbdd0121:upcast, r=compiler-errors
Implement allow-by-default `multiple_supertrait_upcastable` lint The lint detects when an object-safe trait has multiple supertraits. Enabled in libcore and liballoc as they are low-level enough that many embedded programs will use them. r? `@nikomatsakis`
2 parents ade9605 + b656e24 commit 8b3d0c4

File tree

11 files changed

+167
-0
lines changed

11 files changed

+167
-0
lines changed

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
@@ -61,6 +61,7 @@ mod late;
6161
mod let_underscore;
6262
mod levels;
6363
mod methods;
64+
mod multiple_supertrait_upcastable;
6465
mod non_ascii_idents;
6566
mod non_fmt_panic;
6667
mod nonstandard_style;
@@ -95,6 +96,7 @@ use hidden_unicode_codepoints::*;
9596
use internal::*;
9697
use let_underscore::*;
9798
use methods::*;
99+
use multiple_supertrait_upcastable::*;
98100
use non_ascii_idents::*;
99101
use non_fmt_panic::NonPanicFmt;
100102
use nonstandard_style::*;
@@ -229,6 +231,7 @@ late_lint_methods!(
229231
InvalidAtomicOrdering: InvalidAtomicOrdering,
230232
NamedAsmLabels: NamedAsmLabels,
231233
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
234+
MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
232235
]
233236
]
234237
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use crate::{LateContext, LateLintPass, LintContext};
2+
3+
use rustc_errors::DelayDm;
4+
use rustc_hir as hir;
5+
use rustc_span::sym;
6+
7+
declare_lint! {
8+
/// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
9+
/// supertraits.
10+
///
11+
/// ### Example
12+
///
13+
/// ```rust
14+
/// trait A {}
15+
/// trait B {}
16+
///
17+
/// #[warn(multiple_supertrait_upcastable)]
18+
/// trait C: A + B {}
19+
/// ```
20+
///
21+
/// {{produces}}
22+
///
23+
/// ### Explanation
24+
///
25+
/// To support upcasting with multiple supertraits, we need to store multiple vtables and this
26+
/// can result in extra space overhead, even if no code actually uses upcasting.
27+
/// This lint allows users to identify when such scenarios occur and to decide whether the
28+
/// additional overhead is justified.
29+
pub MULTIPLE_SUPERTRAIT_UPCASTABLE,
30+
Allow,
31+
"detect when an object-safe trait has multiple supertraits",
32+
@feature_gate = sym::multiple_supertrait_upcastable;
33+
}
34+
35+
declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTABLE]);
36+
37+
impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
38+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
39+
let def_id = item.owner_id.to_def_id();
40+
if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
41+
&& cx.tcx.is_object_safe(def_id)
42+
{
43+
let direct_super_traits_iter = cx.tcx
44+
.super_predicates_of(def_id)
45+
.predicates
46+
.into_iter()
47+
.filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
48+
if direct_super_traits_iter.count() > 1 {
49+
cx.struct_span_lint(
50+
MULTIPLE_SUPERTRAIT_UPCASTABLE,
51+
cx.tcx.def_span(def_id),
52+
DelayDm(|| {
53+
format!(
54+
"`{}` is object-safe and has multiple supertraits",
55+
item.ident,
56+
)
57+
}),
58+
|diag| diag,
59+
);
60+
}
61+
}
62+
}
63+
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,7 @@ symbols! {
943943
mul,
944944
mul_assign,
945945
mul_with_overflow,
946+
multiple_supertrait_upcastable,
946947
must_not_suspend,
947948
must_use,
948949
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)]
@@ -190,6 +191,7 @@
190191
#![feature(unsized_fn_params)]
191192
#![feature(c_unwind)]
192193
#![feature(with_negative_coherence)]
194+
#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
193195
//
194196
// Rustdoc features:
195197
#![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)]
@@ -231,6 +232,7 @@
231232
#![feature(unsized_fn_params)]
232233
#![feature(asm_const)]
233234
#![feature(const_transmute_copy)]
235+
#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
234236
//
235237
// Target features:
236238
#![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)