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, " = ;"); } + 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, " = ;"); + } + 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, 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, 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;`. - TyAlias(P, Generics), + TyAlias(Generics, GenericBounds, Option>), /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. @@ -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(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: Trait - where - Self: Sized; -} - -impl X for () { - type - Y - 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: `= ;` + +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: `= ;` + +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; +}