Skip to content

Commit 32bd908

Browse files
Just error on recursive opaque ty in HIR typeck
1 parent 0e517d3 commit 32bd908

19 files changed

+146
-199
lines changed

compiler/rustc_hir_typeck/src/writeback.rs

+61-2
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;
1416
use rustc_errors::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;
@@ -597,6 +601,30 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
597601
entry.span = prev.span.substitute_dummy(hidden_type.span);
598602
}
599603
}
604+
605+
let recursive_opaques: Vec<_> = self
606+
.typeck_results
607+
.concrete_opaque_types
608+
.iter()
609+
.filter(|&(&def_id, hidden_ty)| {
610+
hidden_ty
611+
.ty
612+
.visit_with(&mut HasRecursiveOpaque {
613+
def_id,
614+
seen: Default::default(),
615+
opaques: &self.typeck_results.concrete_opaque_types,
616+
tcx,
617+
})
618+
.is_break()
619+
})
620+
.map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span))
621+
.collect();
622+
for (def_id, span) in recursive_opaques {
623+
let guar = self.fcx.dcx().span_err(span, "cannot resolve opaque type");
624+
self.typeck_results
625+
.concrete_opaque_types
626+
.insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
627+
}
600628
}
601629

602630
fn visit_field_id(&mut self, hir_id: HirId) {
@@ -961,3 +989,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
961989
self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
962990
}
963991
}
992+
993+
struct HasRecursiveOpaque<'a, 'tcx> {
994+
def_id: LocalDefId,
995+
seen: FxHashSet<LocalDefId>,
996+
opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
997+
tcx: TyCtxt<'tcx>,
998+
}
999+
1000+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
1001+
type Result = ControlFlow<()>;
1002+
1003+
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1004+
if let ty::Alias(ty::Opaque, alias_ty) = *t.kind()
1005+
&& let Some(def_id) = alias_ty.def_id.as_local()
1006+
{
1007+
if self.def_id == def_id {
1008+
return ControlFlow::Break(());
1009+
}
1010+
1011+
if self.seen.insert(def_id)
1012+
&& let Some(hidden_ty) = self.opaques.get(&def_id)
1013+
{
1014+
ty::EarlyBinder::bind(hidden_ty.ty)
1015+
.instantiate(self.tcx, alias_ty.args)
1016+
.visit_with(self)?;
1017+
}
1018+
}
1019+
1020+
t.super_visit_with(self)
1021+
}
1022+
}
+6-10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error: 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,5 @@ 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

24-
For more information about this error, try `rustc --explain E0720`.
+2-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
error[E0720]: cannot resolve opaque type
1+
error: 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

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

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

+2-3
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

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1+
error: 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

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

+2-2
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

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error: 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,5 @@ 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

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

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

+25-70
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,68 @@
1-
error[E0720]: cannot resolve opaque type
1+
error: 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

12-
error[E0720]: cannot resolve opaque type
7+
error: 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

21-
error[E0720]: cannot resolve opaque type
13+
error: 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

30-
error[E0720]: cannot resolve opaque type
19+
error: 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

39-
error[E0720]: cannot resolve opaque type
25+
error: 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

48-
error[E0720]: cannot resolve opaque type
31+
error: 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

60-
error[E0720]: cannot resolve opaque type
37+
error: 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

72-
error[E0720]: cannot resolve opaque type
43+
error: 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

81-
error[E0720]: cannot resolve opaque type
49+
error: 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

90-
error[E0720]: cannot resolve opaque type
55+
error: 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

103-
error[E0720]: cannot resolve opaque type
61+
error: 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)