Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6f53ddf

Browse files
committedOct 17, 2021
Auto merge of #89514 - davidtwco:polymorphize-shims-and-predicates, r=lcnr
polymorphization: shims and predicates Supersedes #75737 and #75414. This pull request includes up some changes to polymorphization which hadn't landed previously and gets stage2 bootstrapping and the test suite passing when polymorphization is enabled. There are still issues with `type_id` and polymorphization to investigate but this should get polymorphization in a reasonable state to work on. - #75737 and #75414 both worked but were blocked on having the rest of the test suite pass (with polymorphization enabled) with and without the PRs. It makes more sense to just land these so that the changes are in. - #75737's changes remove the restriction of `InstanceDef::Item` on polymorphization, so that shims can now be polymorphized. This won't have much of an effect until polymorphization's analysis is more advanced, but it doesn't hurt. - #75414's changes remove all logic which marks parameters as used based on their presence in predicates - given #75675, this will enable more polymorphization and avoid the symbol clashes that predicate logic previously sidestepped. - Polymorphization now explicitly checks (and skips) foreign items, this is necessary for stage2 bootstrapping to work when polymorphization is enabled. - The conditional determining the emission of a note adding context to a post-monomorphization error has been modified. Polymorphization results in `optimized_mir` running for shims during collection where that wouldn't happen previously, some errors are emitted during `optimized_mir` and these were considered post-monomorphization errors with the existing logic (more errors and shims have a `DefId` coming from the std crate, not the local crate), adding a note that resulted in tests failing. It isn't particularly feasible to change where polymorphization runs or prevent it from using `optimized_mir`, so it seemed more reasonable to not change the conditional. - `characteristic_def_id_of_type` was being invoked during partitioning for self types of impl blocks which had projections that depended on the value of unused generic parameters of a function - this caused a ICE in a debuginfo test. If partitioning is enabled and the instance needs substitution then this is skipped. That test still fails for me locally, but not with an ICE, but it fails in a fresh checkout too, so 🤷‍♂️. r? `@lcnr`
2 parents 1d6f242 + b39e915 commit 6f53ddf

File tree

11 files changed

+182
-108
lines changed

11 files changed

+182
-108
lines changed
 

‎compiler/rustc_const_eval/src/interpret/util.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ where
3535
ty::Closure(def_id, substs)
3636
| ty::Generator(def_id, substs, ..)
3737
| ty::FnDef(def_id, substs) => {
38-
let unused_params = self.tcx.unused_generic_params(def_id);
38+
let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
39+
let unused_params = self.tcx.unused_generic_params(instance);
3940
for (index, subst) in substs.into_iter().enumerate() {
4041
let index = index
4142
.try_into()

‎compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ impl IntoArgs for (CrateNum, DefId) {
8383
}
8484
}
8585

86+
impl IntoArgs for ty::InstanceDef<'tcx> {
87+
fn into_args(self) -> (DefId, DefId) {
88+
(self.def_id(), self.def_id())
89+
}
90+
}
91+
8692
provide! { <'tcx> tcx, def_id, other, cdata,
8793
type_of => { cdata.get_type(def_id.index, tcx) }
8894
generics_of => { cdata.get_generics(def_id.index, tcx.sess) }

‎compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,9 @@ impl EncodeContext<'a, 'tcx> {
13191319
}
13201320
record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
13211321

1322-
let unused = self.tcx.unused_generic_params(def_id);
1322+
let instance =
1323+
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id()));
1324+
let unused = self.tcx.unused_generic_params(instance);
13231325
if !unused.is_empty() {
13241326
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
13251327
}

‎compiler/rustc_middle/src/mir/mono.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ pub enum MonoItem<'tcx> {
4747
}
4848

4949
impl<'tcx> MonoItem<'tcx> {
50+
/// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims).
51+
pub fn is_user_defined(&self) -> bool {
52+
match *self {
53+
MonoItem::Fn(instance) => matches!(instance.def, InstanceDef::Item(..)),
54+
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => true,
55+
}
56+
}
57+
5058
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
5159
match *self {
5260
MonoItem::Fn(instance) => {

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,11 +1558,11 @@ rustc_queries! {
15581558
query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
15591559
desc { "codegen_unit" }
15601560
}
1561-
query unused_generic_params(key: DefId) -> FiniteBitSet<u32> {
1562-
cache_on_disk_if { key.is_local() }
1561+
query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet<u32> {
1562+
cache_on_disk_if { key.def_id().is_local() }
15631563
desc {
15641564
|tcx| "determining which generic parameters are unused by `{}`",
1565-
tcx.def_path_str(key)
1565+
tcx.def_path_str(key.def_id())
15661566
}
15671567
}
15681568
query backend_optimization_level(_: ()) -> OptLevel {

‎compiler/rustc_middle/src/ty/instance.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,22 @@ impl<'tcx> InstanceDef<'tcx> {
152152
}
153153
}
154154

155+
/// Returns the `DefId` of instances which might not require codegen locally.
156+
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
157+
match self {
158+
ty::InstanceDef::Item(def) => Some(def.did),
159+
ty::InstanceDef::DropGlue(def_id, Some(_)) => Some(def_id),
160+
InstanceDef::VtableShim(..)
161+
| InstanceDef::ReifyShim(..)
162+
| InstanceDef::FnPtrShim(..)
163+
| InstanceDef::Virtual(..)
164+
| InstanceDef::Intrinsic(..)
165+
| InstanceDef::ClosureOnceShim { .. }
166+
| InstanceDef::DropGlue(..)
167+
| InstanceDef::CloneShim(..) => None,
168+
}
169+
}
170+
155171
#[inline]
156172
pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
157173
match self {
@@ -567,29 +583,26 @@ impl<'tcx> Instance<'tcx> {
567583
return self;
568584
}
569585

570-
if let InstanceDef::Item(def) = self.def {
571-
let polymorphized_substs = polymorphize(tcx, def.did, self.substs);
572-
debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
573-
Self { def: self.def, substs: polymorphized_substs }
574-
} else {
575-
self
576-
}
586+
let polymorphized_substs = polymorphize(tcx, self.def, self.substs);
587+
debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
588+
Self { def: self.def, substs: polymorphized_substs }
577589
}
578590
}
579591

580592
fn polymorphize<'tcx>(
581593
tcx: TyCtxt<'tcx>,
582-
def_id: DefId,
594+
instance: ty::InstanceDef<'tcx>,
583595
substs: SubstsRef<'tcx>,
584596
) -> SubstsRef<'tcx> {
585-
debug!("polymorphize({:?}, {:?})", def_id, substs);
586-
let unused = tcx.unused_generic_params(def_id);
597+
debug!("polymorphize({:?}, {:?})", instance, substs);
598+
let unused = tcx.unused_generic_params(instance);
587599
debug!("polymorphize: unused={:?}", unused);
588600

589601
// If this is a closure or generator then we need to handle the case where another closure
590602
// from the function is captured as an upvar and hasn't been polymorphized. In this case,
591603
// the unpolymorphized upvar closure would result in a polymorphized closure producing
592604
// multiple mono items (and eventually symbol clashes).
605+
let def_id = instance.def_id();
593606
let upvars_ty = if tcx.is_closure(def_id) {
594607
Some(substs.as_closure().tupled_upvars_ty())
595608
} else if tcx.type_of(def_id).is_generator() {
@@ -613,15 +626,23 @@ fn polymorphize<'tcx>(
613626
debug!("fold_ty: ty={:?}", ty);
614627
match ty.kind {
615628
ty::Closure(def_id, substs) => {
616-
let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
629+
let polymorphized_substs = polymorphize(
630+
self.tcx,
631+
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
632+
substs,
633+
);
617634
if substs == polymorphized_substs {
618635
ty
619636
} else {
620637
self.tcx.mk_closure(def_id, polymorphized_substs)
621638
}
622639
}
623640
ty::Generator(def_id, substs, movability) => {
624-
let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
641+
let polymorphized_substs = polymorphize(
642+
self.tcx,
643+
ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
644+
substs,
645+
);
625646
if substs == polymorphized_substs {
626647
ty
627648
} else {

‎compiler/rustc_monomorphize/src/collector.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,9 @@ fn collect_items_rec<'tcx>(
450450
// involving a dependency, and the lack of context is confusing) in this MVP, we focus on
451451
// diagnostics on edges crossing a crate boundary: the collected mono items which are not
452452
// defined in the local crate.
453-
if tcx.sess.diagnostic().err_count() > error_count && starting_point.node.krate() != LOCAL_CRATE
453+
if tcx.sess.diagnostic().err_count() > error_count
454+
&& starting_point.node.krate() != LOCAL_CRATE
455+
&& starting_point.node.is_user_defined()
454456
{
455457
let formatted_item = with_no_trimmed_paths(|| starting_point.node.to_string());
456458
tcx.sess.span_note_without_error(
@@ -934,21 +936,13 @@ fn visit_instance_use<'tcx>(
934936
}
935937
}
936938

937-
// Returns `true` if we should codegen an instance in the local crate.
938-
// Returns `false` if we can just link to the upstream crate and therefore don't
939-
// need a mono item.
939+
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
940+
/// can just link to the upstream crate and therefore don't need a mono item.
940941
fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
941-
let def_id = match instance.def {
942-
ty::InstanceDef::Item(def) => def.did,
943-
ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
944-
ty::InstanceDef::VtableShim(..)
945-
| ty::InstanceDef::ReifyShim(..)
946-
| ty::InstanceDef::ClosureOnceShim { .. }
947-
| ty::InstanceDef::Virtual(..)
948-
| ty::InstanceDef::FnPtrShim(..)
949-
| ty::InstanceDef::DropGlue(..)
950-
| ty::InstanceDef::Intrinsic(_)
951-
| ty::InstanceDef::CloneShim(..) => return true,
942+
let def_id = if let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() {
943+
def_id
944+
} else {
945+
return true;
952946
};
953947

954948
if tcx.is_foreign_item(def_id) {

‎compiler/rustc_monomorphize/src/partitioning/default.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel;
99
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
1010
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
1111
use rustc_middle::ty::print::characteristic_def_id_of_type;
12-
use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
12+
use rustc_middle::ty::{self, fold::TypeFoldable, DefIdTree, InstanceDef, TyCtxt};
1313
use rustc_span::symbol::Symbol;
1414

1515
use super::PartitioningCx;
@@ -300,14 +300,21 @@ fn characteristic_def_id_of_mono_item<'tcx>(
300300
// call it.
301301
return None;
302302
}
303-
// This is a method within an impl, find out what the self-type is:
304-
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
305-
instance.substs,
306-
ty::ParamEnv::reveal_all(),
307-
tcx.type_of(impl_def_id),
308-
);
309-
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
310-
return Some(def_id);
303+
304+
// When polymorphization is enabled, methods which do not depend on their generic
305+
// parameters, but the self-type of their impl block do will fail to normalize.
306+
if !tcx.sess.opts.debugging_opts.polymorphize
307+
|| !instance.definitely_needs_subst(tcx)
308+
{
309+
// This is a method within an impl, find out what the self-type is:
310+
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
311+
instance.substs,
312+
ty::ParamEnv::reveal_all(),
313+
tcx.type_of(impl_def_id),
314+
);
315+
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
316+
return Some(def_id);
317+
}
311318
}
312319
}
313320

‎compiler/rustc_monomorphize/src/polymorphize.rs

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,23 @@ pub fn provide(providers: &mut Providers) {
2727
providers.unused_generic_params = unused_generic_params;
2828
}
2929

30-
/// Determine which generic parameters are used by the function/method/closure represented by
31-
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
32-
/// indicates all parameters are used).
30+
/// Determine which generic parameters are used by the instance.
31+
///
32+
/// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all
33+
/// parameters are used).
3334
#[instrument(level = "debug", skip(tcx))]
34-
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
35+
fn unused_generic_params<'tcx>(
36+
tcx: TyCtxt<'tcx>,
37+
instance: ty::InstanceDef<'tcx>,
38+
) -> FiniteBitSet<u32> {
3539
if !tcx.sess.opts.debugging_opts.polymorphize {
3640
// If polymorphization disabled, then all parameters are used.
3741
return FiniteBitSet::new_empty();
3842
}
3943

40-
// Polymorphization results are stored in cross-crate metadata only when there are unused
41-
// parameters, so assume that non-local items must have only used parameters (else this query
42-
// would not be invoked, and the cross-crate metadata used instead).
43-
if !def_id.is_local() {
44+
let def_id = instance.def_id();
45+
// Exit early if this instance should not be polymorphized.
46+
if !should_polymorphize(tcx, def_id, instance) {
4447
return FiniteBitSet::new_empty();
4548
}
4649

@@ -52,41 +55,25 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
5255
return FiniteBitSet::new_empty();
5356
}
5457

55-
// Exit early when there is no MIR available.
56-
let context = tcx.hir().body_const_context(def_id.expect_local());
57-
match context {
58-
Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
59-
debug!("no mir available");
60-
return FiniteBitSet::new_empty();
61-
}
62-
Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
63-
debug!("no ctfe mir available");
64-
return FiniteBitSet::new_empty();
65-
}
66-
_ => {}
67-
}
68-
6958
// Create a bitset with N rightmost ones for each parameter.
7059
let generics_count: u32 =
7160
generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
7261
let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
7362
unused_parameters.set_range(0..generics_count);
7463
debug!(?unused_parameters, "(start)");
64+
7565
mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
7666
debug!(?unused_parameters, "(after default)");
7767

7868
// Visit MIR and accumululate used generic parameters.
79-
let body = match context {
69+
let body = match tcx.hir().body_const_context(def_id.expect_local()) {
8070
// Const functions are actually called and should thus be considered for polymorphization
81-
// via their runtime MIR
71+
// via their runtime MIR.
8272
Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id),
8373
Some(_) => tcx.mir_for_ctfe(def_id),
8474
};
8575
let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
8676
vis.visit_body(body);
87-
debug!(?unused_parameters, "(after visitor)");
88-
89-
mark_used_by_predicates(tcx, def_id, &mut unused_parameters);
9077
debug!(?unused_parameters, "(end)");
9178

9279
// Emit errors for debugging and testing if enabled.
@@ -97,6 +84,49 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
9784
unused_parameters
9885
}
9986

87+
/// Returns `true` if the instance should be polymorphized.
88+
fn should_polymorphize<'tcx>(
89+
tcx: TyCtxt<'tcx>,
90+
def_id: DefId,
91+
instance: ty::InstanceDef<'tcx>,
92+
) -> bool {
93+
// If an instance's MIR body is not polymorphic then the modified substitutions that are
94+
// derived from polymorphization's result won't make any difference.
95+
if !instance.has_polymorphic_mir_body() {
96+
return false;
97+
}
98+
99+
// Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic.
100+
if matches!(instance, ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::Virtual(..)) {
101+
return false;
102+
}
103+
104+
// Polymorphization results are stored in cross-crate metadata only when there are unused
105+
// parameters, so assume that non-local items must have only used parameters (else this query
106+
// would not be invoked, and the cross-crate metadata used instead).
107+
if !def_id.is_local() {
108+
return false;
109+
}
110+
111+
// Foreign items have no bodies to analyze.
112+
if tcx.is_foreign_item(def_id) {
113+
return false;
114+
}
115+
116+
// Make sure there is MIR available.
117+
match tcx.hir().body_const_context(def_id.expect_local()) {
118+
Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => {
119+
debug!("no mir available");
120+
return false;
121+
}
122+
Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
123+
debug!("no ctfe mir available");
124+
return false;
125+
}
126+
_ => true,
127+
}
128+
}
129+
100130
/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
101131
/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
102132
/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
@@ -156,44 +186,6 @@ fn mark_used_by_default_parameters<'tcx>(
156186
}
157187
}
158188

159-
/// Search the predicates on used generic parameters for any unused generic parameters, and mark
160-
/// those as used.
161-
#[instrument(level = "debug", skip(tcx, def_id))]
162-
fn mark_used_by_predicates<'tcx>(
163-
tcx: TyCtxt<'tcx>,
164-
def_id: DefId,
165-
unused_parameters: &mut FiniteBitSet<u32>,
166-
) {
167-
let def_id = tcx.closure_base_def_id(def_id);
168-
let predicates = tcx.explicit_predicates_of(def_id);
169-
170-
let mut current_unused_parameters = FiniteBitSet::new_empty();
171-
// Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
172-
// bit set so that this is skipped if all parameters are already used.
173-
while current_unused_parameters != *unused_parameters {
174-
debug!(?current_unused_parameters, ?unused_parameters);
175-
current_unused_parameters = *unused_parameters;
176-
177-
for (predicate, _) in predicates.predicates {
178-
// Consider all generic params in a predicate as used if any other parameter in the
179-
// predicate is used.
180-
let any_param_used = {
181-
let mut vis = HasUsedGenericParams { tcx, unused_parameters };
182-
predicate.visit_with(&mut vis).is_break()
183-
};
184-
185-
if any_param_used {
186-
let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters };
187-
predicate.visit_with(&mut vis);
188-
}
189-
}
190-
}
191-
192-
if let Some(parent) = predicates.parent {
193-
mark_used_by_predicates(tcx, parent, unused_parameters);
194-
}
195-
}
196-
197189
/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
198190
/// parameter which was unused.
199191
#[instrument(level = "debug", skip(tcx, generics))]
@@ -243,7 +235,8 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
243235
/// a closure, generator or constant).
244236
#[instrument(level = "debug", skip(self, def_id, substs))]
245237
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
246-
let unused = self.tcx.unused_generic_params(def_id);
238+
let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
239+
let unused = self.tcx.unused_generic_params(instance);
247240
debug!(?self.unused_parameters, ?unused);
248241
for (i, arg) in substs.iter().enumerate() {
249242
let i = i.try_into().unwrap();

‎src/test/ui/polymorphization/predicates.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fn bar<I>() {
1212

1313
#[rustc_polymorphize_error]
1414
fn foo<I, T>(_: I)
15+
//~^ ERROR item has unused generic parameters
1516
where
1617
I: Iterator<Item = T>,
1718
{
@@ -20,6 +21,7 @@ where
2021

2122
#[rustc_polymorphize_error]
2223
fn baz<I, T>(_: I)
24+
//~^ ERROR item has unused generic parameters
2325
where
2426
std::iter::Repeat<I>: Iterator<Item = T>,
2527
{
@@ -40,6 +42,7 @@ where
4042
#[rustc_polymorphize_error]
4143
fn next(&mut self) -> Option<Self::Item> {
4244
self.find(|_| true)
45+
//~^ ERROR item has unused generic parameters
4346
}
4447
}
4548

@@ -53,6 +56,7 @@ impl Baz<u32> for u16 {}
5356

5457
#[rustc_polymorphize_error]
5558
fn quux<A, B, C: Default>() -> usize
59+
//~^ ERROR item has unused generic parameters
5660
where
5761
A: Baz<B>,
5862
B: Baz<C>,
@@ -69,6 +73,7 @@ impl Foobar<u32, u32> for () {}
6973

7074
#[rustc_polymorphize_error]
7175
fn foobar<F, G>() -> usize
76+
//~^ ERROR item has unused generic parameters
7277
where
7378
(): Foobar<F, G>,
7479
{
Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,45 @@
1+
error: item has unused generic parameters
2+
--> $DIR/predicates.rs:14:4
3+
|
4+
LL | fn foo<I, T>(_: I)
5+
| ^^^ - generic parameter `T` is unused
6+
7+
error: item has unused generic parameters
8+
--> $DIR/predicates.rs:23:4
9+
|
10+
LL | fn baz<I, T>(_: I)
11+
| ^^^ - generic parameter `T` is unused
12+
13+
error: item has unused generic parameters
14+
--> $DIR/predicates.rs:44:19
15+
|
16+
LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
17+
| - - generic parameter `E` is unused
18+
| |
19+
| generic parameter `I` is unused
20+
...
21+
LL | self.find(|_| true)
22+
| ^^^^^^^^
23+
24+
error: item has unused generic parameters
25+
--> $DIR/predicates.rs:58:4
26+
|
27+
LL | fn quux<A, B, C: Default>() -> usize
28+
| ^^^^ - - generic parameter `B` is unused
29+
| |
30+
| generic parameter `A` is unused
31+
32+
error: item has unused generic parameters
33+
--> $DIR/predicates.rs:75:4
34+
|
35+
LL | fn foobar<F, G>() -> usize
36+
| ^^^^^^ - generic parameter `F` is unused
37+
138
error: item has unused generic parameters
239
--> $DIR/predicates.rs:9:4
340
|
441
LL | fn bar<I>() {
542
| ^^^ - generic parameter `I` is unused
643

7-
error: aborting due to previous error
44+
error: aborting due to 6 previous errors
845

0 commit comments

Comments
 (0)
Please sign in to comment.