From d95979912e0c6219fdd13ee6bcdd517d2e45e2d2 Mon Sep 17 00:00:00 2001 From: Osspial Date: Fri, 15 Mar 2019 17:16:28 -0400 Subject: [PATCH 1/2] Add regression test for #34426 --- src/test/run-pass/drop/dropck-hrtb.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/test/run-pass/drop/dropck-hrtb.rs diff --git a/src/test/run-pass/drop/dropck-hrtb.rs b/src/test/run-pass/drop/dropck-hrtb.rs new file mode 100644 index 0000000000000..f952065e01ae7 --- /dev/null +++ b/src/test/run-pass/drop/dropck-hrtb.rs @@ -0,0 +1,25 @@ +// run-pass +//! Regression test for #34426, regarding HRTB in drop impls + +pub trait Lifetime<'a> {} +impl<'a> Lifetime<'a> for i32 {} + +struct Foo + where for<'a> L: Lifetime<'a> +{ + l: L +} + +impl Drop for Foo + where for<'a> L: Lifetime<'a> +{ + fn drop(&mut self) { + println!("drop with hrtb"); + } +} + +fn main() { + let _foo = Foo { + l: 0 + }; +} From 31f6517e96dbec57a43d6426f1f2787ae10d944d Mon Sep 17 00:00:00 2001 From: Osspial Date: Thu, 28 Mar 2019 14:04:03 -0400 Subject: [PATCH 2/2] Add hacky solution to make hrtb dropck work --- src/librustc_typeck/check/dropck.rs | 40 +++++++++++++++++++++++++-- src/test/run-pass/drop/dropck-hrtb.rs | 23 +++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 2184555a07d34..4debb146b4eaa 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -7,7 +7,7 @@ use rustc::infer::{self, InferOk, SuppressRegionErrors}; use rustc::middle::region; use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt}; use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind}; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, BoundRegion, Predicate, RegionKind, Ty, TyCtxt}; use crate::util::common::ErrorReported; use syntax_pos::Span; @@ -34,7 +34,9 @@ pub fn check_drop_impl<'a, 'tcx>( drop_impl_did: DefId, ) -> Result<(), ErrorReported> { let dtor_self_type = tcx.type_of(drop_impl_did); + let dtor_predicates = tcx.predicates_of(drop_impl_did); + match dtor_self_type.sty { ty::Adt(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond( @@ -215,7 +217,41 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // the analysis together via the fulfill , rather than the // repeated `contains` calls. - if !assumptions_in_impl_context.contains(&predicate) { + // Fixes #34426 by ignoring the `DefId` for late-bound regions. + // + // This solution is absolutely awful, and the correct solution + // is probably to find why `RegionKind::ReLateBound` generates + // different `DefId`s in different item blocks and fix it. I say + // that's probably the correct solution because + // `RegionKind::ReEarlyBound`s *also* have `DefId`s and they're + // identical in different item blocks, which indicates that + // something is up here. + // + // Alternatively, we could do the deep analysis of the Drop impl, + // which the above comment says not to do. However, as I'm writing + // this PR I don't know how I'd do that so this solution remains. + let predicate_matches = |p: &'_ &Predicate<'_>| { + match (p, predicate) { + (Predicate::Trait(p), Predicate::Trait(predicate)) => { + let predicate_substs = &*predicate.skip_binder().trait_ref.substs; + let p_substs = &*p.skip_binder().trait_ref.substs; + + predicate_substs.len() == p_substs.len() && + predicate_substs.iter().zip(p_substs.iter()).all(|(a, b)| { + match (a.unpack(), b.unpack()) { + ( + UnpackedKind::Lifetime(RegionKind::ReLateBound(pr_i, BoundRegion::BrNamed(_, pr_n))), + UnpackedKind::Lifetime(RegionKind::ReLateBound(p_i, BoundRegion::BrNamed(_, p_n))) + ) => (pr_i, pr_n) == (p_i, p_n), + _ => a == b + } + }) + }, + _ => &predicate == p + } + }; + + if !assumptions_in_impl_context.iter().find(predicate_matches).is_some() { let item_span = tcx.hir().span_by_hir_id(self_type_hir_id); struct_span_err!( tcx.sess, diff --git a/src/test/run-pass/drop/dropck-hrtb.rs b/src/test/run-pass/drop/dropck-hrtb.rs index f952065e01ae7..3c7011db0f7de 100644 --- a/src/test/run-pass/drop/dropck-hrtb.rs +++ b/src/test/run-pass/drop/dropck-hrtb.rs @@ -4,6 +4,7 @@ pub trait Lifetime<'a> {} impl<'a> Lifetime<'a> for i32 {} +#[allow(dead_code)] struct Foo where for<'a> L: Lifetime<'a> { @@ -18,8 +19,30 @@ impl Drop for Foo } } +pub trait Lifetime2<'a, 'b> {} +impl<'a, 'b> Lifetime2<'a, 'b> for i32 {} + +#[allow(dead_code)] +struct Bar + where for<'a, 'b> L: Lifetime2<'a, 'b> +{ + l: L +} + +impl Drop for Bar + where for<'a, 'b> L: Lifetime2<'a, 'b> +{ + fn drop(&mut self) { + println!("drop with hrtb"); + } +} + fn main() { let _foo = Foo { l: 0 }; + + let _bar = Bar { + l: 0 + }; }