From 877faf38440ada48b0c27100fa3c456b35bc5612 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 15:44:09 +0100 Subject: [PATCH] Check impl trait substs when checking for recursive types This prevents mutual `async fn` recursion --- src/librustc/ty/util.rs | 6 ++-- ...utually-recursive-async-impl-trait-type.rs | 13 +++++++ ...lly-recursive-async-impl-trait-type.stderr | 19 ++++++++++ ...-impl-trait-type--through-non-recursize.rs | 25 +++++++++++++ ...l-trait-type--through-non-recursize.stderr | 35 +++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.rs create mode 100644 src/test/ui/async-await/mutually-recursive-async-impl-trait-type.stderr create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.rs create mode 100644 src/test/ui/impl-trait/recursive-impl-trait-type--through-non-recursize.stderr 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 @@ fn expand_opaque_ty( substs: SubstsRef<'tcx>, ) -> Option> { 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) -> 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) -> 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`. -- 2.44.0