about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-02-23 09:57:43 +0100
committerGitHub <noreply@github.com>2020-02-23 09:57:43 +0100
commitae50725dc3e272a46726f548aaff801a4f456563 (patch)
tree9e831818289723cfa6bdedc9f19243f3dba41434
parentcec00033a78d46df814728bcd831e71355a0efb0 (diff)
parent9f3dfd29a21f1bdc26720703f79d3fabdc7471de (diff)
downloadrust-ae50725dc3e272a46726f548aaff801a4f456563.tar.gz
rust-ae50725dc3e272a46726f548aaff801a4f456563.zip
Rollup merge of #69361 - Centril:free-ty-alias, r=petrochenkov
parse: allow `type Foo: Ord` syntactically

This addresses:
> (Work still remains to fuse this with free type aliases, but this can be done later.)

in https://github.com/rust-lang/rust/pull/69194.

r? @petrochenkov
-rw-r--r--src/librustc_ast_lowering/item.rs18
-rw-r--r--src/librustc_ast_lowering/lib.rs2
-rw-r--r--src/librustc_ast_passes/ast_validation.rs7
-rw-r--r--src/librustc_ast_passes/feature_gate.rs2
-rw-r--r--src/librustc_ast_pretty/pprust.rs70
-rw-r--r--src/librustc_ast_pretty/pprust/tests.rs10
-rw-r--r--src/librustc_parse/parser/item.rs32
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs4
-rw-r--r--src/librustc_resolve/late.rs2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs9
-rw-r--r--src/librustc_save_analysis/sig.rs7
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/mut_visit.rs5
-rw-r--r--src/libsyntax/visit.rs7
-rw-r--r--src/test/pretty/gat-bounds.pp25
-rw-r--r--src/test/pretty/gat-bounds.rs1
-rw-r--r--src/test/pretty/nested-item-vis-defaultness.rs47
-rw-r--r--src/test/ui/parser/bounds-lifetime-where.rs2
-rw-r--r--src/test/ui/parser/bounds-lifetime-where.stderr4
-rw-r--r--src/test/ui/parser/item-free-type-bounds-semantic-fail.rs20
-rw-r--r--src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr67
-rw-r--r--src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs13
22 files changed, 242 insertions, 116 deletions
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index ad7221b16b2..1a19fab0265 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -297,28 +297,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
-            ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() {
+            ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
                 None => {
                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                     let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                     hir::ItemKind::TyAlias(ty, generics)
                 }
                 Some(bounds) => {
+                    let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
                     let ty = hir::OpaqueTy {
-                        generics: self.lower_generics(
-                            generics,
-                            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
-                        ),
-                        bounds: self.lower_param_bounds(
-                            bounds,
-                            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
-                        ),
+                        generics: self.lower_generics(generics, ctx()),
+                        bounds: self.lower_param_bounds(bounds, ctx()),
                         impl_trait_fn: None,
                         origin: hir::OpaqueTyOrigin::TypeAlias,
                     };
                     hir::ItemKind::OpaqueTy(ty)
                 }
             },
+            ItemKind::TyAlias(ref generics, _, None) => {
+                let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
+                let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
+                hir::ItemKind::TyAlias(ty, generics)
+            }
             ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
                 hir::EnumDef {
                     variants: self.arena.alloc_from_iter(
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index ac4ca30382f..9bb46009fe6 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ItemKind::Struct(_, ref generics)
                     | ItemKind::Union(_, ref generics)
                     | ItemKind::Enum(_, ref generics)
-                    | ItemKind::TyAlias(_, ref generics)
+                    | ItemKind::TyAlias(ref generics, ..)
                     | ItemKind::Trait(_, _, ref generics, ..) => {
                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                         let count = generics
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index 1194269e0ee..a9844a7059e 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -969,6 +969,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 let msg = "free static item without body";
                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
             }
+            ItemKind::TyAlias(_, ref bounds, ref body) => {
+                if body.is_none() {
+                    let msg = "free type alias without body";
+                    self.error_item_without_body(item.span, "type", msg, " = <type>;");
+                }
+                self.check_type_no_bounds(bounds, "this context");
+            }
             _ => {}
         }
 
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 3c924847a73..5bddae0d49e 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
 
-            ast::ItemKind::TyAlias(ref ty, ..) => self.check_impl_trait(&ty),
+            ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty),
 
             _ => {}
         }
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 6e1567ce34e..9b7bb574946 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -2,7 +2,7 @@ use crate::pp::Breaks::{Consistent, Inconsistent};
 use crate::pp::{self, Breaks};
 
 use rustc_span::edition::Edition;
-use rustc_span::source_map::{dummy_spanned, SourceMap, Spanned};
+use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, FileName, Span};
 use syntax::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
@@ -1026,7 +1026,7 @@ impl<'a> State<'a> {
         span: Span,
         ident: ast::Ident,
         attrs: &[Attribute],
-        defaultness: ast::Defaultness,
+        def: ast::Defaultness,
         kind: &ast::AssocItemKind,
         vis: &ast::Visibility,
     ) {
@@ -1034,19 +1034,18 @@ impl<'a> State<'a> {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
-        self.print_defaultness(defaultness);
         match kind {
             ast::ForeignItemKind::Fn(sig, gen, body) => {
-                self.print_fn_full(sig, ident, gen, vis, body.as_deref(), attrs);
+                self.print_fn_full(sig, ident, gen, vis, def, body.as_deref(), attrs);
             }
             ast::ForeignItemKind::Const(ty, body) => {
-                self.print_item_const(ident, None, ty, body.as_deref(), vis);
+                self.print_item_const(ident, None, ty, body.as_deref(), vis, def);
             }
             ast::ForeignItemKind::Static(ty, mutbl, body) => {
-                self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis);
+                self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
             }
             ast::ForeignItemKind::TyAlias(generics, bounds, ty) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref());
+                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, def);
             }
             ast::ForeignItemKind::Macro(m) => {
                 self.print_mac(m);
@@ -1065,13 +1064,17 @@ impl<'a> State<'a> {
         ty: &ast::Ty,
         body: Option<&ast::Expr>,
         vis: &ast::Visibility,
+        defaultness: ast::Defaultness,
     ) {
+        self.head("");
+        self.print_visibility(vis);
+        self.print_defaultness(defaultness);
         let leading = match mutbl {
             None => "const",
             Some(ast::Mutability::Not) => "static",
             Some(ast::Mutability::Mut) => "static mut",
         };
-        self.head(visibility_qualified(vis, leading));
+        self.word_space(leading);
         self.print_ident(ident);
         self.word_space(":");
         self.print_type(ty);
@@ -1091,7 +1094,12 @@ impl<'a> State<'a> {
         generics: &ast::Generics,
         bounds: &ast::GenericBounds,
         ty: Option<&ast::Ty>,
+        vis: &ast::Visibility,
+        defaultness: ast::Defaultness,
     ) {
+        self.head("");
+        self.print_visibility(vis);
+        self.print_defaultness(defaultness);
         self.word_space("type");
         self.print_ident(ident);
         self.print_generic_params(&generics.params);
@@ -1102,7 +1110,9 @@ impl<'a> State<'a> {
             self.word_space("=");
             self.print_type(ty);
         }
-        self.s.word(";")
+        self.s.word(";");
+        self.end(); // end inner head-block
+        self.end(); // end outer head-block
     }
 
     /// Pretty-prints an item.
@@ -1133,13 +1143,17 @@ impl<'a> State<'a> {
                 self.end(); // end outer head-block
             }
             ast::ItemKind::Static(ref ty, mutbl, ref body) => {
-                self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis);
+                let def = ast::Defaultness::Final;
+                self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis, def);
             }
             ast::ItemKind::Const(ref ty, ref body) => {
-                self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis);
+                let def = ast::Defaultness::Final;
+                self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
             }
             ast::ItemKind::Fn(ref sig, ref gen, ref body) => {
-                self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs);
+                let def = ast::Defaultness::Final;
+                let body = body.as_deref();
+                self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
             }
             ast::ItemKind::Mod(ref _mod) => {
                 self.head(visibility_qualified(&item.vis, "mod"));
@@ -1171,18 +1185,10 @@ impl<'a> State<'a> {
                 self.s.word(ga.asm.to_string());
                 self.end();
             }
-            ast::ItemKind::TyAlias(ref ty, ref generics) => {
-                self.head(visibility_qualified(&item.vis, "type"));
-                self.print_ident(item.ident);
-                self.print_generic_params(&generics.params);
-                self.end(); // end the inner ibox
-
-                self.print_where_clause(&generics.where_clause);
-                self.s.space();
-                self.word_space("=");
-                self.print_type(ty);
-                self.s.word(";");
-                self.end(); // end the outer ibox
+            ast::ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
+                let def = ast::Defaultness::Final;
+                let ty = ty.as_deref();
+                self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
             }
             ast::ItemKind::Enum(ref enum_definition, ref params) => {
                 self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
@@ -2370,13 +2376,16 @@ impl<'a> State<'a> {
         name: ast::Ident,
         generics: &ast::Generics,
         vis: &ast::Visibility,
+        defaultness: ast::Defaultness,
         body: Option<&ast::Block>,
         attrs: &[ast::Attribute],
     ) {
         if body.is_some() {
             self.head("");
         }
-        self.print_fn(&sig.decl, sig.header, Some(name), generics, vis);
+        self.print_visibility(vis);
+        self.print_defaultness(defaultness);
+        self.print_fn(&sig.decl, sig.header, Some(name), generics);
         if let Some(body) = body {
             self.nbsp();
             self.print_block_with_attrs(body, attrs);
@@ -2391,10 +2400,8 @@ impl<'a> State<'a> {
         header: ast::FnHeader,
         name: Option<ast::Ident>,
         generics: &ast::Generics,
-        vis: &ast::Visibility,
     ) {
-        self.print_fn_header_info(header, vis);
-
+        self.print_fn_header_info(header);
         if let Some(name) = name {
             self.nbsp();
             self.print_ident(name);
@@ -2672,8 +2679,7 @@ impl<'a> State<'a> {
             span: rustc_span::DUMMY_SP,
         };
         let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
-        let vis = dummy_spanned(ast::VisibilityKind::Inherited);
-        self.print_fn(decl, header, name, &generics, &vis);
+        self.print_fn(decl, header, name, &generics);
         self.end();
     }
 
@@ -2700,9 +2706,7 @@ impl<'a> State<'a> {
         }
     }
 
-    crate fn print_fn_header_info(&mut self, header: ast::FnHeader, vis: &ast::Visibility) {
-        self.s.word(visibility_qualified(vis, ""));
-
+    crate fn print_fn_header_info(&mut self, header: ast::FnHeader) {
         self.print_constness(header.constness);
         self.print_asyncness(header.asyncness);
         self.print_unsafety(header.unsafety);
diff --git a/src/librustc_ast_pretty/pprust/tests.rs b/src/librustc_ast_pretty/pprust/tests.rs
index 2c938453533..4531c7392a9 100644
--- a/src/librustc_ast_pretty/pprust/tests.rs
+++ b/src/librustc_ast_pretty/pprust/tests.rs
@@ -1,7 +1,7 @@
 use super::*;
 
 use rustc_span;
-use rustc_span::source_map::{dummy_spanned, respan};
+use rustc_span::source_map::respan;
 use syntax::ast;
 use syntax::with_default_globals;
 
@@ -13,13 +13,7 @@ fn fun_to_string(
 ) -> String {
     to_string(|s| {
         s.head("");
-        s.print_fn(
-            decl,
-            header,
-            Some(name),
-            generics,
-            &dummy_spanned(ast::VisibilityKind::Inherited),
-        );
+        s.print_fn(decl, header, Some(name), generics);
         s.end(); // Close the head box.
         s.end(); // Close the outer box.
     })
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 4dcde2f92db..328cf11c532 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -156,8 +156,7 @@ impl<'a> Parser<'a> {
             self.parse_item_mod(attrs)?
         } else if self.eat_keyword(kw::Type) {
             // TYPE ITEM
-            let (ident, ty, generics) = self.parse_type_alias()?;
-            (ident, ItemKind::TyAlias(ty, generics))
+            self.parse_type_alias()?
         } else if self.eat_keyword(kw::Enum) {
             // ENUM ITEM
             self.parse_item_enum()?
@@ -676,7 +675,10 @@ impl<'a> Parser<'a> {
         vis: &Visibility,
     ) -> PResult<'a, (Ident, AssocItemKind)> {
         if self.eat_keyword(kw::Type) {
-            self.parse_assoc_ty()
+            match self.parse_type_alias()? {
+                (ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))),
+                _ => unreachable!(),
+            }
         } else if self.check_fn_front_matter() {
             let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?;
             Ok((ident, AssocItemKind::Fn(sig, generics, body)))
@@ -700,10 +702,12 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parses the following grammar:
-    ///
-    ///     AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
-    fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
+    /// Parses a `type` alias with the following grammar:
+    /// ```
+    /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
+    /// ```
+    /// The `"type"` has already been eaten.
+    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, ItemKind)> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -715,7 +719,7 @@ impl<'a> Parser<'a> {
         let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
         self.expect_semi()?;
 
-        Ok((ident, AssocItemKind::TyAlias(generics, bounds, default)))
+        Ok((ident, ItemKind::TyAlias(generics, bounds, default)))
     }
 
     /// Parses a `UseTree`.
@@ -989,18 +993,6 @@ impl<'a> Parser<'a> {
         P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID })
     }
 
-    /// Parses the grammar:
-    ///     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
-    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, P<Ty>, Generics)> {
-        let ident = self.parse_ident()?;
-        let mut tps = self.parse_generics()?;
-        tps.where_clause = self.parse_where_clause()?;
-        self.expect(&token::Eq)?;
-        let ty = self.parse_ty()?;
-        self.expect_semi()?;
-        Ok((ident, ty, tps))
-    }
-
     /// Parses an enum declaration.
     fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
         let id = self.parse_ident()?;
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 1f622b80e8e..383bfe18fd0 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -718,8 +718,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(ref ty, _) => {
-                let def_kind = match ty.kind.opaque_top_hack() {
+            ItemKind::TyAlias(_, _, ref ty) => {
+                let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
                     None => DefKind::TyAlias,
                     Some(_) => DefKind::OpaqueTy,
                 };
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 73601cd2ee7..74628e6e5a0 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -797,7 +797,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         debug!("(resolving item) resolving {} ({:?})", name, item.kind);
 
         match item.kind {
-            ItemKind::TyAlias(_, ref generics) | ItemKind::Fn(_, ref generics, _) => {
+            ItemKind::TyAlias(ref generics, _, _) | ItemKind::Fn(_, ref generics, _) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_item(this, item)
                 });
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index db7733e7241..53dd6d28f89 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1311,12 +1311,15 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                 self.process_mod(item);
                 visit::walk_mod(self, m);
             }
-            TyAlias(ref ty, ref ty_params) => {
+            TyAlias(ref ty_params, _, ref ty) => {
                 let qualname = format!(
                     "::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
                 );
-                let value = ty_to_string(&ty);
+                let value = match ty {
+                    Some(ty) => ty_to_string(&ty),
+                    None => "_".to_string(),
+                };
                 if !self.span.filter_generated(item.ident.span) {
                     let span = self.span_from_span(item.ident.span);
                     let id = id_from_node_id(item.id, &self.save_ctxt);
@@ -1341,7 +1344,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     );
                 }
 
-                self.visit_ty(&ty);
+                walk_list!(self, visit_ty, ty);
                 self.process_generic_params(ty_params, &qualname, item.id);
             }
             Mac(_) => (),
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index a2c61db4b7c..2c07ed0571b 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -423,12 +423,15 @@ impl Sig for ast::Item {
 
                 Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ItemKind::TyAlias(ref ty, ref generics) => {
+            ast::ItemKind::TyAlias(ref generics, _, ref ty) => {
                 let text = "type ".to_owned();
                 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
                 sig.text.push_str(" = ");
-                let ty = ty.make(offset + sig.text.len(), id, scx)?;
+                let ty = match ty {
+                    Some(ty) => ty.make(offset + sig.text.len(), id, scx)?,
+                    None => Err("Ty")?,
+                };
                 sig.text.push_str(&ty.text);
                 sig.text.push(';');
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 9ae3010a0f6..849950e939a 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2524,7 +2524,7 @@ pub enum ItemKind {
     /// A type alias (`type`).
     ///
     /// E.g., `type Foo = Bar<u8>;`.
-    TyAlias(P<Ty>, Generics),
+    TyAlias(Generics, GenericBounds, Option<P<Ty>>),
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
@@ -2594,7 +2594,7 @@ impl ItemKind {
     pub fn generics(&self) -> Option<&Generics> {
         match self {
             Self::Fn(_, generics, _)
-            | Self::TyAlias(_, generics)
+            | Self::TyAlias(generics, ..)
             | Self::Enum(_, generics)
             | Self::Struct(_, generics)
             | Self::Union(_, generics)
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 92f20b719f8..02f790dfbb4 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -902,9 +902,10 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         ItemKind::Mod(m) => vis.visit_mod(m),
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
         ItemKind::GlobalAsm(_ga) => {}
-        ItemKind::TyAlias(ty, generics) => {
-            vis.visit_ty(ty);
+        ItemKind::TyAlias(generics, bounds, ty) => {
             vis.visit_generics(generics);
+            visit_bounds(bounds, vis);
+            visit_opt(ty, |ty| vis.visit_ty(ty));
         }
         ItemKind::Enum(EnumDef { variants }, generics) => {
             variants.flat_map_in_place(|variant| vis.flat_map_variant(variant));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index dedd42fe0f6..bd35918dba7 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -312,9 +312,10 @@ 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 ga) => visitor.visit_global_asm(ga),
-        ItemKind::TyAlias(ref typ, ref generics) => {
-            visitor.visit_ty(typ);
-            visitor.visit_generics(generics)
+        ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_ty, ty);
         }
         ItemKind::Enum(ref enum_definition, ref generics) => {
             visitor.visit_generics(generics);
diff --git a/src/test/pretty/gat-bounds.pp b/src/test/pretty/gat-bounds.pp
deleted file mode 100644
index 0c95add4901..00000000000
--- a/src/test/pretty/gat-bounds.pp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Check that associated types print generic parameters and where clauses.
-// See issue #67509.
-
-// pretty-compare-only
-// pp-exact:gat-bounds.pp
-
-#![feature(generic_associated_types)]
-
-trait X {
-    type
-    Y<T>: Trait
-    where
-    Self: Sized;
-}
-
-impl X for () {
-    type
-    Y<T>
-    where
-    Self: Sized
-    =
-    u32;
-}
-
-fn main() { }
diff --git a/src/test/pretty/gat-bounds.rs b/src/test/pretty/gat-bounds.rs
index 1275f432a3c..789e4bc80ac 100644
--- a/src/test/pretty/gat-bounds.rs
+++ b/src/test/pretty/gat-bounds.rs
@@ -2,7 +2,6 @@
 // See issue #67509.
 
 // pretty-compare-only
-// pp-exact:gat-bounds.pp
 
 #![feature(generic_associated_types)]
 
diff --git a/src/test/pretty/nested-item-vis-defaultness.rs b/src/test/pretty/nested-item-vis-defaultness.rs
new file mode 100644
index 00000000000..0a3f2a10c85
--- /dev/null
+++ b/src/test/pretty/nested-item-vis-defaultness.rs
@@ -0,0 +1,47 @@
+// Check that nested items have their visibility and `default`nesses in the right order.
+
+// pp-exact
+
+fn main() { }
+
+#[cfg(FALSE)]
+extern "C" {
+    static X: u8 ;
+    type X;
+    fn foo();
+    pub static X: u8 ;
+    pub type X;
+    pub fn foo();
+}
+
+#[cfg(FALSE)]
+trait T {
+    const X: u8 ;
+    type X;
+    fn foo();
+    default const X: u8 ;
+    default type X;
+    default fn foo();
+    pub const X: u8 ;
+    pub type X;
+    pub fn foo();
+    pub default const X: u8 ;
+    pub default type X;
+    pub default fn foo();
+}
+
+#[cfg(FALSE)]
+impl T for S {
+    const X: u8 ;
+    type X;
+    fn foo();
+    default const X: u8 ;
+    default type X;
+    default fn foo();
+    pub const X: u8 ;
+    pub type X;
+    pub fn foo();
+    pub default const X: u8 ;
+    pub default type X;
+    pub default fn foo();
+}
diff --git a/src/test/ui/parser/bounds-lifetime-where.rs b/src/test/ui/parser/bounds-lifetime-where.rs
index acb04e7859b..e60cc153e67 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 `;`, `=`, 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 05cebd6d351..950fa46c66b 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 `;`, `=`, 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 `;`, `=`, lifetime, or type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs b/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs
new file mode 100644
index 00000000000..9db4111fbab
--- /dev/null
+++ b/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs
@@ -0,0 +1,20 @@
+fn main() {}
+
+fn semantics() {
+    type A: Ord;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR free type alias without body
+    type B: Ord = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    type C: Ord where 'static: 'static = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    type D<_T>: Ord;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR free type alias without body
+    type E<_T>: Ord = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR type parameter `_T` is unused
+    type F<_T>: Ord where 'static: 'static = u8;
+    //~^ ERROR bounds on `type`s in this context have no effect
+    //~| ERROR type parameter `_T` is unused
+}
diff --git a/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr b/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr
new file mode 100644
index 00000000000..1b086512891
--- /dev/null
+++ b/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr
@@ -0,0 +1,67 @@
+error: free type alias without body
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:4:5
+   |
+LL |     type A: Ord;
+   |     ^^^^^^^^^^^-
+   |                |
+   |                help: provide a definition for the type: `= <type>;`
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:4:13
+   |
+LL |     type A: Ord;
+   |             ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:7:13
+   |
+LL |     type B: Ord = u8;
+   |             ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:9:13
+   |
+LL |     type C: Ord where 'static: 'static = u8;
+   |             ^^^
+
+error: free type alias without body
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:11:5
+   |
+LL |     type D<_T>: Ord;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: provide a definition for the type: `= <type>;`
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:11:17
+   |
+LL |     type D<_T>: Ord;
+   |                 ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:14:17
+   |
+LL |     type E<_T>: Ord = u8;
+   |                 ^^^
+
+error: bounds on `type`s in this context have no effect
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:17:17
+   |
+LL |     type F<_T>: Ord where 'static: 'static = u8;
+   |                 ^^^
+
+error[E0091]: type parameter `_T` is unused
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:14:12
+   |
+LL |     type E<_T>: Ord = u8;
+   |            ^^ unused type parameter
+
+error[E0091]: type parameter `_T` is unused
+  --> $DIR/item-free-type-bounds-semantic-fail.rs:17:12
+   |
+LL |     type F<_T>: Ord where 'static: 'static = u8;
+   |            ^^ unused type parameter
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0091`.
diff --git a/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs b/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs
new file mode 100644
index 00000000000..58fc926d08f
--- /dev/null
+++ b/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn syntax() {
+    type A: Ord;
+    type B: Ord = u8;
+    type C: Ord where 'static: 'static = u8;
+    type D<_T>: Ord;
+    type E<_T>: Ord = u8;
+    type F<_T>: Ord where 'static: 'static = u8;
+}