Skip to content

Commit 99e7ce9

Browse files
Just error on recursive opaque ty in HIR typeck
1 parent 0c478fd commit 99e7ce9

9 files changed

+109
-129
lines changed

Diff for: compiler/rustc_hir_typeck/src/writeback.rs

+61-2
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
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_middle::span_bug;
1215
use rustc_middle::traits::ObligationCause;
1316
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
1417
use rustc_middle::ty::{
15-
self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
16-
TypeVisitableExt, fold_regions,
18+
self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
19+
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
20+
fold_regions,
1721
};
1822
use rustc_span::{Span, sym};
1923
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
@@ -622,6 +626,30 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
622626
entry.span = prev.span.substitute_dummy(hidden_type.span);
623627
}
624628
}
629+
630+
let recursive_opaques: Vec<_> = self
631+
.typeck_results
632+
.concrete_opaque_types
633+
.iter()
634+
.filter(|&(&def_id, hidden_ty)| {
635+
hidden_ty
636+
.ty
637+
.visit_with(&mut HasRecursiveOpaque {
638+
def_id,
639+
seen: Default::default(),
640+
opaques: &self.typeck_results.concrete_opaque_types,
641+
tcx,
642+
})
643+
.is_break()
644+
})
645+
.map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span))
646+
.collect();
647+
for (def_id, span) in recursive_opaques {
648+
let guar = self.fcx.dcx().span_err(span, "cannot resolve opaque type");
649+
self.typeck_results
650+
.concrete_opaque_types
651+
.insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
652+
}
625653
}
626654

627655
fn visit_field_id(&mut self, hir_id: HirId) {
@@ -948,3 +976,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
948976
self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
949977
}
950978
}
979+
980+
struct HasRecursiveOpaque<'a, 'tcx> {
981+
def_id: LocalDefId,
982+
seen: FxHashSet<LocalDefId>,
983+
opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
984+
tcx: TyCtxt<'tcx>,
985+
}
986+
987+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
988+
type Result = ControlFlow<()>;
989+
990+
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
991+
if let ty::Alias(ty::Opaque, alias_ty) = *t.kind()
992+
&& let Some(def_id) = alias_ty.def_id.as_local()
993+
{
994+
if self.def_id == def_id {
995+
return ControlFlow::Break(());
996+
}
997+
998+
if self.seen.insert(def_id)
999+
&& let Some(hidden_ty) = self.opaques.get(&def_id)
1000+
{
1001+
ty::EarlyBinder::bind(hidden_ty.ty)
1002+
.instantiate(self.tcx, alias_ty.args)
1003+
.visit_with(self)?;
1004+
}
1005+
}
1006+
1007+
t.super_visit_with(self)
1008+
}
1009+
}

Diff for: tests/ui/impl-trait/issue-100075-2.stderr

+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`.

Diff for: tests/ui/impl-trait/issue-100075.stderr

+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`.

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

+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`.

Diff for: 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
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
error[E0720]: cannot resolve opaque type
2-
--> $DIR/infinite-cycle-involving-weak.rs:3:10
1+
error: cannot resolve opaque type
2+
--> $DIR/infinite-cycle-involving-weak.rs:7:13
33
|
4-
LL | type T = impl Copy;
5-
| ^^^^^^^^^ cannot resolve opaque type
4+
LL | fn foo() -> T {
5+
| ^
66

77
error: aborting due to 1 previous error
88

9-
For more information about this error, try `rustc --explain E0720`.
+2-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error: concrete type differs from previous defining opaque type use
1+
error: cannot resolve opaque type
22
--> $DIR/recursive-fn-tait.rs:15:6
33
|
44
LL | ) -> Diff {
5-
| ^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:17:5: 17:20}`
6-
|
7-
note: previous use here
8-
--> $DIR/recursive-fn-tait.rs:7:18
9-
|
10-
LL | pub fn lift() -> Diff {
11-
| ^^^^
5+
| ^^^^
126

137
error: aborting due to 1 previous error
148

Diff for: tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
error: concrete type differs from previous defining opaque type use
1+
error: cannot resolve opaque type
22
--> $DIR/recursive-tait-conflicting-defn-2.rs:15:13
33
|
44
LL | fn bad() -> Op {
5-
| ^^ expected `&&str`, got `impl std::fmt::Display`
6-
|
7-
note: previous use here
8-
--> $DIR/recursive-tait-conflicting-defn-2.rs:7:13
9-
|
10-
LL | fn foo() -> Op {
115
| ^^
126

137
error: aborting due to 1 previous error
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error: concrete type differs from previous defining opaque type use
1+
error: cannot resolve opaque type
22
--> $DIR/recursive-tait-conflicting-defn.rs:25:22
33
|
44
LL | fn make_option2() -> Option<TestImpl> {
5-
| ^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
6-
|
7-
note: previous use here
8-
--> $DIR/recursive-tait-conflicting-defn.rs:20:18
9-
|
10-
LL | pub fn test() -> TestImpl {
11-
| ^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^
126

137
error: aborting due to 1 previous error
148

0 commit comments

Comments
 (0)