diff options
| author | David Wood <david@davidtw.co> | 2020-08-16 16:35:38 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2020-08-17 14:13:58 +0100 |
| commit | 5703b2863e1b4b815007b5a3380734634acd1f37 (patch) | |
| tree | ab1435787a1a9a3fbcccf2b95e9eaba88439811e | |
| parent | 97ba0c7171c4d2d9b899a2bd8e40a8974c47b86d (diff) | |
| download | rust-5703b2863e1b4b815007b5a3380734634acd1f37.tar.gz rust-5703b2863e1b4b815007b5a3380734634acd1f37.zip | |
polymorphize: ∃ used param ∈ predicate → all used
This commit modifies polymorphization's handling of predicates so that if any generic parameter is used in a predicate then all parameters in that predicate are used. Signed-off-by: David Wood <david@davidtw.co>
| -rw-r--r-- | src/librustc_mir/monomorphize/polymorphize.rs | 87 | ||||
| -rw-r--r-- | src/test/ui/polymorphization/predicates.rs | 17 |
2 files changed, 29 insertions, 75 deletions
diff --git a/src/librustc_mir/monomorphize/polymorphize.rs b/src/librustc_mir/monomorphize/polymorphize.rs index d946c1947c2..69f3288ee39 100644 --- a/src/librustc_mir/monomorphize/polymorphize.rs +++ b/src/librustc_mir/monomorphize/polymorphize.rs @@ -119,16 +119,6 @@ fn mark_used_by_predicates<'tcx>( def_id: DefId, unused_parameters: &mut FiniteBitSet<u32>, ) { - let is_ty_used = |unused_parameters: &FiniteBitSet<u32>, ty: Ty<'tcx>| -> bool { - let mut vis = IsUsedGenericParams { unused_parameters }; - ty.visit_with(&mut vis) - }; - - let mark_ty = |unused_parameters: &mut FiniteBitSet<u32>, ty: Ty<'tcx>| { - let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters }; - ty.visit_with(&mut vis); - }; - 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); @@ -144,69 +134,16 @@ fn mark_used_by_predicates<'tcx>( current_unused_parameters = *unused_parameters; for (predicate, _) in predicates.predicates { - match predicate.skip_binders() { - ty::PredicateAtom::Trait(predicate, ..) => { - let trait_ref = predicate.trait_ref; - debug!("mark_used_by_predicates: (trait) trait_ref={:?}", trait_ref); - - // Consider `T` used if `I` is used in predicates of the form - // `I: Iterator<Item = T>` - debug!("mark_used_by_predicates: checking self"); - if is_ty_used(unused_parameters, trait_ref.self_ty()) { - debug!("mark_used_by_predicates: used!"); - for ty in trait_ref.substs.types() { - mark_ty(unused_parameters, ty); - } - - // No need to check for a type being used in the substs if `self_ty` was - // used. - continue; - } - - // Consider `I` used if `T` is used in predicates of the form - // `I: Iterator<Item = &'a (T, E)>` (see rust-lang/rust#75326) - debug!("mark_used_by_predicates: checking substs"); - for ty in trait_ref.substs.types() { - if is_ty_used(unused_parameters, ty) { - debug!("mark_used_by_predicates: used!"); - mark_ty(unused_parameters, trait_ref.self_ty()); - } - } - } - ty::PredicateAtom::Projection(proj, ..) => { - let self_ty = proj.projection_ty.self_ty(); - debug!( - "mark_used_by_predicates: (projection) self_ty={:?} proj.ty={:?}", - self_ty, proj.ty - ); - - // Consider `T` used if `I` is used in predicates of the form - // `<I as Iterator>::Item = T` - debug!("mark_used_by_predicates: checking self"); - if is_ty_used(unused_parameters, self_ty) { - debug!("mark_used_by_predicates: used!"); - mark_ty(unused_parameters, proj.ty); - - // No need to check for projection type being used if `self_ty` was used. - continue; - } - - // Consider `I` used if `T` is used in predicates of the form - // `<I as Iterator>::Item = &'a (T, E)` (see rust-lang/rust#75326) - debug!("mark_used_by_predicates: checking projection ty"); - if is_ty_used(unused_parameters, proj.ty) { - debug!("mark_used_by_predicates: used!"); - mark_ty(unused_parameters, self_ty); - } - } - ty::PredicateAtom::RegionOutlives(..) - | ty::PredicateAtom::TypeOutlives(..) - | ty::PredicateAtom::WellFormed(..) - | ty::PredicateAtom::ObjectSafe(..) - | ty::PredicateAtom::ClosureKind(..) - | ty::PredicateAtom::Subtype(..) - | ty::PredicateAtom::ConstEvaluatable(..) - | ty::PredicateAtom::ConstEquate(..) => (), + // Consider all generic params in a predicate as used if any other parameter in the + // predicate is used. + let any_param_used = { + let mut vis = HasUsedGenericParams { unused_parameters }; + predicate.visit_with(&mut vis) + }; + + if any_param_used { + let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters }; + predicate.visit_with(&mut vis); } } } @@ -375,11 +312,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } /// Visitor used to check if a generic parameter is used. -struct IsUsedGenericParams<'a> { +struct HasUsedGenericParams<'a> { unused_parameters: &'a FiniteBitSet<u32>, } -impl<'a, 'tcx> TypeVisitor<'tcx> for IsUsedGenericParams<'a> { +impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> { fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool { debug!("visit_const: c={:?}", c); if !c.has_param_types_or_consts() { diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs index 60555dc12dc..97f1ef2c90a 100644 --- a/src/test/ui/polymorphization/predicates.rs +++ b/src/test/ui/polymorphization/predicates.rs @@ -60,6 +60,21 @@ where std::mem::size_of::<C>() } +// Finally, check that `F` is considered used because `G` is used when neither are in the self-ty +// of the predicate. + +trait Foobar<F, G> {} + +impl Foobar<u32, u32> for () {} + +#[rustc_polymorphize_error] +fn foobar<F, G>() -> usize +where + (): Foobar<F, G>, +{ + std::mem::size_of::<G>() +} + fn main() { let x = &[2u32]; foo(x.iter()); @@ -69,4 +84,6 @@ fn main() { let _ = a.next(); let _ = quux::<u8, u16, u32>(); + + let _ = foobar::<u32, u32>(); } |
