diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2021-12-29 10:17:08 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-12-29 10:17:08 +0100 |
| commit | bee14712ab2993c0c6a8af9c72dbfa9b149b7f8d (patch) | |
| tree | 610e13cbefe6dfbb2fbb5b9a0e6688acf4172fd1 | |
| parent | e31314307f09cef0989e2e052b1cad75d0a9e723 (diff) | |
| parent | 4391a11537ce38c919058c292e91f059d658da94 (diff) | |
| download | rust-bee14712ab2993c0c6a8af9c72dbfa9b149b7f8d.tar.gz rust-bee14712ab2993c0c6a8af9c72dbfa9b149b7f8d.zip | |
Rollup merge of #92118 - jackh726:type-alias-position-error, r=petrochenkov
Parse and suggest moving where clauses after equals for type aliases ~Mostly the same as #90076, but doesn't make any syntax changes.~ Whether or not we want to land the syntax changes, we should parse the invalid where clause position and suggest moving. r? `@nikomatsakis` cc `@petrochenkov` you might have thoughts on implementation
| -rw-r--r-- | compiler/rustc_ast_pretty/src/pprust/state.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 53 | ||||
| -rw-r--r-- | src/test/ui/parser/type-alias-where.rs | 37 | ||||
| -rw-r--r-- | src/test/ui/parser/type-alias-where.stderr | 40 |
4 files changed, 158 insertions, 28 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 6c5b38bc4bb..4464b5eee96 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2780,34 +2780,34 @@ impl<'a> State<'a> { self.word_space(","); } - match *predicate { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_generic_params, - ref bounded_ty, - ref bounds, - .. - }) => { - self.print_formal_generic_params(bound_generic_params); - self.print_type(bounded_ty); - self.print_type_bounds(":", bounds); - } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - ref lifetime, - ref bounds, - .. - }) => { - self.print_lifetime_bounds(*lifetime, bounds); - } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - self.print_type(lhs_ty); - self.space(); - self.word_space("="); - self.print_type(rhs_ty); - } + self.print_where_predicate(predicate); + } + } + + pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) { + match predicate { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + bound_generic_params, + bounded_ty, + bounds, + .. + }) => { + self.print_formal_generic_params(bound_generic_params); + self.print_type(bounded_ty); + self.print_type_bounds(":", bounds); + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + lifetime, + bounds, + .. + }) => { + self.print_lifetime_bounds(*lifetime, bounds); + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + self.print_type(lhs_ty); + self.space(); + self.word_space("="); + self.print_type(rhs_ty); } } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 618aa3fd002..d335ef8788b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -794,6 +794,44 @@ 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, + ) { + 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}? ";" ; @@ -806,9 +844,24 @@ 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 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, + ); + + generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter()); + } + self.expect_semi()?; Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty })))) diff --git a/src/test/ui/parser/type-alias-where.rs b/src/test/ui/parser/type-alias-where.rs new file mode 100644 index 00000000000..a9fa23dd95e --- /dev/null +++ b/src/test/ui/parser/type-alias-where.rs @@ -0,0 +1,37 @@ +// check-fail + +#![feature(generic_associated_types)] + +// Fine, but lints as unused +type Foo where u32: Copy = (); +// Not fine. +type Bar = () where u32: Copy; +//~^ ERROR where clause not allowed here +type Baz = () where; +//~^ ERROR where clause not allowed here + +trait Trait { + // Fine. + type Assoc where u32: Copy; + // Fine. + type Assoc2 where u32: Copy, i32: Copy; +} + +impl Trait for u32 { + // Fine. + type Assoc where u32: Copy = (); + // Not fine, suggests moving `i32: 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` + type Assoc = () where u32: Copy; + //~^ ERROR where clause not allowed here + // Not fine, suggests moving both. + type Assoc2 = () where u32: Copy, i32: Copy; + //~^ ERROR 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 new file mode 100644 index 00000000000..7ab0b28c864 --- /dev/null +++ b/src/test/ui/parser/type-alias-where.stderr @@ -0,0 +1,40 @@ +error: where clause not allowed here + --> $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 + --> $DIR/type-alias-where.rs:10:15 + | +LL | type Baz = () where; + | ^^^^^ + +error: where clause not allowed here + --> $DIR/type-alias-where.rs:24:38 + | +LL | type Assoc2 where u32: Copy = () where i32: Copy; + | - ^^^^^^^^^^^^^^^ + | | + | help: move it here: `, i32: Copy` + +error: where clause not allowed here + --> $DIR/type-alias-where.rs:30:21 + | +LL | type Assoc = () where u32: Copy; + | - ^^^^^^^^^^^^^^^ + | | + | help: move it here: `where u32: Copy` + +error: where clause not allowed here + --> $DIR/type-alias-where.rs:33:22 + | +LL | type Assoc2 = () where u32: Copy, i32: Copy; + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: move it here: `where u32: Copy, i32: Copy` + +error: aborting due to 5 previous errors + |
