2024-08-22 21:07:29 +00:00
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
|
|
|
|
use rustc_middle::ty::{GenericArgs, TyCtxt};
|
2024-12-12 23:29:23 +00:00
|
|
|
use rustc_span::sym;
|
2024-06-19 11:11:18 +00:00
|
|
|
|
2024-08-22 21:07:29 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-06-19 11:11:18 +00:00
|
|
|
pub(crate) fn variances(tcx: TyCtxt<'_>) {
|
2024-08-10 03:43:30 +00:00
|
|
|
let crate_items = tcx.hir_crate_items(());
|
2024-06-19 11:11:18 +00:00
|
|
|
|
2024-08-10 03:43:30 +00:00
|
|
|
if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) {
|
|
|
|
for id in crate_items.opaques() {
|
2024-06-19 11:11:18 +00:00
|
|
|
tcx.dcx().emit_err(crate::errors::VariancesOf {
|
2024-08-10 03:43:30 +00:00
|
|
|
span: tcx.def_span(id),
|
|
|
|
variances: format_variances(tcx, id),
|
2024-06-19 11:11:18 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-10 03:43:30 +00:00
|
|
|
for id in crate_items.free_items() {
|
2024-06-19 11:11:18 +00:00
|
|
|
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),
|
2024-08-22 21:07:29 +00:00
|
|
|
variances: format_variances(tcx, id.owner_id.def_id),
|
2024-06-19 11:11:18 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|