diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_monomorphize/src/polymorphize.rs | 64 |
1 files changed, 38 insertions, 26 deletions
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 394843e51..650076c22 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -8,8 +8,9 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext}; use rustc_index::bit_set::FiniteBitSet; use rustc_middle::mir::{ + self, visit::{TyContext, Visitor}, - Local, LocalDecl, Location, + Constant, ConstantKind, Local, LocalDecl, Location, }; use rustc_middle::ty::{ self, @@ -22,6 +23,8 @@ use rustc_span::symbol::sym; use std::convert::TryInto; use std::ops::ControlFlow; +use crate::errors::UnusedGenericParams; + /// Provide implementations of queries relating to polymorphization analysis. pub fn provide(providers: &mut Providers) { providers.unused_generic_params = unused_generic_params; @@ -31,7 +34,6 @@ pub fn provide(providers: &mut Providers) { /// /// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all /// parameters are used). -#[instrument(level = "debug", skip(tcx))] fn unused_generic_params<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, @@ -169,6 +171,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm @@ -206,22 +209,23 @@ fn emit_unused_generic_params_error<'tcx>( _ => tcx.def_span(def_id), }; - let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters"); - + let mut param_spans = Vec::new(); + let mut param_names = Vec::new(); 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) { debug!(?param); let def_span = tcx.def_span(param.def_id); - err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name)); + param_spans.push(def_span); + param_names.push(param.name.to_string()); } } next_generics = generics.parent.map(|did| tcx.generics_of(did)); } - err.emit(); + tcx.sess.emit_err(UnusedGenericParams { span: fn_span, param_spans, param_names }); } /// Visitor used to aggregate generic parameter uses. @@ -267,8 +271,27 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.super_local_decl(local, local_decl); } - fn visit_const(&mut self, c: Const<'tcx>, _: Location) { - c.visit_with(self); + fn visit_constant(&mut self, ct: &Constant<'tcx>, location: Location) { + match ct.literal { + ConstantKind::Ty(c) => { + c.visit_with(self); + } + ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted }, ty) => { + // Avoid considering `T` unused when constants are of the form: + // `<Self as Foo<T>>::foo::promoted[p]` + if let Some(p) = promoted { + if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self { + // If there is a promoted, don't look at the substs - since it will always contain + // the generic parameters, instead, traverse the promoted MIR. + let promoted = self.tcx.promoted_mir(def.did); + self.visit_body(&promoted[p]); + } + } + + Visitor::visit_ty(self, ty, TyContext::Location(location)); + } + ConstantKind::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)), + } } fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) { @@ -279,7 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> { - if !c.has_param_types_or_consts() { + if !c.has_non_region_param() { return ControlFlow::CONTINUE; } @@ -289,21 +312,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)}) - // Avoid considering `T` unused when constants are of the form: - // `<Self as Foo<T>>::foo::promoted[p]` - if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => - { - // If there is a promoted, don't look at the substs - since it will always contain - // the generic parameters, instead, traverse the promoted MIR. - let promoted = self.tcx.promoted_mir(def.did); - self.visit_body(&promoted[p]); - ControlFlow::CONTINUE - } - ty::ConstKind::Unevaluated(uv) - if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) => + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) + if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) => { - self.visit_child_body(uv.def.did, uv.substs); + self.visit_child_body(def.did, substs); ControlFlow::CONTINUE } _ => c.super_visit_with(self), @@ -312,7 +324,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if !ty.has_param_types_or_consts() { + if !ty.has_non_region_param() { return ControlFlow::CONTINUE; } @@ -349,7 +361,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> { #[instrument(level = "debug", skip(self))] fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> { - if !c.has_param_types_or_consts() { + if !c.has_non_region_param() { return ControlFlow::CONTINUE; } @@ -367,7 +379,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> { #[instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if !ty.has_param_types_or_consts() { + if !ty.has_non_region_param() { return ControlFlow::CONTINUE; } |