From c20b4f558440c24e8ef84782a71163fe236d72de Mon Sep 17 00:00:00 2001
From: Jack Huey <31162821+jackh726@users.noreply.github.com>
Date: Tue, 19 Oct 2021 18:45:48 -0400
Subject: [PATCH 1/7] Change syntax for TyAlias where clauses
---
compiler/rustc_ast/src/ast.rs | 13 +++
compiler/rustc_ast/src/mut_visit.rs | 28 ++++-
compiler/rustc_ast/src/visit.rs | 6 +-
compiler/rustc_ast_lowering/src/item.rs | 43 +++++--
.../rustc_ast_passes/src/ast_validation.rs | 80 +++++++++++--
.../rustc_ast_pretty/src/pprust/state/item.rs | 38 +++++-
.../src/deriving/generic/mod.rs | 5 +
compiler/rustc_parse/src/parser/item.rs | 82 +++++--------
.../feature-gate-generic_associated_types.rs | 2 +-
...ature-gate-generic_associated_types.stderr | 2 +-
.../bugs/issue-87735.stderr | 14 ++-
.../bugs/issue-87748.stderr | 8 +-
.../collections-project-default.rs | 2 +-
.../generic-associated-types/collections.rs | 2 +-
.../construct_with_other_type.rs | 4 +-
.../gat-in-trait-path.rs | 2 +-
.../generic-associated-types-where.rs | 2 +-
.../generic-associated-types-where.stderr | 2 +-
.../generic-associated-types/impl_bounds.rs | 6 +-
.../impl_bounds.stderr | 18 ++-
.../impl_bounds_ok.rs | 6 +-
.../issue-47206-where-clause.rs | 2 +-
.../issue-47206-where-clause.stderr | 2 +-
.../generic-associated-types/issue-76826.rs | 2 +-
.../generic-associated-types/issue-79422.rs | 2 +-
.../issue-84931.stderr | 6 +-
.../generic-associated-types/issue-86787.rs | 9 +-
.../generic-associated-types/issue-88287.rs | 5 +-
.../issue-90014.stderr | 4 +-
.../generic-associated-types/issue-91139.rs | 5 +-
.../issue-92033.stderr | 4 +-
.../generic-associated-types/issue-92280.rs | 5 +-
.../ui/generic-associated-types/iterable.rs | 8 +-
.../missing-where-clause-on-trait.rs | 2 +-
.../missing-where-clause-on-trait.stderr | 2 +-
.../projection-bound-cycle-generic.rs | 2 +-
.../projection-bound-cycle.rs | 2 +-
.../streaming_iterator.rs | 4 +-
src/test/ui/parser/bounds-lifetime-where.rs | 2 +-
.../ui/parser/bounds-lifetime-where.stderr | 4 +-
.../ui/parser/removed-syntax-ptr-lifetime.rs | 2 +-
.../parser/removed-syntax-ptr-lifetime.stderr | 4 +-
src/test/ui/parser/type-alias-where.rs | 14 +--
src/test/ui/parser/type-alias-where.stderr | 32 ++----
.../clippy/clippy_utils/src/ast_utils.rs | 48 +-------
src/tools/rustfmt/src/items.rs | 108 ++++++++++++------
46 files changed, 392 insertions(+), 253 deletions(-)
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 725499e5c78ca..2fbafca1681c7 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2662,10 +2662,23 @@ pub struct Trait {
pub items: Vec
>,
}
+/// The location of a where clause on a `TyAlias` (`Span`) and whether there was
+/// a `where` keyword (`bool`). This is split out from `WhereClause`, since there
+/// are two locations for where clause on type aliases, but their predicates
+/// are concatenated together.
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Default)]
+pub struct TyAliasWhereClause(pub bool, pub Span);
+
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TyAlias {
pub defaultness: Defaultness,
pub generics: Generics,
+ /// The span information for the two where clauses (before equals, after equals)
+ 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 ty: Option
>,
}
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index a81a227629539..c60c77e6987a6 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1018,9 +1018,13 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) {
}
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
- ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+ ItemKind::TyAlias(box TyAlias {
+ defaultness, generics, where_clauses, bounds, ty, ..
+ }) => {
visit_defaultness(defaultness, vis);
vis.visit_generics(generics);
+ vis.visit_span(&mut where_clauses.0.1);
+ vis.visit_span(&mut where_clauses.1.1);
visit_bounds(bounds, vis);
visit_opt(ty, |ty| vis.visit_ty(ty));
}
@@ -1087,9 +1091,18 @@ pub fn noop_flat_map_assoc_item(
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+ AssocItemKind::TyAlias(box TyAlias {
+ defaultness,
+ generics,
+ where_clauses,
+ bounds,
+ ty,
+ ..
+ }) => {
visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
+ visitor.visit_span(&mut where_clauses.0.1);
+ visitor.visit_span(&mut where_clauses.1.1);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
}
@@ -1152,9 +1165,18 @@ pub fn noop_flat_map_foreign_item(
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+ ForeignItemKind::TyAlias(box TyAlias {
+ defaultness,
+ generics,
+ where_clauses,
+ bounds,
+ ty,
+ ..
+ }) => {
visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
+ visitor.visit_span(&mut where_clauses.0.1);
+ visitor.visit_span(&mut where_clauses.1.1);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 73e9297549cd4..ed16c25d921e4 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -303,7 +303,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
}
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
- ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => {
+ ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
@@ -559,7 +559,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
+ ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
@@ -665,7 +665,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
+ AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index e8fca6f04ba5b..77c5797442a55 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -277,7 +277,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::GlobalAsm(ref asm) => {
hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
}
- ItemKind::TyAlias(box TyAlias { ref generics, ty: Some(ref ty), .. }) => {
+ ItemKind::TyAlias(box TyAlias {
+ ref generics,
+ where_clauses,
+ ty: Some(ref ty),
+ ..
+ }) => {
// We lower
//
// type Foo = impl Trait
@@ -292,16 +297,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
capturable_lifetimes: &mut FxHashSet::default(),
},
);
+ let mut generics = generics.clone();
+ generics.where_clause.has_where_token = where_clauses.0.0;
+ generics.where_clause.span = where_clauses.0.1;
let generics = self.lower_generics(
- generics,
+ &generics,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
);
hir::ItemKind::TyAlias(ty, generics)
}
- ItemKind::TyAlias(box TyAlias { ref generics, ty: None, .. }) => {
+ ItemKind::TyAlias(box TyAlias {
+ ref generics, ref where_clauses, ty: None, ..
+ }) => {
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
+ let mut generics = generics.clone();
+ generics.where_clause.has_where_token = where_clauses.0.0;
+ generics.where_clause.span = where_clauses.0.1;
let generics = self.lower_generics(
- generics,
+ &generics,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
);
hir::ItemKind::TyAlias(ty, generics)
@@ -832,18 +845,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
}
- AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
+ AssocItemKind::TyAlias(box TyAlias {
+ ref generics,
+ where_clauses,
+ ref bounds,
+ ref ty,
+ ..
+ }) => {
let ty = ty.as_ref().map(|x| {
self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Type))
});
+ let mut generics = generics.clone();
+ generics.where_clause.has_where_token = where_clauses.1.0;
+ generics.where_clause.span = where_clauses.1.1;
let generics = self.lower_generics(
- generics,
+ &generics,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
);
let kind = hir::TraitItemKind::Type(
self.lower_param_bounds(
bounds,
- ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+ ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
),
ty,
);
@@ -917,9 +939,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, hir::ImplItemKind::Fn(sig, body_id))
}
- AssocItemKind::TyAlias(box TyAlias { generics, ty, .. }) => {
+ AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
+ let mut generics = generics.clone();
+ generics.where_clause.has_where_token = where_clauses.1.0;
+ generics.where_clause.span = where_clauses.1.1;
let generics = self.lower_generics(
- generics,
+ &generics,
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
);
let kind = match ty {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 20caed1b230d5..0b97a1b181450 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -11,7 +11,7 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::walk_list;
use rustc_ast::*;
-use rustc_ast_pretty::pprust;
+use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
use rustc_parse::validate_attr;
@@ -122,6 +122,40 @@ impl<'a> AstValidator<'a> {
}
}
+ fn check_gat_where(
+ &self,
+ before_predicates: &[WherePredicate],
+ where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
+ ) {
+ let sess = &self.session;
+ if !before_predicates.is_empty() {
+ let mut state = State::new();
+ if !where_clauses.1.0 {
+ state.space();
+ state.word_space("where");
+ } else {
+ state.word_space(",");
+ }
+ let mut first = true;
+ for p in before_predicates.iter() {
+ if !first {
+ state.word_space(",");
+ }
+ first = false;
+ state.print_where_predicate(p);
+ }
+ let suggestion = state.s.eof();
+ sess.struct_span_err(where_clauses.0.1, "where clause not allowed here")
+ .span_suggestion(
+ where_clauses.1.1.shrink_to_hi(),
+ "move it here",
+ suggestion,
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ }
+ }
+
fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
f(self);
@@ -454,7 +488,7 @@ impl<'a> AstValidator<'a> {
.emit();
}
- fn check_foreign_ty_genericless(&self, generics: &Generics) {
+ fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
let cannot_have = |span, descr, remove_descr| {
self.err_handler()
.struct_span_err(
@@ -477,7 +511,7 @@ impl<'a> AstValidator<'a> {
}
if !generics.where_clause.predicates.is_empty() {
- cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
+ cannot_have(where_span, "`where` clauses", "`where` clause");
}
}
@@ -1223,13 +1257,25 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
let msg = "free static item without body";
self.error_item_without_body(item.span, "static", msg, " = ;");
}
- ItemKind::TyAlias(box TyAlias { defaultness, ref bounds, ref ty, .. }) => {
+ ItemKind::TyAlias(box TyAlias {
+ defaultness,
+ where_clauses,
+ ref bounds,
+ ref ty,
+ ..
+ }) => {
self.check_defaultness(item.span, defaultness);
if ty.is_none() {
let msg = "free type alias without body";
self.error_item_without_body(item.span, "type", msg, " = ;");
}
self.check_type_no_bounds(bounds, "this context");
+ if where_clauses.1.0 {
+ self.err_handler().span_err(
+ where_clauses.1.1,
+ "where clauses are not allowed after the type for type aliases",
+ )
+ }
}
_ => {}
}
@@ -1245,11 +1291,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
self.check_foreign_item_ascii_only(fi.ident);
}
- ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty, .. }) => {
+ ForeignItemKind::TyAlias(box TyAlias {
+ defaultness,
+ generics,
+ where_clauses,
+ bounds,
+ ty,
+ ..
+ }) => {
self.check_defaultness(fi.span, *defaultness);
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_foreign_ty_genericless(generics);
+ self.check_foreign_ty_genericless(generics, where_clauses.0.1);
self.check_foreign_item_ascii_only(fi.ident);
}
ForeignItemKind::Static(_, _, body) => {
@@ -1503,9 +1556,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
AssocItemKind::Fn(box Fn { body, .. }) => {
self.check_impl_item_provided(item.span, body, "function", " { }");
}
- AssocItemKind::TyAlias(box TyAlias { bounds, ty, .. }) => {
+ AssocItemKind::TyAlias(box TyAlias {
+ generics,
+ where_clauses,
+ where_predicates_split,
+ bounds,
+ ty,
+ ..
+ }) => {
self.check_impl_item_provided(item.span, ty, "type", " = ;");
self.check_type_no_bounds(bounds, "`impl`s");
+ if ty.is_some() {
+ self.check_gat_where(
+ generics.where_clause.predicates.split_at(*where_predicates_split).0,
+ *where_clauses,
+ );
+ }
}
_ => {}
}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index d7e9ef0e50dd8..2a35dd1006e7e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -36,12 +36,16 @@ impl<'a> State<'a> {
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
defaultness,
generics,
+ where_clauses,
+ where_predicates_split,
bounds,
ty,
}) => {
self.print_associated_type(
ident,
generics,
+ *where_clauses,
+ *where_predicates_split,
bounds,
ty.as_deref(),
vis,
@@ -95,11 +99,15 @@ impl<'a> State<'a> {
&mut self,
ident: Ident,
generics: &ast::Generics,
+ where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
+ where_predicates_split: usize,
bounds: &ast::GenericBounds,
ty: Option<&ast::Ty>,
vis: &ast::Visibility,
defaultness: ast::Defaultness,
) {
+ let (before_predicates, after_predicates) =
+ generics.where_clause.predicates.split_at(where_predicates_split);
self.head("");
self.print_visibility(vis);
self.print_defaultness(defaultness);
@@ -107,12 +115,13 @@ impl<'a> State<'a> {
self.print_ident(ident);
self.print_generic_params(&generics.params);
self.print_type_bounds(":", bounds);
- self.print_where_clause(&generics.where_clause);
+ self.print_where_clause_parts(where_clauses.0.0, before_predicates);
if let Some(ty) = ty {
self.space();
self.word_space("=");
self.print_type(ty);
}
+ self.print_where_clause_parts(where_clauses.1.0, after_predicates);
self.word(";");
self.end(); // end inner head-block
self.end(); // end outer head-block
@@ -211,6 +220,8 @@ impl<'a> State<'a> {
ast::ItemKind::TyAlias(box ast::TyAlias {
defaultness,
ref generics,
+ where_clauses,
+ where_predicates_split,
ref bounds,
ref ty,
}) => {
@@ -218,6 +229,8 @@ impl<'a> State<'a> {
self.print_associated_type(
item.ident,
generics,
+ where_clauses,
+ where_predicates_split,
bounds,
ty,
&item.vis,
@@ -496,10 +509,19 @@ impl<'a> State<'a> {
ast::AssocItemKind::Const(def, ty, body) => {
self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
}
- ast::AssocItemKind::TyAlias(box ast::TyAlias { defaultness, generics, bounds, ty }) => {
+ ast::AssocItemKind::TyAlias(box ast::TyAlias {
+ defaultness,
+ generics,
+ where_clauses,
+ where_predicates_split,
+ bounds,
+ ty,
+ }) => {
self.print_associated_type(
ident,
generics,
+ *where_clauses,
+ *where_predicates_split,
bounds,
ty.as_deref(),
vis,
@@ -566,14 +588,22 @@ impl<'a> State<'a> {
}
fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
- if where_clause.predicates.is_empty() && !where_clause.has_where_token {
+ self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates);
+ }
+
+ crate fn print_where_clause_parts(
+ &mut self,
+ has_where_token: bool,
+ predicates: &[ast::WherePredicate],
+ ) {
+ if predicates.is_empty() && !has_where_token {
return;
}
self.space();
self.word_space("where");
- for (i, predicate) in where_clause.predicates.iter().enumerate() {
+ for (i, predicate) in predicates.iter().enumerate() {
if i != 0 {
self.word_space(",");
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 985c45e225388..f87f4726d1c69 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -560,6 +560,11 @@ impl<'a> TraitDef<'a> {
kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
defaultness: ast::Defaultness::Final,
generics: Generics::default(),
+ where_clauses: (
+ ast::TyAliasWhereClause::default(),
+ ast::TyAliasWhereClause::default(),
+ ),
+ where_predicates_split: 0,
bounds: Vec::new(),
ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
})),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index ae46bfe354083..3a4fa98fad153 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -13,11 +13,12 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacArgs, MacCall, MacDelimiter};
use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, ErrorGuaranteed, PResult, StashKey};
+use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::DUMMY_SP;
use std::convert::TryFrom;
use std::mem;
@@ -791,44 +792,6 @@ impl<'a> Parser<'a> {
))
}
- /// Emits an error that the where clause at the end of a type alias is not
- /// allowed and suggests moving it.
- fn error_ty_alias_where(
- &self,
- before_where_clause_present: bool,
- before_where_clause_span: Span,
- after_predicates: &[WherePredicate],
- after_where_clause_span: Span,
- ) -> ErrorGuaranteed {
- let mut err =
- self.struct_span_err(after_where_clause_span, "where clause not allowed here");
- if !after_predicates.is_empty() {
- let mut state = crate::pprust::State::new();
- if !before_where_clause_present {
- state.space();
- state.word_space("where");
- } else {
- state.word_space(",");
- }
- let mut first = true;
- for p in after_predicates.iter() {
- if !first {
- state.word_space(",");
- }
- first = false;
- state.print_where_predicate(p);
- }
- let suggestion = state.s.eof();
- err.span_suggestion(
- before_where_clause_span.shrink_to_hi(),
- "move it here",
- suggestion,
- Applicability::MachineApplicable,
- );
- }
- err.emit()
- }
-
/// Parses a `type` alias with the following grammar:
/// ```
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
@@ -841,27 +804,40 @@ impl<'a> Parser<'a> {
// Parse optional colon and param bounds.
let bounds =
if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
-
- generics.where_clause = self.parse_where_clause()?;
+ let before_where_clause = self.parse_where_clause()?;
let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
- if self.token.is_keyword(kw::Where) {
- let after_where_clause = self.parse_where_clause()?;
-
- self.error_ty_alias_where(
- generics.where_clause.has_where_token,
- generics.where_clause.span,
- &after_where_clause.predicates,
- after_where_clause.span,
- );
+ let after_where_clause = self.parse_where_clause()?;
- generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter());
- }
+ let where_clauses = (
+ TyAliasWhereClause(before_where_clause.has_where_token, before_where_clause.span),
+ TyAliasWhereClause(after_where_clause.has_where_token, after_where_clause.span),
+ );
+ let where_predicates_split = before_where_clause.predicates.len();
+ let mut predicates = before_where_clause.predicates;
+ predicates.extend(after_where_clause.predicates.into_iter());
+ let where_clause = WhereClause {
+ has_where_token: before_where_clause.has_where_token
+ || after_where_clause.has_where_token,
+ predicates,
+ span: DUMMY_SP,
+ };
+ generics.where_clause = where_clause;
self.expect_semi()?;
- Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
+ Ok((
+ ident,
+ ItemKind::TyAlias(Box::new(TyAlias {
+ defaultness,
+ generics,
+ where_clauses,
+ where_predicates_split,
+ bounds,
+ ty,
+ })),
+ ))
}
/// Parses a `UseTree`.
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
index 1d2be3657ffb2..c5c1345148891 100644
--- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.rs
@@ -24,7 +24,7 @@ trait Bar {
}
impl Bar for Foo {
- type Assoc where Self: Sized = Foo;
+ type Assoc = Foo where Self: Sized;
//~^ ERROR where clauses on associated types are unstable
}
diff --git a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
index 6c2c3ed9c3655..12a40ff0a12f5 100644
--- a/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generic_associated_types.stderr
@@ -55,7 +55,7 @@ LL | type Assoc where Self: Sized;
error[E0658]: where clauses on associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:27:5
|
-LL | type Assoc where Self: Sized = Foo;
+LL | type Assoc = Foo where Self: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #44265 for more information
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr
index 0a18b5f0cbdaa..a64e52124c8bf 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr
@@ -1,9 +1,21 @@
+error: where clause not allowed here
+ --> $DIR/issue-87735.rs:15:19
+ |
+LL | type Output<'a> where Self: 'a = &'a [T];
+ | ^^^^^^^^^^^^^^ - help: move it here: `where Self: 'a`
+
+error: where clause not allowed here
+ --> $DIR/issue-87735.rs:36:19
+ |
+LL | type Output<'a> where Self: 'a = FooRef<'a, U>;
+ | ^^^^^^^^^^^^^^ - help: move it here: `where Self: 'a`
+
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-87735.rs:27:13
|
LL | impl<'b, T, U> AsRef2 for Foo
| ^ unconstrained type parameter
-error: aborting due to previous error
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr
index 60bb48efbc895..f92930fc94845 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr
@@ -1,3 +1,9 @@
+error: where clause not allowed here
+ --> $DIR/issue-87748.rs:16:24
+ |
+LL | type Assoc<'a, 'b> where 'b: 'a = u32;
+ | ^^^^^^^^^^^^ - help: move it here: `where 'b: 'a`
+
error[E0478]: lifetime bound not satisfied
--> $DIR/issue-87748.rs:18:5
|
@@ -15,6 +21,6 @@ note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/generic-associated-types/collections-project-default.rs b/src/test/ui/generic-associated-types/collections-project-default.rs
index 5b94cdee7c9c7..157e1b1d29573 100644
--- a/src/test/ui/generic-associated-types/collections-project-default.rs
+++ b/src/test/ui/generic-associated-types/collections-project-default.rs
@@ -32,7 +32,7 @@ impl CollectionFamily for VecFamily {
}
impl Collection for Vec {
- type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
+ type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter;
type Family = VecFamily;
fn empty() -> Self {
diff --git a/src/test/ui/generic-associated-types/collections.rs b/src/test/ui/generic-associated-types/collections.rs
index b0f2fb3f56785..1c00aa73feb9f 100644
--- a/src/test/ui/generic-associated-types/collections.rs
+++ b/src/test/ui/generic-associated-types/collections.rs
@@ -32,7 +32,7 @@ impl CollectionFamily for VecFamily {
}
impl Collection for Vec {
- type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
+ type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter;
type Family = VecFamily;
fn empty() -> Self {
diff --git a/src/test/ui/generic-associated-types/construct_with_other_type.rs b/src/test/ui/generic-associated-types/construct_with_other_type.rs
index 9ae328cc48b1d..060804269aa70 100644
--- a/src/test/ui/generic-associated-types/construct_with_other_type.rs
+++ b/src/test/ui/generic-associated-types/construct_with_other_type.rs
@@ -16,9 +16,9 @@ trait Baz {
}
impl Baz for T where T: Foo {
- type Quux<'a> where T: 'a = T;
+ type Quux<'a> = T where T: 'a;
- type Baa<'a> where T: 'a = &'a ::Bar<'a, 'static>;
+ type Baa<'a> = &'a ::Bar<'a, 'static> where T: 'a;
}
fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
index fb03a86e16971..7bbcf950ae183 100644
--- a/src/test/ui/generic-associated-types/gat-in-trait-path.rs
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
@@ -15,7 +15,7 @@ impl Foo for Fooy {
struct Fooer(T);
impl Foo for Fooer {
- type A<'x> where T: 'x = &'x ();
+ type A<'x> = &'x () where T: 'x;
}
fn f(_arg : Box Foo = &'a ()>>) {}
diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.rs b/src/test/ui/generic-associated-types/generic-associated-types-where.rs
index 592ff93992323..2ecbc8c591259 100644
--- a/src/test/ui/generic-associated-types/generic-associated-types-where.rs
+++ b/src/test/ui/generic-associated-types/generic-associated-types-where.rs
@@ -19,7 +19,7 @@ impl Foo for Bar {
type Assoc = usize;
type Assoc2 = Vec;
//~^ ERROR `T` doesn't implement `std::fmt::Display`
- type Assoc3 where T: Iterator = Vec;
+ type Assoc3 = Vec where T: Iterator;
//~^ ERROR impl has stricter requirements than trait
type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator- ;
type NoGenerics = ::std::cell::Cell;
diff --git a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
index 544f2bcbbd777..68594bba48632 100644
--- a/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
+++ b/src/test/ui/generic-associated-types/generic-associated-types-where.stderr
@@ -16,7 +16,7 @@ error[E0276]: impl has stricter requirements than trait
LL | type Assoc3;
| --------------- definition of `Assoc3` from trait
...
-LL | type Assoc3 where T: Iterator = Vec;
+LL | type Assoc3 = Vec where T: Iterator;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs
index ff2ffec22c456..bb5992c88f08f 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.rs
+++ b/src/test/ui/generic-associated-types/impl_bounds.rs
@@ -12,12 +12,12 @@ trait Foo {
struct Fooy(T);
impl Foo for Fooy {
- type A<'a> where Self: 'static = (&'a ());
+ type A<'a> = (&'a ()) where Self: 'static;
//~^ ERROR `impl` associated type
- type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+ type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
//~^ ERROR `impl` associated type
//~| ERROR lifetime bound not satisfied
- type C where Self: Copy = String;
+ type C = String where Self: Copy;
//~^ ERROR the trait bound `T: Copy` is not satisfied
fn d() where Self: Copy {}
//~^ ERROR the trait bound `T: Copy` is not satisfied
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index bd0dea372194d..3d90471e398e6 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -4,7 +4,7 @@ error: `impl` associated type signature for `A` doesn't match `trait` associated
LL | type A<'a> where Self: 'a;
| -------------------------- expected
...
-LL | type A<'a> where Self: 'static = (&'a ());
+LL | type A<'a> = (&'a ()) where Self: 'static;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
@@ -13,35 +13,33 @@ error: `impl` associated type signature for `B` doesn't match `trait` associated
LL | type B<'a, 'b> where 'a: 'b;
| ---------------------------- expected
...
-LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
error[E0478]: lifetime bound not satisfied
- --> $DIR/impl_bounds.rs:17:35
+ --> $DIR/impl_bounds.rs:17:22
|
LL | type B<'a, 'b> where 'a: 'b;
| ---------------------------- definition of `B` from trait
...
-LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
- | - ^^^^^^^^^^^^^^^
- | |
- | help: try copying this clause from the trait: `, 'a: 'b`
+LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
+ | ^^^^^^^^^^^^^^^ - help: try copying this clause from the trait: `, 'a: 'b`
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
--> $DIR/impl_bounds.rs:17:12
|
-LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
| ^^
note: but lifetime parameter must outlive the lifetime `'b` as defined here
--> $DIR/impl_bounds.rs:17:16
|
-LL | type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
+LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a;
| ^^
error[E0277]: the trait bound `T: Copy` is not satisfied
--> $DIR/impl_bounds.rs:20:5
|
-LL | type C where Self: Copy = String;
+LL | type C = String where Self: Copy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
|
note: required because of the requirements on the impl of `Copy` for `Fooy`
diff --git a/src/test/ui/generic-associated-types/impl_bounds_ok.rs b/src/test/ui/generic-associated-types/impl_bounds_ok.rs
index 08120b9670f67..4df8235d95f34 100644
--- a/src/test/ui/generic-associated-types/impl_bounds_ok.rs
+++ b/src/test/ui/generic-associated-types/impl_bounds_ok.rs
@@ -22,9 +22,9 @@ impl Foo for Fooy {
struct Fooer(T);
impl Foo for Fooer {
- type A<'x> where T: 'x = (&'x ());
- type B<'u, 'v> where 'u: 'v = (&'v &'u ());
- type C where Self: Clone + ToOwned = String;
+ type A<'x> = (&'x ()) where T: 'x;
+ type B<'u, 'v> = (&'v &'u ()) where 'u: 'v;
+ type C = String where Self: Clone + ToOwned;
}
fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs
index da5fca2a6569f..d352c1948f234 100644
--- a/src/test/ui/generic-associated-types/issue-47206-where-clause.rs
+++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.rs
@@ -9,7 +9,7 @@ trait Foo {
struct Bar;
impl Foo for Bar {
- type Assoc3 where T: Iterator = Vec;
+ type Assoc3 = Vec where T: Iterator;
//~^ ERROR impl has stricter requirements than trait
}
diff --git a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
index 56677457726f7..39beac38c0b61 100644
--- a/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
+++ b/src/test/ui/generic-associated-types/issue-47206-where-clause.stderr
@@ -4,7 +4,7 @@ error[E0276]: impl has stricter requirements than trait
LL | type Assoc3;
| --------------- definition of `Assoc3` from trait
...
-LL | type Assoc3 where T: Iterator = Vec;
+LL | type Assoc3 = Vec where T: Iterator;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Iterator`
error: aborting due to previous error
diff --git a/src/test/ui/generic-associated-types/issue-76826.rs b/src/test/ui/generic-associated-types/issue-76826.rs
index d3201a156a18c..28eb3b0e750e2 100644
--- a/src/test/ui/generic-associated-types/issue-76826.rs
+++ b/src/test/ui/generic-associated-types/issue-76826.rs
@@ -29,7 +29,7 @@ impl Windows {
}
impl Iter for Windows {
- type Item<'a> where T: 'a = &'a mut [T];
+ type Item<'a> = &'a mut [T] where T: 'a;
fn next<'a>(&'a mut self) -> Option> {
let slice = self.items.get_mut(self.start..self.start + self.len)?;
diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs
index 47ef38ff45d65..b9a3c583f7c89 100644
--- a/src/test/ui/generic-associated-types/issue-79422.rs
+++ b/src/test/ui/generic-associated-types/issue-79422.rs
@@ -22,7 +22,7 @@ trait MapLike {
}
impl MapLike for std::collections::BTreeMap {
- type VRefCont<'a> where Self: 'a = &'a V;
+ type VRefCont<'a> = &'a V where Self: 'a;
fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
std::collections::BTreeMap::get(self, key)
}
diff --git a/src/test/ui/generic-associated-types/issue-84931.stderr b/src/test/ui/generic-associated-types/issue-84931.stderr
index 47decb70ae74c..11c3dffde4b38 100644
--- a/src/test/ui/generic-associated-types/issue-84931.stderr
+++ b/src/test/ui/generic-associated-types/issue-84931.stderr
@@ -2,9 +2,9 @@ error[E0309]: the parameter type `T` may not live long enough
--> $DIR/issue-84931.rs:15:21
|
LL | type Item<'a> = &'a mut T;
- | - ^^^^^^^^^ ...so that the reference type `&'a mut T` does not outlive the data it points at
- | |
- | help: consider adding a where clause: `where T: 'a`
+ | ^^^^^^^^^- help: consider adding a where clause: `where T: 'a`
+ | |
+ | ...so that the reference type `&'a mut T` does not outlive the data it points at
error: aborting due to previous error
diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs
index 5863bac2f9d0b..0f8096c8a7c1b 100644
--- a/src/test/ui/generic-associated-types/issue-86787.rs
+++ b/src/test/ui/generic-associated-types/issue-86787.rs
@@ -21,13 +21,10 @@ where
Right: HasChildrenOf,
{
type T = Either;
- // We used to error below because the where clause doesn't match the trait.
- // Now, we error early on the trait itself.
- type TRef<'a>
+ type TRef<'a> = Either<&'a Left::T, &'a Right::T>
where
- ::T: 'a,
- ::T: 'a
- = Either<&'a Left::T, &'a Right::T>;
+ ::T: 'a,
+ ::T: 'a;
fn ref_children<'a>(&'a self) -> Vec> {
todo!()
diff --git a/src/test/ui/generic-associated-types/issue-88287.rs b/src/test/ui/generic-associated-types/issue-88287.rs
index df5586ed422f8..6b10edf073ff6 100644
--- a/src/test/ui/generic-associated-types/issue-88287.rs
+++ b/src/test/ui/generic-associated-types/issue-88287.rs
@@ -27,11 +27,10 @@ impl SearchableResourceExt for T
where
T: SearchableResource,
{
- type Future<'f, A, B: 'f>
+ type Future<'f, A, B: 'f> = SearchFutureTy<'f, A, B>
where
A: SearchableResource + ?Sized + 'f,
- Self: 'f,
- = SearchFutureTy<'f, A, B>;
+ Self: 'f;
fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
async move { todo!() }
diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr
index f8fb71bbddb4b..51fe3360c7eb2 100644
--- a/src/test/ui/generic-associated-types/issue-90014.stderr
+++ b/src/test/ui/generic-associated-types/issue-90014.stderr
@@ -5,9 +5,7 @@ LL | type Fut<'a> where Self: 'a;
| ---------------------------- definition of `Fut` from trait
...
LL | type Fut<'a> = impl Future