]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
Rollup merge of #104493 - adamncasey:cgroupzeroperiod, r=m-ou-se
[rust.git] / compiler / rustc_lint / src / multiple_supertrait_upcastable.rs
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 }