]> git.lizzy.rs Git - rust.git/commitdiff
ignore higher-ranked WF requirements for trait objects
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 12 Mar 2019 14:57:06 +0000 (10:57 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 12 Mar 2019 14:57:06 +0000 (10:57 -0400)
In the `issue-53548` test added in this commit, the `Box<dyn Trait>`
type is expanded to `Box<dyn Trait + 'static>`, but the generator
"witness" that results is `for<'r> { Box<dyn Trait + 'r> }`. 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
src/test/ui/generator/issue-53548-1.rs [new file with mode: 0644]
src/test/ui/generator/issue-53548.rs [new file with mode: 0644]

index 599d38bc4ab6ee56c76fee7d674729b5e3ac0784..fa35416cdd4982fd50f11376e006635eb97d111e 100644 (file)
@@ -482,8 +482,7 @@ fn from_object_ty(&mut self, ty: Ty<'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 (file)
index 0000000..df11800
--- /dev/null
@@ -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<C> {
+    inner: Rc<RefCell<Option<C>>>,
+}
+
+fn main() {
+    let store = Store::<Box<for<'a> 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 (file)
index 0000000..00fdb91
--- /dev/null
@@ -0,0 +1,39 @@
+// Regression test for #53548. The `Box<dyn Trait>` type below is
+// expanded to `Box<dyn Trait + 'static>`, but the generator "witness"
+// that results is `for<'r> { Box<dyn Trait + 'r> }`. 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<C> {
+    inner: Rc<RefCell<Option<C>>>,
+}
+
+fn main() {
+    Box::new(static move || {
+        let store = Store::<Box<dyn Trait>> {
+            inner: Default::default(),
+        };
+        yield ();
+    });
+}
+