mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-05 11:33:04 +00:00
Spread tracing instrumentation into the polymorphization logic
This commit is contained in:
parent
0559e50a6c
commit
63af264d62
@ -30,9 +30,8 @@ pub fn provide(providers: &mut Providers) {
|
||||
/// Determine which generic parameters are used by the function/method/closure represented by
|
||||
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
|
||||
/// indicates all parameters are used).
|
||||
#[instrument(skip(tcx))]
|
||||
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
debug!("unused_generic_params({:?})", def_id);
|
||||
|
||||
if !tcx.sess.opts.debugging_opts.polymorphize {
|
||||
// If polymorphization disabled, then all parameters are used.
|
||||
return FiniteBitSet::new_empty();
|
||||
@ -46,7 +45,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
}
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
debug!("unused_generic_params: generics={:?}", generics);
|
||||
debug!(?generics);
|
||||
|
||||
// Exit early when there are no parameters to be unused.
|
||||
if generics.count() == 0 {
|
||||
@ -57,11 +56,11 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
let context = tcx.hir().body_const_context(def_id.expect_local());
|
||||
match context {
|
||||
Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
|
||||
debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
|
||||
debug!("no mir available");
|
||||
return FiniteBitSet::new_empty();
|
||||
}
|
||||
Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
|
||||
debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id);
|
||||
debug!("no ctfe mir available");
|
||||
return FiniteBitSet::new_empty();
|
||||
}
|
||||
_ => {}
|
||||
@ -72,9 +71,9 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<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);
|
||||
debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters);
|
||||
debug!(?unused_parameters, "(start)");
|
||||
mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
|
||||
debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);
|
||||
debug!(?unused_parameters, "(after default)");
|
||||
|
||||
// Visit MIR and accumululate used generic parameters.
|
||||
let body = match context {
|
||||
@ -85,10 +84,10 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
};
|
||||
let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
|
||||
vis.visit_body(body);
|
||||
debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
|
||||
debug!(?unused_parameters, "(after visitor)");
|
||||
|
||||
mark_used_by_predicates(tcx, def_id, &mut unused_parameters);
|
||||
debug!("unused_generic_params: (end) unused_parameters={:?}", unused_parameters);
|
||||
debug!(?unused_parameters, "(end)");
|
||||
|
||||
// Emit errors for debugging and testing if enabled.
|
||||
if !unused_parameters.is_empty() {
|
||||
@ -101,6 +100,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
|
||||
/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
|
||||
/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
|
||||
/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
|
||||
#[instrument(skip(tcx, def_id, generics, unused_parameters))]
|
||||
fn mark_used_by_default_parameters<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
@ -109,12 +109,12 @@ fn mark_used_by_default_parameters<'tcx>(
|
||||
) {
|
||||
if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) {
|
||||
for param in &generics.params {
|
||||
debug!("mark_used_by_default_parameters: (closure/gen) param={:?}", param);
|
||||
debug!(?param, "(closure/gen)");
|
||||
unused_parameters.clear(param.index);
|
||||
}
|
||||
} else {
|
||||
for param in &generics.params {
|
||||
debug!("mark_used_by_default_parameters: (other) param={:?}", param);
|
||||
debug!(?param, "(other)");
|
||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||
unused_parameters.clear(param.index);
|
||||
}
|
||||
@ -128,6 +128,7 @@ fn mark_used_by_default_parameters<'tcx>(
|
||||
|
||||
/// Search the predicates on used generic parameters for any unused generic parameters, and mark
|
||||
/// those as used.
|
||||
#[instrument(skip(tcx, def_id))]
|
||||
fn mark_used_by_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
@ -135,16 +136,12 @@ fn mark_used_by_predicates<'tcx>(
|
||||
) {
|
||||
let def_id = tcx.closure_base_def_id(def_id);
|
||||
let predicates = tcx.explicit_predicates_of(def_id);
|
||||
debug!("mark_used_by_predicates: predicates_of={:?}", predicates);
|
||||
|
||||
let mut current_unused_parameters = FiniteBitSet::new_empty();
|
||||
// Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
|
||||
// bit set so that this is skipped if all parameters are already used.
|
||||
while current_unused_parameters != *unused_parameters {
|
||||
debug!(
|
||||
"mark_used_by_predicates: current_unused_parameters={:?} = unused_parameters={:?}",
|
||||
current_unused_parameters, unused_parameters
|
||||
);
|
||||
debug!(?current_unused_parameters, ?unused_parameters);
|
||||
current_unused_parameters = *unused_parameters;
|
||||
|
||||
for (predicate, _) in predicates.predicates {
|
||||
@ -169,13 +166,13 @@ fn mark_used_by_predicates<'tcx>(
|
||||
|
||||
/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
|
||||
/// parameter which was unused.
|
||||
#[instrument(skip(tcx, generics))]
|
||||
fn emit_unused_generic_params_error<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
generics: &'tcx ty::Generics,
|
||||
unused_parameters: &FiniteBitSet<u32>,
|
||||
) {
|
||||
debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
|
||||
let base_def_id = tcx.closure_base_def_id(def_id);
|
||||
if !tcx
|
||||
.get_attrs(base_def_id)
|
||||
@ -185,7 +182,6 @@ fn emit_unused_generic_params_error<'tcx>(
|
||||
return;
|
||||
}
|
||||
|
||||
debug!("emit_unused_generic_params_error: unused_parameters={:?}", unused_parameters);
|
||||
let fn_span = match tcx.opt_item_name(def_id) {
|
||||
Some(ident) => ident.span,
|
||||
_ => tcx.def_span(def_id),
|
||||
@ -197,7 +193,7 @@ fn emit_unused_generic_params_error<'tcx>(
|
||||
while let Some(generics) = next_generics {
|
||||
for param in &generics.params {
|
||||
if unused_parameters.contains(param.index).unwrap_or(false) {
|
||||
debug!("emit_unused_generic_params_error: param={:?}", param);
|
||||
debug!(?param);
|
||||
let def_span = tcx.def_span(param.def_id);
|
||||
err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name));
|
||||
}
|
||||
@ -219,25 +215,23 @@ struct MarkUsedGenericParams<'a, 'tcx> {
|
||||
impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
|
||||
/// Invoke `unused_generic_params` on a body contained within the current item (e.g.
|
||||
/// a closure, generator or constant).
|
||||
#[instrument(skip(self, def_id, substs))]
|
||||
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
|
||||
let unused = self.tcx.unused_generic_params(def_id);
|
||||
debug!(
|
||||
"visit_child_body: unused_parameters={:?} unused={:?}",
|
||||
self.unused_parameters, unused
|
||||
);
|
||||
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) {
|
||||
arg.visit_with(self);
|
||||
}
|
||||
}
|
||||
debug!("visit_child_body: unused_parameters={:?}", self.unused_parameters);
|
||||
debug!(?self.unused_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
#[instrument(skip(self, local))]
|
||||
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
|
||||
debug!("visit_local_decl: local_decl={:?}", local_decl);
|
||||
if local == Local::from_usize(1) {
|
||||
let def_kind = self.tcx.def_kind(self.def_id);
|
||||
if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
|
||||
@ -245,7 +239,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
// happens because the first argument to the closure is a reference to itself and
|
||||
// that will call `visit_substs`, resulting in each generic parameter captured being
|
||||
// considered used by default.
|
||||
debug!("visit_local_decl: skipping closure substs");
|
||||
debug!("skipping closure substs");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -263,15 +257,15 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
#[instrument(skip(self))]
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_const: c={:?}", c);
|
||||
if !c.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
match c.val {
|
||||
ty::ConstKind::Param(param) => {
|
||||
debug!("visit_const: param={:?}", param);
|
||||
debug!(?param);
|
||||
self.unused_parameters.clear(param.index);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
@ -296,15 +290,15 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_ty: ty={:?}", ty);
|
||||
if !ty.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
match *ty.kind() {
|
||||
ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
|
||||
debug!("visit_ty: def_id={:?}", def_id);
|
||||
debug!(?def_id);
|
||||
// Avoid cycle errors with generators.
|
||||
if def_id == self.def_id {
|
||||
return ControlFlow::CONTINUE;
|
||||
@ -316,7 +310,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
ty::Param(param) => {
|
||||
debug!("visit_ty: param={:?}", param);
|
||||
debug!(?param);
|
||||
self.unused_parameters.clear(param.index);
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
@ -333,8 +327,8 @@ struct HasUsedGenericParams<'a> {
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
||||
type BreakTy = ();
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_const: c={:?}", c);
|
||||
if !c.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
@ -351,8 +345,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!("visit_ty: ty={:?}", ty);
|
||||
if !ty.has_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user