Rollup merge of #121326 - fmease:detect-empty-leading-where-clauses-on-ty-aliases, r=compiler-errors
Detect empty leading where clauses on type aliases 1. commit: refactor the AST of type alias where clauses * I could no longer bear the look of `.0.1` and `.1.0` * Arguably moving `split` out of `TyAlias` into a substruct might not make that much sense from a semantic standpoint since it reprs an index into `TyAlias.predicates` but it's alright and it cleans up the usage sites of `TyAlias` 2. commit: fix an oversight: An empty leading where clause is still a leading where clause * semantically reject empty leading where clauses on lazy type aliases * e.g., on `#![feature(lazy_type_alias)] type X where = ();` * make empty leading where clauses on assoc types trigger lint `deprecated_where_clause_location` * e.g., `impl Trait for () { type X where = (); }`
This commit is contained in:
commit
dd4ecd1cf4
@ -403,9 +403,10 @@ fn default() -> Generics {
|
|||||||
/// A where-clause in a definition.
|
/// A where-clause in a definition.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct WhereClause {
|
pub struct WhereClause {
|
||||||
/// `true` if we ate a `where` token: this can happen
|
/// `true` if we ate a `where` token.
|
||||||
/// if we parsed no predicates (e.g. `struct Foo where {}`).
|
///
|
||||||
/// This allows us to pretty-print accurately.
|
/// This can happen if we parsed no predicates, e.g., `struct Foo where {}`.
|
||||||
|
/// This allows us to pretty-print accurately and provide correct suggestion diagnostics.
|
||||||
pub has_where_token: bool,
|
pub has_where_token: bool,
|
||||||
pub predicates: ThinVec<WherePredicate>,
|
pub predicates: ThinVec<WherePredicate>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -3007,18 +3008,29 @@ pub struct Trait {
|
|||||||
///
|
///
|
||||||
/// If there is no where clause, then this is `false` with `DUMMY_SP`.
|
/// If there is no where clause, then this is `false` with `DUMMY_SP`.
|
||||||
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
|
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
|
||||||
pub struct TyAliasWhereClause(pub bool, pub Span);
|
pub struct TyAliasWhereClause {
|
||||||
|
pub has_where_token: bool,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The span information for the two where clauses on a `TyAlias`.
|
||||||
|
#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
|
||||||
|
pub struct TyAliasWhereClauses {
|
||||||
|
/// Before the equals sign.
|
||||||
|
pub before: TyAliasWhereClause,
|
||||||
|
/// After the equals sign.
|
||||||
|
pub after: TyAliasWhereClause,
|
||||||
|
/// The index in `TyAlias.generics.where_clause.predicates` that would split
|
||||||
|
/// into predicates from the where clause before the equals sign and the ones
|
||||||
|
/// from the where clause after the equals sign.
|
||||||
|
pub split: usize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct TyAlias {
|
pub struct TyAlias {
|
||||||
pub defaultness: Defaultness,
|
pub defaultness: Defaultness,
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
/// The span information for the two where clauses (before equals, after equals)
|
pub where_clauses: TyAliasWhereClauses,
|
||||||
pub where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
|
|
||||||
/// The index in `generics.where_clause.predicates` that would split into
|
|
||||||
/// predicates from the where clause before the equals and the predicates
|
|
||||||
/// from the where clause after the equals
|
|
||||||
pub where_predicates_split: usize,
|
|
||||||
pub bounds: GenericBounds,
|
pub bounds: GenericBounds,
|
||||||
pub ty: Option<P<Ty>>,
|
pub ty: Option<P<Ty>>,
|
||||||
}
|
}
|
||||||
|
@ -1079,8 +1079,8 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
|||||||
}) => {
|
}) => {
|
||||||
visit_defaultness(defaultness, vis);
|
visit_defaultness(defaultness, vis);
|
||||||
vis.visit_generics(generics);
|
vis.visit_generics(generics);
|
||||||
vis.visit_span(&mut where_clauses.0.1);
|
vis.visit_span(&mut where_clauses.before.span);
|
||||||
vis.visit_span(&mut where_clauses.1.1);
|
vis.visit_span(&mut where_clauses.after.span);
|
||||||
visit_bounds(bounds, vis);
|
visit_bounds(bounds, vis);
|
||||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||||
}
|
}
|
||||||
@ -1163,8 +1163,8 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
|
|||||||
}) => {
|
}) => {
|
||||||
visit_defaultness(defaultness, visitor);
|
visit_defaultness(defaultness, visitor);
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
visitor.visit_span(&mut where_clauses.0.1);
|
visitor.visit_span(&mut where_clauses.before.span);
|
||||||
visitor.visit_span(&mut where_clauses.1.1);
|
visitor.visit_span(&mut where_clauses.after.span);
|
||||||
visit_bounds(bounds, visitor);
|
visit_bounds(bounds, visitor);
|
||||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||||
}
|
}
|
||||||
@ -1257,8 +1257,8 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
|
|||||||
}) => {
|
}) => {
|
||||||
visit_defaultness(defaultness, visitor);
|
visit_defaultness(defaultness, visitor);
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
visitor.visit_span(&mut where_clauses.0.1);
|
visitor.visit_span(&mut where_clauses.before.span);
|
||||||
visitor.visit_span(&mut where_clauses.1.1);
|
visitor.visit_span(&mut where_clauses.after.span);
|
||||||
visit_bounds(bounds, visitor);
|
visit_bounds(bounds, visitor);
|
||||||
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
visit_opt(ty, |ty| visitor.visit_ty(ty));
|
||||||
}
|
}
|
||||||
|
@ -33,19 +33,20 @@ pub(super) struct ItemLowerer<'a, 'hir> {
|
|||||||
/// clause if it exists.
|
/// clause if it exists.
|
||||||
fn add_ty_alias_where_clause(
|
fn add_ty_alias_where_clause(
|
||||||
generics: &mut ast::Generics,
|
generics: &mut ast::Generics,
|
||||||
mut where_clauses: (TyAliasWhereClause, TyAliasWhereClause),
|
mut where_clauses: TyAliasWhereClauses,
|
||||||
prefer_first: bool,
|
prefer_first: bool,
|
||||||
) {
|
) {
|
||||||
if !prefer_first {
|
if !prefer_first {
|
||||||
where_clauses = (where_clauses.1, where_clauses.0);
|
(where_clauses.before, where_clauses.after) = (where_clauses.after, where_clauses.before);
|
||||||
}
|
|
||||||
if where_clauses.0.0 || !where_clauses.1.0 {
|
|
||||||
generics.where_clause.has_where_token = where_clauses.0.0;
|
|
||||||
generics.where_clause.span = where_clauses.0.1;
|
|
||||||
} else {
|
|
||||||
generics.where_clause.has_where_token = where_clauses.1.0;
|
|
||||||
generics.where_clause.span = where_clauses.1.1;
|
|
||||||
}
|
}
|
||||||
|
let where_clause =
|
||||||
|
if where_clauses.before.has_where_token || !where_clauses.after.has_where_token {
|
||||||
|
where_clauses.before
|
||||||
|
} else {
|
||||||
|
where_clauses.after
|
||||||
|
};
|
||||||
|
generics.where_clause.has_where_token = where_clause.has_where_token;
|
||||||
|
generics.where_clause.span = where_clause.span;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
|
@ -280,4 +280,5 @@ ast_passes_where_clause_after_type_alias = where clauses are not allowed after t
|
|||||||
|
|
||||||
ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
|
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
|
.remove_suggestion = remove this `where`
|
||||||
|
.move_suggestion = move it to the end of the type declaration
|
||||||
|
@ -138,38 +138,42 @@ fn check_type_alias_where_clause_location(
|
|||||||
&mut self,
|
&mut self,
|
||||||
ty_alias: &TyAlias,
|
ty_alias: &TyAlias,
|
||||||
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
|
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
|
||||||
let before_predicates =
|
if ty_alias.ty.is_none() || !ty_alias.where_clauses.before.has_where_token {
|
||||||
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0;
|
|
||||||
|
|
||||||
if ty_alias.ty.is_none() || before_predicates.is_empty() {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut state = State::new();
|
let (before_predicates, after_predicates) =
|
||||||
if !ty_alias.where_clauses.1.0 {
|
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_clauses.split);
|
||||||
state.space();
|
let span = ty_alias.where_clauses.before.span;
|
||||||
state.word_space("where");
|
|
||||||
} else {
|
|
||||||
state.word_space(",");
|
|
||||||
}
|
|
||||||
let mut first = true;
|
|
||||||
for p in before_predicates {
|
|
||||||
if !first {
|
|
||||||
state.word_space(",");
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
state.print_where_predicate(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
let span = ty_alias.where_clauses.0.1;
|
let sugg = if !before_predicates.is_empty() || !ty_alias.where_clauses.after.has_where_token
|
||||||
Err(errors::WhereClauseBeforeTypeAlias {
|
{
|
||||||
span,
|
let mut state = State::new();
|
||||||
sugg: errors::WhereClauseBeforeTypeAliasSugg {
|
|
||||||
|
if !ty_alias.where_clauses.after.has_where_token {
|
||||||
|
state.space();
|
||||||
|
state.word_space("where");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut first = after_predicates.is_empty();
|
||||||
|
for p in before_predicates {
|
||||||
|
if !first {
|
||||||
|
state.word_space(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
state.print_where_predicate(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
errors::WhereClauseBeforeTypeAliasSugg::Move {
|
||||||
left: span,
|
left: span,
|
||||||
snippet: state.s.eof(),
|
snippet: state.s.eof(),
|
||||||
right: ty_alias.where_clauses.1.1.shrink_to_hi(),
|
right: ty_alias.where_clauses.after.span.shrink_to_hi(),
|
||||||
},
|
}
|
||||||
})
|
} else {
|
||||||
|
errors::WhereClauseBeforeTypeAliasSugg::Remove { span }
|
||||||
|
};
|
||||||
|
|
||||||
|
Err(errors::WhereClauseBeforeTypeAlias { span, sugg })
|
||||||
}
|
}
|
||||||
|
|
||||||
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)) {
|
||||||
@ -457,8 +461,7 @@ fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
|
|||||||
fn check_foreign_ty_genericless(
|
fn check_foreign_ty_genericless(
|
||||||
&self,
|
&self,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
before_where_clause: &TyAliasWhereClause,
|
where_clauses: &TyAliasWhereClauses,
|
||||||
after_where_clause: &TyAliasWhereClause,
|
|
||||||
) {
|
) {
|
||||||
let cannot_have = |span, descr, remove_descr| {
|
let cannot_have = |span, descr, remove_descr| {
|
||||||
self.dcx().emit_err(errors::ExternTypesCannotHave {
|
self.dcx().emit_err(errors::ExternTypesCannotHave {
|
||||||
@ -473,14 +476,14 @@ fn check_foreign_ty_genericless(
|
|||||||
cannot_have(generics.span, "generic parameters", "generic parameters");
|
cannot_have(generics.span, "generic parameters", "generic parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
let check_where_clause = |where_clause: &TyAliasWhereClause| {
|
let check_where_clause = |where_clause: TyAliasWhereClause| {
|
||||||
if let TyAliasWhereClause(true, where_clause_span) = where_clause {
|
if where_clause.has_where_token {
|
||||||
cannot_have(*where_clause_span, "`where` clauses", "`where` clause");
|
cannot_have(where_clause.span, "`where` clauses", "`where` clause");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
check_where_clause(before_where_clause);
|
check_where_clause(where_clauses.before);
|
||||||
check_where_clause(after_where_clause);
|
check_where_clause(where_clauses.after);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
|
fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
|
||||||
@ -1122,9 +1125,9 @@ fn visit_item(&mut self, item: &'a Item) {
|
|||||||
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
|
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
|
||||||
self.dcx().emit_err(err);
|
self.dcx().emit_err(err);
|
||||||
}
|
}
|
||||||
} else if where_clauses.1.0 {
|
} else if where_clauses.after.has_where_token {
|
||||||
self.dcx().emit_err(errors::WhereClauseAfterTypeAlias {
|
self.dcx().emit_err(errors::WhereClauseAfterTypeAlias {
|
||||||
span: where_clauses.1.1,
|
span: where_clauses.after.span,
|
||||||
help: self.session.is_nightly_build().then_some(()),
|
help: self.session.is_nightly_build().then_some(()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1154,7 +1157,7 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
|||||||
self.check_defaultness(fi.span, *defaultness);
|
self.check_defaultness(fi.span, *defaultness);
|
||||||
self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
|
self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
|
||||||
self.check_type_no_bounds(bounds, "`extern` blocks");
|
self.check_type_no_bounds(bounds, "`extern` blocks");
|
||||||
self.check_foreign_ty_genericless(generics, &where_clauses.0, &where_clauses.1);
|
self.check_foreign_ty_genericless(generics, where_clauses);
|
||||||
self.check_foreign_item_ascii_only(fi.ident);
|
self.check_foreign_item_ascii_only(fi.ident);
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(_, _, body) => {
|
ForeignItemKind::Static(_, _, body) => {
|
||||||
@ -1477,15 +1480,18 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|
|||||||
if let AssocItemKind::Type(ty_alias) = &item.kind
|
if let AssocItemKind::Type(ty_alias) = &item.kind
|
||||||
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
|
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
|
||||||
{
|
{
|
||||||
|
let sugg = match err.sugg {
|
||||||
|
errors::WhereClauseBeforeTypeAliasSugg::Remove { .. } => None,
|
||||||
|
errors::WhereClauseBeforeTypeAliasSugg::Move { snippet, right, .. } => {
|
||||||
|
Some((right, snippet))
|
||||||
|
}
|
||||||
|
};
|
||||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||||
item.id,
|
item.id,
|
||||||
err.span,
|
err.span,
|
||||||
fluent::ast_passes_deprecated_where_clause_location,
|
fluent::ast_passes_deprecated_where_clause_location,
|
||||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
|
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg),
|
||||||
err.sugg.right,
|
|
||||||
err.sugg.snippet,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,17 +515,25 @@ pub struct WhereClauseBeforeTypeAlias {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[multipart_suggestion(
|
|
||||||
ast_passes_suggestion,
|
pub enum WhereClauseBeforeTypeAliasSugg {
|
||||||
applicability = "machine-applicable",
|
#[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")]
|
||||||
style = "verbose"
|
Remove {
|
||||||
)]
|
#[primary_span]
|
||||||
pub struct WhereClauseBeforeTypeAliasSugg {
|
span: Span,
|
||||||
#[suggestion_part(code = "")]
|
},
|
||||||
pub left: Span,
|
#[multipart_suggestion(
|
||||||
pub snippet: String,
|
ast_passes_move_suggestion,
|
||||||
#[suggestion_part(code = "{snippet}")]
|
applicability = "machine-applicable",
|
||||||
pub right: Span,
|
style = "verbose"
|
||||||
|
)]
|
||||||
|
Move {
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
left: Span,
|
||||||
|
snippet: String,
|
||||||
|
#[suggestion_part(code = "{snippet}")]
|
||||||
|
right: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -43,7 +43,6 @@ fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
|||||||
defaultness,
|
defaultness,
|
||||||
generics,
|
generics,
|
||||||
where_clauses,
|
where_clauses,
|
||||||
where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty,
|
ty,
|
||||||
}) => {
|
}) => {
|
||||||
@ -51,7 +50,6 @@ fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
|
|||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
*where_clauses,
|
*where_clauses,
|
||||||
*where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty.as_deref(),
|
ty.as_deref(),
|
||||||
vis,
|
vis,
|
||||||
@ -108,15 +106,14 @@ fn print_associated_type(
|
|||||||
&mut self,
|
&mut self,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
generics: &ast::Generics,
|
generics: &ast::Generics,
|
||||||
where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
|
where_clauses: ast::TyAliasWhereClauses,
|
||||||
where_predicates_split: usize,
|
|
||||||
bounds: &ast::GenericBounds,
|
bounds: &ast::GenericBounds,
|
||||||
ty: Option<&ast::Ty>,
|
ty: Option<&ast::Ty>,
|
||||||
vis: &ast::Visibility,
|
vis: &ast::Visibility,
|
||||||
defaultness: ast::Defaultness,
|
defaultness: ast::Defaultness,
|
||||||
) {
|
) {
|
||||||
let (before_predicates, after_predicates) =
|
let (before_predicates, after_predicates) =
|
||||||
generics.where_clause.predicates.split_at(where_predicates_split);
|
generics.where_clause.predicates.split_at(where_clauses.split);
|
||||||
self.head("");
|
self.head("");
|
||||||
self.print_visibility(vis);
|
self.print_visibility(vis);
|
||||||
self.print_defaultness(defaultness);
|
self.print_defaultness(defaultness);
|
||||||
@ -127,13 +124,13 @@ fn print_associated_type(
|
|||||||
self.word_nbsp(":");
|
self.word_nbsp(":");
|
||||||
self.print_type_bounds(bounds);
|
self.print_type_bounds(bounds);
|
||||||
}
|
}
|
||||||
self.print_where_clause_parts(where_clauses.0.0, before_predicates);
|
self.print_where_clause_parts(where_clauses.before.has_where_token, before_predicates);
|
||||||
if let Some(ty) = ty {
|
if let Some(ty) = ty {
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("=");
|
self.word_space("=");
|
||||||
self.print_type(ty);
|
self.print_type(ty);
|
||||||
}
|
}
|
||||||
self.print_where_clause_parts(where_clauses.1.0, after_predicates);
|
self.print_where_clause_parts(where_clauses.after.has_where_token, after_predicates);
|
||||||
self.word(";");
|
self.word(";");
|
||||||
self.end(); // end inner head-block
|
self.end(); // end inner head-block
|
||||||
self.end(); // end outer head-block
|
self.end(); // end outer head-block
|
||||||
@ -249,7 +246,6 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
|||||||
defaultness,
|
defaultness,
|
||||||
generics,
|
generics,
|
||||||
where_clauses,
|
where_clauses,
|
||||||
where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty,
|
ty,
|
||||||
}) => {
|
}) => {
|
||||||
@ -257,7 +253,6 @@ pub(crate) fn print_item(&mut self, item: &ast::Item) {
|
|||||||
item.ident,
|
item.ident,
|
||||||
generics,
|
generics,
|
||||||
*where_clauses,
|
*where_clauses,
|
||||||
*where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty.as_deref(),
|
ty.as_deref(),
|
||||||
&item.vis,
|
&item.vis,
|
||||||
@ -536,7 +531,6 @@ fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
|||||||
defaultness,
|
defaultness,
|
||||||
generics,
|
generics,
|
||||||
where_clauses,
|
where_clauses,
|
||||||
where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty,
|
ty,
|
||||||
}) => {
|
}) => {
|
||||||
@ -544,7 +538,6 @@ fn print_assoc_item(&mut self, item: &ast::AssocItem) {
|
|||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
*where_clauses,
|
*where_clauses,
|
||||||
*where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty.as_deref(),
|
ty.as_deref(),
|
||||||
vis,
|
vis,
|
||||||
|
@ -601,11 +601,7 @@ fn create_derived_impl(
|
|||||||
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
|
kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
|
||||||
defaultness: ast::Defaultness::Final,
|
defaultness: ast::Defaultness::Final,
|
||||||
generics: Generics::default(),
|
generics: Generics::default(),
|
||||||
where_clauses: (
|
where_clauses: ast::TyAliasWhereClauses::default(),
|
||||||
ast::TyAliasWhereClause::default(),
|
|
||||||
ast::TyAliasWhereClause::default(),
|
|
||||||
),
|
|
||||||
where_predicates_split: 0,
|
|
||||||
bounds: Vec::new(),
|
bounds: Vec::new(),
|
||||||
ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
|
ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
|
||||||
})),
|
})),
|
||||||
|
@ -428,15 +428,22 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
|
|||||||
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => {
|
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg) => {
|
||||||
diag.multipart_suggestion(
|
let left_sp = diag.span.primary_span().unwrap();
|
||||||
"move it to the end of the type declaration",
|
match sugg {
|
||||||
vec![(diag.span.primary_span().unwrap(), "".to_string()), (new_span, suggestion)],
|
Some((right_sp, sugg)) => diag.multipart_suggestion(
|
||||||
Applicability::MachineApplicable,
|
"move it to the end of the type declaration",
|
||||||
);
|
vec![(left_sp, String::new()), (right_sp, sugg)],
|
||||||
diag.note(
|
Applicability::MachineApplicable,
|
||||||
"see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
|
),
|
||||||
);
|
None => diag.span_suggestion(
|
||||||
|
left_sp,
|
||||||
|
"remove this `where`",
|
||||||
|
"",
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
diag.note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information");
|
||||||
}
|
}
|
||||||
BuiltinLintDiagnostics::SingleUseLifetime {
|
BuiltinLintDiagnostics::SingleUseLifetime {
|
||||||
param_span,
|
param_span,
|
||||||
|
@ -597,7 +597,7 @@ pub enum BuiltinLintDiagnostics {
|
|||||||
UnicodeTextFlow(Span, String),
|
UnicodeTextFlow(Span, String),
|
||||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||||
DeprecatedWhereclauseLocation(Span, String),
|
DeprecatedWhereclauseLocation(Option<(Span, String)>),
|
||||||
SingleUseLifetime {
|
SingleUseLifetime {
|
||||||
/// Span of the parameter which declares this lifetime.
|
/// Span of the parameter which declares this lifetime.
|
||||||
param_span: Span,
|
param_span: Span,
|
||||||
|
@ -971,11 +971,17 @@ fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo
|
|||||||
|
|
||||||
let after_where_clause = self.parse_where_clause()?;
|
let after_where_clause = self.parse_where_clause()?;
|
||||||
|
|
||||||
let where_clauses = (
|
let where_clauses = TyAliasWhereClauses {
|
||||||
TyAliasWhereClause(before_where_clause.has_where_token, before_where_clause.span),
|
before: TyAliasWhereClause {
|
||||||
TyAliasWhereClause(after_where_clause.has_where_token, after_where_clause.span),
|
has_where_token: before_where_clause.has_where_token,
|
||||||
);
|
span: before_where_clause.span,
|
||||||
let where_predicates_split = before_where_clause.predicates.len();
|
},
|
||||||
|
after: TyAliasWhereClause {
|
||||||
|
has_where_token: after_where_clause.has_where_token,
|
||||||
|
span: after_where_clause.span,
|
||||||
|
},
|
||||||
|
split: before_where_clause.predicates.len(),
|
||||||
|
};
|
||||||
let mut predicates = before_where_clause.predicates;
|
let mut predicates = before_where_clause.predicates;
|
||||||
predicates.extend(after_where_clause.predicates);
|
predicates.extend(after_where_clause.predicates);
|
||||||
let where_clause = WhereClause {
|
let where_clause = WhereClause {
|
||||||
@ -994,7 +1000,6 @@ fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo
|
|||||||
defaultness,
|
defaultness,
|
||||||
generics,
|
generics,
|
||||||
where_clauses,
|
where_clauses,
|
||||||
where_predicates_split,
|
|
||||||
bounds,
|
bounds,
|
||||||
ty,
|
ty,
|
||||||
})),
|
})),
|
||||||
|
@ -1651,8 +1651,7 @@ struct TyAliasRewriteInfo<'c, 'g>(
|
|||||||
&'c RewriteContext<'c>,
|
&'c RewriteContext<'c>,
|
||||||
Indent,
|
Indent,
|
||||||
&'g ast::Generics,
|
&'g ast::Generics,
|
||||||
(ast::TyAliasWhereClause, ast::TyAliasWhereClause),
|
ast::TyAliasWhereClauses,
|
||||||
usize,
|
|
||||||
symbol::Ident,
|
symbol::Ident,
|
||||||
Span,
|
Span,
|
||||||
);
|
);
|
||||||
@ -1672,7 +1671,6 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
|
|||||||
ref bounds,
|
ref bounds,
|
||||||
ref ty,
|
ref ty,
|
||||||
where_clauses,
|
where_clauses,
|
||||||
where_predicates_split,
|
|
||||||
} = *ty_alias_kind;
|
} = *ty_alias_kind;
|
||||||
let ty_opt = ty.as_ref();
|
let ty_opt = ty.as_ref();
|
||||||
let (ident, vis) = match visitor_kind {
|
let (ident, vis) = match visitor_kind {
|
||||||
@ -1680,15 +1678,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
|
|||||||
AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
|
AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
|
||||||
ForeignItem(i) => (i.ident, &i.vis),
|
ForeignItem(i) => (i.ident, &i.vis),
|
||||||
};
|
};
|
||||||
let rw_info = &TyAliasRewriteInfo(
|
let rw_info = &TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span);
|
||||||
context,
|
|
||||||
indent,
|
|
||||||
generics,
|
|
||||||
where_clauses,
|
|
||||||
where_predicates_split,
|
|
||||||
ident,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
let op_ty = opaque_ty(ty);
|
let op_ty = opaque_ty(ty);
|
||||||
// Type Aliases are formatted slightly differently depending on the context
|
// Type Aliases are formatted slightly differently depending on the context
|
||||||
// in which they appear, whether they are opaque, and whether they are associated.
|
// in which they appear, whether they are opaque, and whether they are associated.
|
||||||
@ -1724,19 +1714,11 @@ fn rewrite_ty<R: Rewrite>(
|
|||||||
vis: &ast::Visibility,
|
vis: &ast::Visibility,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
let mut result = String::with_capacity(128);
|
let mut result = String::with_capacity(128);
|
||||||
let TyAliasRewriteInfo(
|
let TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span) = *rw_info;
|
||||||
context,
|
|
||||||
indent,
|
|
||||||
generics,
|
|
||||||
where_clauses,
|
|
||||||
where_predicates_split,
|
|
||||||
ident,
|
|
||||||
span,
|
|
||||||
) = *rw_info;
|
|
||||||
let (before_where_predicates, after_where_predicates) = generics
|
let (before_where_predicates, after_where_predicates) = generics
|
||||||
.where_clause
|
.where_clause
|
||||||
.predicates
|
.predicates
|
||||||
.split_at(where_predicates_split);
|
.split_at(where_clauses.split);
|
||||||
if !after_where_predicates.is_empty() {
|
if !after_where_predicates.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -1771,7 +1753,7 @@ fn rewrite_ty<R: Rewrite>(
|
|||||||
let where_clause_str = rewrite_where_clause(
|
let where_clause_str = rewrite_where_clause(
|
||||||
context,
|
context,
|
||||||
before_where_predicates,
|
before_where_predicates,
|
||||||
where_clauses.0.1,
|
where_clauses.before.span,
|
||||||
context.config.brace_style(),
|
context.config.brace_style(),
|
||||||
Shape::legacy(where_budget, indent),
|
Shape::legacy(where_budget, indent),
|
||||||
false,
|
false,
|
||||||
@ -1795,7 +1777,7 @@ fn rewrite_ty<R: Rewrite>(
|
|||||||
let comment_span = context
|
let comment_span = context
|
||||||
.snippet_provider
|
.snippet_provider
|
||||||
.opt_span_before(span, "=")
|
.opt_span_before(span, "=")
|
||||||
.map(|op_lo| mk_sp(where_clauses.0.1.hi(), op_lo));
|
.map(|op_lo| mk_sp(where_clauses.before.span.hi(), op_lo));
|
||||||
|
|
||||||
let lhs = match comment_span {
|
let lhs = match comment_span {
|
||||||
Some(comment_span)
|
Some(comment_span)
|
||||||
|
@ -2,14 +2,22 @@
|
|||||||
|
|
||||||
#![feature(lazy_type_alias)]
|
#![feature(lazy_type_alias)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
// Check that we *reject* leading where-clauses on lazy type aliases.
|
// Check that we *reject* leading where-clauses on lazy type aliases.
|
||||||
|
|
||||||
type Alias<T>
|
pub type Leading0<T>
|
||||||
|
|
||||||
= T where String: From<T>;
|
= T where String: From<T>;
|
||||||
//~^^^ ERROR where clauses are not allowed before the type for type aliases
|
|
||||||
|
|
||||||
fn main() {
|
pub type Leading1<T, U>
|
||||||
let _: Alias<&str>;
|
|
||||||
}
|
= (T, U)
|
||||||
|
where
|
||||||
|
U: Copy, String: From<T>;
|
||||||
|
|
||||||
|
pub type EmptyLeading0 = () where;
|
||||||
|
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||||
|
|
||||||
|
pub type EmptyLeading1<T> = T where T: Copy;
|
||||||
|
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||||
|
@ -2,15 +2,24 @@
|
|||||||
|
|
||||||
#![feature(lazy_type_alias)]
|
#![feature(lazy_type_alias)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
// Check that we *reject* leading where-clauses on lazy type aliases.
|
// Check that we *reject* leading where-clauses on lazy type aliases.
|
||||||
|
|
||||||
type Alias<T>
|
pub type Leading0<T>
|
||||||
where
|
where //~ ERROR where clauses are not allowed before the type for type aliases
|
||||||
String: From<T>,
|
String: From<T>,
|
||||||
= T;
|
= T;
|
||||||
//~^^^ ERROR where clauses are not allowed before the type for type aliases
|
|
||||||
|
|
||||||
fn main() {
|
pub type Leading1<T, U>
|
||||||
let _: Alias<&str>;
|
where //~ ERROR where clauses are not allowed before the type for type aliases
|
||||||
}
|
String: From<T>,
|
||||||
|
= (T, U)
|
||||||
|
where
|
||||||
|
U: Copy;
|
||||||
|
|
||||||
|
pub type EmptyLeading0 where = ();
|
||||||
|
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||||
|
|
||||||
|
pub type EmptyLeading1<T> where = T where T: Copy;
|
||||||
|
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: where clauses are not allowed before the type for type aliases
|
error: where clauses are not allowed before the type for type aliases
|
||||||
--> $DIR/leading-where-clause.rs:9:1
|
--> $DIR/leading-where-clause.rs:10:1
|
||||||
|
|
|
|
||||||
LL | / where
|
LL | / where
|
||||||
LL | | String: From<T>,
|
LL | | String: From<T>,
|
||||||
@ -12,5 +12,42 @@ LL +
|
|||||||
LL ~ = T where String: From<T>;
|
LL ~ = T where String: From<T>;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: where clauses are not allowed before the type for type aliases
|
||||||
|
--> $DIR/leading-where-clause.rs:15: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, U)
|
||||||
|
LL | where
|
||||||
|
LL ~ U: Copy, String: From<T>;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: where clauses are not allowed before the type for type aliases
|
||||||
|
--> $DIR/leading-where-clause.rs:21:24
|
||||||
|
|
|
||||||
|
LL | pub type EmptyLeading0 where = ();
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= 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 - pub type EmptyLeading0 where = ();
|
||||||
|
LL + pub type EmptyLeading0 = () where;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: where clauses are not allowed before the type for type aliases
|
||||||
|
--> $DIR/leading-where-clause.rs:24:27
|
||||||
|
|
|
||||||
|
LL | pub type EmptyLeading1<T> where = T where T: Copy;
|
||||||
|
| ^^^^^ help: remove this `where`
|
||||||
|
|
|
||||||
|
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ trait Trait {
|
|||||||
type Assoc where u32: Copy;
|
type Assoc where u32: Copy;
|
||||||
// Fine.
|
// Fine.
|
||||||
type Assoc2 where u32: Copy, i32: Copy;
|
type Assoc2 where u32: Copy, i32: Copy;
|
||||||
|
//
|
||||||
|
type Assoc3;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for u32 {
|
impl Trait for u32 {
|
||||||
@ -17,6 +19,8 @@ impl Trait for u32 {
|
|||||||
// Not fine, suggests moving `u32: Copy`
|
// Not fine, suggests moving `u32: Copy`
|
||||||
type Assoc2 = () where i32: Copy, u32: Copy;
|
type Assoc2 = () where i32: Copy, u32: Copy;
|
||||||
//~^ WARNING where clause not allowed here
|
//~^ WARNING where clause not allowed here
|
||||||
|
type Assoc3 = () where;
|
||||||
|
//~^ WARNING where clause not allowed here
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for i32 {
|
impl Trait for i32 {
|
||||||
@ -25,6 +29,8 @@ impl Trait for i32 {
|
|||||||
// Not fine, suggests moving both.
|
// Not fine, suggests moving both.
|
||||||
type Assoc2 = () where u32: Copy, i32: Copy;
|
type Assoc2 = () where u32: Copy, i32: Copy;
|
||||||
//~^ WARNING where clause not allowed here
|
//~^ WARNING where clause not allowed here
|
||||||
|
type Assoc3 = () where;
|
||||||
|
//~^ WARNING where clause not allowed here
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -8,6 +8,8 @@ trait Trait {
|
|||||||
type Assoc where u32: Copy;
|
type Assoc where u32: Copy;
|
||||||
// Fine.
|
// Fine.
|
||||||
type Assoc2 where u32: Copy, i32: Copy;
|
type Assoc2 where u32: Copy, i32: Copy;
|
||||||
|
//
|
||||||
|
type Assoc3;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for u32 {
|
impl Trait for u32 {
|
||||||
@ -17,6 +19,8 @@ impl Trait for u32 {
|
|||||||
// Not fine, suggests moving `u32: Copy`
|
// Not fine, suggests moving `u32: Copy`
|
||||||
type Assoc2 where u32: Copy = () where i32: Copy;
|
type Assoc2 where u32: Copy = () where i32: Copy;
|
||||||
//~^ WARNING where clause not allowed here
|
//~^ WARNING where clause not allowed here
|
||||||
|
type Assoc3 where = ();
|
||||||
|
//~^ WARNING where clause not allowed here
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for i32 {
|
impl Trait for i32 {
|
||||||
@ -25,6 +29,8 @@ impl Trait for i32 {
|
|||||||
// Not fine, suggests moving both.
|
// Not fine, suggests moving both.
|
||||||
type Assoc2 where u32: Copy, i32: Copy = ();
|
type Assoc2 where u32: Copy, i32: Copy = ();
|
||||||
//~^ WARNING where clause not allowed here
|
//~^ WARNING where clause not allowed here
|
||||||
|
type Assoc3 where = () where;
|
||||||
|
//~^ WARNING where clause not allowed here
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
warning: where clause not allowed here
|
warning: where clause not allowed here
|
||||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:15:16
|
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:17:16
|
||||||
|
|
|
|
||||||
LL | type Assoc where u32: Copy = ();
|
LL | type Assoc where u32: Copy = ();
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy;
|
|||||||
|
|
|
|
||||||
|
|
||||||
warning: where clause not allowed here
|
warning: where clause not allowed here
|
||||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:18:17
|
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:20:17
|
||||||
|
|
|
|
||||||
LL | type Assoc2 where u32: Copy = () where i32: Copy;
|
LL | type Assoc2 where u32: Copy = () where i32: Copy;
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@ -26,7 +26,20 @@ LL + type Assoc2 = () where i32: Copy, u32: Copy;
|
|||||||
|
|
|
|
||||||
|
|
||||||
warning: where clause not allowed here
|
warning: where clause not allowed here
|
||||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:26:17
|
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:22:17
|
||||||
|
|
|
||||||
|
LL | type Assoc3 where = ();
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= 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 - type Assoc3 where = ();
|
||||||
|
LL + type Assoc3 = () where;
|
||||||
|
|
|
||||||
|
|
||||||
|
warning: where clause not allowed here
|
||||||
|
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:30:17
|
||||||
|
|
|
|
||||||
LL | type Assoc2 where u32: Copy, i32: Copy = ();
|
LL | type Assoc2 where u32: Copy, i32: Copy = ();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -38,5 +51,13 @@ LL - type Assoc2 where u32: Copy, i32: Copy = ();
|
|||||||
LL + type Assoc2 = () where u32: Copy, i32: Copy;
|
LL + type Assoc2 = () where u32: Copy, i32: Copy;
|
||||||
|
|
|
|
||||||
|
|
||||||
warning: 3 warnings emitted
|
warning: where clause not allowed here
|
||||||
|
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:32:17
|
||||||
|
|
|
||||||
|
LL | type Assoc3 where = () where;
|
||||||
|
| ^^^^^ help: remove this `where`
|
||||||
|
|
|
||||||
|
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||||
|
|
||||||
|
warning: 5 warnings emitted
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user