Skip to content

Commit 9f3dfd2

Browse files
committed
parse: allow type Foo: Ord syntactically.
1 parent 14442e0 commit 9f3dfd2

18 files changed

+160
-61
lines changed

src/librustc_ast_lowering/item.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -297,28 +297,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
297297
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
298298
ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
299299
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
300-
ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() {
300+
ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
301301
None => {
302302
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
303303
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
304304
hir::ItemKind::TyAlias(ty, generics)
305305
}
306306
Some(bounds) => {
307+
let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
307308
let ty = hir::OpaqueTy {
308-
generics: self.lower_generics(
309-
generics,
310-
ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
311-
),
312-
bounds: self.lower_param_bounds(
313-
bounds,
314-
ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
315-
),
309+
generics: self.lower_generics(generics, ctx()),
310+
bounds: self.lower_param_bounds(bounds, ctx()),
316311
impl_trait_fn: None,
317312
origin: hir::OpaqueTyOrigin::TypeAlias,
318313
};
319314
hir::ItemKind::OpaqueTy(ty)
320315
}
321316
},
317+
ItemKind::TyAlias(ref generics, _, None) => {
318+
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
319+
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
320+
hir::ItemKind::TyAlias(ty, generics)
321+
}
322322
ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
323323
hir::EnumDef {
324324
variants: self.arena.alloc_from_iter(

src/librustc_ast_lowering/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
462462
ItemKind::Struct(_, ref generics)
463463
| ItemKind::Union(_, ref generics)
464464
| ItemKind::Enum(_, ref generics)
465-
| ItemKind::TyAlias(_, ref generics)
465+
| ItemKind::TyAlias(ref generics, ..)
466466
| ItemKind::Trait(_, _, ref generics, ..) => {
467467
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
468468
let count = generics

src/librustc_ast_passes/ast_validation.rs

+7
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
969969
let msg = "free static item without body";
970970
self.error_item_without_body(item.span, "static", msg, " = <expr>;");
971971
}
972+
ItemKind::TyAlias(_, ref bounds, ref body) => {
973+
if body.is_none() {
974+
let msg = "free type alias without body";
975+
self.error_item_without_body(item.span, "type", msg, " = <type>;");
976+
}
977+
self.check_type_no_bounds(bounds, "this context");
978+
}
972979
_ => {}
973980
}
974981

src/librustc_ast_passes/feature_gate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
372372
gate_feature_post!(&self, decl_macro, i.span, msg);
373373
}
374374

375-
ast::ItemKind::TyAlias(ref ty, ..) => self.check_impl_trait(&ty),
375+
ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty),
376376

377377
_ => {}
378378
}

src/librustc_ast_pretty/pprust.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -1185,18 +1185,10 @@ impl<'a> State<'a> {
11851185
self.s.word(ga.asm.to_string());
11861186
self.end();
11871187
}
1188-
ast::ItemKind::TyAlias(ref ty, ref generics) => {
1189-
self.head(visibility_qualified(&item.vis, "type"));
1190-
self.print_ident(item.ident);
1191-
self.print_generic_params(&generics.params);
1192-
self.end(); // end the inner ibox
1193-
1194-
self.print_where_clause(&generics.where_clause);
1195-
self.s.space();
1196-
self.word_space("=");
1197-
self.print_type(ty);
1198-
self.s.word(";");
1199-
self.end(); // end the outer ibox
1188+
ast::ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
1189+
let def = ast::Defaultness::Final;
1190+
let ty = ty.as_deref();
1191+
self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
12001192
}
12011193
ast::ItemKind::Enum(ref enum_definition, ref params) => {
12021194
self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);

src/librustc_parse/parser/item.rs

+12-20
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,7 @@ impl<'a> Parser<'a> {
156156
self.parse_item_mod(attrs)?
157157
} else if self.eat_keyword(kw::Type) {
158158
// TYPE ITEM
159-
let (ident, ty, generics) = self.parse_type_alias()?;
160-
(ident, ItemKind::TyAlias(ty, generics))
159+
self.parse_type_alias()?
161160
} else if self.eat_keyword(kw::Enum) {
162161
// ENUM ITEM
163162
self.parse_item_enum()?
@@ -676,7 +675,10 @@ impl<'a> Parser<'a> {
676675
vis: &Visibility,
677676
) -> PResult<'a, (Ident, AssocItemKind)> {
678677
if self.eat_keyword(kw::Type) {
679-
self.parse_assoc_ty()
678+
match self.parse_type_alias()? {
679+
(ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))),
680+
_ => unreachable!(),
681+
}
680682
} else if self.check_fn_front_matter() {
681683
let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?;
682684
Ok((ident, AssocItemKind::Fn(sig, generics, body)))
@@ -700,10 +702,12 @@ impl<'a> Parser<'a> {
700702
}
701703
}
702704

703-
/// Parses the following grammar:
704-
///
705-
/// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
706-
fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
705+
/// Parses a `type` alias with the following grammar:
706+
/// ```
707+
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
708+
/// ```
709+
/// The `"type"` has already been eaten.
710+
fn parse_type_alias(&mut self) -> PResult<'a, (Ident, ItemKind)> {
707711
let ident = self.parse_ident()?;
708712
let mut generics = self.parse_generics()?;
709713

@@ -715,7 +719,7 @@ impl<'a> Parser<'a> {
715719
let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
716720
self.expect_semi()?;
717721

718-
Ok((ident, AssocItemKind::TyAlias(generics, bounds, default)))
722+
Ok((ident, ItemKind::TyAlias(generics, bounds, default)))
719723
}
720724

721725
/// Parses a `UseTree`.
@@ -989,18 +993,6 @@ impl<'a> Parser<'a> {
989993
P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID })
990994
}
991995

992-
/// Parses the grammar:
993-
/// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
994-
fn parse_type_alias(&mut self) -> PResult<'a, (Ident, P<Ty>, Generics)> {
995-
let ident = self.parse_ident()?;
996-
let mut tps = self.parse_generics()?;
997-
tps.where_clause = self.parse_where_clause()?;
998-
self.expect(&token::Eq)?;
999-
let ty = self.parse_ty()?;
1000-
self.expect_semi()?;
1001-
Ok((ident, ty, tps))
1002-
}
1003-
1004996
/// Parses an enum declaration.
1005997
fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
1006998
let id = self.parse_ident()?;

src/librustc_resolve/build_reduced_graph.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -718,8 +718,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
718718
}
719719

720720
// These items live in the type namespace.
721-
ItemKind::TyAlias(ref ty, _) => {
722-
let def_kind = match ty.kind.opaque_top_hack() {
721+
ItemKind::TyAlias(_, _, ref ty) => {
722+
let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
723723
None => DefKind::TyAlias,
724724
Some(_) => DefKind::OpaqueTy,
725725
};

src/librustc_resolve/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
797797
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
798798

799799
match item.kind {
800-
ItemKind::TyAlias(_, ref generics) | ItemKind::Fn(_, ref generics, _) => {
800+
ItemKind::TyAlias(ref generics, _, _) | ItemKind::Fn(_, ref generics, _) => {
801801
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
802802
visit::walk_item(this, item)
803803
});

src/librustc_save_analysis/dump_visitor.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1311,12 +1311,15 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
13111311
self.process_mod(item);
13121312
visit::walk_mod(self, m);
13131313
}
1314-
TyAlias(ref ty, ref ty_params) => {
1314+
TyAlias(ref ty_params, _, ref ty) => {
13151315
let qualname = format!(
13161316
"::{}",
13171317
self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
13181318
);
1319-
let value = ty_to_string(&ty);
1319+
let value = match ty {
1320+
Some(ty) => ty_to_string(&ty),
1321+
None => "_".to_string(),
1322+
};
13201323
if !self.span.filter_generated(item.ident.span) {
13211324
let span = self.span_from_span(item.ident.span);
13221325
let id = id_from_node_id(item.id, &self.save_ctxt);
@@ -1341,7 +1344,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
13411344
);
13421345
}
13431346

1344-
self.visit_ty(&ty);
1347+
walk_list!(self, visit_ty, ty);
13451348
self.process_generic_params(ty_params, &qualname, item.id);
13461349
}
13471350
Mac(_) => (),

src/librustc_save_analysis/sig.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,15 @@ impl Sig for ast::Item {
423423

424424
Ok(Signature { text, defs, refs: vec![] })
425425
}
426-
ast::ItemKind::TyAlias(ref ty, ref generics) => {
426+
ast::ItemKind::TyAlias(ref generics, _, ref ty) => {
427427
let text = "type ".to_owned();
428428
let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
429429

430430
sig.text.push_str(" = ");
431-
let ty = ty.make(offset + sig.text.len(), id, scx)?;
431+
let ty = match ty {
432+
Some(ty) => ty.make(offset + sig.text.len(), id, scx)?,
433+
None => Err("Ty")?,
434+
};
432435
sig.text.push_str(&ty.text);
433436
sig.text.push(';');
434437

src/libsyntax/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2524,7 +2524,7 @@ pub enum ItemKind {
25242524
/// A type alias (`type`).
25252525
///
25262526
/// E.g., `type Foo = Bar<u8>;`.
2527-
TyAlias(P<Ty>, Generics),
2527+
TyAlias(Generics, GenericBounds, Option<P<Ty>>),
25282528
/// An enum definition (`enum`).
25292529
///
25302530
/// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
@@ -2594,7 +2594,7 @@ impl ItemKind {
25942594
pub fn generics(&self) -> Option<&Generics> {
25952595
match self {
25962596
Self::Fn(_, generics, _)
2597-
| Self::TyAlias(_, generics)
2597+
| Self::TyAlias(generics, ..)
25982598
| Self::Enum(_, generics)
25992599
| Self::Struct(_, generics)
26002600
| Self::Union(_, generics)

src/libsyntax/mut_visit.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -902,9 +902,10 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
902902
ItemKind::Mod(m) => vis.visit_mod(m),
903903
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
904904
ItemKind::GlobalAsm(_ga) => {}
905-
ItemKind::TyAlias(ty, generics) => {
906-
vis.visit_ty(ty);
905+
ItemKind::TyAlias(generics, bounds, ty) => {
907906
vis.visit_generics(generics);
907+
visit_bounds(bounds, vis);
908+
visit_opt(ty, |ty| vis.visit_ty(ty));
908909
}
909910
ItemKind::Enum(EnumDef { variants }, generics) => {
910911
variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));

src/libsyntax/visit.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,10 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
312312
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
313313
}
314314
ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
315-
ItemKind::TyAlias(ref typ, ref generics) => {
316-
visitor.visit_ty(typ);
317-
visitor.visit_generics(generics)
315+
ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
316+
visitor.visit_generics(generics);
317+
walk_list!(visitor, visit_param_bound, bounds);
318+
walk_list!(visitor, visit_ty, ty);
318319
}
319320
ItemKind::Enum(ref enum_definition, ref generics) => {
320321
visitor.visit_generics(generics);

src/test/ui/parser/bounds-lifetime-where.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ type A where 'a:, = u8; // OK
55
type A where 'a: 'b + 'c = u8; // OK
66
type A where = u8; // OK
77
type A where 'a: 'b + = u8; // OK
8-
type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,`
8+
type A where , = u8; //~ ERROR expected one of `;`, `=`, lifetime, or type, found `,`
99

1010
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: expected one of `=`, lifetime, or type, found `,`
1+
error: expected one of `;`, `=`, lifetime, or type, found `,`
22
--> $DIR/bounds-lifetime-where.rs:8:14
33
|
44
LL | type A where , = u8;
5-
| ^ expected one of `=`, lifetime, or type
5+
| ^ expected one of `;`, `=`, lifetime, or type
66

77
error: aborting due to previous error
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fn main() {}
2+
3+
fn semantics() {
4+
type A: Ord;
5+
//~^ ERROR bounds on `type`s in this context have no effect
6+
//~| ERROR free type alias without body
7+
type B: Ord = u8;
8+
//~^ ERROR bounds on `type`s in this context have no effect
9+
type C: Ord where 'static: 'static = u8;
10+
//~^ ERROR bounds on `type`s in this context have no effect
11+
type D<_T>: Ord;
12+
//~^ ERROR bounds on `type`s in this context have no effect
13+
//~| ERROR free type alias without body
14+
type E<_T>: Ord = u8;
15+
//~^ ERROR bounds on `type`s in this context have no effect
16+
//~| ERROR type parameter `_T` is unused
17+
type F<_T>: Ord where 'static: 'static = u8;
18+
//~^ ERROR bounds on `type`s in this context have no effect
19+
//~| ERROR type parameter `_T` is unused
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error: free type alias without body
2+
--> $DIR/item-free-type-bounds-semantic-fail.rs:4:5
3+
|
4+
LL | type A: Ord;
5+
| ^^^^^^^^^^^-
6+
| |
7+
| help: provide a definition for the type: `= <type>;`
8+
9+
error: bounds on `type`s in this context have no effect
10+
--> $DIR/item-free-type-bounds-semantic-fail.rs:4:13
11+
|
12+
LL | type A: Ord;
13+
| ^^^
14+
15+
error: bounds on `type`s in this context have no effect
16+
--> $DIR/item-free-type-bounds-semantic-fail.rs:7:13
17+
|
18+
LL | type B: Ord = u8;
19+
| ^^^
20+
21+
error: bounds on `type`s in this context have no effect
22+
--> $DIR/item-free-type-bounds-semantic-fail.rs:9:13
23+
|
24+
LL | type C: Ord where 'static: 'static = u8;
25+
| ^^^
26+
27+
error: free type alias without body
28+
--> $DIR/item-free-type-bounds-semantic-fail.rs:11:5
29+
|
30+
LL | type D<_T>: Ord;
31+
| ^^^^^^^^^^^^^^^-
32+
| |
33+
| help: provide a definition for the type: `= <type>;`
34+
35+
error: bounds on `type`s in this context have no effect
36+
--> $DIR/item-free-type-bounds-semantic-fail.rs:11:17
37+
|
38+
LL | type D<_T>: Ord;
39+
| ^^^
40+
41+
error: bounds on `type`s in this context have no effect
42+
--> $DIR/item-free-type-bounds-semantic-fail.rs:14:17
43+
|
44+
LL | type E<_T>: Ord = u8;
45+
| ^^^
46+
47+
error: bounds on `type`s in this context have no effect
48+
--> $DIR/item-free-type-bounds-semantic-fail.rs:17:17
49+
|
50+
LL | type F<_T>: Ord where 'static: 'static = u8;
51+
| ^^^
52+
53+
error[E0091]: type parameter `_T` is unused
54+
--> $DIR/item-free-type-bounds-semantic-fail.rs:14:12
55+
|
56+
LL | type E<_T>: Ord = u8;
57+
| ^^ unused type parameter
58+
59+
error[E0091]: type parameter `_T` is unused
60+
--> $DIR/item-free-type-bounds-semantic-fail.rs:17:12
61+
|
62+
LL | type F<_T>: Ord where 'static: 'static = u8;
63+
| ^^ unused type parameter
64+
65+
error: aborting due to 10 previous errors
66+
67+
For more information about this error, try `rustc --explain E0091`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// check-pass
2+
3+
fn main() {}
4+
5+
#[cfg(FALSE)]
6+
fn syntax() {
7+
type A: Ord;
8+
type B: Ord = u8;
9+
type C: Ord where 'static: 'static = u8;
10+
type D<_T>: Ord;
11+
type E<_T>: Ord = u8;
12+
type F<_T>: Ord where 'static: 'static = u8;
13+
}

0 commit comments

Comments
 (0)