Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polymorphization cleanup #106648

Merged
merged 2 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/rustc_const_eval/src/interpret/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@ where
let index = index
.try_into()
.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
// are used and require substitution.
// Just in case there are closures or generators within this subst,
// recurse.
if is_used && subst.needs_subst() {
if unused_params.is_used(index) && subst.needs_subst() {
return subst.visit_with(self);
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1429,7 +1429,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let instance =
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
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);
}
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
use rustc_hir::definitions::DefKey;
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_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
Expand All @@ -22,7 +22,7 @@ use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType;
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_serialize::opaque::FileEncoder;
use rustc_session::config::SymbolManglingVersion;
Expand Down Expand Up @@ -384,7 +384,7 @@ define_tables! {
trait_item_def_id: Table<DefIndex, RawDefId>,
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
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>>>,
repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
// `def_keys` and `def_path_hashes` represent a lazy version of a
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,7 @@ rustc_queries! {
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() }
desc {
|tcx| "determining which generic parameters are unused by `{}`",
Expand Down
38 changes: 36 additions & 2 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::FiniteBitSet;
use rustc_macros::HashStable;
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
use rustc_span::Symbol;
Expand Down Expand Up @@ -711,7 +712,7 @@ fn polymorphize<'tcx>(
}

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);
match param.kind {
// Upvar case: If parameter is a type parameter..
Expand All @@ -733,7 +734,7 @@ fn polymorphize<'tcx>(
// Simple case: If parameter is a const or type parameter..
ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if
// ..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.
tcx.mk_param_from_def(param),

Expand Down Expand Up @@ -774,3 +775,36 @@ fn needs_fn_once_adapter_shim(
(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()
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub use self::context::{
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
TyCtxtFeed,
};
pub use self::instance::{Instance, InstanceDef, ShortInstance};
pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
pub use self::list::List;
pub use self::parameterized::ParameterizedOverTcx;
pub use self::rvalue_scopes::RvalueScopes;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ trivially_parameterized_over_tcx! {
ty::ImplPolarity,
ty::ReprOptions,
ty::TraitDef,
ty::UnusedGenericParams,
ty::Visibility<DefIndex>,
ty::adjustment::CoerceUnsizedInfo,
ty::fast_reject::SimplifiedType,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::ty::layout::TyAndLayout;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
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::expand::allocator::AllocatorKind;
use rustc_attr as attr;
Expand All @@ -50,7 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems};
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::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_monomorphize/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ pub struct TypeLengthLimit {
pub type_length: usize,
}

pub struct UnusedGenericParams {
pub struct UnusedGenericParamsHint {
compiler-errors marked this conversation as resolved.
Show resolved Hide resolved
pub span: Span,
pub param_spans: Vec<Span>,
pub param_names: Vec<String>,
}

impl IntoDiagnostic<'_> for UnusedGenericParams {
impl IntoDiagnostic<'_> for UnusedGenericParamsHint {
#[track_caller]
fn into_diagnostic(
self,
Expand Down
83 changes: 18 additions & 65 deletions compiler/rustc_monomorphize/src/polymorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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) {
Expand All @@ -36,31 +35,30 @@ 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);
debug!(?generics);

// 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);
Expand All @@ -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);
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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> {
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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 })
Expand Down Expand Up @@ -342,55 +340,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
}
ty::Param(param) => {
debug!(?param);
self.unused_parameters.clear(param.index);
self.unused_parameters.mark_used(param.index);
ControlFlow::CONTINUE
}
_ => ty.super_visit_with(self),
}
}
}

/// Visitor used to check if a generic parameter is used.
struct HasUsedGenericParams<'a> {
Copy link
Member

@compiler-errors compiler-errors Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this not used? why wasn't deny(unused) triggering for it? lol... anyways r=me

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe the trait impl was confusing it..

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),
}
}
}