Rollup merge of #64842 - pnkfelix:fix-issue-61631-self-in-type-param-default, r=alexreg
Disallow Self in type param defaults of ADTs Fix #61631 (also includes a drive-by fix to a typo in some related diagnostic output.)
This commit is contained in:
commit
27c90524a0
@ -354,6 +354,17 @@ impl<'a> Resolver<'a> {
|
||||
span, "defaulted type parameters cannot be forward declared".to_string());
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfInTyParamDefault => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
span,
|
||||
E0735,
|
||||
"type parameters cannot use `Self` in their defaults"
|
||||
);
|
||||
err.span_label(
|
||||
span, "`Self` in type parameter default".to_string());
|
||||
err
|
||||
}
|
||||
ResolutionError::ConstParamDependentOnTypeParam => {
|
||||
let mut err = struct_span_err!(
|
||||
self.session,
|
||||
|
@ -8,9 +8,9 @@ Type parameter defaults can only use parameters that occur before them.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0128
|
||||
struct Foo<T=U, U=()> {
|
||||
struct Foo<T = U, U = ()> {
|
||||
field1: T,
|
||||
filed2: U,
|
||||
field2: U,
|
||||
}
|
||||
// error: type parameters with a default cannot use forward declared
|
||||
// identifiers
|
||||
@ -20,9 +20,9 @@ Since type parameters are evaluated in-order, you may be able to fix this issue
|
||||
by doing:
|
||||
|
||||
```
|
||||
struct Foo<U=(), T=U> {
|
||||
struct Foo<U = (), T = U> {
|
||||
field1: T,
|
||||
filed2: U,
|
||||
field2: U,
|
||||
}
|
||||
```
|
||||
|
||||
@ -1705,6 +1705,21 @@ fn const_id<T, const N: T>() -> T { // error: const parameter
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0735: r##"
|
||||
Type parameter defaults cannot use `Self` on structs, enums, or unions.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0735
|
||||
struct Foo<X = Box<Self>> {
|
||||
field1: Option<X>,
|
||||
field2: Option<X>,
|
||||
}
|
||||
// error: type parameters cannot use `Self` in their defaults.
|
||||
```
|
||||
"##,
|
||||
|
||||
;
|
||||
// E0153, unused error code
|
||||
// E0157, unused error code
|
||||
|
@ -468,6 +468,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
|
||||
}
|
||||
}));
|
||||
|
||||
// rust-lang/rust#61631: The type `Self` is essentially
|
||||
// another type parameter. For ADTs, we consider it
|
||||
// well-defined only after all of the ADT type parameters have
|
||||
// been provided. Therefore, we do not allow use of `Self`
|
||||
// anywhere in ADT type parameter defaults.
|
||||
//
|
||||
// (We however cannot ban `Self` for defaults on *all* generic
|
||||
// lists; e.g. trait generics can usefully refer to `Self`,
|
||||
// such as in the case of `trait Add<Rhs = Self>`.)
|
||||
if self.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.)
|
||||
default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
|
||||
}
|
||||
|
||||
// We also ban access to type parameters for use as the types of const parameters.
|
||||
let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
|
||||
const_ty_param_ban_rib.bindings.extend(generics.params.iter()
|
||||
|
@ -214,6 +214,8 @@ enum ResolutionError<'a> {
|
||||
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
|
||||
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
|
||||
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
|
||||
/// Error E0735: type parameters with a default cannot use `Self`
|
||||
SelfInTyParamDefault,
|
||||
/// Error E0671: const parameter cannot depend on type parameter.
|
||||
ConstParamDependentOnTypeParam,
|
||||
}
|
||||
@ -1536,7 +1538,7 @@ impl<'a> Resolver<'a> {
|
||||
if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
|
||||
// The ident resolves to a type parameter or local variable.
|
||||
return Some(LexicalScopeBinding::Res(
|
||||
self.validate_res_from_ribs(i, res, record_used, path_span, ribs),
|
||||
self.validate_res_from_ribs(i, rib_ident, res, record_used, path_span, ribs),
|
||||
));
|
||||
}
|
||||
|
||||
@ -2122,6 +2124,7 @@ impl<'a> Resolver<'a> {
|
||||
fn validate_res_from_ribs(
|
||||
&mut self,
|
||||
rib_index: usize,
|
||||
rib_ident: Ident,
|
||||
res: Res,
|
||||
record_used: bool,
|
||||
span: Span,
|
||||
@ -2133,7 +2136,12 @@ impl<'a> Resolver<'a> {
|
||||
// An invalid forward use of a type parameter from a previous default.
|
||||
if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind {
|
||||
if record_used {
|
||||
self.report_error(span, ResolutionError::ForwardDeclaredTyParam);
|
||||
let res_error = if rib_ident.name == kw::SelfUpper {
|
||||
ResolutionError::SelfInTyParamDefault
|
||||
} else {
|
||||
ResolutionError::ForwardDeclaredTyParam
|
||||
};
|
||||
self.report_error(span, res_error);
|
||||
}
|
||||
assert_eq!(res, Res::Err);
|
||||
return Res::Err;
|
||||
|
@ -0,0 +1,20 @@
|
||||
#![crate_type="lib"]
|
||||
|
||||
// rust-lang/rust#61631: The use of `Self` in the defaults of generic
|
||||
// types in a *trait* definition are allowed.
|
||||
//
|
||||
// It *must* be accepted; we have used this pattern extensively since
|
||||
// Rust 1.0 (see e.g. `trait Add<Rhs=Self>`).
|
||||
trait Tnobound<P = Self> {}
|
||||
|
||||
impl Tnobound for () { }
|
||||
|
||||
// This variant is accepted at the definition site; but it will be
|
||||
// rejected at every possible usage site (such as the one immediately
|
||||
// below). Maybe one day we will attempt to catch it at the definition
|
||||
// site, but today this is accepted due to compiler implementation
|
||||
// limitations.
|
||||
trait Tsized<P: Sized = [Self]> {}
|
||||
|
||||
impl Tsized for () {}
|
||||
//~^ ERROR the size for values of type `[()]` cannot be known at compilation time [E0277]
|
@ -0,0 +1,12 @@
|
||||
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
|
||||
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6
|
||||
|
|
||||
LL | impl Tsized for () {}
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[()]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,45 @@
|
||||
#![crate_type="lib"]
|
||||
|
||||
// rust-lang/rust#61631: Uses of `Self` in the defaults of generic
|
||||
// types for ADT's are not allowed. We justify this because the `Self`
|
||||
// type could be considered the "final" type parameter, that is only
|
||||
// well-defined after all of the other type parameters on the ADT have
|
||||
// been instantiated.
|
||||
//
|
||||
// These were previously were ICE'ing at the usage point anyway (see
|
||||
// `demo_usages` below), so there should not be any backwards
|
||||
// compatibility concern.
|
||||
|
||||
struct Snobound<'a, P = Self> { x: Option<&'a P> }
|
||||
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
|
||||
|
||||
enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
|
||||
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
|
||||
|
||||
union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
|
||||
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
|
||||
|
||||
// Disallowing `Self` in defaults sidesteps need to check the bounds
|
||||
// on the defaults in cases like these.
|
||||
|
||||
struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
|
||||
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
|
||||
|
||||
enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
|
||||
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
|
||||
|
||||
union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
|
||||
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
|
||||
|
||||
fn demo_usages() {
|
||||
// An ICE means you only get the error from the first line of the
|
||||
// demo; comment each out to observe the other ICEs when trying
|
||||
// this out on older versions of Rust.
|
||||
|
||||
let _ice: Snobound;
|
||||
let _ice: Enobound;
|
||||
let _ice: Unobound;
|
||||
let _ice: Ssized;
|
||||
let _ice: Esized;
|
||||
let _ice: Usized;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
error[E0735]: type parameters cannot use `Self` in their defaults
|
||||
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25
|
||||
|
|
||||
LL | struct Snobound<'a, P = Self> { x: Option<&'a P> }
|
||||
| ^^^^ `Self` in type parameter default
|
||||
|
||||
error[E0735]: type parameters cannot use `Self` in their defaults
|
||||
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23
|
||||
|
|
||||
LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
|
||||
| ^^^^ `Self` in type parameter default
|
||||
|
||||
error[E0735]: type parameters cannot use `Self` in their defaults
|
||||
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24
|
||||
|
|
||||
LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
|
||||
| ^^^^ `Self` in type parameter default
|
||||
|
||||
error[E0735]: type parameters cannot use `Self` in their defaults
|
||||
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31
|
||||
|
|
||||
LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
|
||||
| ^^^^ `Self` in type parameter default
|
||||
|
||||
error[E0735]: type parameters cannot use `Self` in their defaults
|
||||
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29
|
||||
|
|
||||
LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
|
||||
| ^^^^ `Self` in type parameter default
|
||||
|
||||
error[E0735]: type parameters cannot use `Self` in their defaults
|
||||
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30
|
||||
|
|
||||
LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
|
||||
| ^^^^ `Self` in type parameter default
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0735`.
|
Loading…
x
Reference in New Issue
Block a user