diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-01-16 15:15:09 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2023-01-16 16:54:14 +0000 |
| commit | 6b69b5e4607e32d8860c4cd0ebf0132f1998b14d (patch) | |
| tree | a051c4ecb109517248ad6a4bb8998b7d08f61ef6 | |
| parent | 41edaac716dde55b6a9d83ae4da0fba354ae5ba8 (diff) | |
| download | rust-6b69b5e4607e32d8860c4cd0ebf0132f1998b14d.tar.gz rust-6b69b5e4607e32d8860c4cd0ebf0132f1998b14d.zip | |
Improve a TAIT error and add an error code plus documentation
21 files changed, 145 insertions, 82 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index c6e42336ef8..9d8812b7eea 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -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> { @@ -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; } } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 577332c0744..23acf159240 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -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; @@ -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, +} diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 24258974bb9..5c77448f908 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -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 diff --git a/compiler/rustc_error_codes/src/error_codes/E0792.md b/compiler/rustc_error_codes/src/error_codes/E0792.md new file mode 100644 index 00000000000..bad2b5abfe4 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0792.md @@ -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() +} +``` diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 2cd4733220e..9e4332c4283 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -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 diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 8c22df7395f..771b63f59c1 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -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() } } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 8f764011d0a..75a8dda3157 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -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}; @@ -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; diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs index 4d2890b5de5..0bcc9e002ca 100644 --- a/tests/ui/type-alias-impl-trait/bound_reduction2.rs +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs @@ -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` } diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr index c405b1f6af2..3c259bd9e97 100644 --- a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs index f39741a6a62..f5045d382aa 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -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> { @@ -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` } diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr index e7565525ad3..564648630b1 100644 --- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -1,17 +1,14 @@ -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 @@ -19,17 +16,15 @@ LL | type OneLifetime<'a> = impl Debug; 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`. diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs index cb90776472b..d3e169a70d3 100644 --- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -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; diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index ba583241a69..19115fd2866 100644 --- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -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 @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs index 4fc7679311a..c2f4c370807 100644 --- a/tests/ui/type-alias-impl-trait/issue-60564.rs +++ b/tests/ui/type-alias-impl-trait/issue-60564.rs @@ -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` } } diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr index bbc93657be3..f8fdb004d09 100644 --- a/tests/ui/type-alias-impl-trait/issue-60564.stderr +++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs index 5223fb1c702..5e0a82a7286 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr index 7fb9a0c410e..271743a4010 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs index b50462bf237..3b32260c96f 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr index 8059621b61a..4d9a8d6eef9 100644 --- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -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`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs index 428454bc048..7657fe2fb1a 100644 --- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs @@ -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() {} diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr index 7b50c8af26e..d1250786d93 100644 --- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -14,18 +14,16 @@ help: consider introducing lifetime `'a` here LL | type Return<'a, A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; | +++ -error: non-defining opaque type use in defining scope +error[E0792]: expected generic type parameter, found `()` --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27 | +LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; + | - this generic parameter must be used with a generic type parameter +... LL | fn my_fun() -> Return<()> {} | ^^ - | -note: used non-generic type `()` for generic parameter - --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:13 - | -LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>; - | ^ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0261`. +Some errors have detailed explanations: E0261, E0792. +For more information about an error, try `rustc --explain E0261`. |
