Unlock trailing where-clauses for lazy type aliases
This commit is contained in:
parent
617821ab32
commit
051eb7ca7c
9 changed files with 175 additions and 49 deletions
|
@ -239,5 +239,10 @@ ast_passes_visibility_not_permitted =
|
||||||
.individual_impl_items = place qualifiers on individual impl items instead
|
.individual_impl_items = place qualifiers on individual impl items instead
|
||||||
.individual_foreign_items = place qualifiers on individual foreign items instead
|
.individual_foreign_items = place qualifiers on individual foreign items instead
|
||||||
|
|
||||||
ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
|
ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases
|
||||||
|
.note = see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||||
|
.help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
|
||||||
.note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
.note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||||
|
.suggestion = move it to the end of the type declaration
|
||||||
|
|
|
@ -136,40 +136,42 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_gat_where(
|
fn check_type_alias_where_clause_location(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: NodeId,
|
ty_alias: &TyAlias,
|
||||||
before_predicates: &[WherePredicate],
|
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
|
||||||
where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
|
let before_predicates =
|
||||||
) {
|
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0;
|
||||||
if !before_predicates.is_empty() {
|
|
||||||
|
if ty_alias.ty.is_none() || before_predicates.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
if !where_clauses.1.0 {
|
if !ty_alias.where_clauses.1.0 {
|
||||||
state.space();
|
state.space();
|
||||||
state.word_space("where");
|
state.word_space("where");
|
||||||
} else {
|
} else {
|
||||||
state.word_space(",");
|
state.word_space(",");
|
||||||
}
|
}
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for p in before_predicates.iter() {
|
for p in before_predicates {
|
||||||
if !first {
|
if !first {
|
||||||
state.word_space(",");
|
state.word_space(",");
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
state.print_where_predicate(p);
|
state.print_where_predicate(p);
|
||||||
}
|
}
|
||||||
let suggestion = state.s.eof();
|
|
||||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
let span = ty_alias.where_clauses.0.1;
|
||||||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
Err(errors::WhereClauseBeforeTypeAlias {
|
||||||
id,
|
span,
|
||||||
where_clauses.0.1,
|
sugg: errors::WhereClauseBeforeTypeAliasSugg {
|
||||||
fluent::ast_passes_deprecated_where_clause_location,
|
left: span,
|
||||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
|
snippet: state.s.eof(),
|
||||||
where_clauses.1.1.shrink_to_hi(),
|
right: ty_alias.where_clauses.1.1.shrink_to_hi(),
|
||||||
suggestion,
|
},
|
||||||
),
|
})
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
|
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> {
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
|
ItemKind::TyAlias(
|
||||||
|
ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
|
||||||
|
) => {
|
||||||
self.check_defaultness(item.span, *defaultness);
|
self.check_defaultness(item.span, *defaultness);
|
||||||
if ty.is_none() {
|
if ty.is_none() {
|
||||||
self.session.emit_err(errors::TyAliasWithoutBody {
|
self.session.emit_err(errors::TyAliasWithoutBody {
|
||||||
|
@ -1018,9 +1022,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.check_type_no_bounds(bounds, "this context");
|
self.check_type_no_bounds(bounds, "this context");
|
||||||
if where_clauses.1.0 {
|
|
||||||
self.err_handler()
|
if self.session.features_untracked().lazy_type_alias {
|
||||||
.emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 });
|
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
|
||||||
|
self.err_handler().emit_err(err);
|
||||||
|
}
|
||||||
|
} else if where_clauses.1.0 {
|
||||||
|
self.err_handler().emit_err(errors::WhereClauseAfterTypeAlias {
|
||||||
|
span: where_clauses.1.1,
|
||||||
|
help: self.session.is_nightly_build().then_some(()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1313,18 +1324,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let AssocItemKind::Type(box TyAlias {
|
if let AssocItemKind::Type(ty_alias) = &item.kind
|
||||||
generics,
|
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
|
||||||
where_clauses,
|
|
||||||
where_predicates_split,
|
|
||||||
ty: Some(_),
|
|
||||||
..
|
|
||||||
}) = &item.kind
|
|
||||||
{
|
{
|
||||||
self.check_gat_where(
|
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||||
|
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||||
item.id,
|
item.id,
|
||||||
generics.where_clause.predicates.split_at(*where_predicates_split).0,
|
err.span,
|
||||||
*where_clauses,
|
fluent::ast_passes_deprecated_where_clause_location,
|
||||||
|
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
|
||||||
|
err.sugg.right,
|
||||||
|
err.sugg.snippet,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,11 +496,37 @@ pub struct FieldlessUnion {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_where_after_type_alias)]
|
#[diag(ast_passes_where_clause_after_type_alias)]
|
||||||
#[note]
|
#[note]
|
||||||
pub struct WhereAfterTypeAlias {
|
pub struct WhereClauseAfterTypeAlias {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
#[help]
|
||||||
|
pub help: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_where_clause_before_type_alias)]
|
||||||
|
#[note]
|
||||||
|
pub struct WhereClauseBeforeTypeAlias {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub sugg: WhereClauseBeforeTypeAliasSugg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(
|
||||||
|
ast_passes_suggestion,
|
||||||
|
applicability = "machine-applicable",
|
||||||
|
style = "verbose"
|
||||||
|
)]
|
||||||
|
pub struct WhereClauseBeforeTypeAliasSugg {
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub left: Span,
|
||||||
|
pub snippet: String,
|
||||||
|
#[suggestion_part(code = "{snippet}")]
|
||||||
|
pub right: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
15
tests/ui/lazy-type-alias/leading-where-clause.fixed
Normal file
15
tests/ui/lazy-type-alias/leading-where-clause.fixed
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![feature(lazy_type_alias)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// Check that we *reject* leading where-clauses on lazy type aliases.
|
||||||
|
|
||||||
|
type Alias<T>
|
||||||
|
|
||||||
|
= T where String: From<T>;
|
||||||
|
//~^^^ ERROR where clauses are not allowed before the type for type aliases
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: Alias<&str>;
|
||||||
|
}
|
16
tests/ui/lazy-type-alias/leading-where-clause.rs
Normal file
16
tests/ui/lazy-type-alias/leading-where-clause.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![feature(lazy_type_alias)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// Check that we *reject* leading where-clauses on lazy type aliases.
|
||||||
|
|
||||||
|
type Alias<T>
|
||||||
|
where
|
||||||
|
String: From<T>,
|
||||||
|
= T;
|
||||||
|
//~^^^ ERROR where clauses are not allowed before the type for type aliases
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: Alias<&str>;
|
||||||
|
}
|
16
tests/ui/lazy-type-alias/leading-where-clause.stderr
Normal file
16
tests/ui/lazy-type-alias/leading-where-clause.stderr
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
error: where clauses are not allowed before the type for type aliases
|
||||||
|
--> $DIR/leading-where-clause.rs:9:1
|
||||||
|
|
|
||||||
|
LL | / where
|
||||||
|
LL | | String: From<T>,
|
||||||
|
| |____________________^
|
||||||
|
|
|
||||||
|
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||||
|
help: move it to the end of the type declaration
|
||||||
|
|
|
||||||
|
LL +
|
||||||
|
LL ~ = T where String: From<T>;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
13
tests/ui/lazy-type-alias/trailing-where-clause.rs
Normal file
13
tests/ui/lazy-type-alias/trailing-where-clause.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(lazy_type_alias)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// Check that we allow & respect trailing where-clauses on lazy type aliases.
|
||||||
|
|
||||||
|
type Alias<T> = T
|
||||||
|
where
|
||||||
|
String: From<T>;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: Alias<&str>;
|
||||||
|
let _: Alias<()>; //~ ERROR the trait bound `String: From<()>` is not satisfied
|
||||||
|
}
|
22
tests/ui/lazy-type-alias/trailing-where-clause.stderr
Normal file
22
tests/ui/lazy-type-alias/trailing-where-clause.stderr
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
error[E0277]: the trait bound `String: From<()>` is not satisfied
|
||||||
|
--> $DIR/trailing-where-clause.rs:12:12
|
||||||
|
|
|
||||||
|
LL | let _: Alias<()>;
|
||||||
|
| ^^^^^^^^^ the trait `From<()>` is not implemented for `String`
|
||||||
|
|
|
||||||
|
= help: the following other types implement trait `From<T>`:
|
||||||
|
<String as From<char>>
|
||||||
|
<String as From<Box<str>>>
|
||||||
|
<String as From<Cow<'a, str>>>
|
||||||
|
<String as From<&str>>
|
||||||
|
<String as From<&mut str>>
|
||||||
|
<String as From<&String>>
|
||||||
|
note: required by a bound on the type alias `Alias`
|
||||||
|
--> $DIR/trailing-where-clause.rs:8:13
|
||||||
|
|
|
||||||
|
LL | String: From<T>;
|
||||||
|
| ^^^^^^^ required by this bound
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -4,7 +4,8 @@ error: where clauses are not allowed after the type for type aliases
|
||||||
LL | type Bar = () where u32: Copy;
|
LL | type Bar = () where u32: Copy;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||||
|
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: where clauses are not allowed after the type for type aliases
|
error: where clauses are not allowed after the type for type aliases
|
||||||
--> $DIR/where-clause-placement-type-alias.rs:8:15
|
--> $DIR/where-clause-placement-type-alias.rs:8:15
|
||||||
|
@ -12,7 +13,8 @@ error: where clauses are not allowed after the type for type aliases
|
||||||
LL | type Baz = () where;
|
LL | type Baz = () where;
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
|
||||||
|
= help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue