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; - | - ^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-90014.rs:14:14 diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs index 2b82d2946b3ba..5c4a7cf6ffc60 100644 --- a/src/test/ui/generic-associated-types/issue-91139.rs +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -9,10 +9,9 @@ trait Foo { } impl Foo for () { - type Type<'a> + type Type<'a> = () where - T: 'a, - = (); + T: 'a; } fn foo() { diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr index caa6618f39884..5b90199b8091f 100644 --- a/src/test/ui/generic-associated-types/issue-92033.stderr +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -7,9 +7,7 @@ LL | | Self: 'a; | |_________________- definition of `TextureIter` from trait ... LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; - | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-92033.rs:22:22 diff --git a/src/test/ui/generic-associated-types/issue-92280.rs b/src/test/ui/generic-associated-types/issue-92280.rs index db26493ecadfa..81d000f1076ca 100644 --- a/src/test/ui/generic-associated-types/issue-92280.rs +++ b/src/test/ui/generic-associated-types/issue-92280.rs @@ -17,10 +17,9 @@ struct KeySegment_Broken { key: T, } impl Iterate for KeySegment_Broken { - type Iter<'a> + type Iter<'a> = () where - Self: 'a, - = (); + Self: 'a; } fn main() {} diff --git a/src/test/ui/generic-associated-types/iterable.rs b/src/test/ui/generic-associated-types/iterable.rs index 952fca8ab8a65..af0049891b696 100644 --- a/src/test/ui/generic-associated-types/iterable.rs +++ b/src/test/ui/generic-associated-types/iterable.rs @@ -11,8 +11,8 @@ trait Iterable { // Impl for struct type impl Iterable for Vec { - type Item<'a> where T: 'a = as Iterator>::Item; - type Iter<'a> where T: 'a = std::slice::Iter<'a, T>; + type Item<'a> = as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; fn iter<'a>(&'a self) -> Self::Iter<'a> { self[..].iter() @@ -21,8 +21,8 @@ impl Iterable for Vec { // Impl for a primitive type impl Iterable for [T] { - type Item<'a> where T: 'a = as Iterator>::Item; - type Iter<'a> where T: 'a = std::slice::Iter<'a, T>; + type Item<'a> = as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; fn iter<'a>(&'a self) -> Self::Iter<'a> { self.iter() diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs index ad9f2e3e4ec4a..5fb8f7a4773d6 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -6,7 +6,7 @@ trait Foo { type Assoc<'a, 'b>; } impl Foo for () { - type Assoc<'a, 'b> where 'a: 'b = (); + type Assoc<'a, 'b> = () where 'a: 'b; //~^ `impl` associated type } diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr index 0e183c8d69a4c..9e0896127a8a3 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -4,7 +4,7 @@ error: `impl` associated type signature for `Assoc` doesn't match `trait` associ LL | type Assoc<'a, 'b>; | ------------------- expected ... -LL | type Assoc<'a, 'b> where 'a: 'b = (); +LL | type Assoc<'a, 'b> = () where 'a: 'b; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs index 7517e1fa9d061..794d677c8b657 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -22,7 +22,7 @@ impl Foo for Number { // } // ``` // which it is :) - type Item where [T]: Sized = [T]; + type Item = [T] where [T]: Sized; } struct OnlySized where T: Sized { f: T } diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle.rs b/src/test/ui/generic-associated-types/projection-bound-cycle.rs index 8f8cb679e9c0e..6564a3608ec0e 100644 --- a/src/test/ui/generic-associated-types/projection-bound-cycle.rs +++ b/src/test/ui/generic-associated-types/projection-bound-cycle.rs @@ -24,7 +24,7 @@ impl Foo for Number { // } // ``` // which it is :) - type Item where str: Sized = str; + type Item = str where str: Sized; } struct OnlySized where T: Sized { f: T } diff --git a/src/test/ui/generic-associated-types/streaming_iterator.rs b/src/test/ui/generic-associated-types/streaming_iterator.rs index f83d4d7b68e48..e71b6805ad412 100644 --- a/src/test/ui/generic-associated-types/streaming_iterator.rs +++ b/src/test/ui/generic-associated-types/streaming_iterator.rs @@ -30,7 +30,7 @@ struct StreamEnumerate { } impl StreamingIterator for StreamEnumerate { - type Item<'a> where Self: 'a = (usize, I::Item<'a>); + type Item<'a> = (usize, I::Item<'a>) where Self: 'a; fn next<'a>(&'a mut self) -> Option> { match self.iter.next() { None => None, @@ -44,7 +44,7 @@ impl StreamingIterator for StreamEnumerate { } impl StreamingIterator for I { - type Item<'a> where Self: 'a = ::Item; + type Item<'a> = ::Item where Self: 'a; fn next(&mut self) -> Option<::Item<'_>> { Iterator::next(self) } diff --git a/src/test/ui/parser/bounds-lifetime-where.rs b/src/test/ui/parser/bounds-lifetime-where.rs index e60cc153e670f..7ff75233d3a8e 100644 --- a/src/test/ui/parser/bounds-lifetime-where.rs +++ b/src/test/ui/parser/bounds-lifetime-where.rs @@ -5,6 +5,6 @@ type A where 'a:, = u8; // OK type A where 'a: 'b + 'c = u8; // OK type A where = u8; // OK type A where 'a: 'b + = u8; // OK -type A where , = u8; //~ ERROR expected one of `;`, `=`, lifetime, or type, found `,` +type A where , = u8; //~ ERROR expected one of `;`, `=`, `where`, lifetime, or type, found `,` fn main() {} diff --git a/src/test/ui/parser/bounds-lifetime-where.stderr b/src/test/ui/parser/bounds-lifetime-where.stderr index 950fa46c66b7e..785a1fb679324 100644 --- a/src/test/ui/parser/bounds-lifetime-where.stderr +++ b/src/test/ui/parser/bounds-lifetime-where.stderr @@ -1,8 +1,8 @@ -error: expected one of `;`, `=`, lifetime, or type, found `,` +error: expected one of `;`, `=`, `where`, lifetime, or type, found `,` --> $DIR/bounds-lifetime-where.rs:8:14 | LL | type A where , = u8; - | ^ expected one of `;`, `=`, lifetime, or type + | ^ expected one of `;`, `=`, `where`, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/parser/removed-syntax-ptr-lifetime.rs b/src/test/ui/parser/removed-syntax-ptr-lifetime.rs index 5b551addbc893..cc69af44a13ca 100644 --- a/src/test/ui/parser/removed-syntax-ptr-lifetime.rs +++ b/src/test/ui/parser/removed-syntax-ptr-lifetime.rs @@ -1 +1 @@ -type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, or `<`, found `/` +type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` diff --git a/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr b/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr index 5b388ff4ce059..914de43e62d66 100644 --- a/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr +++ b/src/test/ui/parser/removed-syntax-ptr-lifetime.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `::`, `;`, or `<`, found `/` +error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` --> $DIR/removed-syntax-ptr-lifetime.rs:1:22 | LL | type bptr = &lifetime/isize; - | ^ expected one of `!`, `(`, `::`, `;`, or `<` + | ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where` error: aborting due to previous error diff --git a/src/test/ui/parser/type-alias-where.rs b/src/test/ui/parser/type-alias-where.rs index a9fa23dd95ef4..99ab8a7c48ccf 100644 --- a/src/test/ui/parser/type-alias-where.rs +++ b/src/test/ui/parser/type-alias-where.rs @@ -6,9 +6,9 @@ type Foo where u32: Copy = (); // Not fine. type Bar = () where u32: Copy; -//~^ ERROR where clause not allowed here +//~^ ERROR where clauses are not allowed type Baz = () where; -//~^ ERROR where clause not allowed here +//~^ ERROR where clauses are not allowed trait Trait { // Fine. @@ -18,19 +18,19 @@ trait Trait { } impl Trait for u32 { - // Fine. + // Not fine, suggests moving. type Assoc where u32: Copy = (); - // Not fine, suggests moving `i32: Copy` + //~^ ERROR where clause not allowed here + // Not fine, suggests moving `u32: Copy` type Assoc2 where u32: Copy = () where i32: Copy; //~^ ERROR where clause not allowed here } impl Trait for i32 { - // Not fine, suggests moving `u32: Copy` + // Fine. type Assoc = () where u32: Copy; - //~^ ERROR where clause not allowed here // Not fine, suggests moving both. - type Assoc2 = () where u32: Copy, i32: Copy; + type Assoc2 where u32: Copy, i32: Copy = (); //~^ ERROR where clause not allowed here } diff --git a/src/test/ui/parser/type-alias-where.stderr b/src/test/ui/parser/type-alias-where.stderr index 7ab0b28c8640a..4cc8b703cede9 100644 --- a/src/test/ui/parser/type-alias-where.stderr +++ b/src/test/ui/parser/type-alias-where.stderr @@ -1,40 +1,32 @@ -error: where clause not allowed here +error: where clauses are not allowed after the type for type aliases --> $DIR/type-alias-where.rs:8:15 | LL | type Bar = () where u32: Copy; - | - ^^^^^^^^^^^^^^^ - | | - | help: move it here: `where u32: Copy` + | ^^^^^^^^^^^^^^^ -error: where clause not allowed here +error: where clauses are not allowed after the type for type aliases --> $DIR/type-alias-where.rs:10:15 | LL | type Baz = () where; | ^^^^^ error: where clause not allowed here - --> $DIR/type-alias-where.rs:24:38 + --> $DIR/type-alias-where.rs:22:16 | -LL | type Assoc2 where u32: Copy = () where i32: Copy; - | - ^^^^^^^^^^^^^^^ - | | - | help: move it here: `, i32: Copy` +LL | type Assoc where u32: Copy = (); + | ^^^^^^^^^^^^^^^ - help: move it here: `where u32: Copy` error: where clause not allowed here - --> $DIR/type-alias-where.rs:30:21 + --> $DIR/type-alias-where.rs:25:17 | -LL | type Assoc = () where u32: Copy; - | - ^^^^^^^^^^^^^^^ - | | - | help: move it here: `where u32: Copy` +LL | type Assoc2 where u32: Copy = () where i32: Copy; + | ^^^^^^^^^^^^^^^ - help: move it here: `, u32: Copy` error: where clause not allowed here - --> $DIR/type-alias-where.rs:33:22 + --> $DIR/type-alias-where.rs:33:17 | -LL | type Assoc2 = () where u32: Copy, i32: Copy; - | - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | help: move it here: `where u32: Copy, i32: Copy` +LL | type Assoc2 where u32: Copy, i32: Copy = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - help: move it here: `where u32: Copy, i32: Copy` error: aborting due to 5 previous errors diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3f4043ad052a0..3a47845ec82ce 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -279,20 +279,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (ForeignMod(l), ForeignMod(r)) => { both(&l.abi, &r.abi, eq_str_lit) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind)) }, - ( - TyAlias(box ast::TyAlias { - defaultness: ld, - generics: lg, - bounds: lb, - ty: lt, - }), - TyAlias(box ast::TyAlias { - defaultness: rd, - generics: rg, - bounds: rb, - ty: rt, - }), - ) => { + (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }), + TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt, .. })) => { eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) @@ -382,20 +370,8 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) }, - ( - TyAlias(box ast::TyAlias { - defaultness: ld, - generics: lg, - bounds: lb, - ty: lt, - }), - TyAlias(box ast::TyAlias { - defaultness: rd, - generics: rg, - bounds: rb, - ty: rt, - }), - ) => { + (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }), + TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt, .. })) => { eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) @@ -426,20 +402,8 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ) => { eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r)) }, - ( - TyAlias(box ast::TyAlias { - defaultness: ld, - generics: lg, - bounds: lb, - ty: lt, - }), - TyAlias(box ast::TyAlias { - defaultness: rd, - generics: rg, - bounds: rb, - ty: rt, - }), - ) => { + (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt, .. }), + TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt, .. })) => { eq_defaultness(*ld, *rd) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index babc56f86edc6..8498cb6addaa1 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -694,7 +694,8 @@ pub(crate) fn format_impl( let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{"); let where_clause_str = rewrite_where_clause( context, - &generics.where_clause, + &generics.where_clause.predicates, + generics.where_clause.span, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), false, @@ -1059,7 +1060,8 @@ pub(crate) fn format_trait( let option = WhereClauseOption::snuggled(&generics_str); let where_clause_str = rewrite_where_clause( context, - &generics.where_clause, + &generics.where_clause.predicates, + generics.where_clause.span, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), where_on_new_line, @@ -1178,7 +1180,8 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { let where_str = rewrite_where_clause( context, - &self.generics.where_clause, + &self.generics.where_clause.predicates, + self.generics.where_clause.span, context.config.brace_style(), shape, false, @@ -1437,7 +1440,8 @@ fn format_tuple_struct( let option = WhereClauseOption::new(true, WhereClauseSpace::Newline); rewrite_where_clause( context, - &generics.where_clause, + &generics.where_clause.predicates, + generics.where_clause.span, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), false, @@ -1503,6 +1507,8 @@ struct TyAliasRewriteInfo<'c, 'g>( &'c RewriteContext<'c>, Indent, &'g ast::Generics, + (ast::TyAliasWhereClause, ast::TyAliasWhereClause), + usize, symbol::Ident, Span, ); @@ -1521,6 +1527,8 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( ref generics, ref bounds, ref ty, + where_clauses, + where_predicates_split, } = *ty_alias_kind; let ty_opt = ty.as_ref(); let (ident, vis) = match visitor_kind { @@ -1528,7 +1536,15 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis), ForeignItem(i) => (i.ident, &i.vis), }; - let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span); + let rw_info = &TyAliasRewriteInfo( + context, + indent, + generics, + where_clauses, + where_predicates_split, + ident, + span, + ); let op_ty = opaque_ty(ty); // Type Aliases are formatted slightly differently depending on the context // in which they appear, whether they are opaque, and whether they are associated. @@ -1564,7 +1580,22 @@ fn rewrite_ty( vis: &ast::Visibility, ) -> Option { let mut result = String::with_capacity(128); - let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info; + let TyAliasRewriteInfo( + context, + indent, + generics, + where_clauses, + where_predicates_split, + ident, + span, + ) = *rw_info; + let (before_where_predicates, after_where_predicates) = generics + .where_clause + .predicates + .split_at(where_predicates_split); + if !after_where_predicates.is_empty() { + return None; + } result.push_str(&format!("{}type ", format_visibility(context, vis))); let ident_str = rewrite_ident(context, ident); @@ -1595,7 +1626,8 @@ fn rewrite_ty( } let where_clause_str = rewrite_where_clause( context, - &generics.where_clause, + before_where_predicates, + where_clauses.0.1, context.config.brace_style(), Shape::legacy(where_budget, indent), false, @@ -1609,7 +1641,7 @@ fn rewrite_ty( if let Some(ty) = rhs { // If there's a where clause, add a newline before the assignment. Otherwise just add a // space. - let has_where = !generics.where_clause.predicates.is_empty(); + let has_where = !before_where_predicates.is_empty(); if has_where { result.push_str(&indent.to_string_with_newline(context.config)); } else { @@ -1619,7 +1651,7 @@ fn rewrite_ty( let comment_span = context .snippet_provider .opt_span_before(span, "=") - .map(|op_lo| mk_sp(generics.where_clause.span.hi(), op_lo)); + .map(|op_lo| mk_sp(where_clauses.0.1.hi(), op_lo)); let lhs = match comment_span { Some(comment_span) @@ -2176,7 +2208,7 @@ fn rewrite_fn_base( let generics_str = rewrite_generics( context, rewrite_ident(context, ident), - fn_sig.generics, + &fn_sig.generics, shape, )?; result.push_str(&generics_str); @@ -2416,7 +2448,8 @@ fn rewrite_fn_base( } let where_clause_str = rewrite_where_clause( context, - where_clause, + &where_clause.predicates, + where_clause.span, context.config.brace_style(), Shape::indented(indent, context.config), true, @@ -2692,7 +2725,8 @@ fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> O fn rewrite_where_clause_rfc_style( context: &RewriteContext<'_>, - where_clause: &ast::WhereClause, + predicates: &[ast::WherePredicate], + where_span: Span, shape: Shape, terminator: &str, span_end: Option, @@ -2701,7 +2735,8 @@ fn rewrite_where_clause_rfc_style( ) -> Option { let (where_keyword, allow_single_line) = rewrite_where_keyword( context, - where_clause, + predicates, + where_span, shape, span_end_before_where, where_clause_option, @@ -2714,12 +2749,12 @@ fn rewrite_where_clause_rfc_style( .block_left(context.config.tab_spaces())? .sub_width(1)?; let force_single_line = context.config.where_single_line() - && where_clause.predicates.len() == 1 + && predicates.len() == 1 && !where_clause_option.veto_single_line; let preds_str = rewrite_bounds_on_where_clause( context, - where_clause, + predicates, clause_shape, terminator, span_end, @@ -2743,7 +2778,8 @@ fn rewrite_where_clause_rfc_style( /// Rewrite `where` and comment around it. fn rewrite_where_keyword( context: &RewriteContext<'_>, - where_clause: &ast::WhereClause, + predicates: &[ast::WherePredicate], + where_span: Span, shape: Shape, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, @@ -2763,7 +2799,7 @@ fn rewrite_where_keyword( }; let (span_before, span_after) = - missing_span_before_after_where(span_end_before_where, where_clause); + missing_span_before_after_where(span_end_before_where, predicates, where_span); let (comment_before, comment_after) = rewrite_comments_before_after_where(context, span_before, span_after, shape)?; @@ -2789,22 +2825,22 @@ fn rewrite_where_keyword( /// Rewrite bounds on a where clause. fn rewrite_bounds_on_where_clause( context: &RewriteContext<'_>, - where_clause: &ast::WhereClause, + predicates: &[ast::WherePredicate], shape: Shape, terminator: &str, span_end: Option, where_clause_option: WhereClauseOption, force_single_line: bool, ) -> Option { - let span_start = where_clause.predicates[0].span().lo(); + let span_start = predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi(); + let len = predicates.len(); + let end_of_preds = predicates[len - 1].span().hi(); let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list( context.snippet_provider, - where_clause.predicates.iter(), + predicates.iter(), terminator, ",", |pred| pred.span().lo(), @@ -2837,7 +2873,8 @@ fn rewrite_bounds_on_where_clause( fn rewrite_where_clause( context: &RewriteContext<'_>, - where_clause: &ast::WhereClause, + predicates: &[ast::WherePredicate], + where_span: Span, brace_style: BraceStyle, shape: Shape, on_new_line: bool, @@ -2846,14 +2883,15 @@ fn rewrite_where_clause( span_end_before_where: BytePos, where_clause_option: WhereClauseOption, ) -> Option { - if where_clause.predicates.is_empty() { + if predicates.is_empty() { return Some(String::new()); } if context.config.indent_style() == IndentStyle::Block { return rewrite_where_clause_rfc_style( context, - where_clause, + predicates, + where_span, shape, terminator, span_end, @@ -2873,15 +2911,15 @@ fn rewrite_where_clause( // be out by a char or two. let budget = context.config.max_width() - offset.width(); - let span_start = where_clause.predicates[0].span().lo(); + let span_start = predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi(); + let len = predicates.len(); + let end_of_preds = predicates[len - 1].span().hi(); let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list( context.snippet_provider, - where_clause.predicates.iter(), + predicates.iter(), terminator, ",", |pred| pred.span().lo(), @@ -2936,12 +2974,13 @@ fn rewrite_where_clause( fn missing_span_before_after_where( before_item_span_end: BytePos, - where_clause: &ast::WhereClause, + predicates: &[ast::WherePredicate], + where_span: Span, ) -> (Span, Span) { - let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo()); + let missing_span_before = mk_sp(before_item_span_end, where_span.lo()); // 5 = `where` - let pos_after_where = where_clause.span.lo() + BytePos(5); - let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo()); + let pos_after_where = where_span.lo() + BytePos(5); + let missing_span_after = mk_sp(pos_after_where, predicates[0].span().lo()); (missing_span_before, missing_span_after) } @@ -3030,7 +3069,8 @@ fn format_generics( } let where_clause_str = rewrite_where_clause( context, - &generics.where_clause, + &generics.where_clause.predicates, + generics.where_clause.span, brace_style, Shape::legacy(budget, offset.block_only()), true, From 3f504f6984331f9465496d9d96c1f43dab5ce9c6 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Mon, 7 Feb 2022 01:23:37 -0500 Subject: [PATCH 2/7] Change to lint --- .../rustc_ast_passes/src/ast_validation.rs | 23 ++++++++----- compiler/rustc_lint/src/context.rs | 8 +++++ compiler/rustc_lint_defs/src/builtin.rs | 34 +++++++++++++++++++ compiler/rustc_lint_defs/src/lib.rs | 1 + .../bugs/issue-87735.stderr | 8 +++-- .../bugs/issue-87748.stderr | 6 ++-- src/test/ui/parser/type-alias-where.rs | 6 ++-- src/test/ui/parser/type-alias-where.stderr | 10 +++--- 8 files changed, 75 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0b97a1b181450..c519d05d2275c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -15,7 +15,9 @@ 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; -use rustc_session::lint::builtin::{MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY}; +use rustc_session::lint::builtin::{ + DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, +}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; use rustc_span::source_map::Spanned; @@ -123,11 +125,11 @@ impl<'a> AstValidator<'a> { } fn check_gat_where( - &self, + &mut self, + id: NodeId, 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 { @@ -145,14 +147,16 @@ impl<'a> AstValidator<'a> { 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( + self.lint_buffer.buffer_lint_with_diagnostic( + DEPRECATED_WHERE_CLAUSE_LOCATION, + id, + where_clauses.0.1, + "where clause not allowed here", + BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( where_clauses.1.1.shrink_to_hi(), - "move it here", suggestion, - Applicability::MachineApplicable, - ) - .emit(); + ), + ); } } @@ -1568,6 +1572,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_type_no_bounds(bounds, "`impl`s"); if ty.is_some() { self.check_gat_where( + item.id, generics.where_clause.predicates.split_at(*where_predicates_split).0, *where_clauses, ); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index c6bbf769b2349..92adb718933f4 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -818,6 +818,14 @@ pub trait LintContext: Sized { } } }, + BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => { + db.span_suggestion( + new_span, + "move it here", + suggestion, + Applicability::MachineApplicable, + ); + }, } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 272913f3f0e02..04a339f3c95a6 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3127,6 +3127,7 @@ declare_lint_pass! { DUPLICATE_MACRO_ATTRIBUTES, SUSPICIOUS_AUTO_TRAIT_IMPLS, UNEXPECTED_CFGS, + DEPRECATED_WHERE_CLAUSE_LOCATION, ] } @@ -3737,3 +3738,36 @@ declare_lint! { reference: "issue #93367 ", }; } + +declare_lint! { + /// The `deprecated_where_clause_location` lint detects when a where clause in front of the equals + /// in an associated type. + /// + /// ### Example + /// + /// ```rust + /// #![feature(generic_associated_types)] + /// + /// trait Trait { + /// type Assoc<'a> where Self: 'a; + /// } + /// + /// impl Trait for () { + /// type Assoc<'a> where Self: 'a = (); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The preferred location for where clauses on associated types in impls + /// is after the type. However, for most of generic associated types development, + /// it was only accepted before the equals. To provide a transition period and + /// further evaluate this change, both are currently accepted. At some point in + /// the future, this may be disallowed at an edition boundary; but, that is + /// undecided currently. + pub DEPRECATED_WHERE_CLAUSE_LOCATION, + Warn, + "deprecated where clause location" +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index e7f6dfa67b9a6..cd328b087358c 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -427,6 +427,7 @@ pub enum BuiltinLintDiagnostics { NamedAsmLabel(String), UnicodeTextFlow(Span, String), UnexpectedCfg((Symbol, Span), Option<(Symbol, Span)>), + DeprecatedWhereclauseLocation(Span, String), } /// Lints that are buffered up early on in the `Session` before the 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 a64e52124c8bf..a694f1ffaad92 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr @@ -1,10 +1,12 @@ -error: where clause not allowed here +warning: 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` + | + = note: `#[warn(deprecated_where_clause_location)]` on by default -error: where clause not allowed here +warning: where clause not allowed here --> $DIR/issue-87735.rs:36:19 | LL | type Output<'a> where Self: 'a = FooRef<'a, U>; @@ -16,6 +18,6 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self LL | impl<'b, T, U> AsRef2 for Foo | ^ unconstrained type parameter -error: aborting due to 3 previous errors +error: aborting due to previous error; 2 warnings emitted 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 f92930fc94845..9a7cdd02eab02 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr @@ -1,8 +1,10 @@ -error: where clause not allowed here +warning: 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` + | + = note: `#[warn(deprecated_where_clause_location)]` on by default error[E0478]: lifetime bound not satisfied --> $DIR/issue-87748.rs:18:5 @@ -21,6 +23,6 @@ note: but lifetime parameter must outlive the anonymous lifetime #1 defined here LL | fn do_sth(_: u32) {} | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/parser/type-alias-where.rs b/src/test/ui/parser/type-alias-where.rs index 99ab8a7c48ccf..941acd5b5ab97 100644 --- a/src/test/ui/parser/type-alias-where.rs +++ b/src/test/ui/parser/type-alias-where.rs @@ -20,10 +20,10 @@ trait Trait { impl Trait for u32 { // Not fine, suggests moving. type Assoc where u32: Copy = (); - //~^ ERROR where clause not allowed here + //~^ WARNING where clause not allowed here // Not fine, suggests moving `u32: Copy` type Assoc2 where u32: Copy = () where i32: Copy; - //~^ ERROR where clause not allowed here + //~^ WARNING where clause not allowed here } impl Trait for i32 { @@ -31,7 +31,7 @@ impl Trait for i32 { type Assoc = () where u32: Copy; // Not fine, suggests moving both. type Assoc2 where u32: Copy, i32: Copy = (); - //~^ ERROR where clause not allowed here + //~^ WARNING where clause not allowed here } fn main() {} diff --git a/src/test/ui/parser/type-alias-where.stderr b/src/test/ui/parser/type-alias-where.stderr index 4cc8b703cede9..166302c9e1dd7 100644 --- a/src/test/ui/parser/type-alias-where.stderr +++ b/src/test/ui/parser/type-alias-where.stderr @@ -10,23 +10,25 @@ error: where clauses are not allowed after the type for type aliases LL | type Baz = () where; | ^^^^^ -error: where clause not allowed here +warning: where clause not allowed here --> $DIR/type-alias-where.rs:22:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ - help: move it here: `where u32: Copy` + | + = note: `#[warn(deprecated_where_clause_location)]` on by default -error: where clause not allowed here +warning: where clause not allowed here --> $DIR/type-alias-where.rs:25:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ - help: move it here: `, u32: Copy` -error: where clause not allowed here +warning: where clause not allowed here --> $DIR/type-alias-where.rs:33:17 | LL | type Assoc2 where u32: Copy, i32: Copy = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - help: move it here: `where u32: Copy, i32: Copy` -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors; 3 warnings emitted From c920eb88b247c40a64437db54c652f14b83113c3 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Mon, 7 Feb 2022 12:20:09 -0500 Subject: [PATCH 3/7] Fallback to other where clause if preferred is missing --- compiler/rustc_ast_lowering/src/item.rs | 32 ++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 77c5797442a55..b452290dff460 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -25,6 +25,26 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>, } +/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span +/// to the where clause that is prefered, if it exists. Otherwise, it sets the span to the other where +/// clause if it exists. +fn add_ty_alias_where_clause( + generics: &mut ast::Generics, + mut where_clauses: (TyAliasWhereClause, TyAliasWhereClause), + prefer_first: bool, +) { + if !prefer_first { + where_clauses = (where_clauses.1, where_clauses.0); + } + 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; + } +} + impl ItemLowerer<'_, '_, '_> { fn with_trait_impl_ref( &mut self, @@ -298,8 +318,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ); let mut generics = generics.clone(); - generics.where_clause.has_where_token = where_clauses.0.0; - generics.where_clause.span = where_clauses.0.1; + add_ty_alias_where_clause(&mut generics, where_clauses, true); let generics = self.lower_generics( &generics, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -311,8 +330,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => { 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; + add_ty_alias_where_clause(&mut generics, *where_clauses, true); let generics = self.lower_generics( &generics, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -856,8 +874,7 @@ impl<'hir> LoweringContext<'_, 'hir> { 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; + add_ty_alias_where_clause(&mut generics, where_clauses, false); let generics = self.lower_generics( &generics, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -941,8 +958,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } 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; + add_ty_alias_where_clause(&mut generics, *where_clauses, false); let generics = self.lower_generics( &generics, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), From 2b151fd5c8a106f276477357b5371d1184d940d4 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Mon, 14 Feb 2022 13:00:10 -0500 Subject: [PATCH 4/7] Review changes --- compiler/rustc_ast/src/ast.rs | 12 ++++++ .../rustc_ast_passes/src/ast_validation.rs | 8 +++- compiler/rustc_lint/src/context.rs | 10 +++-- .../ui/parser/type-alias-where-fixable.fixed | 30 +++++++++++++ .../ui/parser/type-alias-where-fixable.rs | 30 +++++++++++++ .../ui/parser/type-alias-where-fixable.stderr | 42 +++++++++++++++++++ src/test/ui/parser/type-alias-where.rs | 24 ----------- src/test/ui/parser/type-alias-where.stderr | 24 ++--------- 8 files changed, 130 insertions(+), 50 deletions(-) create mode 100644 src/test/ui/parser/type-alias-where-fixable.fixed create mode 100644 src/test/ui/parser/type-alias-where-fixable.rs create mode 100644 src/test/ui/parser/type-alias-where-fixable.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2fbafca1681c7..ad1d4430c6b19 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2666,6 +2666,18 @@ pub struct Trait { /// 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. +/// +/// Take this example: +/// ```rust, ignore +/// trait Foo { +/// type Assoc<'a, 'b> where Self: 'a, Self: 'b; +/// } +/// impl Foo for () { +/// type Assoc<'a, 'b> where Self: 'a = () where Self: 'b; +/// // ^^^^^^^^^^^^^^ first where clause +/// // ^^^^^^^^^^^^^^ second where clause +/// } +/// ``` #[derive(Copy, Clone, Encodable, Decodable, Debug, Default)] pub struct TyAliasWhereClause(pub bool, pub Span); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c519d05d2275c..0cf73178d679d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1275,10 +1275,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } self.check_type_no_bounds(bounds, "this context"); if where_clauses.1.0 { - self.err_handler().span_err( + let mut err = self.err_handler().struct_span_err( where_clauses.1.1, "where clauses are not allowed after the type for type aliases", - ) + ); + err.note( + "see issue #89122 for more information", + ); + err.emit(); } } _ => {} diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 92adb718933f4..b892e520d3bde 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -819,12 +819,14 @@ pub trait LintContext: Sized { } }, BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => { - db.span_suggestion( - new_span, - "move it here", - suggestion, + db.multipart_suggestion( + "move it to the end of the type declaration", + vec![(db.span.primary_span().unwrap(), "".to_string()), (new_span, suggestion)], Applicability::MachineApplicable, ); + db.note( + "see issue #89122 for more information", + ); }, } // Rewrap `db`, and pass control to the user. diff --git a/src/test/ui/parser/type-alias-where-fixable.fixed b/src/test/ui/parser/type-alias-where-fixable.fixed new file mode 100644 index 0000000000000..41dd10676d5fd --- /dev/null +++ b/src/test/ui/parser/type-alias-where-fixable.fixed @@ -0,0 +1,30 @@ +// check-pass +// run-rustfix + +#![feature(generic_associated_types)] + +trait Trait { + // Fine. + type Assoc where u32: Copy; + // Fine. + type Assoc2 where u32: Copy, i32: Copy; +} + +impl Trait for u32 { + // Not fine, suggests moving. + type Assoc = () where u32: Copy; + //~^ WARNING where clause not allowed here + // Not fine, suggests moving `u32: Copy` + type Assoc2 = () where i32: Copy, u32: Copy; + //~^ WARNING where clause not allowed here +} + +impl Trait for i32 { + // Fine. + type Assoc = () where u32: Copy; + // Not fine, suggests moving both. + type Assoc2 = () where u32: Copy, i32: Copy; + //~^ WARNING where clause not allowed here +} + +fn main() {} diff --git a/src/test/ui/parser/type-alias-where-fixable.rs b/src/test/ui/parser/type-alias-where-fixable.rs new file mode 100644 index 0000000000000..562a530a7f302 --- /dev/null +++ b/src/test/ui/parser/type-alias-where-fixable.rs @@ -0,0 +1,30 @@ +// check-pass +// run-rustfix + +#![feature(generic_associated_types)] + +trait Trait { + // Fine. + type Assoc where u32: Copy; + // Fine. + type Assoc2 where u32: Copy, i32: Copy; +} + +impl Trait for u32 { + // Not fine, suggests moving. + type Assoc where u32: Copy = (); + //~^ WARNING where clause not allowed here + // Not fine, suggests moving `u32: Copy` + type Assoc2 where u32: Copy = () where i32: Copy; + //~^ WARNING where clause not allowed here +} + +impl Trait for i32 { + // Fine. + type Assoc = () where u32: Copy; + // Not fine, suggests moving both. + type Assoc2 where u32: Copy, i32: Copy = (); + //~^ WARNING where clause not allowed here +} + +fn main() {} diff --git a/src/test/ui/parser/type-alias-where-fixable.stderr b/src/test/ui/parser/type-alias-where-fixable.stderr new file mode 100644 index 0000000000000..7ec1a965bae72 --- /dev/null +++ b/src/test/ui/parser/type-alias-where-fixable.stderr @@ -0,0 +1,42 @@ +warning: where clause not allowed here + --> $DIR/type-alias-where-fixable.rs:15:16 + | +LL | type Assoc where u32: Copy = (); + | ^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated_where_clause_location)]` on by default + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL - type Assoc where u32: Copy = (); +LL + type Assoc = () where u32: Copy; + | + +warning: where clause not allowed here + --> $DIR/type-alias-where-fixable.rs:18:17 + | +LL | type Assoc2 where u32: Copy = () where i32: Copy; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL - type Assoc2 where u32: Copy = () where i32: Copy; +LL + type Assoc2 = () where i32: Copy, u32: Copy; + | + +warning: where clause not allowed here + --> $DIR/type-alias-where-fixable.rs:26:17 + | +LL | type Assoc2 where u32: Copy, i32: Copy = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL - type Assoc2 where u32: Copy, i32: Copy = (); +LL + type Assoc2 = () where u32: Copy, i32: Copy; + | + +warning: 3 warnings emitted + diff --git a/src/test/ui/parser/type-alias-where.rs b/src/test/ui/parser/type-alias-where.rs index 941acd5b5ab97..f6e7dfb7b7b2e 100644 --- a/src/test/ui/parser/type-alias-where.rs +++ b/src/test/ui/parser/type-alias-where.rs @@ -10,28 +10,4 @@ type Bar = () where u32: Copy; type Baz = () where; //~^ ERROR where clauses are not allowed -trait Trait { - // Fine. - type Assoc where u32: Copy; - // Fine. - type Assoc2 where u32: Copy, i32: Copy; -} - -impl Trait for u32 { - // Not fine, suggests moving. - type Assoc where u32: Copy = (); - //~^ WARNING where clause not allowed here - // Not fine, suggests moving `u32: Copy` - type Assoc2 where u32: Copy = () where i32: Copy; - //~^ WARNING where clause not allowed here -} - -impl Trait for i32 { - // Fine. - type Assoc = () where u32: Copy; - // Not fine, suggests moving both. - type Assoc2 where u32: Copy, i32: Copy = (); - //~^ WARNING where clause not allowed here -} - fn main() {} diff --git a/src/test/ui/parser/type-alias-where.stderr b/src/test/ui/parser/type-alias-where.stderr index 166302c9e1dd7..8789d2665ad92 100644 --- a/src/test/ui/parser/type-alias-where.stderr +++ b/src/test/ui/parser/type-alias-where.stderr @@ -3,32 +3,16 @@ error: where clauses are not allowed after the type for type aliases | LL | type Bar = () where u32: Copy; | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information error: where clauses are not allowed after the type for type aliases --> $DIR/type-alias-where.rs:10:15 | LL | type Baz = () where; | ^^^^^ - -warning: where clause not allowed here - --> $DIR/type-alias-where.rs:22:16 - | -LL | type Assoc where u32: Copy = (); - | ^^^^^^^^^^^^^^^ - help: move it here: `where u32: Copy` - | - = note: `#[warn(deprecated_where_clause_location)]` on by default - -warning: where clause not allowed here - --> $DIR/type-alias-where.rs:25:17 - | -LL | type Assoc2 where u32: Copy = () where i32: Copy; - | ^^^^^^^^^^^^^^^ - help: move it here: `, u32: Copy` - -warning: where clause not allowed here - --> $DIR/type-alias-where.rs:33:17 | -LL | type Assoc2 where u32: Copy, i32: Copy = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - help: move it here: `where u32: Copy, i32: Copy` + = note: see issue #89122 for more information -error: aborting due to 2 previous errors; 3 warnings emitted +error: aborting due to 2 previous errors From 084c0f36efb44ccce8c523b6fdd9726aa5df6da1 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Mon, 14 Feb 2022 14:10:01 -0500 Subject: [PATCH 5/7] Update new tests --- .../generic-associated-types/bugs/issue-87735.rs | 4 ++-- .../bugs/issue-87735.stderr | 16 +--------------- .../generic-associated-types/bugs/issue-87748.rs | 2 +- .../bugs/issue-87748.stderr | 10 +--------- 4 files changed, 5 insertions(+), 27 deletions(-) diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs index 6d6063f8085ba..53e3ad7fe6943 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs @@ -12,7 +12,7 @@ pub trait AsRef2 { } impl AsRef2 for Vec { - type Output<'a> where Self: 'a = &'a [T]; + type Output<'a> = &'a [T] where Self: 'a; fn as_ref2<'a>(&'a self) -> Self::Output<'a> { &self[..] @@ -33,7 +33,7 @@ where T: AsRef2 = &'b [U]>, U: 'b { - type Output<'a> where Self: 'a = FooRef<'a, U>; + type Output<'a> = FooRef<'a, U> where Self: 'a; fn as_ref2<'a>(&'a self) -> Self::Output<'a> { FooRef(self.0.as_ref2()) 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 a694f1ffaad92..0a18b5f0cbdaa 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr @@ -1,23 +1,9 @@ -warning: 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` - | - = note: `#[warn(deprecated_where_clause_location)]` on by default - -warning: 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; 2 warnings emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs index ffcfd62cbb3be..6e7cd45bdb1f6 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs @@ -13,7 +13,7 @@ trait MyTrait { struct Foo; impl MyTrait for Foo { - type Assoc<'a, 'b> where 'b: 'a = u32; + type Assoc<'a, 'b> = u32 where 'b: 'a; fn do_sth(_: u32) {} // fn do_sth(_: Self::Assoc<'static, 'static>) {} 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 9a7cdd02eab02..60bb48efbc895 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr @@ -1,11 +1,3 @@ -warning: 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` - | - = note: `#[warn(deprecated_where_clause_location)]` on by default - error[E0478]: lifetime bound not satisfied --> $DIR/issue-87748.rs:18:5 | @@ -23,6 +15,6 @@ note: but lifetime parameter must outlive the anonymous lifetime #1 defined here LL | fn do_sth(_: u32) {} | ^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0478`. From 9dc05f383279765a4ab587c3972b73d93fbf3148 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 4 Mar 2022 23:21:33 -0500 Subject: [PATCH 6/7] Add commment covering the case with no where clause --- compiler/rustc_ast/src/ast.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ad1d4430c6b19..3ba4c11e2c1fa 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2677,6 +2677,8 @@ pub struct Trait { /// // ^^^^^^^^^^^^^^ first where clause /// // ^^^^^^^^^^^^^^ second where clause /// } +/// +/// If there is no where clause, then this is `false` with `DUMMY_SP`. /// ``` #[derive(Copy, Clone, Encodable, Decodable, Debug, Default)] pub struct TyAliasWhereClause(pub bool, pub Span); From d16ec7b9d1bc6550af3a68e250582a628f5be800 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sat, 5 Mar 2022 19:38:53 -0500 Subject: [PATCH 7/7] Ignore --- compiler/rustc_ast/src/ast.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3ba4c11e2c1fa..ed5a282ec0635 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2668,7 +2668,7 @@ pub struct Trait { /// are concatenated together. /// /// Take this example: -/// ```rust, ignore +/// ```ignore (only-for-syntax-highlight) /// trait Foo { /// type Assoc<'a, 'b> where Self: 'a, Self: 'b; /// } @@ -2677,9 +2677,9 @@ pub struct Trait { /// // ^^^^^^^^^^^^^^ first where clause /// // ^^^^^^^^^^^^^^ second where clause /// } +/// ``` /// /// If there is no where clause, then this is `false` with `DUMMY_SP`. -/// ``` #[derive(Copy, Clone, Encodable, Decodable, Debug, Default)] pub struct TyAliasWhereClause(pub bool, pub Span);