From 261daf27c9e4b9332ac8d17fc4f9997fcd1ded3f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 12 Mar 2019 10:57:06 -0400 Subject: [PATCH] ignore higher-ranked WF requirements for trait objects In the `issue-53548` test added in this commit, the `Box` type is expanded to `Box`, but the generator "witness" that results is `for<'r> { Box }`. The WF code was encountering an ICE (when debug-assertions were enabled) and an unexpected compilation error (without debug-asserions) when trying to process this `'r` region bound. In particular, to be WF, the region bound must meet the requirements of the trait, and hence we got `for<'r> { 'r: 'static }`. This would ICE because the `Binder` constructor we were using was assering that no higher-ranked regions were involved (because the WF code is supposed to skip those). The error (if debug-asserions were disabled) came because we obviously cannot prove that `'r: 'static` for any region `'r`. Pursuant with our "lazy WF" strategy for higher-ranked regions, the fix is not to require that `for<'r> { 'r: 'static }` holds (this is also analogous to what we would do for higher-ranked regions appearing within the trait in other positions). --- src/librustc/ty/wf.rs | 3 +- src/test/ui/generator/issue-53548-1.rs | 20 +++++++++++++ src/test/ui/generator/issue-53548.rs | 39 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/generator/issue-53548-1.rs create mode 100644 src/test/ui/generator/issue-53548.rs diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 599d38bc4ab..fa35416cdd4 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -482,8 +482,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // // Note: in fact we only permit builtin traits, not `Bar<'d>`, I // am looking forward to the future here. - - if !data.has_escaping_bound_vars() { + if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() { let implicit_bounds = object_region_bounds(self.infcx.tcx, data); diff --git a/src/test/ui/generator/issue-53548-1.rs b/src/test/ui/generator/issue-53548-1.rs new file mode 100644 index 00000000000..df11800731c --- /dev/null +++ b/src/test/ui/generator/issue-53548-1.rs @@ -0,0 +1,20 @@ +// A variant of #53548 that does not actually require generators, +// but which encountered the same ICE/error. See `issue-53548.rs` +// for details. +// +// compile-pass + +use std::cell::RefCell; +use std::rc::Rc; + +trait Trait: 'static {} + +struct Store { + inner: Rc>>, +} + +fn main() { + let store = Store:: fn(&(dyn Trait + 'a))>> { + inner: Default::default(), + }; +} diff --git a/src/test/ui/generator/issue-53548.rs b/src/test/ui/generator/issue-53548.rs new file mode 100644 index 00000000000..00fdb91faab --- /dev/null +++ b/src/test/ui/generator/issue-53548.rs @@ -0,0 +1,39 @@ +// Regression test for #53548. The `Box` type below is +// expanded to `Box`, but the generator "witness" +// that results is `for<'r> { Box }`. The WF code was +// encountering an ICE (when debug-assertions were enabled) and an +// unexpected compilation error (without debug-asserions) when trying +// to process this `'r` region bound. In particular, to be WF, the +// region bound must meet the requirements of the trait, and hence we +// got `for<'r> { 'r: 'static }`. This would ICE because the `Binder` +// constructor we were using was assering that no higher-ranked +// regions were involved (because the WF code is supposed to skip +// those). The error (if debug-asserions were disabled) came because +// we obviously cannot prove that `'r: 'static` for any region `'r`. +// Pursuant with our "lazy WF" strategy for higher-ranked regions, the +// fix is not to require that `for<'r> { 'r: 'static }` holds (this is +// also analogous to what we would do for higher-ranked regions +// appearing within the trait in other positions). +// +// compile-pass + +#![feature(generators)] + +use std::cell::RefCell; +use std::rc::Rc; + +trait Trait: 'static {} + +struct Store { + inner: Rc>>, +} + +fn main() { + Box::new(static move || { + let store = Store::> { + inner: Default::default(), + }; + yield (); + }); +} +