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.
This commit is contained in:
commit
8d57c0ab2b
3 changed files with 48 additions and 1 deletions
|
@ -540,6 +540,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
expanded_cache: FxHashMap::default(),
|
||||
primary_def_id: Some(def_id),
|
||||
found_recursion: false,
|
||||
found_any_recursion: false,
|
||||
check_recursion: true,
|
||||
tcx: self,
|
||||
};
|
||||
|
@ -560,6 +561,7 @@ struct OpaqueTypeExpander<'tcx> {
|
|||
expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>,
|
||||
primary_def_id: Option<DefId>,
|
||||
found_recursion: bool,
|
||||
found_any_recursion: bool,
|
||||
/// Whether or not to check for recursive opaque types.
|
||||
/// This is `true` when we're explicitly checking for opaque type
|
||||
/// recursion, and 'false' otherwise to avoid unnecessary work.
|
||||
|
@ -569,7 +571,7 @@ struct OpaqueTypeExpander<'tcx> {
|
|||
|
||||
impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||
fn expand_opaque_ty(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
|
||||
if self.found_recursion {
|
||||
if self.found_any_recursion {
|
||||
return None;
|
||||
}
|
||||
let substs = substs.fold_with(self);
|
||||
|
@ -591,6 +593,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
|
|||
} else {
|
||||
// If another opaque type that we contain is recursive, then it
|
||||
// will report the error, so we don't have to.
|
||||
self.found_any_recursion = true;
|
||||
self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
|
||||
None
|
||||
}
|
||||
|
@ -1078,6 +1081,7 @@ pub fn normalize_opaque_types(
|
|||
expanded_cache: FxHashMap::default(),
|
||||
primary_def_id: None,
|
||||
found_recursion: false,
|
||||
found_any_recursion: false,
|
||||
check_recursion: false,
|
||||
tcx,
|
||||
};
|
||||
|
|
16
src/test/ui/impl-trait/issue-87450.rs
Normal file
16
src/test/ui/impl-trait/issue-87450.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
fn bar() -> impl Fn() {
|
||||
wrap(wrap(wrap(wrap(foo()))))
|
||||
}
|
||||
|
||||
fn foo() -> impl Fn() {
|
||||
//~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion]
|
||||
//~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720]
|
||||
wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
|
||||
}
|
||||
|
||||
fn wrap(f: impl Fn()) -> impl Fn() {
|
||||
move || f()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
27
src/test/ui/impl-trait/issue-87450.stderr
Normal file
27
src/test/ui/impl-trait/issue-87450.stderr
Normal file
|
@ -0,0 +1,27 @@
|
|||
warning: function cannot return without recursing
|
||||
--> $DIR/issue-87450.rs:5:1
|
||||
|
|
||||
LL | fn foo() -> impl Fn() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
...
|
||||
LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
|
||||
| ----- recursive call site
|
||||
|
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/issue-87450.rs:5:13
|
||||
|
|
||||
LL | fn foo() -> impl Fn() {
|
||||
| ^^^^^^^^^ recursive opaque type
|
||||
...
|
||||
LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
|
||||
| ----------------------------------------------- returning here with type `impl Fn<()>`
|
||||
...
|
||||
LL | fn wrap(f: impl Fn()) -> impl Fn() {
|
||||
| --------- returning this opaque type `impl Fn<()>`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
Loading…
Reference in a new issue