Skip to content

Commit eb82e63

Browse files
authored
Rollup merge of rust-lang#64842 - pnkfelix:fix-issue-61631-self-in-type-param-default, r=alexreg
Disallow Self in type param defaults of ADTs Fix rust-lang#61631 (also includes a drive-by fix to a typo in some related diagnostic output.)
2 parents d7a4f9d + e443e1b commit eb82e63

8 files changed

+169
-6
lines changed

src/librustc_resolve/diagnostics.rs

+11
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,17 @@ impl<'a> Resolver<'a> {
354354
span, "defaulted type parameters cannot be forward declared".to_string());
355355
err
356356
}
357+
ResolutionError::SelfInTyParamDefault => {
358+
let mut err = struct_span_err!(
359+
self.session,
360+
span,
361+
E0735,
362+
"type parameters cannot use `Self` in their defaults"
363+
);
364+
err.span_label(
365+
span, "`Self` in type parameter default".to_string());
366+
err
367+
}
357368
ResolutionError::ConstParamDependentOnTypeParam => {
358369
let mut err = struct_span_err!(
359370
self.session,

src/librustc_resolve/error_codes.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Type parameter defaults can only use parameters that occur before them.
88
Erroneous code example:
99
1010
```compile_fail,E0128
11-
struct Foo<T=U, U=()> {
11+
struct Foo<T = U, U = ()> {
1212
field1: T,
13-
filed2: U,
13+
field2: U,
1414
}
1515
// error: type parameters with a default cannot use forward declared
1616
// identifiers
@@ -20,9 +20,9 @@ Since type parameters are evaluated in-order, you may be able to fix this issue
2020
by doing:
2121
2222
```
23-
struct Foo<U=(), T=U> {
23+
struct Foo<U = (), T = U> {
2424
field1: T,
25-
filed2: U,
25+
field2: U,
2626
}
2727
```
2828
@@ -1705,6 +1705,21 @@ fn const_id<T, const N: T>() -> T { // error: const parameter
17051705
}
17061706
```
17071707
"##,
1708+
1709+
E0735: r##"
1710+
Type parameter defaults cannot use `Self` on structs, enums, or unions.
1711+
1712+
Erroneous code example:
1713+
1714+
```compile_fail,E0735
1715+
struct Foo<X = Box<Self>> {
1716+
field1: Option<X>,
1717+
field2: Option<X>,
1718+
}
1719+
// error: type parameters cannot use `Self` in their defaults.
1720+
```
1721+
"##,
1722+
17081723
;
17091724
// E0153, unused error code
17101725
// E0157, unused error code

src/librustc_resolve/late.rs

+13
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
468468
}
469469
}));
470470

471+
// rust-lang/rust#61631: The type `Self` is essentially
472+
// another type parameter. For ADTs, we consider it
473+
// well-defined only after all of the ADT type parameters have
474+
// been provided. Therefore, we do not allow use of `Self`
475+
// anywhere in ADT type parameter defaults.
476+
//
477+
// (We however cannot ban `Self` for defaults on *all* generic
478+
// lists; e.g. trait generics can usefully refer to `Self`,
479+
// such as in the case of `trait Add<Rhs = Self>`.)
480+
if self.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.)
481+
default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
482+
}
483+
471484
// We also ban access to type parameters for use as the types of const parameters.
472485
let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
473486
const_ty_param_ban_rib.bindings.extend(generics.params.iter()

src/librustc_resolve/lib.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ enum ResolutionError<'a> {
214214
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
215215
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
216216
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
217+
/// Error E0735: type parameters with a default cannot use `Self`
218+
SelfInTyParamDefault,
217219
/// Error E0671: const parameter cannot depend on type parameter.
218220
ConstParamDependentOnTypeParam,
219221
}
@@ -1536,7 +1538,7 @@ impl<'a> Resolver<'a> {
15361538
if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
15371539
// The ident resolves to a type parameter or local variable.
15381540
return Some(LexicalScopeBinding::Res(
1539-
self.validate_res_from_ribs(i, res, record_used, path_span, ribs),
1541+
self.validate_res_from_ribs(i, rib_ident, res, record_used, path_span, ribs),
15401542
));
15411543
}
15421544

@@ -2122,6 +2124,7 @@ impl<'a> Resolver<'a> {
21222124
fn validate_res_from_ribs(
21232125
&mut self,
21242126
rib_index: usize,
2127+
rib_ident: Ident,
21252128
res: Res,
21262129
record_used: bool,
21272130
span: Span,
@@ -2133,7 +2136,12 @@ impl<'a> Resolver<'a> {
21332136
// An invalid forward use of a type parameter from a previous default.
21342137
if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind {
21352138
if record_used {
2136-
self.report_error(span, ResolutionError::ForwardDeclaredTyParam);
2139+
let res_error = if rib_ident.name == kw::SelfUpper {
2140+
ResolutionError::SelfInTyParamDefault
2141+
} else {
2142+
ResolutionError::ForwardDeclaredTyParam
2143+
};
2144+
self.report_error(span, res_error);
21372145
}
21382146
assert_eq!(res, Res::Err);
21392147
return Res::Err;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![crate_type="lib"]
2+
3+
// rust-lang/rust#61631: The use of `Self` in the defaults of generic
4+
// types in a *trait* definition are allowed.
5+
//
6+
// It *must* be accepted; we have used this pattern extensively since
7+
// Rust 1.0 (see e.g. `trait Add<Rhs=Self>`).
8+
trait Tnobound<P = Self> {}
9+
10+
impl Tnobound for () { }
11+
12+
// This variant is accepted at the definition site; but it will be
13+
// rejected at every possible usage site (such as the one immediately
14+
// below). Maybe one day we will attempt to catch it at the definition
15+
// site, but today this is accepted due to compiler implementation
16+
// limitations.
17+
trait Tsized<P: Sized = [Self]> {}
18+
19+
impl Tsized for () {}
20+
//~^ ERROR the size for values of type `[()]` cannot be known at compilation time [E0277]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0277]: the size for values of type `[()]` cannot be known at compilation time
2+
--> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6
3+
|
4+
LL | impl Tsized for () {}
5+
| ^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `std::marker::Sized` is not implemented for `[()]`
8+
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#![crate_type="lib"]
2+
3+
// rust-lang/rust#61631: Uses of `Self` in the defaults of generic
4+
// types for ADT's are not allowed. We justify this because the `Self`
5+
// type could be considered the "final" type parameter, that is only
6+
// well-defined after all of the other type parameters on the ADT have
7+
// been instantiated.
8+
//
9+
// These were previously were ICE'ing at the usage point anyway (see
10+
// `demo_usages` below), so there should not be any backwards
11+
// compatibility concern.
12+
13+
struct Snobound<'a, P = Self> { x: Option<&'a P> }
14+
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
15+
16+
enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
17+
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
18+
19+
union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
20+
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
21+
22+
// Disallowing `Self` in defaults sidesteps need to check the bounds
23+
// on the defaults in cases like these.
24+
25+
struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
26+
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
27+
28+
enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
29+
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
30+
31+
union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
32+
//~^ ERROR type parameters cannot use `Self` in their defaults [E0735]
33+
34+
fn demo_usages() {
35+
// An ICE means you only get the error from the first line of the
36+
// demo; comment each out to observe the other ICEs when trying
37+
// this out on older versions of Rust.
38+
39+
let _ice: Snobound;
40+
let _ice: Enobound;
41+
let _ice: Unobound;
42+
let _ice: Ssized;
43+
let _ice: Esized;
44+
let _ice: Usized;
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0735]: type parameters cannot use `Self` in their defaults
2+
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25
3+
|
4+
LL | struct Snobound<'a, P = Self> { x: Option<&'a P> }
5+
| ^^^^ `Self` in type parameter default
6+
7+
error[E0735]: type parameters cannot use `Self` in their defaults
8+
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23
9+
|
10+
LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
11+
| ^^^^ `Self` in type parameter default
12+
13+
error[E0735]: type parameters cannot use `Self` in their defaults
14+
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24
15+
|
16+
LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
17+
| ^^^^ `Self` in type parameter default
18+
19+
error[E0735]: type parameters cannot use `Self` in their defaults
20+
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31
21+
|
22+
LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
23+
| ^^^^ `Self` in type parameter default
24+
25+
error[E0735]: type parameters cannot use `Self` in their defaults
26+
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29
27+
|
28+
LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
29+
| ^^^^ `Self` in type parameter default
30+
31+
error[E0735]: type parameters cannot use `Self` in their defaults
32+
--> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30
33+
|
34+
LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
35+
| ^^^^ `Self` in type parameter default
36+
37+
error: aborting due to 6 previous errors
38+
39+
For more information about this error, try `rustc --explain E0735`.

0 commit comments

Comments
 (0)