Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Just error on recursive opaque ty in HIR typeck #139419

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
// generic parameters.

use std::mem;
use std::ops::ControlFlow;

use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, InferKind, Visitor};
use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::{
self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, fold_regions,
self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
fold_regions,
};
use rustc_span::{Span, sym};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
Expand Down Expand Up @@ -622,6 +626,30 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
entry.span = prev.span.substitute_dummy(hidden_type.span);
}
}

let recursive_opaques: Vec<_> = self
.typeck_results
.concrete_opaque_types
.iter()
.filter(|&(&def_id, hidden_ty)| {
hidden_ty
.ty
.visit_with(&mut HasRecursiveOpaque {
def_id,
seen: Default::default(),
opaques: &self.typeck_results.concrete_opaque_types,
tcx,
})
.is_break()
})
.map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span))
.collect();
for (def_id, span) in recursive_opaques {
let guar = self.fcx.dcx().span_err(span, "cannot resolve opaque type");
self.typeck_results
.concrete_opaque_types
.insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
}
}

fn visit_field_id(&mut self, hir_id: HirId) {
Expand Down Expand Up @@ -948,3 +976,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
}
}

struct HasRecursiveOpaque<'a, 'tcx> {
def_id: LocalDefId,
seen: FxHashSet<LocalDefId>,
opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
tcx: TyCtxt<'tcx>,
}

impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
type Result = ControlFlow<()>;

fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if let ty::Alias(ty::Opaque, alias_ty) = *t.kind()
&& let Some(def_id) = alias_ty.def_id.as_local()
{
if self.def_id == def_id {
return ControlFlow::Break(());
}

if self.seen.insert(def_id)
&& let Some(hidden_ty) = self.opaques.get(&def_id)
{
ty::EarlyBinder::bind(hidden_ty.ty)
.instantiate(self.tcx, alias_ty.args)
.visit_with(self)?;
}
}

t.super_visit_with(self)
}
}
16 changes: 6 additions & 10 deletions tests/ui/impl-trait/issue-100075-2.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
error: cannot resolve opaque type
--> $DIR/issue-100075-2.rs:1:23
|
LL | fn opaque<T>(t: T) -> impl Sized {
| ^^^^^^^^^^

warning: function cannot return without recursing
--> $DIR/issue-100075-2.rs:1:1
|
Expand All @@ -10,15 +16,5 @@ LL | opaque(Some(t))
= help: a `loop` may express intention better if this is on purpose
= note: `#[warn(unconditional_recursion)]` on by default

error[E0720]: cannot resolve opaque type
--> $DIR/issue-100075-2.rs:1:23
|
LL | fn opaque<T>(t: T) -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | opaque(Some(t))
| --------------- returning here with type `impl Sized`

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0720`.
8 changes: 2 additions & 6 deletions tests/ui/impl-trait/issue-100075.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/issue-100075.rs:13:37
|
LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
| ^^^^^^^^^^^ recursive opaque type
...
LL | return _g(t);
| ----- returning here with type `&impl Marker`
| ^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0720`.
19 changes: 6 additions & 13 deletions tests/ui/impl-trait/issue-87450.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
error: cannot resolve opaque type
--> $DIR/issue-87450.rs:5:13
|
LL | fn foo() -> impl Fn() {
| ^^^^^^^^^

warning: function cannot return without recursing
--> $DIR/issue-87450.rs:5:1
|
Expand All @@ -10,18 +16,5 @@ LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
= help: a `loop` may express intention better if this is on purpose
= note: `#[warn(unconditional_recursion)]` on by default

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 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0720`.
95 changes: 25 additions & 70 deletions tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
Original file line number Diff line number Diff line change
@@ -1,113 +1,68 @@
error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:6:22
|
LL | fn option(i: i32) -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | if i < 0 { None } else { Some((option(i - 1), i)) }
| ---- ------------------------ returning here with type `Option<(impl Sized, i32)>`
| |
| returning here with type `Option<(impl Sized, i32)>`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:11:15
|
LL | fn tuple() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | (tuple(),)
| ---------- returning here with type `(impl Sized,)`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:16:15
|
LL | fn array() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | [array()]
| --------- returning here with type `[impl Sized; 1]`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:21:13
|
LL | fn ptr() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | &ptr() as *const _
| ------------------ returning here with type `*const impl Sized`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:26:16
|
LL | fn fn_ptr() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | fn_ptr as fn() -> _
| ------------------- returning here with type `fn() -> impl Sized`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:31:25
|
LL | fn closure_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | / move || {
LL | | x;
| | - closure captures itself here
LL | | }
| |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:34:5: 34:12}`
LL | fn closure_capture() -> impl Sized {
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:39:29
|
LL | fn closure_ref_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | / move || {
LL | | &x;
| | - closure captures itself here
LL | | }
| |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:42:5: 42:12}`
LL | fn closure_ref_capture() -> impl Sized {
| ^^^^^^^^^^

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

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:52:23
|
LL | fn coroutine_sig() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | || coroutine_sig()
| ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7}`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:57:27
|
LL | fn coroutine_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
...
LL | / move || {
LL | | yield;
LL | | x;
| | - coroutine captures itself here
LL | | }
| |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:62:5: 62:12}`
LL | fn coroutine_capture() -> impl Sized {
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
error: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:68:35
|
LL | fn substs_change<T: 'static>() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | (substs_change::<&T>(),)
| ------------------------ returning here with type `(impl Sized,)`
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:78:26
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
error[E0720]: cannot resolve opaque type
--> $DIR/infinite-cycle-involving-weak.rs:3:10
error: cannot resolve opaque type
--> $DIR/infinite-cycle-involving-weak.rs:7:13
|
LL | type T = impl Copy;
| ^^^^^^^^^ cannot resolve opaque type
LL | fn foo() -> T {
| ^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0720`.
10 changes: 2 additions & 8 deletions tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
error: concrete type differs from previous defining opaque type use
error: cannot resolve opaque type
--> $DIR/recursive-fn-tait.rs:15:6
|
LL | ) -> Diff {
| ^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:17:5: 17:20}`
|
note: previous use here
--> $DIR/recursive-fn-tait.rs:7:18
|
LL | pub fn lift() -> Diff {
| ^^^^
| ^^^^

error: aborting due to 1 previous error

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

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

error: aborting due to 1 previous error

Loading