Skip to content

Commit

Permalink
Check impl trait substs when checking for recursive types
Browse files Browse the repository at this point in the history
This prevents mutual `async fn` recursion
  • Loading branch information
matthewjasper committed Aug 31, 2019
1 parent 7bb2d8b commit 877faf3
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 877faf3

Please sign in to comment.