use std::fmt::Write; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_middle::ty::{GenericArgs, TyCtxt}; use rustc_span::sym; fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { let variances = tcx.variances_of(def_id); let generics = GenericArgs::identity_for_item(tcx, def_id); // 7 = 2-letter parameter + ": " + 1-letter variance + ", " let mut ret = String::with_capacity(2 + 7 * variances.len()); ret.push('['); for (arg, variance) in generics.iter().zip(variances.iter()) { write!(ret, "{arg}: {variance:?}, ").unwrap(); } // Remove trailing `, `. if !variances.is_empty() { ret.pop(); ret.pop(); } ret.push(']'); ret } pub(crate) fn variances(tcx: TyCtxt<'_>) { let crate_items = tcx.hir_crate_items(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in crate_items.opaques() { tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id), variances: format_variances(tcx, id), }); } } for id in crate_items.free_items() { if !tcx.has_attr(id.owner_id, sym::rustc_variance) { continue; } tcx.dcx().emit_err(crate::errors::VariancesOf { span: tcx.def_span(id.owner_id), variances: format_variances(tcx, id.owner_id.def_id), }); } }