1
Fork 0

Use newtype for unused generic parameters

This commit is contained in:
Nilstrieb 2022-12-01 18:57:53 +01:00
parent 89e0576bd3
commit 2855794257
10 changed files with 65 additions and 33 deletions

View file

@ -6,7 +6,6 @@
//! for their size, offset of a field, etc.).
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{
self,
visit::{TyContext, Visitor},
@ -17,12 +16,12 @@ use rustc_middle::ty::{
query::Providers,
subst::SubstsRef,
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
Const, Ty, TyCtxt,
Const, Ty, TyCtxt, UnusedGenericParams,
};
use rustc_span::symbol::sym;
use std::ops::ControlFlow;
use crate::errors::UnusedGenericParams;
use crate::errors::UnusedGenericParamsHint;
/// Provide implementations of queries relating to polymorphization analysis.
pub fn provide(providers: &mut Providers) {
@ -36,16 +35,16 @@ pub fn provide(providers: &mut Providers) {
fn unused_generic_params<'tcx>(
tcx: TyCtxt<'tcx>,
instance: ty::InstanceDef<'tcx>,
) -> FiniteBitSet<u32> {
) -> UnusedGenericParams {
if !tcx.sess.opts.unstable_opts.polymorphize {
// If polymorphization disabled, then all parameters are used.
return FiniteBitSet::new_empty();
return UnusedGenericParams::new_all_used();
}
let def_id = instance.def_id();
// Exit early if this instance should not be polymorphized.
if !should_polymorphize(tcx, def_id, instance) {
return FiniteBitSet::new_empty();
return UnusedGenericParams::new_all_used();
}
let generics = tcx.generics_of(def_id);
@ -53,14 +52,13 @@ fn unused_generic_params<'tcx>(
// Exit early when there are no parameters to be unused.
if generics.count() == 0 {
return FiniteBitSet::new_empty();
return UnusedGenericParams::new_all_used();
}
// Create a bitset with N rightmost ones for each parameter.
let generics_count: u32 =
generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
unused_parameters.set_range(0..generics_count);
let mut unused_parameters = UnusedGenericParams::new_all_unused(generics_count);
debug!(?unused_parameters, "(start)");
mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
@ -78,7 +76,7 @@ fn unused_generic_params<'tcx>(
debug!(?unused_parameters, "(end)");
// Emit errors for debugging and testing if enabled.
if !unused_parameters.is_empty() {
if !unused_parameters.all_used() {
emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters);
}
@ -136,13 +134,13 @@ fn mark_used_by_default_parameters<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
generics: &'tcx ty::Generics,
unused_parameters: &mut FiniteBitSet<u32>,
unused_parameters: &mut UnusedGenericParams,
) {
match tcx.def_kind(def_id) {
DefKind::Closure | DefKind::Generator => {
for param in &generics.params {
debug!(?param, "(closure/gen)");
unused_parameters.clear(param.index);
unused_parameters.mark_used(param.index);
}
}
DefKind::Mod
@ -178,7 +176,7 @@ fn mark_used_by_default_parameters<'tcx>(
for param in &generics.params {
debug!(?param, "(other)");
if let ty::GenericParamDefKind::Lifetime = param.kind {
unused_parameters.clear(param.index);
unused_parameters.mark_used(param.index);
}
}
}
@ -196,7 +194,7 @@ fn emit_unused_generic_params_error<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
generics: &'tcx ty::Generics,
unused_parameters: &FiniteBitSet<u32>,
unused_parameters: &UnusedGenericParams,
) {
let base_def_id = tcx.typeck_root_def_id(def_id);
if !tcx.has_attr(base_def_id, sym::rustc_polymorphize_error) {
@ -213,7 +211,7 @@ fn emit_unused_generic_params_error<'tcx>(
let mut next_generics = Some(generics);
while let Some(generics) = next_generics {
for param in &generics.params {
if unused_parameters.contains(param.index).unwrap_or(false) {
if unused_parameters.is_unused(param.index) {
debug!(?param);
let def_span = tcx.def_span(param.def_id);
param_spans.push(def_span);
@ -224,14 +222,14 @@ fn emit_unused_generic_params_error<'tcx>(
next_generics = generics.parent.map(|did| tcx.generics_of(did));
}
tcx.sess.emit_err(UnusedGenericParams { span: fn_span, param_spans, param_names });
tcx.sess.emit_err(UnusedGenericParamsHint { span: fn_span, param_spans, param_names });
}
/// Visitor used to aggregate generic parameter uses.
struct MarkUsedGenericParams<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
def_id: DefId,
unused_parameters: &'a mut FiniteBitSet<u32>,
unused_parameters: &'a mut UnusedGenericParams,
}
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
@ -244,7 +242,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
debug!(?self.unused_parameters, ?unused);
for (i, arg) in substs.iter().enumerate() {
let i = i.try_into().unwrap();
if !unused.contains(i).unwrap_or(false) {
if unused.is_used(i) {
arg.visit_with(self);
}
}
@ -308,7 +306,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
match c.kind() {
ty::ConstKind::Param(param) => {
debug!(?param);
self.unused_parameters.clear(param.index);
self.unused_parameters.mark_used(param.index);
ControlFlow::CONTINUE
}
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })