Rollup merge of #139419 - compiler-errors:recursive-opaque, r=lcnr
Error on recursive opaque ty in HIR typeck
"Non-trivially recursive" opaques are opaques whose hidden types are inferred to be equal to something other than themselves. For example, if we have a TAIT like `type TAIT = impl Sized`, if we infer the hidden type to be `TAIT := (TAIT,)`, that would be a non-trivial recursive definition. We don't want to support opaques that are non-trivially recursive, since they will (almost!! -- see caveat below) always result in borrowck errors, and are generally a pain to deal with.
On the contrary, trivially recursive opaques may occur today because the old solver overagerly uses `replace_opaque_types_with_inference_vars`. This infer var can then later be constrained to be equal to the opaque itself. These cases will not necessarily result in borrow-checker errors, since other uses of the opaque may properly constrain the opaque. If there are no other uses we may instead fall back to `()` today.
The only weird case that we have to unfortunately deal with was discovered in https://github.com/rust-lang/rust/issues/139406:
```rust
#![allow(unconditional_recursion)]
fn what1<T>(x: T) -> impl Sized {
what1(x)
}
fn what2<T>(x: T) -> impl Sized {
what2(what2(x))
}
fn print_return_type<T, U>(_: impl Fn(T) -> U) {
println!("{}", std::any::type_name::<U>())
}
fn main() {
print_return_type(what1::<i32>); // ()
print_return_type(what2::<i32>); // i32
}
```
> HIR typeck eagerly replaces the return type with an infer var, ending up with `RPIT<T> = RPIT<RPIT<T>>` in the storage. While we return this in the `TypeckResults`, it's never actually used anywhere.
>
> MIR building then results in the following statement
> ```rust
> let _0: impl RPIT<T> /* the return place */ = build<RPIT<T>>(_some_local);
> ```
> Unlike HIR typeck MIR typeck now directly equates `RPIT<T>` with `RPIT<RPIT<T>>`. This does not try to define `RPIT` but instead relates its generic arguments b9856b6e40/compiler/rustc_infer/src/infer/relate/type_relating.rs (L185-L190)
>
> This means we relate `T` with `RPIT<T>`, which results in a defining use `RPIT<T> = T`
I think it's pretty obvious that this is not desirable behavior, and according to the crater run there were no regressions, so let's break this so that we don't have any inference hazards in the new solver.
In the future `what2` may end up compiling again by also falling back to `()`. However, that is not yet guaranteed and the transition to this state is made significantly harder by not temporarily breaking it on the way. It is also concerning to change the inferred hidden type like this without any notification to the user, even if likely not an issue in this concrete case.
This commit is contained in:
commit
7e3af744bb
22 changed files with 162 additions and 218 deletions
|
|
@ -9,17 +9,21 @@
|
|||
//! which creates a new `TypeckResults` which doesn't contain any inference variables.
|
||||
|
||||
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_errors::{E0720, ErrorGuaranteed};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{self, InferKind, Visitor};
|
||||
use rustc_hir::{self as hir, AmbigArg, HirId};
|
||||
use rustc_infer::traits::solve::Goal;
|
||||
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;
|
||||
|
|
@ -595,6 +599,35 @@ 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()
|
||||
.struct_span_err(span, "cannot resolve opaque type")
|
||||
.with_code(E0720)
|
||||
.emit();
|
||||
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) {
|
||||
|
|
@ -959,3 +992,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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::fmt;
|
||||
use std::iter::once;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
|
||||
use rustc_arena::DroplessArena;
|
||||
|
|
@ -12,8 +11,7 @@ use rustc_middle::mir::{self, Const};
|
|||
use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::ty::{
|
||||
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor, VariantDef,
|
||||
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
|
|
@ -137,22 +135,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
/// Returns the hidden type corresponding to this key if the body under analysis is allowed to
|
||||
/// know it.
|
||||
fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
|
||||
if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) {
|
||||
let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args);
|
||||
if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() {
|
||||
Some(ty)
|
||||
} else {
|
||||
// HACK: We skip revealing opaque types which recursively expand
|
||||
// to themselves. This is because we may infer hidden types like
|
||||
// `Opaque<T> = Opaque<Opaque<T>>` or `Opaque<T> = Opaque<(T,)>`
|
||||
// in hir typeck.
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.typeck_results
|
||||
.concrete_opaque_types
|
||||
.get(&key.def_id)
|
||||
.map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
|
||||
}
|
||||
|
||||
// This can take a non-revealed `Ty` because it reveals opaques itself.
|
||||
pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
|
||||
!ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
|
||||
|
|
@ -1177,20 +1164,3 @@ fn detect_mixed_deref_pat_ctors<'p, 'tcx>(
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct RecursiveOpaque {
|
||||
def_id: DefId,
|
||||
}
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for RecursiveOpaque {
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = t.kind() {
|
||||
if alias_ty.def_id == self.def_id {
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
}
|
||||
|
||||
if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
error[E0720]: 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
|
||||
|
|
||||
|
|
@ -10,15 +16,6 @@ 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`.
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ error[E0720]: 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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
//@ check-pass
|
||||
|
||||
trait T {}
|
||||
|
||||
fn wrap(x: impl T) -> impl T {
|
||||
//~^ WARN function cannot return without recursing
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
//~| WARN function cannot return without recursing
|
||||
wrap(wrap(x))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/issue-103599.rs:3:23
|
||||
|
|
||||
LL | fn wrap(x: impl T) -> impl T {
|
||||
| ^^^^^^
|
||||
|
||||
warning: function cannot return without recursing
|
||||
--> $DIR/issue-103599.rs:5:1
|
||||
--> $DIR/issue-103599.rs:3:1
|
||||
|
|
||||
LL | fn wrap(x: impl T) -> impl T {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
...
|
||||
LL | wrap(wrap(x))
|
||||
| ------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ fn bar() -> impl Fn() {
|
|||
}
|
||||
|
||||
fn foo() -> impl Fn() {
|
||||
//~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion]
|
||||
//~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720]
|
||||
//~^ WARN function cannot return without recursing
|
||||
//~| ERROR cannot resolve opaque type
|
||||
wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
error[E0720]: 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
|
||||
|
|
||||
|
|
@ -10,18 +16,6 @@ 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`.
|
||||
|
|
|
|||
|
|
@ -2,112 +2,67 @@ error[E0720]: 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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
--> $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
|
||||
|
|
|
|||
|
|
@ -1,56 +1,21 @@
|
|||
warning: function cannot return without recursing
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:17:1
|
||||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:17:22
|
||||
|
|
||||
LL | fn build<T>(x: T) -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | let (x,) = (build(x),);
|
||||
| -------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
warning: function cannot return without recursing
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:27:1
|
||||
|
|
||||
LL | fn build2<T>(x: T) -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
...
|
||||
LL | let (x,) = (build2(x),);
|
||||
| --------- recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:27:23
|
||||
|
|
||||
LL | fn build2<T>(x: T) -> impl Sized {
|
||||
| ^^^^^^^^^^ recursive opaque type
|
||||
...
|
||||
LL | (build2(x),)
|
||||
| ------------ returning here with type `(impl Sized,)`
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: function cannot return without recursing
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:40:1
|
||||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:39:23
|
||||
|
|
||||
LL | fn build3<T>(x: T) -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
LL |
|
||||
LL | let (x,) = (build3((x,)),);
|
||||
| ------------ recursive call site
|
||||
|
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0792]: expected generic type parameter, found `(T,)`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:49:5
|
||||
|
|
||||
LL | fn build3<T>(x: T) -> impl Sized {
|
||||
| - this generic parameter must be used with a generic type parameter
|
||||
...
|
||||
LL | build3(x)
|
||||
| ^^^^^^^^^
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
error: aborting due to 2 previous errors; 3 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0720, E0792.
|
||||
For more information about an error, try `rustc --explain E0720`.
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
|
|
|
|||
|
|
@ -5,19 +5,19 @@ LL | let (x,) = (build(x),);
|
|||
| ^^^^^^^^ cannot satisfy `impl Sized == _`
|
||||
|
||||
error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:31:6
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:30:6
|
||||
|
|
||||
LL | (build2(x),)
|
||||
| ^^^^^^^^^ types differ
|
||||
|
||||
error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:31:5
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:30:5
|
||||
|
|
||||
LL | (build2(x),)
|
||||
| ^^^^^^^^^^^^ types differ
|
||||
|
||||
error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:31:5
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:30:5
|
||||
|
|
||||
LL | (build2(x),)
|
||||
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
@ -26,13 +26,13 @@ LL | (build2(x),)
|
|||
= note: tuples must have a statically known size to be initialized
|
||||
|
||||
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:42:17
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:41:17
|
||||
|
|
||||
LL | let (x,) = (build3((x,)),);
|
||||
| ^^^^^^^^^^^^ types differ
|
||||
|
||||
error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:42:16
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:41:16
|
||||
|
|
||||
LL | let (x,) = (build3((x,)),);
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
@ -41,7 +41,7 @@ LL | let (x,) = (build3((x,)),);
|
|||
= note: tuples must have a statically known size to be initialized
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:42:16
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:41:16
|
||||
|
|
||||
LL | fn build3<T>(x: T) -> impl Sized {
|
||||
| ---------- the found opaque type
|
||||
|
|
@ -53,7 +53,7 @@ LL | let (x,) = (build3((x,)),);
|
|||
found tuple `(impl Sized,)`
|
||||
|
||||
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:42:17
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:41:17
|
||||
|
|
||||
LL | let (x,) = (build3((x,)),);
|
||||
| ^^^^^^^^^^^^ types differ
|
||||
|
|
@ -61,13 +61,13 @@ LL | let (x,) = (build3((x,)),);
|
|||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:42:16
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:41:16
|
||||
|
|
||||
LL | let (x,) = (build3((x,)),);
|
||||
| ^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:42:17
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:41:17
|
||||
|
|
||||
LL | let (x,) = (build3((x,)),);
|
||||
| ^^^^^^^^^^^^ types differ
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
// We unfortunately accept this today, and due to how opaque type relating is implemented
|
||||
// in the NLL type relation, this defines `Opaque<T> = T`.
|
||||
fn build<T>(x: T) -> impl Sized {
|
||||
//[current]~^ WARN function cannot return without recursing
|
||||
//[current]~^ ERROR cannot resolve opaque type
|
||||
let (x,) = (build(x),);
|
||||
//[next]~^ ERROR type annotations needed
|
||||
build(x)
|
||||
|
|
@ -26,7 +26,6 @@ fn build<T>(x: T) -> impl Sized {
|
|||
// Not allowed today. Detected as recursive.
|
||||
fn build2<T>(x: T) -> impl Sized {
|
||||
//[current]~^ ERROR cannot resolve opaque type
|
||||
//[current]~| WARN function cannot return without recursing
|
||||
let (x,) = (build2(x),);
|
||||
(build2(x),)
|
||||
//[next]~^ ERROR type mismatch resolving
|
||||
|
|
@ -38,7 +37,7 @@ fn build2<T>(x: T) -> impl Sized {
|
|||
//
|
||||
// Not allowed today. Detected as not defining.
|
||||
fn build3<T>(x: T) -> impl Sized {
|
||||
//[current]~^ WARN function cannot return without recursing
|
||||
//[current]~^ ERROR cannot resolve opaque type
|
||||
let (x,) = (build3((x,)),);
|
||||
//[next]~^ ERROR type mismatch resolving
|
||||
//[next]~| ERROR type mismatch resolving
|
||||
|
|
@ -47,7 +46,6 @@ fn build3<T>(x: T) -> impl Sized {
|
|||
//[next]~| ERROR the size for values of type
|
||||
//[next]~| ERROR mismatched types
|
||||
build3(x)
|
||||
//[current]~^ ERROR expected generic type parameter, found `(T,)`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type T = impl Copy;
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
|
||||
#[define_opaque(T)]
|
||||
fn foo() -> T {
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
None::<&'static T>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/infinite-cycle-involving-weak.rs:3:10
|
||||
--> $DIR/infinite-cycle-involving-weak.rs:6:13
|
||||
|
|
||||
LL | type T = impl Copy;
|
||||
| ^^^^^^^^^ cannot resolve opaque type
|
||||
LL | fn foo() -> T {
|
||||
| ^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
//@ known-bug: #139817
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
fn enum_upvar() {
|
||||
type T = impl Copy;
|
||||
let foo: T = Some((42, std::marker::PhantomData::<T>));
|
||||
let x = move || match foo {
|
||||
None => (),
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/match-upvar-discriminant-of-opaque.rs:7:9
|
||||
|
|
||||
LL | None => (),
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
|
|
@ -13,7 +13,7 @@ pub fn add(
|
|||
n: Diff,
|
||||
m: Diff,
|
||||
) -> Diff {
|
||||
//~^ ERROR concrete type differs
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
move |x: usize| m(n(x))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
error: concrete type differs from previous defining opaque type use
|
||||
error[E0720]: 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
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ fn transform<S>() -> impl std::fmt::Display {
|
|||
}
|
||||
#[define_opaque(Op)]
|
||||
fn bad() -> Op {
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
transform::<Op>()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
error: concrete type differs from previous defining opaque type use
|
||||
error[E0720]: 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
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub fn test() -> TestImpl {
|
|||
|
||||
#[define_opaque(TestImpl)]
|
||||
fn make_option2() -> Option<TestImpl> {
|
||||
//~^ ERROR concrete type differs from previous defining opaque type use
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
let inner = make_option().unwrap();
|
||||
Some(B { inner })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
error: concrete type differs from previous defining opaque type use
|
||||
error[E0720]: 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
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue