Skip to main content

miniextendr_lint/rules/
impl_validation.rs

1//! Impl block validation: class system compatibility.
2//!
3//! - MXL008: Trait impl class system incompatible with inherent impl.
4
5use crate::crate_index::CrateIndex;
6use crate::diagnostic::Diagnostic;
7use crate::lint_code::LintCode;
8
9pub fn check(index: &CrateIndex, diagnostics: &mut Vec<Diagnostic>) {
10    for (path, data) in &index.file_data {
11        // MXL008: Class system compatibility
12        //
13        // S3 trait impls are compatible with ALL inherent styles because S3 generics
14        // dispatch on the class attribute, which every class system provides.
15        // S4 trait impls work on S4 inherent (needs proper S4 class with slots).
16        // S7/R6/Env trait impls require matching inherent for dispatch to work.
17        for ati in &data.attributed_trait_impls {
18            let trait_style = ati.class_system.as_deref().unwrap_or("env");
19
20            if let Some((inherent_style, _)) = data.inherent_impl_class_systems.get(&ati.type_name)
21            {
22                let inherent = if inherent_style.is_empty() {
23                    "env"
24                } else {
25                    inherent_style.as_str()
26                };
27
28                // S3 trait dispatch works on any class system's objects
29                let compatible = trait_style == inherent || trait_style == "s3";
30
31                if !compatible {
32                    diagnostics.push(Diagnostic::new(
33                        LintCode::MXL008,
34                        path,
35                        ati.line,
36                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[miniextendr] impl {0} for {1} uses {2}-style, but the inherent impl uses {3}-style. Trait and inherent impls must use the same class system (S3 traits are compatible with all inherent styles). Either change the trait impl to #[miniextendr({4})] or change the inherent impl to #[miniextendr({5})].",
                ati.trait_name, ati.type_name, trait_style, inherent,
                inherent, trait_style))
    })format!(
37                            "#[miniextendr] impl {} for {} uses {}-style, but the inherent \
38                             impl uses {}-style. Trait and inherent impls must use the same \
39                             class system (S3 traits are compatible with all inherent styles). \
40                             Either change the trait impl to #[miniextendr({})] or change \
41                             the inherent impl to #[miniextendr({})].",
42                            ati.trait_name,
43                            ati.type_name,
44                            trait_style,
45                            inherent,
46                            inherent,
47                            trait_style,
48                        ),
49                    ));
50                }
51            }
52        }
53    }
54}