Skip to content

Commit a1f3ba0

Browse files
Just error on recursive opaque ty in HIR typeck
1 parent f8e9e76 commit a1f3ba0

19 files changed

+143
-182
lines changed

compiler/rustc_hir_typeck/src/writeback.rs

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@
99
//! which creates a new `TypeckResults` which doesn't contain any inference variables.
1010
1111
use std::mem;
12+
use std::ops::ControlFlow;
1213

14+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
1315
use rustc_data_structures::unord::ExtendUnord;
14-
use rustc_errors::ErrorGuaranteed;
16+
use rustc_errors::{E0720, ErrorGuaranteed};
17+
use rustc_hir::def_id::LocalDefId;
1518
use rustc_hir::intravisit::{self, InferKind, Visitor};
1619
use rustc_hir::{self as hir, AmbigArg, HirId};
1720
use rustc_infer::traits::solve::Goal;
1821
use rustc_middle::traits::ObligationCause;
1922
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
2023
use rustc_middle::ty::{
21-
self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
22-
TypeVisitableExt, fold_regions,
24+
self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
25+
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
26+
fold_regions,
2327
};
2428
use rustc_span::{Span, sym};
2529
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
@@ -595,6 +599,35 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
595599
entry.span = prev.span.substitute_dummy(hidden_type.span);
596600
}
597601
}
602+
603+
let recursive_opaques: Vec<_> = self
604+
.typeck_results
605+
.concrete_opaque_types
606+
.iter()
607+
.filter(|&(&def_id, hidden_ty)| {
608+
hidden_ty
609+
.ty
610+
.visit_with(&mut HasRecursiveOpaque {
611+
def_id,
612+
seen: Default::default(),
613+
opaques: &self.typeck_results.concrete_opaque_types,
614+
tcx,
615+
})
616+
.is_break()
617+
})
618+
.map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span))
619+
.collect();
620+
for (def_id, span) in recursive_opaques {
621+
let guar = self
622+
.fcx
623+
.dcx()
624+
.struct_span_err(span, "cannot resolve opaque type")
625+
.with_code(E0720)
626+
.emit();
627+
self.typeck_results
628+
.concrete_opaque_types
629+
.insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
630+
}
598631
}
599632

600633
fn visit_field_id(&mut self, hir_id: HirId) {
@@ -959,3 +992,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
959992
self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
960993
}
961994
}
995+
996+
struct HasRecursiveOpaque<'a, 'tcx> {
997+
def_id: LocalDefId,
998+
seen: FxHashSet<LocalDefId>,
999+
opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
1000+
tcx: TyCtxt<'tcx>,
1001+
}
1002+
1003+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
1004+
type Result = ControlFlow<()>;
1005+
1006+
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1007+
if let ty::Alias(ty::Opaque, alias_ty) = *t.kind()
1008+
&& let Some(def_id) = alias_ty.def_id.as_local()
1009+
{
1010+
if self.def_id == def_id {
1011+
return ControlFlow::Break(());
1012+
}
1013+
1014+
if self.seen.insert(def_id)
1015+
&& let Some(hidden_ty) = self.opaques.get(&def_id)
1016+
{
1017+
ty::EarlyBinder::bind(hidden_ty.ty)
1018+
.instantiate(self.tcx, alias_ty.args)
1019+
.visit_with(self)?;
1020+
}
1021+
}
1022+
1023+
t.super_visit_with(self)
1024+
}
1025+
}
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error[E0720]: cannot resolve opaque type
2+
--> $DIR/issue-100075-2.rs:1:23
3+
|
4+
LL | fn opaque<T>(t: T) -> impl Sized {
5+
| ^^^^^^^^^^
6+
17
warning: function cannot return without recursing
28
--> $DIR/issue-100075-2.rs:1:1
39
|
@@ -10,15 +16,6 @@ LL | opaque(Some(t))
1016
= help: a `loop` may express intention better if this is on purpose
1117
= note: `#[warn(unconditional_recursion)]` on by default
1218

13-
error[E0720]: cannot resolve opaque type
14-
--> $DIR/issue-100075-2.rs:1:23
15-
|
16-
LL | fn opaque<T>(t: T) -> impl Sized {
17-
| ^^^^^^^^^^ recursive opaque type
18-
...
19-
LL | opaque(Some(t))
20-
| --------------- returning here with type `impl Sized`
21-
2219
error: aborting due to 1 previous error; 1 warning emitted
2320

2421
For more information about this error, try `rustc --explain E0720`.

tests/ui/impl-trait/issues/issue-100075.stderr

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ error[E0720]: cannot resolve opaque type
22
--> $DIR/issue-100075.rs:13:37
33
|
44
LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
5-
| ^^^^^^^^^^^ recursive opaque type
6-
...
7-
LL | return _g(t);
8-
| ----- returning here with type `&impl Marker`
5+
| ^^^^^^^^^^^
96

107
error: aborting due to 1 previous error
118

tests/ui/impl-trait/issues/issue-103599.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
//@ check-pass
2-
31
trait T {}
42

53
fn wrap(x: impl T) -> impl T {
6-
//~^ WARN function cannot return without recursing
4+
//~^ ERROR cannot resolve opaque type
5+
//~| WARN function cannot return without recursing
76
wrap(wrap(x))
87
}
98

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
error[E0720]: cannot resolve opaque type
2+
--> $DIR/issue-103599.rs:3:23
3+
|
4+
LL | fn wrap(x: impl T) -> impl T {
5+
| ^^^^^^
6+
17
warning: function cannot return without recursing
2-
--> $DIR/issue-103599.rs:5:1
8+
--> $DIR/issue-103599.rs:3:1
39
|
410
LL | fn wrap(x: impl T) -> impl T {
511
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
6-
LL |
12+
...
713
LL | wrap(wrap(x))
814
| ------- recursive call site
915
|
1016
= help: a `loop` may express intention better if this is on purpose
1117
= note: `#[warn(unconditional_recursion)]` on by default
1218

13-
warning: 1 warning emitted
19+
error: aborting due to 1 previous error; 1 warning emitted
1420

21+
For more information about this error, try `rustc --explain E0720`.

tests/ui/impl-trait/issues/issue-87450.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ fn bar() -> impl Fn() {
33
}
44

55
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]
6+
//~^ WARN function cannot return without recursing
7+
//~| ERROR cannot resolve opaque type
88
wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
99
}
1010

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error[E0720]: cannot resolve opaque type
2+
--> $DIR/issue-87450.rs:5:13
3+
|
4+
LL | fn foo() -> impl Fn() {
5+
| ^^^^^^^^^
6+
17
warning: function cannot return without recursing
28
--> $DIR/issue-87450.rs:5:1
39
|
@@ -10,18 +16,6 @@ LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
1016
= help: a `loop` may express intention better if this is on purpose
1117
= note: `#[warn(unconditional_recursion)]` on by default
1218

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-
2519
error: aborting due to 1 previous error; 1 warning emitted
2620

2721
For more information about this error, try `rustc --explain E0720`.

tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr

Lines changed: 14 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,112 +2,67 @@ error[E0720]: cannot resolve opaque type
22
--> $DIR/recursive-impl-trait-type-indirect.rs:6:22
33
|
44
LL | fn option(i: i32) -> impl Sized {
5-
| ^^^^^^^^^^ recursive opaque type
6-
LL |
7-
LL | if i < 0 { None } else { Some((option(i - 1), i)) }
8-
| ---- ------------------------ returning here with type `Option<(impl Sized, i32)>`
9-
| |
10-
| returning here with type `Option<(impl Sized, i32)>`
5+
| ^^^^^^^^^^
116

127
error[E0720]: cannot resolve opaque type
138
--> $DIR/recursive-impl-trait-type-indirect.rs:11:15
149
|
1510
LL | fn tuple() -> impl Sized {
16-
| ^^^^^^^^^^ recursive opaque type
17-
LL |
18-
LL | (tuple(),)
19-
| ---------- returning here with type `(impl Sized,)`
11+
| ^^^^^^^^^^
2012

2113
error[E0720]: cannot resolve opaque type
2214
--> $DIR/recursive-impl-trait-type-indirect.rs:16:15
2315
|
2416
LL | fn array() -> impl Sized {
25-
| ^^^^^^^^^^ recursive opaque type
26-
LL |
27-
LL | [array()]
28-
| --------- returning here with type `[impl Sized; 1]`
17+
| ^^^^^^^^^^
2918

3019
error[E0720]: cannot resolve opaque type
3120
--> $DIR/recursive-impl-trait-type-indirect.rs:21:13
3221
|
3322
LL | fn ptr() -> impl Sized {
34-
| ^^^^^^^^^^ recursive opaque type
35-
LL |
36-
LL | &ptr() as *const _
37-
| ------------------ returning here with type `*const impl Sized`
23+
| ^^^^^^^^^^
3824

3925
error[E0720]: cannot resolve opaque type
4026
--> $DIR/recursive-impl-trait-type-indirect.rs:26:16
4127
|
4228
LL | fn fn_ptr() -> impl Sized {
43-
| ^^^^^^^^^^ recursive opaque type
44-
LL |
45-
LL | fn_ptr as fn() -> _
46-
| ------------------- returning here with type `fn() -> impl Sized`
29+
| ^^^^^^^^^^
4730

4831
error[E0720]: cannot resolve opaque type
4932
--> $DIR/recursive-impl-trait-type-indirect.rs:31:25
5033
|
51-
LL | fn closure_capture() -> impl Sized {
52-
| ^^^^^^^^^^ recursive opaque type
53-
...
54-
LL | / move || {
55-
LL | | x;
56-
| | - closure captures itself here
57-
LL | | }
58-
| |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:34:5: 34:12}`
34+
LL | fn closure_capture() -> impl Sized {
35+
| ^^^^^^^^^^
5936

6037
error[E0720]: cannot resolve opaque type
6138
--> $DIR/recursive-impl-trait-type-indirect.rs:39:29
6239
|
63-
LL | fn closure_ref_capture() -> impl Sized {
64-
| ^^^^^^^^^^ recursive opaque type
65-
...
66-
LL | / move || {
67-
LL | | &x;
68-
| | - closure captures itself here
69-
LL | | }
70-
| |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:42:5: 42:12}`
40+
LL | fn closure_ref_capture() -> impl Sized {
41+
| ^^^^^^^^^^
7142

7243
error[E0720]: cannot resolve opaque type
7344
--> $DIR/recursive-impl-trait-type-indirect.rs:47:21
7445
|
7546
LL | fn closure_sig() -> impl Sized {
76-
| ^^^^^^^^^^ recursive opaque type
77-
LL |
78-
LL | || closure_sig()
79-
| ---------------- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:49:5: 49:7}`
47+
| ^^^^^^^^^^
8048

8149
error[E0720]: cannot resolve opaque type
8250
--> $DIR/recursive-impl-trait-type-indirect.rs:52:23
8351
|
8452
LL | fn coroutine_sig() -> impl Sized {
85-
| ^^^^^^^^^^ recursive opaque type
86-
LL |
87-
LL | || coroutine_sig()
88-
| ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7}`
53+
| ^^^^^^^^^^
8954

9055
error[E0720]: cannot resolve opaque type
9156
--> $DIR/recursive-impl-trait-type-indirect.rs:57:27
9257
|
93-
LL | fn coroutine_capture() -> impl Sized {
94-
| ^^^^^^^^^^ recursive opaque type
95-
...
96-
LL | / move || {
97-
LL | | yield;
98-
LL | | x;
99-
| | - coroutine captures itself here
100-
LL | | }
101-
| |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:62:5: 62:12}`
58+
LL | fn coroutine_capture() -> impl Sized {
59+
| ^^^^^^^^^^
10260

10361
error[E0720]: cannot resolve opaque type
10462
--> $DIR/recursive-impl-trait-type-indirect.rs:68:35
10563
|
10664
LL | fn substs_change<T: 'static>() -> impl Sized {
107-
| ^^^^^^^^^^ recursive opaque type
108-
LL |
109-
LL | (substs_change::<&T>(),)
110-
| ------------------------ returning here with type `(impl Sized,)`
65+
| ^^^^^^^^^^
11166

11267
error[E0720]: cannot resolve opaque type
11368
--> $DIR/recursive-impl-trait-type-indirect.rs:78:26

0 commit comments

Comments
 (0)