Skip to content

Commit 8d57c0a

Browse files
committed
Auto merge of #87546 - rusticstuff:issue87450-take-two, r=davidtwco
Bail on any found recursion when expanding opaque types Fixes #87450. More of a bandaid because it does not fix the exponential complexity of the type folding used for opaque type expansion.
2 parents aadd618 + 2aa1996 commit 8d57c0a

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

Diff for: compiler/rustc_middle/src/ty/util.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ impl<'tcx> TyCtxt<'tcx> {
540540
expanded_cache: FxHashMap::default(),
541541
primary_def_id: Some(def_id),
542542
found_recursion: false,
543+
found_any_recursion: false,
543544
check_recursion: true,
544545
tcx: self,
545546
};
@@ -560,6 +561,7 @@ struct OpaqueTypeExpander<'tcx> {
560561
expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
561562
primary_def_id: Option<DefId>,
562563
found_recursion: bool,
564+
found_any_recursion: bool,
563565
/// Whether or not to check for recursive opaque types.
564566
/// This is `true` when we're explicitly checking for opaque type
565567
/// recursion, and 'false' otherwise to avoid unnecessary work.
@@ -569,7 +571,7 @@ struct OpaqueTypeExpander<'tcx> {
569571

570572
impl<'tcx> OpaqueTypeExpander<'tcx> {
571573
fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
572-
if self.found_recursion {
574+
if self.found_any_recursion {
573575
return None;
574576
}
575577
let substs = substs.fold_with(self);
@@ -591,6 +593,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
591593
} else {
592594
// If another opaque type that we contain is recursive, then it
593595
// will report the error, so we don't have to.
596+
self.found_any_recursion = true;
594597
self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
595598
None
596599
}
@@ -1078,6 +1081,7 @@ pub fn normalize_opaque_types(
10781081
expanded_cache: FxHashMap::default(),
10791082
primary_def_id: None,
10801083
found_recursion: false,
1084+
found_any_recursion: false,
10811085
check_recursion: false,
10821086
tcx,
10831087
};

Diff for: src/test/ui/impl-trait/issue-87450.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
fn bar() -> impl Fn() {
2+
wrap(wrap(wrap(wrap(foo()))))
3+
}
4+
5+
fn foo() -> impl Fn() {
6+
//~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion]
7+
//~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720]
8+
wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
9+
}
10+
11+
fn wrap(f: impl Fn()) -> impl Fn() {
12+
move || f()
13+
}
14+
15+
fn main() {
16+
}

Diff for: src/test/ui/impl-trait/issue-87450.stderr

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
warning: function cannot return without recursing
2+
--> $DIR/issue-87450.rs:5:1
3+
|
4+
LL | fn foo() -> impl Fn() {
5+
| ^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
6+
...
7+
LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
8+
| ----- recursive call site
9+
|
10+
= note: `#[warn(unconditional_recursion)]` on by default
11+
= help: a `loop` may express intention better if this is on purpose
12+
13+
error[E0720]: cannot resolve opaque type
14+
--> $DIR/issue-87450.rs:5:13
15+
|
16+
LL | fn foo() -> impl Fn() {
17+
| ^^^^^^^^^ recursive opaque type
18+
...
19+
LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
20+
| ----------------------------------------------- returning here with type `impl Fn<()>`
21+
...
22+
LL | fn wrap(f: impl Fn()) -> impl Fn() {
23+
| --------- returning this opaque type `impl Fn<()>`
24+
25+
error: aborting due to previous error; 1 warning emitted
26+
27+
For more information about this error, try `rustc --explain E0720`.

0 commit comments

Comments
 (0)