Skip to content

Commit 076c9d7

Browse files
Rollup merge of rust-lang#114662 - fmease:lazy-ty-aliases-unlock-trailing-wcs, r=oli-obk
Unlock trailing where-clauses for lazy type aliases Allows trailing where-clauses on lazy type aliases and forbids[^1] leading ones. Completes rust-lang#89122 (see section *Top-level type aliases*). `@rustbot` label F-lazy_type_alias r? `@oli-obk` [^1]: This is absolutely fine since lazy type aliases are only meant to be stabilized as part of a new edition.
2 parents 94533d9 + 051eb7c commit 076c9d7

9 files changed

+175
-49
lines changed

compiler/rustc_ast_passes/messages.ftl

+6-1
Original file line numberDiff line numberDiff line change
@@ -239,5 +239,10 @@ ast_passes_visibility_not_permitted =
239239
.individual_impl_items = place qualifiers on individual impl items instead
240240
.individual_foreign_items = place qualifiers on individual foreign items instead
241241
242-
ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
242+
ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases
243+
.note = see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
244+
.help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable
245+
246+
ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
243247
.note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
248+
.suggestion = move it to the end of the type declaration

compiler/rustc_ast_passes/src/ast_validation.rs

+55-44
Original file line numberDiff line numberDiff line change
@@ -136,40 +136,42 @@ impl<'a> AstValidator<'a> {
136136
}
137137
}
138138

139-
fn check_gat_where(
139+
fn check_type_alias_where_clause_location(
140140
&mut self,
141-
id: NodeId,
142-
before_predicates: &[WherePredicate],
143-
where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
144-
) {
145-
if !before_predicates.is_empty() {
146-
let mut state = State::new();
147-
if !where_clauses.1.0 {
148-
state.space();
149-
state.word_space("where");
150-
} else {
141+
ty_alias: &TyAlias,
142+
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
143+
let before_predicates =
144+
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0;
145+
146+
if ty_alias.ty.is_none() || before_predicates.is_empty() {
147+
return Ok(());
148+
}
149+
150+
let mut state = State::new();
151+
if !ty_alias.where_clauses.1.0 {
152+
state.space();
153+
state.word_space("where");
154+
} else {
155+
state.word_space(",");
156+
}
157+
let mut first = true;
158+
for p in before_predicates {
159+
if !first {
151160
state.word_space(",");
152161
}
153-
let mut first = true;
154-
for p in before_predicates.iter() {
155-
if !first {
156-
state.word_space(",");
157-
}
158-
first = false;
159-
state.print_where_predicate(p);
160-
}
161-
let suggestion = state.s.eof();
162-
self.lint_buffer.buffer_lint_with_diagnostic(
163-
DEPRECATED_WHERE_CLAUSE_LOCATION,
164-
id,
165-
where_clauses.0.1,
166-
fluent::ast_passes_deprecated_where_clause_location,
167-
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
168-
where_clauses.1.1.shrink_to_hi(),
169-
suggestion,
170-
),
171-
);
162+
first = false;
163+
state.print_where_predicate(p);
172164
}
165+
166+
let span = ty_alias.where_clauses.0.1;
167+
Err(errors::WhereClauseBeforeTypeAlias {
168+
span,
169+
sugg: errors::WhereClauseBeforeTypeAliasSugg {
170+
left: span,
171+
snippet: state.s.eof(),
172+
right: ty_alias.where_clauses.1.1.shrink_to_hi(),
173+
},
174+
})
173175
}
174176

175177
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
@@ -1009,7 +1011,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10091011
replace_span: self.ending_semi_or_hi(item.span),
10101012
});
10111013
}
1012-
ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
1014+
ItemKind::TyAlias(
1015+
ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
1016+
) => {
10131017
self.check_defaultness(item.span, *defaultness);
10141018
if ty.is_none() {
10151019
self.session.emit_err(errors::TyAliasWithoutBody {
@@ -1018,9 +1022,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10181022
});
10191023
}
10201024
self.check_type_no_bounds(bounds, "this context");
1021-
if where_clauses.1.0 {
1022-
self.err_handler()
1023-
.emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 });
1025+
1026+
if self.session.features_untracked().lazy_type_alias {
1027+
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
1028+
self.err_handler().emit_err(err);
1029+
}
1030+
} else if where_clauses.1.0 {
1031+
self.err_handler().emit_err(errors::WhereClauseAfterTypeAlias {
1032+
span: where_clauses.1.1,
1033+
help: self.session.is_nightly_build().then_some(()),
1034+
});
10241035
}
10251036
}
10261037
_ => {}
@@ -1313,18 +1324,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13131324
}
13141325
}
13151326

1316-
if let AssocItemKind::Type(box TyAlias {
1317-
generics,
1318-
where_clauses,
1319-
where_predicates_split,
1320-
ty: Some(_),
1321-
..
1322-
}) = &item.kind
1327+
if let AssocItemKind::Type(ty_alias) = &item.kind
1328+
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
13231329
{
1324-
self.check_gat_where(
1330+
self.lint_buffer.buffer_lint_with_diagnostic(
1331+
DEPRECATED_WHERE_CLAUSE_LOCATION,
13251332
item.id,
1326-
generics.where_clause.predicates.split_at(*where_predicates_split).0,
1327-
*where_clauses,
1333+
err.span,
1334+
fluent::ast_passes_deprecated_where_clause_location,
1335+
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
1336+
err.sugg.right,
1337+
err.sugg.snippet,
1338+
),
13281339
);
13291340
}
13301341

compiler/rustc_ast_passes/src/errors.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -496,11 +496,37 @@ pub struct FieldlessUnion {
496496
}
497497

498498
#[derive(Diagnostic)]
499-
#[diag(ast_passes_where_after_type_alias)]
499+
#[diag(ast_passes_where_clause_after_type_alias)]
500500
#[note]
501-
pub struct WhereAfterTypeAlias {
501+
pub struct WhereClauseAfterTypeAlias {
502502
#[primary_span]
503503
pub span: Span,
504+
#[help]
505+
pub help: Option<()>,
506+
}
507+
508+
#[derive(Diagnostic)]
509+
#[diag(ast_passes_where_clause_before_type_alias)]
510+
#[note]
511+
pub struct WhereClauseBeforeTypeAlias {
512+
#[primary_span]
513+
pub span: Span,
514+
#[subdiagnostic]
515+
pub sugg: WhereClauseBeforeTypeAliasSugg,
516+
}
517+
518+
#[derive(Subdiagnostic)]
519+
#[multipart_suggestion(
520+
ast_passes_suggestion,
521+
applicability = "machine-applicable",
522+
style = "verbose"
523+
)]
524+
pub struct WhereClauseBeforeTypeAliasSugg {
525+
#[suggestion_part(code = "")]
526+
pub left: Span,
527+
pub snippet: String,
528+
#[suggestion_part(code = "{snippet}")]
529+
pub right: Span,
504530
}
505531

506532
#[derive(Diagnostic)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
3+
#![feature(lazy_type_alias)]
4+
#![allow(incomplete_features)]
5+
6+
// Check that we *reject* leading where-clauses on lazy type aliases.
7+
8+
type Alias<T>
9+
10+
= T where String: From<T>;
11+
//~^^^ ERROR where clauses are not allowed before the type for type aliases
12+
13+
fn main() {
14+
let _: Alias<&str>;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// run-rustfix
2+
3+
#![feature(lazy_type_alias)]
4+
#![allow(incomplete_features)]
5+
6+
// Check that we *reject* leading where-clauses on lazy type aliases.
7+
8+
type Alias<T>
9+
where
10+
String: From<T>,
11+
= T;
12+
//~^^^ ERROR where clauses are not allowed before the type for type aliases
13+
14+
fn main() {
15+
let _: Alias<&str>;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: where clauses are not allowed before the type for type aliases
2+
--> $DIR/leading-where-clause.rs:9:1
3+
|
4+
LL | / where
5+
LL | | String: From<T>,
6+
| |____________________^
7+
|
8+
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
9+
help: move it to the end of the type declaration
10+
|
11+
LL +
12+
LL ~ = T where String: From<T>;
13+
|
14+
15+
error: aborting due to previous error
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(lazy_type_alias)]
2+
#![allow(incomplete_features)]
3+
4+
// Check that we allow & respect trailing where-clauses on lazy type aliases.
5+
6+
type Alias<T> = T
7+
where
8+
String: From<T>;
9+
10+
fn main() {
11+
let _: Alias<&str>;
12+
let _: Alias<()>; //~ ERROR the trait bound `String: From<()>` is not satisfied
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: the trait bound `String: From<()>` is not satisfied
2+
--> $DIR/trailing-where-clause.rs:12:12
3+
|
4+
LL | let _: Alias<()>;
5+
| ^^^^^^^^^ the trait `From<()>` is not implemented for `String`
6+
|
7+
= help: the following other types implement trait `From<T>`:
8+
<String as From<char>>
9+
<String as From<Box<str>>>
10+
<String as From<Cow<'a, str>>>
11+
<String as From<&str>>
12+
<String as From<&mut str>>
13+
<String as From<&String>>
14+
note: required by a bound on the type alias `Alias`
15+
--> $DIR/trailing-where-clause.rs:8:13
16+
|
17+
LL | String: From<T>;
18+
| ^^^^^^^ required by this bound
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.

tests/ui/where-clauses/where-clause-placement-type-alias.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ error: where clauses are not allowed after the type for type aliases
44
LL | type Bar = () where u32: Copy;
55
| ^^^^^^^^^^^^^^^
66
|
7-
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
7+
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
8+
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
89

910
error: where clauses are not allowed after the type for type aliases
1011
--> $DIR/where-clause-placement-type-alias.rs:8:15
1112
|
1213
LL | type Baz = () where;
1314
| ^^^^^
1415
|
15-
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
16+
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
17+
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
1618

1719
error: aborting due to 2 previous errors
1820

0 commit comments

Comments
 (0)