]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
Auto merge of #107443 - cjgillot:generator-less-query, r=compiler-errors
[rust.git] / compiler / rustc_lint / src / multiple_supertrait_upcastable.rs
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 }