Skip to content

Improve a TAIT error and add an error code plus documentation #106940

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

Merged
merged 1 commit into from
Jan 16, 2023
Merged
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
20 changes: 9 additions & 11 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::ObligationCtxt;

use crate::session_diagnostics::NonGenericOpaqueTypeParam;

use super::RegionInferenceContext;

impl<'tcx> RegionInferenceContext<'tcx> {
Expand Down Expand Up @@ -389,17 +391,13 @@ fn check_opaque_type_parameter_valid(
} else {
// Prevent `fn foo() -> Foo<u32>` from being defining.
let opaque_param = opaque_generics.param_at(i, tcx);
tcx.sess
.struct_span_err(span, "non-defining opaque type use in defining scope")
.span_note(
tcx.def_span(opaque_param.def_id),
&format!(
"used non-generic {} `{}` for generic parameter",
opaque_param.kind.descr(),
arg,
),
)
.emit();
let kind = opaque_param.kind.descr();
tcx.sess.emit_err(NonGenericOpaqueTypeParam {
ty: arg,
kind,
span,
param_span: tcx.def_span(opaque_param.def_id),
});
return false;
}
}
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_borrowck/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_middle::ty::{GenericArg, Ty};
use rustc_span::Span;

use crate::diagnostics::RegionName;
Expand Down Expand Up @@ -240,3 +240,14 @@ pub(crate) struct MoveBorrow<'a> {
#[label]
pub borrow_span: Span,
}

#[derive(Diagnostic)]
#[diag(borrowck_opaque_type_non_generic_param, code = "E0792")]
pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
pub ty: GenericArg<'tcx>,
pub kind: &'a str,
#[primary_span]
pub span: Span,
#[label]
pub param_span: Span,
}
1 change: 1 addition & 0 deletions compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ E0787: include_str!("./error_codes/E0787.md"),
E0788: include_str!("./error_codes/E0788.md"),
E0790: include_str!("./error_codes/E0790.md"),
E0791: include_str!("./error_codes/E0791.md"),
E0792: include_str!("./error_codes/E0792.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
Expand Down
60 changes: 60 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0792.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
A type alias impl trait can only have its hidden type assigned
when used fully generically (and within their defining scope).
This means

```compile_fail,E0792
#![feature(type_alias_impl_trait)]

type Foo<T> = impl std::fmt::Debug;

fn foo() -> Foo<u32> {
5u32
}
```

is not accepted. If it were accepted, one could create unsound situations like

```compile_fail,E0792
#![feature(type_alias_impl_trait)]

type Foo<T> = impl Default;

fn foo() -> Foo<u32> {
5u32
}

fn main() {
let x = Foo::<&'static mut String>::default();
}
```


Instead you need to make the function generic:

```
#![feature(type_alias_impl_trait)]

type Foo<T> = impl std::fmt::Debug;

fn foo<U>() -> Foo<U> {
5u32
}
```

This means that no matter the generic parameter to `foo`,
the hidden type will always be `u32`.
If you want to link the generic parameter to the hidden type,
you can do that, too:


```
#![feature(type_alias_impl_trait)]

use std::fmt::Debug;

type Foo<T: Debug> = impl Debug;

fn foo<U: Debug>() -> Foo<U> {
Vec::<U>::new()
}
```
4 changes: 4 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/borrowck.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,7 @@ borrowck_cannot_move_when_borrowed =
[value] value
*[other] {$value_place}
} occurs here

borrowck_opaque_type_non_generic_param =
expected generic {$kind} parameter, found `{$ty}`
.label = this generic parameter must be used with a generic {$kind} parameter
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use rustc_type_ir::sty::TyKind::*;

impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
format!("{}", self).into_diagnostic_arg()
self.to_string().into_diagnostic_arg()
}
}

Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};

use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
Expand Down Expand Up @@ -36,6 +37,12 @@ pub struct GenericArg<'tcx> {
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
}

impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
self.to_string().into_diagnostic_arg()
}
}

const TAG_MASK: usize = 0b11;
const TYPE_TAG: usize = 0b00;
const REGION_TAG: usize = 0b01;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/bound_reduction2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ impl<W> Trait<W> for () {}

fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
()
//~^ ERROR non-defining opaque type use
//~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
}
12 changes: 5 additions & 7 deletions tests/ui/type-alias-impl-trait/bound_reduction2.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
error: non-defining opaque type use in defining scope
error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
--> $DIR/bound_reduction2.rs:16:5
|
LL | type Foo<V> = impl Trait<V>;
| - this generic parameter must be used with a generic type parameter
...
LL | ()
| ^^
|
note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
--> $DIR/bound_reduction2.rs:9:10
|
LL | type Foo<V> = impl Trait<V>;
| ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0792`.
5 changes: 2 additions & 3 deletions tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ type OneLifetime<'a> = impl Debug;

type OneConst<const X: usize> = impl Debug;


// Not defining uses, because they doesn't define *all* possible generics.

fn concrete_ty() -> OneTy<u32> {
5u32
//~^ ERROR non-defining opaque type use in defining scope
//~^ ERROR expected generic type parameter, found `u32`
}

fn concrete_lifetime() -> OneLifetime<'static> {
Expand All @@ -25,5 +24,5 @@ fn concrete_lifetime() -> OneLifetime<'static> {

fn concrete_const() -> OneConst<{ 123 }> {
7u32
//~^ ERROR non-defining opaque type use in defining scope
//~^ ERROR expected generic constant parameter, found `123`
}
29 changes: 12 additions & 17 deletions tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
error: non-defining opaque type use in defining scope
--> $DIR/generic_nondefining_use.rs:17:5
error[E0792]: expected generic type parameter, found `u32`
--> $DIR/generic_nondefining_use.rs:16:5
|
LL | type OneTy<T> = impl Debug;
| - this generic parameter must be used with a generic type parameter
...
LL | 5u32
| ^^^^
|
note: used non-generic type `u32` for generic parameter
--> $DIR/generic_nondefining_use.rs:7:12
|
LL | type OneTy<T> = impl Debug;
| ^

error: non-defining opaque type use in defining scope
--> $DIR/generic_nondefining_use.rs:22:5
--> $DIR/generic_nondefining_use.rs:21:5
|
LL | type OneLifetime<'a> = impl Debug;
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
...
LL | 6u32
| ^^^^

error: non-defining opaque type use in defining scope
--> $DIR/generic_nondefining_use.rs:27:5
error[E0792]: expected generic constant parameter, found `123`
--> $DIR/generic_nondefining_use.rs:26:5
|
LL | type OneConst<const X: usize> = impl Debug;
| -------------- this generic parameter must be used with a generic constant parameter
...
LL | 7u32
| ^^^^
|
note: used non-generic constant `123` for generic parameter
--> $DIR/generic_nondefining_use.rs:11:15
|
LL | type OneConst<const X: usize> = impl Debug;
| ^^^^^^^^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0792`.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ fn main() {
let y = 42;
let x = wrong_generic(&y);
let z: i32 = x;
//~^ ERROR non-defining opaque type use
//~^ ERROR expected generic type parameter, found `&'static i32
}

type WrongGeneric<T> = impl 'static;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ error: at least one trait must be specified
LL | type WrongGeneric<T> = impl 'static;
| ^^^^^^^^^^^^

error: non-defining opaque type use in defining scope
error[E0792]: expected generic type parameter, found `&'static i32`
--> $DIR/generic_type_does_not_live_long_enough.rs:6:18
|
LL | let z: i32 = x;
| ^
|
note: used non-generic type `&'static i32` for generic parameter
--> $DIR/generic_type_does_not_live_long_enough.rs:10:19
|
...
LL | type WrongGeneric<T> = impl 'static;
| ^
| - this generic parameter must be used with a generic type parameter

error[E0310]: the parameter type `T` may not live long enough
--> $DIR/generic_type_does_not_live_long_enough.rs:14:5
Expand All @@ -29,4 +26,5 @@ LL | fn wrong_generic<T: 'static>(t: T) -> WrongGeneric<T> {

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0310`.
Some errors have detailed explanations: E0310, E0792.
For more information about an error, try `rustc --explain E0310`.
2 changes: 1 addition & 1 deletion tests/ui/type-alias-impl-trait/issue-60564.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ where
type BitsIter = IterBitsIter<T, E, u8>;
fn iter_bits(self, n: u8) -> Self::BitsIter {
(0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
//~^ ERROR non-defining opaque type use in defining scope
//~^ ERROR expected generic type parameter, found `u8`
}
}

Expand Down
12 changes: 5 additions & 7 deletions tests/ui/type-alias-impl-trait/issue-60564.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
error: non-defining opaque type use in defining scope
error[E0792]: expected generic type parameter, found `u8`
--> $DIR/issue-60564.rs:20:9
|
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
| - this generic parameter must be used with a generic type parameter
...
LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: used non-generic type `u8` for generic parameter
--> $DIR/issue-60564.rs:8:25
|
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
| ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0792`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trait Trait<T> {}
type Alias<'a, U> = impl Trait<U>;

fn f<'a>() -> Alias<'a, ()> {}
//~^ ERROR non-defining opaque type use in defining scope
//~^ ERROR expected generic type parameter, found `()`

fn main() {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
error: non-defining opaque type use in defining scope
error[E0792]: expected generic type parameter, found `()`
--> $DIR/issue-68368-non-defining-use-2.rs:9:29
|
LL | type Alias<'a, U> = impl Trait<U>;
| - this generic parameter must be used with a generic type parameter
LL |
LL | fn f<'a>() -> Alias<'a, ()> {}
| ^^
|
note: used non-generic type `()` for generic parameter
--> $DIR/issue-68368-non-defining-use-2.rs:7:16
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0792`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trait Trait<T> {}
type Alias<'a, U> = impl Trait<U>;

fn f<'a>() -> Alias<'a, ()> {}
//~^ ERROR non-defining opaque type use in defining scope
//~^ ERROR expected generic type parameter, found `()`

fn main() {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
error: non-defining opaque type use in defining scope
error[E0792]: expected generic type parameter, found `()`
--> $DIR/issue-68368-non-defining-use.rs:9:29
|
LL | type Alias<'a, U> = impl Trait<U>;
| - this generic parameter must be used with a generic type parameter
LL |
LL | fn f<'a>() -> Alias<'a, ()> {}
| ^^
|
note: used non-generic type `()` for generic parameter
--> $DIR/issue-68368-non-defining-use.rs:7:16
|
LL | type Alias<'a, U> = impl Trait<U>;
| ^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0792`.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
//~^ ERROR use of undeclared lifetime name `'a`

fn my_fun() -> Return<()> {}
//~^ ERROR non-defining opaque type use in defining scope
//~^ ERROR expected generic type parameter, found `()`

fn main() {}
Loading