Rollup merge of #106648 - Nilstrieb:poly-cleanup, r=compiler-errors
Polymorphization cleanup Split out of #106233 Use a newtype instead of a bitset directly. This makes the code way easier to read and easier to adapt for future changes.
This commit is contained in:
commit
6e0c404f76
10 changed files with 66 additions and 79 deletions
|
@ -40,12 +40,11 @@ where
|
||||||
let index = index
|
let index = index
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("more generic parameters than can fit into a `u32`");
|
.expect("more generic parameters than can fit into a `u32`");
|
||||||
let is_used = unused_params.contains(index).map_or(true, |unused| !unused);
|
|
||||||
// Only recurse when generic parameters in fns, closures and generators
|
// Only recurse when generic parameters in fns, closures and generators
|
||||||
// are used and require substitution.
|
// are used and require substitution.
|
||||||
// Just in case there are closures or generators within this subst,
|
// Just in case there are closures or generators within this subst,
|
||||||
// recurse.
|
// recurse.
|
||||||
if is_used && subst.needs_subst() {
|
if unused_params.is_used(index) && subst.needs_subst() {
|
||||||
return subst.visit_with(self);
|
return subst.visit_with(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1429,7 +1429,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
let instance =
|
let instance =
|
||||||
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
|
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
|
||||||
let unused = tcx.unused_generic_params(instance);
|
let unused = tcx.unused_generic_params(instance);
|
||||||
if !unused.is_empty() {
|
if !unused.all_used() {
|
||||||
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use rustc_hir::def::{CtorKind, DefKind};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
|
||||||
use rustc_hir::definitions::DefKey;
|
use rustc_hir::definitions::DefKey;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_index::bit_set::{BitSet, FiniteBitSet};
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::metadata::ModChild;
|
use rustc_middle::metadata::ModChild;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
|
@ -22,7 +22,7 @@ use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, ReprOptions, Ty};
|
use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
|
||||||
use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
|
use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
|
||||||
use rustc_serialize::opaque::FileEncoder;
|
use rustc_serialize::opaque::FileEncoder;
|
||||||
use rustc_session::config::SymbolManglingVersion;
|
use rustc_session::config::SymbolManglingVersion;
|
||||||
|
@ -384,7 +384,7 @@ define_tables! {
|
||||||
trait_item_def_id: Table<DefIndex, RawDefId>,
|
trait_item_def_id: Table<DefIndex, RawDefId>,
|
||||||
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
||||||
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
|
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
|
||||||
unused_generic_params: Table<DefIndex, LazyValue<FiniteBitSet<u32>>>,
|
unused_generic_params: Table<DefIndex, LazyValue<UnusedGenericParams>>,
|
||||||
params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
|
params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
|
||||||
repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
|
repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
|
||||||
// `def_keys` and `def_path_hashes` represent a lazy version of a
|
// `def_keys` and `def_path_hashes` represent a lazy version of a
|
||||||
|
|
|
@ -1839,7 +1839,7 @@ rustc_queries! {
|
||||||
desc { "getting codegen unit `{sym}`" }
|
desc { "getting codegen unit `{sym}`" }
|
||||||
}
|
}
|
||||||
|
|
||||||
query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet<u32> {
|
query unused_generic_params(key: ty::InstanceDef<'tcx>) -> UnusedGenericParams {
|
||||||
cache_on_disk_if { key.def_id().is_local() }
|
cache_on_disk_if { key.def_id().is_local() }
|
||||||
desc {
|
desc {
|
||||||
|tcx| "determining which generic parameters are unused by `{}`",
|
|tcx| "determining which generic parameters are unused by `{}`",
|
||||||
|
|
|
@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def::Namespace;
|
use rustc_hir::def::Namespace;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
|
use rustc_index::bit_set::FiniteBitSet;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
@ -711,7 +712,7 @@ fn polymorphize<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalSubsts::for_item(tcx, def_id, |param, _| {
|
InternalSubsts::for_item(tcx, def_id, |param, _| {
|
||||||
let is_unused = unused.contains(param.index).unwrap_or(false);
|
let is_unused = unused.is_unused(param.index);
|
||||||
debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
|
debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
|
||||||
match param.kind {
|
match param.kind {
|
||||||
// Upvar case: If parameter is a type parameter..
|
// Upvar case: If parameter is a type parameter..
|
||||||
|
@ -733,7 +734,7 @@ fn polymorphize<'tcx>(
|
||||||
// Simple case: If parameter is a const or type parameter..
|
// Simple case: If parameter is a const or type parameter..
|
||||||
ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if
|
ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if
|
||||||
// ..and is within range and unused..
|
// ..and is within range and unused..
|
||||||
unused.contains(param.index).unwrap_or(false) =>
|
unused.is_unused(param.index) =>
|
||||||
// ..then use the identity for this parameter.
|
// ..then use the identity for this parameter.
|
||||||
tcx.mk_param_from_def(param),
|
tcx.mk_param_from_def(param),
|
||||||
|
|
||||||
|
@ -774,3 +775,36 @@ fn needs_fn_once_adapter_shim(
|
||||||
(ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()),
|
(ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set bits represent unused generic parameters.
|
||||||
|
// An empty set indicates that all parameters are used.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
|
||||||
|
pub struct UnusedGenericParams(FiniteBitSet<u32>);
|
||||||
|
|
||||||
|
impl UnusedGenericParams {
|
||||||
|
pub fn new_all_unused(amount: u32) -> Self {
|
||||||
|
let mut bitset = FiniteBitSet::new_empty();
|
||||||
|
bitset.set_range(0..amount);
|
||||||
|
Self(bitset)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_all_used() -> Self {
|
||||||
|
Self(FiniteBitSet::new_empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mark_used(&mut self, idx: u32) {
|
||||||
|
self.0.clear(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_unused(&self, idx: u32) -> bool {
|
||||||
|
self.0.contains(idx).unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_used(&self, idx: u32) -> bool {
|
||||||
|
!self.is_unused(idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_used(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ pub use self::context::{
|
||||||
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
|
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
|
||||||
TyCtxtFeed,
|
TyCtxtFeed,
|
||||||
};
|
};
|
||||||
pub use self::instance::{Instance, InstanceDef, ShortInstance};
|
pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
|
||||||
pub use self::list::List;
|
pub use self::list::List;
|
||||||
pub use self::parameterized::ParameterizedOverTcx;
|
pub use self::parameterized::ParameterizedOverTcx;
|
||||||
pub use self::rvalue_scopes::RvalueScopes;
|
pub use self::rvalue_scopes::RvalueScopes;
|
||||||
|
|
|
@ -60,6 +60,7 @@ trivially_parameterized_over_tcx! {
|
||||||
ty::ImplPolarity,
|
ty::ImplPolarity,
|
||||||
ty::ReprOptions,
|
ty::ReprOptions,
|
||||||
ty::TraitDef,
|
ty::TraitDef,
|
||||||
|
ty::UnusedGenericParams,
|
||||||
ty::Visibility<DefIndex>,
|
ty::Visibility<DefIndex>,
|
||||||
ty::adjustment::CoerceUnsizedInfo,
|
ty::adjustment::CoerceUnsizedInfo,
|
||||||
ty::fast_reject::SimplifiedType,
|
ty::fast_reject::SimplifiedType,
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::ty::layout::TyAndLayout;
|
||||||
use crate::ty::subst::{GenericArg, SubstsRef};
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::util::AlwaysRequiresDrop;
|
use crate::ty::util::AlwaysRequiresDrop;
|
||||||
use crate::ty::GeneratorDiagnosticData;
|
use crate::ty::GeneratorDiagnosticData;
|
||||||
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
|
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::expand::allocator::AllocatorKind;
|
use rustc_ast::expand::allocator::AllocatorKind;
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
|
@ -50,7 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
|
||||||
use rustc_hir::hir_id::OwnerId;
|
use rustc_hir::hir_id::OwnerId;
|
||||||
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
||||||
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
|
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
|
||||||
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||||
use rustc_session::cstore::{CrateDepKind, CrateSource};
|
use rustc_session::cstore::{CrateDepKind, CrateSource};
|
||||||
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
|
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
|
||||||
|
|
|
@ -32,13 +32,13 @@ pub struct TypeLengthLimit {
|
||||||
pub type_length: usize,
|
pub type_length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnusedGenericParams {
|
pub struct UnusedGenericParamsHint {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub param_spans: Vec<Span>,
|
pub param_spans: Vec<Span>,
|
||||||
pub param_names: Vec<String>,
|
pub param_names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDiagnostic<'_> for UnusedGenericParams {
|
impl IntoDiagnostic<'_> for UnusedGenericParamsHint {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn into_diagnostic(
|
fn into_diagnostic(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
//! for their size, offset of a field, etc.).
|
//! for their size, offset of a field, etc.).
|
||||||
|
|
||||||
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
|
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
|
||||||
use rustc_index::bit_set::FiniteBitSet;
|
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
self,
|
self,
|
||||||
visit::{TyContext, Visitor},
|
visit::{TyContext, Visitor},
|
||||||
|
@ -17,12 +16,12 @@ use rustc_middle::ty::{
|
||||||
query::Providers,
|
query::Providers,
|
||||||
subst::SubstsRef,
|
subst::SubstsRef,
|
||||||
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
|
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
|
||||||
Const, Ty, TyCtxt,
|
Const, Ty, TyCtxt, UnusedGenericParams,
|
||||||
};
|
};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use crate::errors::UnusedGenericParams;
|
use crate::errors::UnusedGenericParamsHint;
|
||||||
|
|
||||||
/// Provide implementations of queries relating to polymorphization analysis.
|
/// Provide implementations of queries relating to polymorphization analysis.
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
|
@ -36,16 +35,16 @@ pub fn provide(providers: &mut Providers) {
|
||||||
fn unused_generic_params<'tcx>(
|
fn unused_generic_params<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
instance: ty::InstanceDef<'tcx>,
|
instance: ty::InstanceDef<'tcx>,
|
||||||
) -> FiniteBitSet<u32> {
|
) -> UnusedGenericParams {
|
||||||
if !tcx.sess.opts.unstable_opts.polymorphize {
|
if !tcx.sess.opts.unstable_opts.polymorphize {
|
||||||
// If polymorphization disabled, then all parameters are used.
|
// If polymorphization disabled, then all parameters are used.
|
||||||
return FiniteBitSet::new_empty();
|
return UnusedGenericParams::new_all_used();
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_id = instance.def_id();
|
let def_id = instance.def_id();
|
||||||
// Exit early if this instance should not be polymorphized.
|
// Exit early if this instance should not be polymorphized.
|
||||||
if !should_polymorphize(tcx, def_id, instance) {
|
if !should_polymorphize(tcx, def_id, instance) {
|
||||||
return FiniteBitSet::new_empty();
|
return UnusedGenericParams::new_all_used();
|
||||||
}
|
}
|
||||||
|
|
||||||
let generics = tcx.generics_of(def_id);
|
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.
|
// Exit early when there are no parameters to be unused.
|
||||||
if generics.count() == 0 {
|
if generics.count() == 0 {
|
||||||
return FiniteBitSet::new_empty();
|
return UnusedGenericParams::new_all_used();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a bitset with N rightmost ones for each parameter.
|
// Create a bitset with N rightmost ones for each parameter.
|
||||||
let generics_count: u32 =
|
let generics_count: u32 =
|
||||||
generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
|
generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
|
||||||
let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
|
let mut unused_parameters = UnusedGenericParams::new_all_unused(generics_count);
|
||||||
unused_parameters.set_range(0..generics_count);
|
|
||||||
debug!(?unused_parameters, "(start)");
|
debug!(?unused_parameters, "(start)");
|
||||||
|
|
||||||
mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
|
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)");
|
debug!(?unused_parameters, "(end)");
|
||||||
|
|
||||||
// Emit errors for debugging and testing if enabled.
|
// 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);
|
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>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
generics: &'tcx ty::Generics,
|
generics: &'tcx ty::Generics,
|
||||||
unused_parameters: &mut FiniteBitSet<u32>,
|
unused_parameters: &mut UnusedGenericParams,
|
||||||
) {
|
) {
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
DefKind::Closure | DefKind::Generator => {
|
DefKind::Closure | DefKind::Generator => {
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
debug!(?param, "(closure/gen)");
|
debug!(?param, "(closure/gen)");
|
||||||
unused_parameters.clear(param.index);
|
unused_parameters.mark_used(param.index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefKind::Mod
|
DefKind::Mod
|
||||||
|
@ -178,7 +176,7 @@ fn mark_used_by_default_parameters<'tcx>(
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
debug!(?param, "(other)");
|
debug!(?param, "(other)");
|
||||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
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>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
generics: &'tcx ty::Generics,
|
generics: &'tcx ty::Generics,
|
||||||
unused_parameters: &FiniteBitSet<u32>,
|
unused_parameters: &UnusedGenericParams,
|
||||||
) {
|
) {
|
||||||
let base_def_id = tcx.typeck_root_def_id(def_id);
|
let base_def_id = tcx.typeck_root_def_id(def_id);
|
||||||
if !tcx.has_attr(base_def_id, sym::rustc_polymorphize_error) {
|
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);
|
let mut next_generics = Some(generics);
|
||||||
while let Some(generics) = next_generics {
|
while let Some(generics) = next_generics {
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
if unused_parameters.contains(param.index).unwrap_or(false) {
|
if unused_parameters.is_unused(param.index) {
|
||||||
debug!(?param);
|
debug!(?param);
|
||||||
let def_span = tcx.def_span(param.def_id);
|
let def_span = tcx.def_span(param.def_id);
|
||||||
param_spans.push(def_span);
|
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));
|
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.
|
/// Visitor used to aggregate generic parameter uses.
|
||||||
struct MarkUsedGenericParams<'a, 'tcx> {
|
struct MarkUsedGenericParams<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
unused_parameters: &'a mut FiniteBitSet<u32>,
|
unused_parameters: &'a mut UnusedGenericParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
|
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
|
||||||
|
@ -244,7 +242,7 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
|
||||||
debug!(?self.unused_parameters, ?unused);
|
debug!(?self.unused_parameters, ?unused);
|
||||||
for (i, arg) in substs.iter().enumerate() {
|
for (i, arg) in substs.iter().enumerate() {
|
||||||
let i = i.try_into().unwrap();
|
let i = i.try_into().unwrap();
|
||||||
if !unused.contains(i).unwrap_or(false) {
|
if unused.is_used(i) {
|
||||||
arg.visit_with(self);
|
arg.visit_with(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,7 +306,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||||
match c.kind() {
|
match c.kind() {
|
||||||
ty::ConstKind::Param(param) => {
|
ty::ConstKind::Param(param) => {
|
||||||
debug!(?param);
|
debug!(?param);
|
||||||
self.unused_parameters.clear(param.index);
|
self.unused_parameters.mark_used(param.index);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
|
||||||
|
@ -342,55 +340,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::Param(param) => {
|
ty::Param(param) => {
|
||||||
debug!(?param);
|
debug!(?param);
|
||||||
self.unused_parameters.clear(param.index);
|
self.unused_parameters.mark_used(param.index);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => ty.super_visit_with(self),
|
_ => ty.super_visit_with(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor used to check if a generic parameter is used.
|
|
||||||
struct HasUsedGenericParams<'a> {
|
|
||||||
unused_parameters: &'a FiniteBitSet<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
|
||||||
type BreakTy = ();
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
|
||||||
if !c.has_non_region_param() {
|
|
||||||
return ControlFlow::CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
match c.kind() {
|
|
||||||
ty::ConstKind::Param(param) => {
|
|
||||||
if self.unused_parameters.contains(param.index).unwrap_or(false) {
|
|
||||||
ControlFlow::CONTINUE
|
|
||||||
} else {
|
|
||||||
ControlFlow::BREAK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => c.super_visit_with(self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
|
||||||
if !ty.has_non_region_param() {
|
|
||||||
return ControlFlow::CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
match ty.kind() {
|
|
||||||
ty::Param(param) => {
|
|
||||||
if self.unused_parameters.contains(param.index).unwrap_or(false) {
|
|
||||||
ControlFlow::CONTINUE
|
|
||||||
} else {
|
|
||||||
ControlFlow::BREAK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => ty.super_visit_with(self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue