Skip to main content

rustc_hir_analysis/variance/
dump.rs

1use std::fmt::Write;
2
3use rustc_hir::def::DefKind;
4use rustc_hir::def_id::LocalDefId;
5use rustc_hir::find_attr;
6use rustc_middle::ty::{GenericArgs, TyCtxt};
7
8fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String {
9    let variances = tcx.variances_of(def_id);
10    let generics = GenericArgs::identity_for_item(tcx, def_id);
11    // 7 = 2-letter parameter + ": " + 1-letter variance + ", "
12    let mut ret = String::with_capacity(2 + 7 * variances.len());
13    ret.push('[');
14    for (arg, variance) in generics.iter().zip(variances.iter()) {
15        ret.write_fmt(format_args!("{0}: {1:?}, ", arg, variance))write!(ret, "{arg}: {variance:?}, ").unwrap();
16    }
17    // Remove trailing `, `.
18    if !variances.is_empty() {
19        ret.pop();
20        ret.pop();
21    }
22    ret.push(']');
23    ret
24}
25
26pub(crate) fn variances(tcx: TyCtxt<'_>) {
27    let crate_items = tcx.hir_crate_items(());
28
29    if {
        'done:
            {
            for i in tcx.hir_krate_attrs() {
                #[allow(unused_imports)]
                use rustc_hir::attrs::AttributeKind::*;
                let i: &rustc_hir::Attribute = i;
                match i {
                    rustc_hir::Attribute::Parsed(RustcDumpVariancesOfOpaques) =>
                        {
                        break 'done Some(());
                    }
                    rustc_hir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }.is_some()find_attr!(tcx, crate, RustcDumpVariancesOfOpaques) {
30        for id in crate_items.opaques() {
31            tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id));
32        }
33    }
34
35    for id in crate_items.owners() {
36        if !{

        #[allow(deprecated)]
        {
            {
                'done:
                    {
                    for i in tcx.get_all_attrs(id) {
                        #[allow(unused_imports)]
                        use rustc_hir::attrs::AttributeKind::*;
                        let i: &rustc_hir::Attribute = i;
                        match i {
                            rustc_hir::Attribute::Parsed(RustcDumpVariances) => {
                                break 'done Some(());
                            }
                            rustc_hir::Attribute::Unparsed(..) =>
                                {}
                                #[deny(unreachable_patterns)]
                                _ => {}
                        }
                    }
                    None
                }
            }
        }
    }.is_some()find_attr!(tcx, id, RustcDumpVariances) {
37            continue;
38        }
39
40        match tcx.def_kind(id) {
41            DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => {}
42            DefKind::TyAlias if tcx.type_alias_is_lazy(id) => {}
43            kind => {
44                let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("attr parsing didn\'t report an error for `#[{0}]` on {1:?}",
                rustc_span::sym::rustc_dump_variances, kind))
    })format!(
45                    "attr parsing didn't report an error for `#[{}]` on {kind:?}",
46                    rustc_span::sym::rustc_dump_variances,
47                );
48                tcx.dcx().span_delayed_bug(tcx.def_span(id), message);
49                continue;
50            }
51        }
52
53        tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id));
54    }
55}