about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-08-31 15:44:09 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2019-08-31 15:44:09 +0100
commit877faf38440ada48b0c27100fa3c456b35bc5612 (patch)
treeab75959b7524e88df196697a291b61238b2ab739
parent7bb2d8b0765e6737f43b501135d91bc8ab64db7a (diff)
downloadrust-877faf38440ada48b0c27100fa3c456b35bc5612.tar.gz
rust-877faf38440ada48b0c27100fa3c456b35bc5612.zip
Check impl trait substs when checking for recursive types
This prevents mutual `async fn` recursion
-rw-r--r--src/librustc/ty/util.rs6
-rw-r--r--src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs13
-rw-r--r--src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr19
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs25
-rw-r--r--src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr35
5 files changed, 96 insertions, 2 deletions
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 7a77418050c..a08c82a0ae8 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -709,8 +709,10 @@ impl<'tcx> TyCtxt<'tcx> {
                 substs: SubstsRef<'tcx>,
             ) -> Option<Ty<'tcx>> {
                 if self.found_recursion {
-                    None
-                } else if self.seen_opaque_tys.insert(def_id) {
+                    return None;
+                }
+                let substs = substs.fold_with(self);
+                if self.seen_opaque_tys.insert(def_id) {
                     let generic_ty = self.tcx.type_of(def_id);
                     let concrete_ty = generic_ty.subst(self.tcx, substs);
                     let expanded_ty = self.fold_ty(concrete_ty);
diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs
new file mode 100644
index 00000000000..bb2a61f03ce
--- /dev/null
+++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs
@@ -0,0 +1,13 @@
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+async fn rec_1() { //~ ERROR recursion in an `async fn`
+    rec_2().await;
+}
+
+async fn rec_2() { //~ ERROR recursion in an `async fn`
+    rec_1().await;
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
new file mode 100644
index 00000000000..9249308936e
--- /dev/null
+++ b/src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -0,0 +1,19 @@
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18
+   |
+LL | async fn rec_1() {
+   |                  ^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
+
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+   |
+LL | async fn rec_2() {
+   |                  ^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`.
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs
new file mode 100644
index 00000000000..cfd9c0ec5b4
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs
@@ -0,0 +1,25 @@
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden. Even when there's an opaque type in another crate
+// hiding this.
+
+fn id<T>(t: T) -> impl Sized { t }
+
+fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    id(recursive_id2())
+}
+
+fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    id(recursive_id())
+}
+
+fn wrap<T>(t: T) -> impl Sized { (t,) }
+
+fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    wrap(recursive_wrap2())
+}
+
+fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+    wrap(recursive_wrap())
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr
new file mode 100644
index 00000000000..7572c6c1bf0
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr
@@ -0,0 +1,35 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:7:22
+   |
+LL | fn recursive_id() -> impl Sized {
+   |                      ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:11:23
+   |
+LL | fn recursive_id2() -> impl Sized {
+   |                       ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: type resolves to itself
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:17:24
+   |
+LL | fn recursive_wrap() -> impl Sized {
+   |                        ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: expanded type is `((impl Sized,),)`
+
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-impl-trait-type--through-non-recursize.rs:21:25
+   |
+LL | fn recursive_wrap2() -> impl Sized {
+   |                         ^^^^^^^^^^ expands to a recursive type
+   |
+   = note: expanded type is `((impl Sized,),)`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0720`.