Skip to content

Commit 7d82b60

Browse files
Just error on recursive opaque ty in HIR typeck
1 parent 7d65abf commit 7d82b60

19 files changed

+146
-199
lines changed

compiler/rustc_hir_typeck/src/writeback.rs

+61-2
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@
33
// generic parameters.
44

55
use std::mem;
6+
use std::ops::ControlFlow;
67

8+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
79
use rustc_data_structures::unord::ExtendUnord;
810
use rustc_errors::ErrorGuaranteed;
11+
use rustc_hir::def_id::LocalDefId;
912
use rustc_hir::intravisit::{self, InferKind, Visitor};
1013
use rustc_hir::{self as hir, AmbigArg, HirId};
1114
use rustc_infer::traits::solve::Goal;
1215
use rustc_middle::span_bug;
1316
use rustc_middle::traits::ObligationCause;
1417
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
1518
use rustc_middle::ty::{
16-
self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
17-
TypeVisitableExt, fold_regions,
19+
self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
20+
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
21+
fold_regions,
1822
};
1923
use rustc_span::{Span, sym};
2024
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
@@ -623,6 +627,30 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
623627
entry.span = prev.span.substitute_dummy(hidden_type.span);
624628
}
625629
}
630+
631+
let recursive_opaques: Vec<_> = self
632+
.typeck_results
633+
.concrete_opaque_types
634+
.iter()
635+
.filter(|&(&def_id, hidden_ty)| {
636+
hidden_ty
637+
.ty
638+
.visit_with(&mut HasRecursiveOpaque {
639+
def_id,
640+
seen: Default::default(),
641+
opaques: &self.typeck_results.concrete_opaque_types,
642+
tcx,
643+
})
644+
.is_break()
645+
})
646+
.map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span))
647+
.collect();
648+
for (def_id, span) in recursive_opaques {
649+
let guar = self.fcx.dcx().span_err(span, "cannot resolve opaque type");
650+
self.typeck_results
651+
.concrete_opaque_types
652+
.insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
653+
}
626654
}
627655

628656
fn visit_field_id(&mut self, hir_id: HirId) {
@@ -987,3 +1015,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
9871015
self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
9881016
}
9891017
}
1018+
1019+
struct HasRecursiveOpaque<'a, 'tcx> {
1020+
def_id: LocalDefId,
1021+
seen: FxHashSet<LocalDefId>,
1022+
opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
1023+
tcx: TyCtxt<'tcx>,
1024+
}
1025+
1026+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
1027+
type Result = ControlFlow<()>;
1028+
1029+
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1030+
if let ty::Alias(ty::Opaque, alias_ty) = *t.kind()
1031+
&& let Some(def_id) = alias_ty.def_id.as_local()
1032+
{
1033+
if self.def_id == def_id {
1034+
return ControlFlow::Break(());
1035+
}
1036+
1037+
if self.seen.insert(def_id)
1038+
&& let Some(hidden_ty) = self.opaques.get(&def_id)
1039+
{
1040+
ty::EarlyBinder::bind(hidden_ty.ty)
1041+
.instantiate(self.tcx, alias_ty.args)
1042+
.visit_with(self)?;
1043+
}
1044+
}
1045+
1046+
t.super_visit_with(self)
1047+
}
1048+
}
+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)