Skip to content

Commit bee1471

Browse files
authored
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
2 parents e313143 + 4391a11 commit bee1471

File tree

4 files changed

+158
-28
lines changed

4 files changed

+158
-28
lines changed

compiler/rustc_ast_pretty/src/pprust/state.rs

+28-28
Original file line numberDiff line numberDiff line change
@@ -2780,34 +2780,34 @@ impl<'a> State<'a> {
27802780
self.word_space(",");
27812781
}
27822782

2783-
match *predicate {
2784-
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
2785-
ref bound_generic_params,
2786-
ref bounded_ty,
2787-
ref bounds,
2788-
..
2789-
}) => {
2790-
self.print_formal_generic_params(bound_generic_params);
2791-
self.print_type(bounded_ty);
2792-
self.print_type_bounds(":", bounds);
2793-
}
2794-
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
2795-
ref lifetime,
2796-
ref bounds,
2797-
..
2798-
}) => {
2799-
self.print_lifetime_bounds(*lifetime, bounds);
2800-
}
2801-
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
2802-
ref lhs_ty,
2803-
ref rhs_ty,
2804-
..
2805-
}) => {
2806-
self.print_type(lhs_ty);
2807-
self.space();
2808-
self.word_space("=");
2809-
self.print_type(rhs_ty);
2810-
}
2783+
self.print_where_predicate(predicate);
2784+
}
2785+
}
2786+
2787+
pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
2788+
match predicate {
2789+
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
2790+
bound_generic_params,
2791+
bounded_ty,
2792+
bounds,
2793+
..
2794+
}) => {
2795+
self.print_formal_generic_params(bound_generic_params);
2796+
self.print_type(bounded_ty);
2797+
self.print_type_bounds(":", bounds);
2798+
}
2799+
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
2800+
lifetime,
2801+
bounds,
2802+
..
2803+
}) => {
2804+
self.print_lifetime_bounds(*lifetime, bounds);
2805+
}
2806+
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
2807+
self.print_type(lhs_ty);
2808+
self.space();
2809+
self.word_space("=");
2810+
self.print_type(rhs_ty);
28112811
}
28122812
}
28132813
}

compiler/rustc_parse/src/parser/item.rs

+53
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,44 @@ impl<'a> Parser<'a> {
794794
))
795795
}
796796

797+
/// Emits an error that the where clause at the end of a type alias is not
798+
/// allowed and suggests moving it.
799+
fn error_ty_alias_where(
800+
&self,
801+
before_where_clause_present: bool,
802+
before_where_clause_span: Span,
803+
after_predicates: &[WherePredicate],
804+
after_where_clause_span: Span,
805+
) {
806+
let mut err =
807+
self.struct_span_err(after_where_clause_span, "where clause not allowed here");
808+
if !after_predicates.is_empty() {
809+
let mut state = crate::pprust::State::new();
810+
if !before_where_clause_present {
811+
state.space();
812+
state.word_space("where");
813+
} else {
814+
state.word_space(",");
815+
}
816+
let mut first = true;
817+
for p in after_predicates.iter() {
818+
if !first {
819+
state.word_space(",");
820+
}
821+
first = false;
822+
state.print_where_predicate(p);
823+
}
824+
let suggestion = state.s.eof();
825+
err.span_suggestion(
826+
before_where_clause_span.shrink_to_hi(),
827+
"move it here",
828+
suggestion,
829+
Applicability::MachineApplicable,
830+
);
831+
}
832+
err.emit()
833+
}
834+
797835
/// Parses a `type` alias with the following grammar:
798836
/// ```
799837
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
@@ -806,9 +844,24 @@ impl<'a> Parser<'a> {
806844
// Parse optional colon and param bounds.
807845
let bounds =
808846
if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
847+
809848
generics.where_clause = self.parse_where_clause()?;
810849

811850
let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
851+
852+
if self.token.is_keyword(kw::Where) {
853+
let after_where_clause = self.parse_where_clause()?;
854+
855+
self.error_ty_alias_where(
856+
generics.where_clause.has_where_token,
857+
generics.where_clause.span,
858+
&after_where_clause.predicates,
859+
after_where_clause.span,
860+
);
861+
862+
generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter());
863+
}
864+
812865
self.expect_semi()?;
813866

814867
Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// check-fail
2+
3+
#![feature(generic_associated_types)]
4+
5+
// Fine, but lints as unused
6+
type Foo where u32: Copy = ();
7+
// Not fine.
8+
type Bar = () where u32: Copy;
9+
//~^ ERROR where clause not allowed here
10+
type Baz = () where;
11+
//~^ ERROR where clause not allowed here
12+
13+
trait Trait {
14+
// Fine.
15+
type Assoc where u32: Copy;
16+
// Fine.
17+
type Assoc2 where u32: Copy, i32: Copy;
18+
}
19+
20+
impl Trait for u32 {
21+
// Fine.
22+
type Assoc where u32: Copy = ();
23+
// Not fine, suggests moving `i32: Copy`
24+
type Assoc2 where u32: Copy = () where i32: Copy;
25+
//~^ ERROR where clause not allowed here
26+
}
27+
28+
impl Trait for i32 {
29+
// Not fine, suggests moving `u32: Copy`
30+
type Assoc = () where u32: Copy;
31+
//~^ ERROR where clause not allowed here
32+
// Not fine, suggests moving both.
33+
type Assoc2 = () where u32: Copy, i32: Copy;
34+
//~^ ERROR where clause not allowed here
35+
}
36+
37+
fn main() {}
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
error: where clause not allowed here
2+
--> $DIR/type-alias-where.rs:8:15
3+
|
4+
LL | type Bar = () where u32: Copy;
5+
| - ^^^^^^^^^^^^^^^
6+
| |
7+
| help: move it here: `where u32: Copy`
8+
9+
error: where clause not allowed here
10+
--> $DIR/type-alias-where.rs:10:15
11+
|
12+
LL | type Baz = () where;
13+
| ^^^^^
14+
15+
error: where clause not allowed here
16+
--> $DIR/type-alias-where.rs:24:38
17+
|
18+
LL | type Assoc2 where u32: Copy = () where i32: Copy;
19+
| - ^^^^^^^^^^^^^^^
20+
| |
21+
| help: move it here: `, i32: Copy`
22+
23+
error: where clause not allowed here
24+
--> $DIR/type-alias-where.rs:30:21
25+
|
26+
LL | type Assoc = () where u32: Copy;
27+
| - ^^^^^^^^^^^^^^^
28+
| |
29+
| help: move it here: `where u32: Copy`
30+
31+
error: where clause not allowed here
32+
--> $DIR/type-alias-where.rs:33:22
33+
|
34+
LL | type Assoc2 = () where u32: Copy, i32: Copy;
35+
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
| |
37+
| help: move it here: `where u32: Copy, i32: Copy`
38+
39+
error: aborting due to 5 previous errors
40+

0 commit comments

Comments
 (0)