From c4bbe9cbbe9921646cdedb856e34dc951641ed96 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 30 Nov 2019 18:25:44 +0100 Subject: Alias `TraitItem` & `ImplItem`. Allow defaultness on trait items syntactically. --- src/librustc_parse/parser/item.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 34ef12e818c..c159fb66d50 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -714,9 +714,9 @@ impl<'a> Parser<'a> { id: DUMMY_NODE_ID, span: lo.to(self.prev_span), ident: name, + attrs, vis, defaultness, - attrs, generics, kind, tokens: None, @@ -882,6 +882,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, TraitItem> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; + let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { @@ -895,12 +896,13 @@ impl<'a> Parser<'a> { Ok(TraitItem { id: DUMMY_NODE_ID, + span: lo.to(self.prev_span), ident: name, attrs, vis, + defaultness, generics, kind, - span: lo.to(self.prev_span), tokens: None, }) } -- cgit 1.4.1-3-g733a5 From 73557faed23678fc443f3fa52727b5f200f597d2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 04:12:28 +0100 Subject: Use `Option` in `ImplItemKind::Const`. --- src/librustc/hir/lowering/item.rs | 8 ++++++- src/librustc_parse/parser/item.rs | 17 ++++++++------ src/librustc_passes/ast_validation.rs | 26 +++++++++++++++++----- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 4 ++-- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- src/test/ui/parser/impl-item-const-pass.rs | 8 +++++++ .../ui/parser/impl-item-const-semantic-fail.rs | 7 ++++++ .../ui/parser/impl-item-const-semantic-fail.stderr | 8 +++++++ 11 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/parser/impl-item-const-pass.rs create mode 100644 src/test/ui/parser/impl-item-const-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-const-semantic-fail.stderr (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index ff9d8c85df8..32b36d2021b 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -899,7 +899,13 @@ impl LoweringContext<'_> { self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Const( self.lower_ty(ty, ImplTraitContext::disallowed()), - self.lower_const_body(expr), + match expr { + Some(expr) => self.lower_const_body(expr), + None => self.lower_body(|this| ( + hir_vec![], + this.expr(i.span, hir::ExprKind::Err, ThinVec::new()), + )), + } ), ), ImplItemKind::Method(ref sig, ref body) => { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index c159fb66d50..68fdfd24d61 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -756,13 +756,16 @@ impl<'a> Parser<'a> { /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";" fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { self.expect_keyword(kw::Const)?; - let name = self.parse_ident()?; + let ident = self.parse_ident()?; self.expect(&token::Colon)?; - let typ = self.parse_ty()?; - self.expect(&token::Eq)?; - let expr = self.parse_expr()?; + let ty = self.parse_ty()?; + let expr = if self.eat(&token::Eq) { + Some(self.parse_expr()?) + } else { + None + }; self.expect_semi()?; - Ok((name, ImplItemKind::Const(typ, expr), Generics::default())) + Ok((ident, ImplItemKind::Const(ty, expr), Generics::default())) } /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. @@ -912,13 +915,13 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; - let default = if self.eat(&token::Eq) { + let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - Ok((ident, TraitItemKind::Const(ty, default), Generics::default())) + Ok((ident, TraitItemKind::Const(ty, expr), Generics::default())) } /// Parses the following grammar: diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index a078a36db7a..ba0e6b100ee 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -259,12 +259,12 @@ impl<'a> AstValidator<'a> { !arr.contains(&attr.name_or_empty()) && attr::is_builtin_attr(attr) }) .for_each(|attr| if attr.is_doc_comment() { - let mut err = self.err_handler().struct_span_err( + self.err_handler().struct_span_err( attr.span, "documentation comments cannot be applied to function parameters" - ); - err.span_label(attr.span, "doc comments are not allowed here"); - err.emit(); + ) + .span_label(attr.span, "doc comments are not allowed here") + .emit(); } else { self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \ @@ -746,8 +746,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_impl_item(&mut self, ii: &'a ImplItem) { - if let ImplItemKind::Method(ref sig, _) = ii.kind { - self.check_fn_decl(&sig.decl); + match &ii.kind { + ImplItemKind::Const(ty, None) => { + self.err_handler() + .struct_span_err(ii.span, "associated constant in `impl` without body") + .span_suggestion( + ii.span, + "provide a definition for the constant", + format!("const {}: {} = ;", ii.ident, pprust::ty_to_string(ty)), + Applicability::HasPlaceholders, + ) + .emit(); + } + ImplItemKind::Method(sig, _) => { + self.check_fn_decl(&sig.decl); + } + _ => {} } visit::walk_impl_item(self, ii); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 396d9484339..97cbcb6401c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1110,7 +1110,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { impl_item.id, impl_item.ident, &ty, - Some(expr), + expr.as_deref(), impl_id, impl_item.vis.clone(), &impl_item.attrs, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 964acfa92b9..17a57387da7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1635,8 +1635,8 @@ pub struct ImplItem { /// Represents various kinds of content within an `impl`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ImplItemKind { - Const(P, P), +pub enum ImplItemKind { + Const(P, Option>), Method(FnSig, P), TyAlias(P), Macro(Mac), diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 9d0a29f2951..14701455013 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -981,7 +981,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut match kind { ImplItemKind::Const(ty, expr) => { visitor.visit_ty(ty); - visitor.visit_expr(expr); + visit_opt(expr, |expr| visitor.visit_expr(expr)); } ImplItemKind::Method(sig, body) => { visit_fn_sig(sig, visitor); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 2e3ea5e2444..c1405e15819 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1599,7 +1599,7 @@ impl<'a> State<'a> { self.print_defaultness(ii.defaultness); match ii.kind { ast::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.ident, ty, Some(expr), &ii.vis); + self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis); } ast::ImplItemKind::Method(ref sig, ref body) => { self.head(""); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4ee09b4b87a..0b7a7d993aa 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -617,7 +617,7 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt match impl_item.kind { ImplItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); - visitor.visit_expr(expr); + walk_list!(visitor, visit_expr, expr); } ImplItemKind::Method(ref sig, ref body) => { visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body), diff --git a/src/test/ui/parser/impl-item-const-pass.rs b/src/test/ui/parser/impl-item-const-pass.rs new file mode 100644 index 00000000000..d1124561374 --- /dev/null +++ b/src/test/ui/parser/impl-item-const-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + const Y: u8; +} diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.rs b/src/test/ui/parser/impl-item-const-semantic-fail.rs new file mode 100644 index 00000000000..5d4692f9f14 --- /dev/null +++ b/src/test/ui/parser/impl-item-const-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + const Y: u8; //~ ERROR associated constant in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr new file mode 100644 index 00000000000..31a15f8e80e --- /dev/null +++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr @@ -0,0 +1,8 @@ +error: associated constant in `impl` without body + --> $DIR/impl-item-const-semantic-fail.rs:6:5 + | +LL | const Y: u8; + | ^^^^^^^^^^^^ help: provide a definition for the constant: `const Y: u8 = ;` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From f6403c6c766c704569564b9021071c4917d45a25 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 07:24:07 +0100 Subject: Use `Option` in `ImplItemKind::Method`. --- src/librustc/hir/lowering.rs | 4 +- src/librustc/hir/lowering/item.rs | 71 +++++++++++++++------- src/librustc_parse/parser/item.rs | 12 ++-- src/librustc_passes/ast_validation.rs | 31 ++++++---- src/librustc_resolve/def_collector.rs | 10 +-- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 26 ++++---- src/libsyntax/visit.rs | 12 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- src/test/ui/issues/issue-58856-1.rs | 2 + src/test/ui/issues/issue-58856-1.stderr | 17 +++++- .../ui/parser/impl-item-const-semantic-fail.stderr | 4 +- src/test/ui/parser/impl-item-fn-no-body-pass.rs | 8 +++ .../parser/impl-item-fn-no-body-semantic-fail.rs | 7 +++ .../impl-item-fn-no-body-semantic-fail.stderr | 10 +++ 17 files changed, 149 insertions(+), 73 deletions(-) create mode 100644 src/test/ui/parser/impl-item-fn-no-body-pass.rs create mode 100644 src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e13f6cabb52..a82febba38a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1211,7 +1211,7 @@ impl<'a> LoweringContext<'a> { let ct = self.with_new_scopes(|this| { hir::AnonConst { hir_id: this.lower_node_id(node_id), - body: this.lower_const_body(&path_expr), + body: this.lower_const_body(path_expr.span, Some(&path_expr)), } }); return GenericArg::Const(ConstArg { @@ -3003,7 +3003,7 @@ impl<'a> LoweringContext<'a> { self.with_new_scopes(|this| { hir::AnonConst { hir_id: this.lower_node_id(c.id), - body: this.lower_const_body(&c.value), + body: this.lower_const_body(c.value.span, Some(&c.value)), } }) } diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 32b36d2021b..7e231cd6b59 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -250,7 +250,7 @@ impl LoweringContext<'_> { return None; } - let kind = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, &mut ident, &attrs, &mut vis, &i.kind); Some(hir::Item { hir_id: self.lower_node_id(i.id), @@ -264,6 +264,7 @@ impl LoweringContext<'_> { fn lower_item_kind( &mut self, + span: Span, id: NodeId, ident: &mut Ident, attrs: &hir::HirVec, @@ -292,7 +293,7 @@ impl LoweringContext<'_> { } ), m, - self.lower_const_body(e), + self.lower_const_body(span, Some(e)), ) } ItemKind::Const(ref t, ref e) => { @@ -305,7 +306,7 @@ impl LoweringContext<'_> { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } ), - self.lower_const_body(e) + self.lower_const_body(span, Some(e)) ) } ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => { @@ -317,7 +318,12 @@ impl LoweringContext<'_> { // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body); + let body_id = this.lower_maybe_async_body( + span, + &decl, + header.asyncness.node, + Some(body), + ); let (generics, decl) = this.add_in_band_defs( generics, @@ -817,7 +823,7 @@ impl LoweringContext<'_> { self.lower_ty(ty, ImplTraitContext::disallowed()), default .as_ref() - .map(|x| self.lower_const_body(x)), + .map(|x| self.lower_const_body(i.span, Some(x))), ), ), TraitItemKind::Method(ref sig, None) => { @@ -832,7 +838,7 @@ impl LoweringContext<'_> { (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } TraitItemKind::Method(ref sig, Some(ref body)) => { - let body_id = self.lower_fn_body_block(&sig.decl, body); + let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig( &i.generics, sig, @@ -891,6 +897,11 @@ impl LoweringContext<'_> { } } + /// Construct `ExprKind::Err` for the given `span`. + fn expr_err(&mut self, span: Span) -> hir::Expr { + self.expr(span, hir::ExprKind::Err, ThinVec::new()) + } + fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); @@ -899,19 +910,16 @@ impl LoweringContext<'_> { self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Const( self.lower_ty(ty, ImplTraitContext::disallowed()), - match expr { - Some(expr) => self.lower_const_body(expr), - None => self.lower_body(|this| ( - hir_vec![], - this.expr(i.span, hir::ExprKind::Err, ThinVec::new()), - )), - } + self.lower_const_body(i.span, expr.as_deref()), ), ), ImplItemKind::Method(ref sig, ref body) => { self.current_item = Some(i.span); let body_id = self.lower_maybe_async_body( - &sig.decl, sig.header.asyncness.node, body + i.span, + &sig.decl, + sig.header.asyncness.node, + body.as_deref(), ); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( @@ -1069,23 +1077,39 @@ impl LoweringContext<'_> { )) } - fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId { - self.lower_fn_body(decl, |this| this.lower_block_expr(body)) + fn lower_fn_body_block( + &mut self, + span: Span, + decl: &FnDecl, + body: Option<&Block>, + ) -> hir::BodyId { + self.lower_fn_body(decl, |this| this.lower_block_expr_opt(span, body)) + } + + fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr { + match block { + Some(block) => self.lower_block_expr(block), + None => self.expr_err(span), + } } - pub(super) fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId { - self.lower_body(|this| (hir_vec![], this.lower_expr(expr))) + pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId { + self.lower_body(|this| (hir_vec![], match expr { + Some(expr) => this.lower_expr(expr), + None => this.expr_err(span), + })) } fn lower_maybe_async_body( &mut self, + span: Span, decl: &FnDecl, asyncness: IsAsync, - body: &Block, + body: Option<&Block>, ) -> hir::BodyId { let closure_id = match asyncness { IsAsync::Async { closure_id, .. } => closure_id, - IsAsync::NotAsync => return self.lower_fn_body_block(decl, body), + IsAsync::NotAsync => return self.lower_fn_body_block(span, decl, body), }; self.lower_body(|this| { @@ -1219,15 +1243,16 @@ impl LoweringContext<'_> { parameters.push(new_parameter); } + let body_span = body.map_or(span, |b| b.span); let async_expr = this.make_async_expr( CaptureBy::Value, closure_id, None, - body.span, + body_span, hir::AsyncGeneratorKind::Fn, |this| { // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); + let user_body = this.lower_block_expr_opt(body_span, body); // Transform into `drop-temps { }`, an expression: let desugared_span = this.mark_span_with_reason( @@ -1257,7 +1282,7 @@ impl LoweringContext<'_> { ); this.expr_block(P(body), ThinVec::new()) }); - (HirVec::from(parameters), this.expr(body.span, async_expr, ThinVec::new())) + (HirVec::from(parameters), this.expr(body_span, async_expr, ThinVec::new())) }) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 68fdfd24d61..053502c43dc 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -705,9 +705,7 @@ impl<'a> Parser<'a> { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) } else { - let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?; - attrs.extend(inner_attrs); - (name, kind, generics) + self.parse_impl_method(at_end, &mut attrs)? }; Ok(ImplItem { @@ -1842,11 +1840,11 @@ impl<'a> Parser<'a> { fn parse_impl_method( &mut self, at_end: &mut bool, - ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> { + attrs: &mut Vec, + ) -> PResult<'a, (Ident, ImplItemKind, Generics)> { let (ident, sig, generics) = self.parse_method_sig(|_| true)?; - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body))) + let body = self.parse_trait_method_body(at_end, attrs)?; + Ok((ident, ast::ImplItemKind::Method(sig, body), generics)) } fn parse_trait_item_method( diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ba0e6b100ee..78866dc9cc9 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -279,6 +279,22 @@ impl<'a> AstValidator<'a> { .emit(); } } + + fn check_impl_item_provided(&self, sp: Span, body: &Option, ctx: &str, sugg: &str) { + if body.is_some() { + return; + } + + self.err_handler() + .struct_span_err(sp, &format!("associated {} in `impl` without body", ctx)) + .span_suggestion( + self.session.source_map().end_point(sp), + &format!("provide a definition for the {}", ctx), + sugg.to_string(), + Applicability::HasPlaceholders, + ) + .emit(); + } } enum GenericPosition { @@ -747,18 +763,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { match &ii.kind { - ImplItemKind::Const(ty, None) => { - self.err_handler() - .struct_span_err(ii.span, "associated constant in `impl` without body") - .span_suggestion( - ii.span, - "provide a definition for the constant", - format!("const {}: {} = ;", ii.ident, pprust::ty_to_string(ty)), - Applicability::HasPlaceholders, - ) - .emit(); + ImplItemKind::Const(_, body) => { + self.check_impl_item_provided(ii.span, body, "constant", " = ;"); } - ImplItemKind::Method(sig, _) => { + ImplItemKind::Method(sig, body) => { + self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } _ => {} diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index dd6b1d2119e..76a52bb7f7f 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -50,7 +50,7 @@ impl<'a> DefCollector<'a> { header: &FnHeader, generics: &'a Generics, decl: &'a FnDecl, - body: &'a Block, + body: Option<&'a Block>, ) { let (closure_id, return_impl_trait_id) = match header.asyncness.node { IsAsync::Async { @@ -74,7 +74,9 @@ impl<'a> DefCollector<'a> { closure_id, DefPathData::ClosureExpr, span, ); this.with_parent(closure_def, |this| { - visit::walk_block(this, body); + if let Some(body) = body { + visit::walk_block(this, body); + } }) }) } @@ -123,7 +125,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { &sig.header, generics, &sig.decl, - body, + Some(body), ) } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => @@ -237,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { header, &ii.generics, decl, - body, + body.as_deref(), ) } ImplItemKind::Method(..) | diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 97cbcb6401c..99f9c3b1f2e 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1119,7 +1119,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ast::ImplItemKind::Method(ref sig, ref body) => { self.process_method( sig, - Some(body), + body.as_deref(), impl_item.id, impl_item.ident, &impl_item.generics, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 17a57387da7..f6af5d8637e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1637,7 +1637,7 @@ pub struct ImplItem { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ImplItemKind { Const(P, Option>), - Method(FnSig, P), + Method(FnSig, Option>), TyAlias(P), Macro(Mac), } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 14701455013..0fa4dcf3ad9 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -985,7 +985,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut } ImplItemKind::Method(sig, body) => { visit_fn_sig(sig, visitor); - visitor.visit_block(body); + visit_opt(body, |body| visitor.visit_block(body)); } ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty), ImplItemKind::Macro(mac) => visitor.visit_mac(mac), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c1405e15819..34097841b4a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1553,23 +1553,13 @@ impl<'a> State<'a> { self.print_defaultness(ti.defaultness); match ti.kind { ast::TraitItemKind::Const(ref ty, ref default) => { - self.print_associated_const( - ti.ident, - ty, - default.as_ref().map(|expr| &**expr), - &source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - ); + self.print_associated_const(ti.ident, ty, default.as_deref(), &ti.vis); } ast::TraitItemKind::Method(ref sig, ref body) => { if body.is_some() { self.head(""); } - self.print_method_sig( - ti.ident, - &ti.generics, - sig, - &source_map::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - ); + self.print_method_sig(ti.ident, &ti.generics, sig, &ti.vis); if let Some(ref body) = *body { self.nbsp(); self.print_block_with_attrs(body, &ti.attrs); @@ -1602,10 +1592,16 @@ impl<'a> State<'a> { self.print_associated_const(ii.ident, ty, expr.as_deref(), &ii.vis); } ast::ImplItemKind::Method(ref sig, ref body) => { - self.head(""); + if body.is_some() { + self.head(""); + } self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis); - self.nbsp(); - self.print_block_with_attrs(body, &ii.attrs); + if let Some(body) = body { + self.nbsp(); + self.print_block_with_attrs(body, &ii.attrs); + } else { + self.s.word(";"); + } } ast::ImplItemKind::TyAlias(ref ty) => { self.print_associated_type(ii.ident, None, Some(ty)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 0b7a7d993aa..bdf70ec46f7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -25,7 +25,7 @@ pub enum FnKind<'a> { ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block), /// E.g., `fn foo(&self)`. - Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a Block), + Method(Ident, &'a FnSig, &'a Visibility, &'a Block), /// E.g., `|x, y| body`. Closure(&'a Expr), @@ -596,7 +596,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai walk_fn_decl(visitor, &sig.decl); } TraitItemKind::Method(ref sig, Some(ref body)) => { - visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body), + visitor.visit_fn(FnKind::Method(trait_item.ident, sig, &trait_item.vis, body), &sig.decl, trait_item.span, trait_item.id); } TraitItemKind::Type(ref bounds, ref default) => { @@ -619,8 +619,12 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - ImplItemKind::Method(ref sig, ref body) => { - visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body), + ImplItemKind::Method(ref sig, None) => { + visitor.visit_fn_header(&sig.header); + walk_fn_decl(visitor, &sig.decl); + } + ImplItemKind::Method(ref sig, Some(ref body)) => { + visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body), &sig.decl, impl_item.span, impl_item.id); } ImplItemKind::TyAlias(ref ty) => { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 5bd84b43a78..e8c4f993d4f 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -956,7 +956,7 @@ impl<'a> MethodDef<'a> { vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::ImplItemKind::Method(sig, body_block), + kind: ast::ImplItemKind::Method(sig, Some(body_block)), tokens: None, } } diff --git a/src/test/ui/issues/issue-58856-1.rs b/src/test/ui/issues/issue-58856-1.rs index db3984cd189..8b1a39a94e6 100644 --- a/src/test/ui/issues/issue-58856-1.rs +++ b/src/test/ui/issues/issue-58856-1.rs @@ -1,6 +1,8 @@ impl A { + //~^ ERROR cannot find type `A` in this scope fn b(self> //~^ ERROR expected one of `)`, `,`, or `:`, found `>` + //~| ERROR expected `;` or `{`, found `>` } fn main() {} diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index 58ab0a142d6..0ea6b017548 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -1,10 +1,23 @@ error: expected one of `)`, `,`, or `:`, found `>` - --> $DIR/issue-58856-1.rs:2:14 + --> $DIR/issue-58856-1.rs:3:14 | LL | fn b(self> | - ^ help: `)` may belong here | | | unclosed delimiter -error: aborting due to previous error +error: expected `;` or `{`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | fn b(self> + | ^ expected `;` or `{` + +error[E0412]: cannot find type `A` in this scope + --> $DIR/issue-58856-1.rs:1:6 + | +LL | impl A { + | ^ not found in this scope + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/parser/impl-item-const-semantic-fail.stderr b/src/test/ui/parser/impl-item-const-semantic-fail.stderr index 31a15f8e80e..ec3bee0ce68 100644 --- a/src/test/ui/parser/impl-item-const-semantic-fail.stderr +++ b/src/test/ui/parser/impl-item-const-semantic-fail.stderr @@ -2,7 +2,9 @@ error: associated constant in `impl` without body --> $DIR/impl-item-const-semantic-fail.rs:6:5 | LL | const Y: u8; - | ^^^^^^^^^^^^ help: provide a definition for the constant: `const Y: u8 = ;` + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` error: aborting due to previous error diff --git a/src/test/ui/parser/impl-item-fn-no-body-pass.rs b/src/test/ui/parser/impl-item-fn-no-body-pass.rs new file mode 100644 index 00000000000..16b09d64e8c --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + fn f(); +} diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs new file mode 100644 index 00000000000..cb183db5964 --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + fn f(); //~ ERROR associated function in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr new file mode 100644 index 00000000000..1acb727368b --- /dev/null +++ b/src/test/ui/parser/impl-item-fn-no-body-semantic-fail.stderr @@ -0,0 +1,10 @@ +error: associated function in `impl` without body + --> $DIR/impl-item-fn-no-body-semantic-fail.rs:6:5 + | +LL | fn f(); + | ^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From c02fd3130284921f7077f78271b5501b402ec469 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 08:41:35 +0100 Subject: `TraitItemKind::Type` -> `TraitItemKind::TyAlias`. --- src/librustc/hir/lowering/item.rs | 4 ++-- src/librustc_parse/parser/item.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/def_collector.rs | 2 +- src/librustc_resolve/late.rs | 4 ++-- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/feature_gate/check.rs | 2 +- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 7e231cd6b59..ec78bcf1403 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -848,7 +848,7 @@ impl LoweringContext<'_> { ); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } - TraitItemKind::Type(ref bounds, ref default) => { + TraitItemKind::TyAlias(ref bounds, ref default) => { let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); let kind = hir::TraitItemKind::Type( self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), @@ -877,7 +877,7 @@ impl LoweringContext<'_> { TraitItemKind::Const(_, ref default) => { (hir::AssocItemKind::Const, default.is_some()) } - TraitItemKind::Type(_, ref default) => { + TraitItemKind::TyAlias(_, ref default) => { (hir::AssocItemKind::Type, default.is_some()) } TraitItemKind::Method(ref sig, ref default) => ( diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 053502c43dc..5bfecf78e71 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -944,7 +944,7 @@ impl<'a> Parser<'a> { }; self.expect_semi()?; - Ok((ident, TraitItemKind::Type(bounds, default), generics)) + Ok((ident, TraitItemKind::TyAlias(bounds, default), generics)) } /// Parses a `UseTree`. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e2578d67e73..d2d5a33ec7a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1182,7 +1182,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { } (Res::Def(DefKind::Method, item_def_id), ValueNS) } - TraitItemKind::Type(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), + TraitItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), TraitItemKind::Macro(_) => bug!(), // handled above }; diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 76a52bb7f7f..471e2634b8a 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -216,7 +216,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let def_data = match ti.kind { TraitItemKind::Method(..) | TraitItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name), - TraitItemKind::Type(..) => { + TraitItemKind::TyAlias(..) => { DefPathData::TypeNs(ti.ident.name) }, TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 4f95d6fe70f..d32a6a4b3e6 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -821,7 +821,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { TraitItemKind::Method(_, _) => { visit::walk_trait_item(this, trait_item) } - TraitItemKind::Type(..) => { + TraitItemKind::TyAlias(..) => { visit::walk_trait_item(this, trait_item) } TraitItemKind::Macro(_) => { @@ -995,7 +995,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let trait_assoc_types = replace( &mut self.diagnostic_metadata.current_trait_assoc_types, trait_items.iter().filter_map(|item| match &item.kind { - TraitItemKind::Type(bounds, _) if bounds.len() == 0 => Some(item.ident), + TraitItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident), _ => None, }).collect(), ); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 99f9c3b1f2e..bd7851296dd 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1056,7 +1056,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { trait_item.span, ); } - ast::TraitItemKind::Type(ref bounds, ref default_ty) => { + ast::TraitItemKind::TyAlias(ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f6af5d8637e..4e2f78e8ab8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1613,7 +1613,7 @@ pub type TraitItem = ImplItem; pub enum TraitItemKind { Const(P, Option>), Method(FnSig, Option>), - Type(GenericBounds, Option>), + TyAlias(GenericBounds, Option>), Macro(Mac), } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 3d2c3b1d4f9..10f6bbb5949 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -585,7 +585,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); } } - ast::TraitItemKind::Type(_, ref default) => { + ast::TraitItemKind::TyAlias(_, ref default) => { if let Some(ty) = default { self.check_impl_trait(ty); gate_feature_post!(&self, associated_type_defaults, ti.span, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 0fa4dcf3ad9..66cac0f917d 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -955,7 +955,7 @@ pub fn noop_flat_map_trait_item(mut item: TraitItem, visitor: &mu visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - TraitItemKind::Type(bounds, default) => { + TraitItemKind::TyAlias(bounds, default) => { visit_bounds(bounds, visitor); visit_opt(default, |default| visitor.visit_ty(default)); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 34097841b4a..00dcd7e8d0b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1567,7 +1567,7 @@ impl<'a> State<'a> { self.s.word(";"); } } - ast::TraitItemKind::Type(ref bounds, ref default) => { + ast::TraitItemKind::TyAlias(ref bounds, ref default) => { self.print_associated_type(ti.ident, Some(bounds), default.as_ref().map(|ty| &**ty)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index bdf70ec46f7..f96290ec4f8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -599,7 +599,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai visitor.visit_fn(FnKind::Method(trait_item.ident, sig, &trait_item.vis, body), &sig.decl, trait_item.span, trait_item.id); } - TraitItemKind::Type(ref bounds, ref default) => { + TraitItemKind::TyAlias(ref bounds, ref default) => { walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, default); } -- cgit 1.4.1-3-g733a5 From 39073767a483d10f8b4b2ac2f32bc9573d9dabbf Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:25:45 +0100 Subject: Unify `{Trait,Impl}ItemKind::TyAlias` structures. --- src/librustc/hir/lowering.rs | 37 +++++------ src/librustc/hir/lowering/item.rs | 24 ++++--- src/librustc_parse/parser/item.rs | 30 ++++++++- src/librustc_passes/ast_validation.rs | 15 +++++ src/librustc_passes/lib.rs | 1 + src/librustc_resolve/late.rs | 3 +- src/librustc_save_analysis/dump_visitor.rs | 3 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/feature_gate/check.rs | 6 +- src/libsyntax/mut_visit.rs | 5 +- src/libsyntax/print/pprust.rs | 22 +++---- src/libsyntax/visit.rs | 5 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +- src/test/ui/parser/impl-item-type-no-body-pass.rs | 11 ++++ .../parser/impl-item-type-no-body-semantic-fail.rs | 22 +++++++ .../impl-item-type-no-body-semantic-fail.stderr | 73 ++++++++++++++++++++++ 16 files changed, 209 insertions(+), 54 deletions(-) create mode 100644 src/test/ui/parser/impl-item-type-no-body-pass.rs create mode 100644 src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs create mode 100644 src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a82febba38a..54ff1f56eec 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1253,6 +1253,14 @@ impl<'a> LoweringContext<'a> { ty } + fn ty(&mut self, span: Span, kind: hir::TyKind) -> hir::Ty { + hir::Ty { hir_id: self.next_id(), kind, span } + } + + fn ty_tup(&mut self, span: Span, tys: HirVec) -> hir::Ty { + self.ty(span, hir::TyKind::Tup(tys)) + } + fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, @@ -2084,12 +2092,9 @@ impl<'a> LoweringContext<'a> { .iter() .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())) .collect(); - let mk_tup = |this: &mut Self, tys, span| { - hir::Ty { kind: hir::TyKind::Tup(tys), hir_id: this.next_id(), span } - }; ( hir::GenericArgs { - args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))], + args: hir_vec![GenericArg::Type(this.ty_tup(span, inputs))], bindings: hir_vec![ hir::TypeBinding { hir_id: this.next_id(), @@ -2102,7 +2107,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::disallowed() )) .unwrap_or_else(|| - P(mk_tup(this, hir::HirVec::new(), span)) + P(this.ty_tup(span, hir::HirVec::new())) ), }, span: output.as_ref().map_or(span, |ty| ty.span), @@ -2474,17 +2479,13 @@ impl<'a> LoweringContext<'a> { }) ); - // Create the `Foo<...>` refernece itself. Note that the `type + // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the // async fn, so the *type parameters* are inherited. It's // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into()); - - hir::FunctionRetTy::Return(P(hir::Ty { - kind: opaque_ty_ref, - span: opaque_ty_span, - hir_id: self.next_id(), - })) + let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); + hir::FunctionRetTy::Return(P(opaque_ty)) } /// Transforms `-> T` into `Future` @@ -2496,16 +2497,8 @@ impl<'a> LoweringContext<'a> { ) -> hir::GenericBound { // Compute the `T` in `Future` from the return type. let output_ty = match output { - FunctionRetTy::Ty(ty) => { - self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))) - } - FunctionRetTy::Default(ret_ty_span) => { - P(hir::Ty { - hir_id: self.next_id(), - kind: hir::TyKind::Tup(hir_vec![]), - span: *ret_ty_span, - }) - } + FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))), + FunctionRetTy::Default(ret_ty_span) => P(self.ty_tup(*ret_ty_span, hir_vec![])), }; // "" diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index ec78bcf1403..f77523e6382 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -932,16 +932,21 @@ impl LoweringContext<'_> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - ImplItemKind::TyAlias(ref ty) => { + ImplItemKind::TyAlias(_, ref ty) => { let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); - let kind = match ty.kind.opaque_top_hack() { + let kind = match ty { None => { - let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); - hir::ImplItemKind::TyAlias(ty) + hir::ImplItemKind::TyAlias(P(self.ty(i.span, hir::TyKind::Err))) } - Some(bs) => { - let bounds = self.lower_param_bounds(bs, ImplTraitContext::disallowed()); - hir::ImplItemKind::OpaqueTy(bounds) + Some(ty) => match ty.kind.opaque_top_hack() { + None => { + let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); + hir::ImplItemKind::TyAlias(ty) + } + Some(bs) => { + let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed()); + hir::ImplItemKind::OpaqueTy(bs) + } } }; (generics, kind) @@ -972,7 +977,10 @@ impl LoweringContext<'_> { defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match &i.kind { ImplItemKind::Const(..) => hir::AssocItemKind::Const, - ImplItemKind::TyAlias(ty) => match ty.kind.opaque_top_hack() { + ImplItemKind::TyAlias(_, ty) => match ty + .as_deref() + .and_then(|ty| ty.kind.opaque_top_hack()) + { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, }, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 5bfecf78e71..302fcba4cf8 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -697,8 +697,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { - let (name, ty, generics) = self.parse_type_alias()?; - (name, ast::ImplItemKind::TyAlias(ty), generics) + self.parse_impl_assoc_ty()? } else if self.is_const_item() { self.parse_impl_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { @@ -766,6 +765,31 @@ impl<'a> Parser<'a> { Ok((ident, ImplItemKind::Const(ty, expr), Generics::default())) } + /// Parses the following grammar: + /// + /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] + fn parse_impl_assoc_ty(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { + let ident = self.parse_ident()?; + let mut generics = self.parse_generics()?; + + // 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 default = if self.eat(&token::Eq) { + Some(self.parse_ty()?) + } else { + None + }; + self.expect_semi()?; + + Ok((ident, ImplItemKind::TyAlias(bounds, default), generics)) + } + /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -924,7 +948,7 @@ impl<'a> Parser<'a> { /// Parses the following grammar: /// - /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] + /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 78866dc9cc9..f4b28077e9f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -295,6 +295,17 @@ impl<'a> AstValidator<'a> { ) .emit(); } + + fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) { + let span = match bounds { + [] => return, + [b0] => b0.span(), + [b0, .., bl] => b0.span().to(bl.span()), + }; + self.err_handler() + .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect") + .emit(); + } } enum GenericPosition { @@ -770,6 +781,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } + ImplItemKind::TyAlias(bounds, body) => { + self.check_impl_item_provided(ii.span, body, "type", " = ;"); + self.check_impl_assoc_type_no_bounds(bounds); + } _ => {} } visit::walk_impl_item(self, ii); diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 81f06a14d95..f01867f32c6 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,6 +8,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] +#![feature(slice_patterns)] #![recursion_limit="256"] diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index d32a6a4b3e6..33e24c8cfd4 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1119,7 +1119,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { visit::walk_impl_item(this, impl_item); } - ImplItemKind::TyAlias(ref ty) => { + ImplItemKind::TyAlias(_, Some(ref ty)) => { // If this is a trait impl, ensure the type // exists in trait this.check_trait_item(impl_item.ident, @@ -1129,6 +1129,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { this.visit_ty(ty); } + ImplItemKind::TyAlias(_, None) => {} ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index bd7851296dd..d63a9df8d9b 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1127,7 +1127,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { impl_item.span, ); } - ast::ImplItemKind::TyAlias(ref ty) => { + ast::ImplItemKind::TyAlias(_, None) => {} + ast::ImplItemKind::TyAlias(_, Some(ref ty)) => { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 4e2f78e8ab8..89868a9cd29 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1638,7 +1638,7 @@ pub struct ImplItem { pub enum ImplItemKind { Const(P, Option>), Method(FnSig, Option>), - TyAlias(P), + TyAlias(GenericBounds, Option>), Macro(Mac), } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 10f6bbb5949..f786de6401a 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -612,8 +612,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "C-variadic functions are unstable"); } } - ast::ImplItemKind::TyAlias(ref ty) => { - self.check_impl_trait(ty); + ast::ImplItemKind::TyAlias(_, ref ty) => { + if let Some(ty) = ty { + self.check_impl_trait(ty); + } self.check_gat(&ii.generics, ii.span); } _ => {} diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 66cac0f917d..bb0462c19cd 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -987,7 +987,10 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - ImplItemKind::TyAlias(ty) => visitor.visit_ty(ty), + ImplItemKind::TyAlias(bounds, ty) => { + visit_bounds(bounds, visitor); + visit_opt(ty, |ty| visitor.visit_ty(ty)); + } ImplItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 00dcd7e8d0b..03e394b8c7e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1128,16 +1128,15 @@ impl<'a> State<'a> { self.s.word(";") } - fn print_associated_type(&mut self, - ident: ast::Ident, - bounds: Option<&ast::GenericBounds>, - ty: Option<&ast::Ty>) - { + fn print_associated_type( + &mut self, + ident: ast::Ident, + bounds: &ast::GenericBounds, + ty: Option<&ast::Ty>, + ) { self.word_space("type"); self.print_ident(ident); - if let Some(bounds) = bounds { - self.print_type_bounds(":", bounds); - } + self.print_type_bounds(":", bounds); if let Some(ty) = ty { self.s.space(); self.word_space("="); @@ -1568,8 +1567,7 @@ impl<'a> State<'a> { } } ast::TraitItemKind::TyAlias(ref bounds, ref default) => { - self.print_associated_type(ti.ident, Some(bounds), - default.as_ref().map(|ty| &**ty)); + self.print_associated_type(ti.ident, bounds, default.as_deref()); } ast::TraitItemKind::Macro(ref mac) => { self.print_mac(mac); @@ -1603,8 +1601,8 @@ impl<'a> State<'a> { self.s.word(";"); } } - ast::ImplItemKind::TyAlias(ref ty) => { - self.print_associated_type(ii.ident, None, Some(ty)); + ast::ImplItemKind::TyAlias(ref bounds, ref ty) => { + self.print_associated_type(ii.ident, bounds, ty.as_deref()); } ast::ImplItemKind::Macro(ref mac) => { self.print_mac(mac); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f96290ec4f8..7cc1a769e52 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -627,8 +627,9 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt visitor.visit_fn(FnKind::Method(impl_item.ident, sig, &impl_item.vis, body), &sig.decl, impl_item.span, impl_item.id); } - ImplItemKind::TyAlias(ref ty) => { - visitor.visit_ty(ty); + ImplItemKind::TyAlias(ref bounds, ref ty) => { + walk_list!(visitor, visit_param_bound, bounds); + walk_list!(visitor, visit_ty, ty); } ImplItemKind::Macro(ref mac) => { visitor.visit_mac(mac); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index e8c4f993d4f..d51fcf315a6 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -519,7 +519,9 @@ impl<'a> TraitDef<'a> { attrs: Vec::new(), generics: Generics::default(), kind: ast::ImplItemKind::TyAlias( - type_def.to_ty(cx, self.span, type_ident, generics)), + Vec::new(), + Some(type_def.to_ty(cx, self.span, type_ident, generics)), + ), tokens: None, } }); diff --git a/src/test/ui/parser/impl-item-type-no-body-pass.rs b/src/test/ui/parser/impl-item-type-no-body-pass.rs new file mode 100644 index 00000000000..74a9c6ab7e8 --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-pass.rs @@ -0,0 +1,11 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + type Y; + type Z: Ord; + type W: Ord where Self: Eq; + type W where Self: Eq; +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs new file mode 100644 index 00000000000..71c7d4ba21d --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -0,0 +1,22 @@ +#![feature(generic_associated_types)] +//~^ WARN the feature `generic_associated_types` is incomplete + +fn main() {} + +struct X; + +impl X { + type Y; + //~^ ERROR associated type in `impl` without body + //~| ERROR associated types are not yet supported in inherent impls + type Z: Ord; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR associated types are not yet supported in inherent impls + type W: Ord where Self: Eq; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR associated types are not yet supported in inherent impls + type W where Self: Eq; + //~^ ERROR associated type in `impl` without body +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr new file mode 100644 index 00000000000..6f1439c8f0b --- /dev/null +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -0,0 +1,73 @@ +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Y; + | ^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on associated `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13 + | +LL | type Z: Ord; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on associated `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13 + | +LL | type W: Ord where Self: Eq; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:20:5 + | +LL | type W where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash + --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12 + | +LL | #![feature(generic_associated_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Y; + | ^^^^^^^ + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^^ + +error[E0202]: associated types are not yet supported in inherent impls (see #8995) + --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0202`. -- cgit 1.4.1-3-g733a5 From 2d92aa5535e9b28f4c9244785baed719b72b9d59 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:53:20 +0100 Subject: Fuse associated constant parsing. --- src/librustc_parse/parser/item.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 302fcba4cf8..d07fe358272 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -7,6 +7,7 @@ use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey}; use rustc_error_codes::*; use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; +use syntax::ast::{AssocItemKind}; use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField}; @@ -699,7 +700,7 @@ impl<'a> Parser<'a> { let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_impl_assoc_ty()? } else if self.is_const_item() { - self.parse_impl_const()? + self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) @@ -749,22 +750,6 @@ impl<'a> Parser<'a> { !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) } - /// This parses the grammar: - /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";" - fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { - self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let expr = if self.eat(&token::Eq) { - Some(self.parse_expr()?) - } else { - None - }; - self.expect_semi()?; - Ok((ident, ImplItemKind::Const(ty, expr), Generics::default())) - } - /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] @@ -911,7 +896,7 @@ impl<'a> Parser<'a> { let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { - self.parse_trait_item_const()? + self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { // trait item macro. (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) @@ -932,7 +917,10 @@ impl<'a> Parser<'a> { }) } - fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { + /// This parses the grammar: + /// + /// AssocConst = "const" Ident ":" Ty "=" Expr ";" + fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { self.expect_keyword(kw::Const)?; let ident = self.parse_ident()?; self.expect(&token::Colon)?; @@ -943,7 +931,7 @@ impl<'a> Parser<'a> { None }; self.expect_semi()?; - Ok((ident, TraitItemKind::Const(ty, expr), Generics::default())) + Ok((ident, AssocItemKind::Const(ty, expr), Generics::default())) } /// Parses the following grammar: -- cgit 1.4.1-3-g733a5 From 10270bcd30d1d85a003412e597e367f2e7c89942 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 10:55:41 +0100 Subject: Fuse associated type parsing. --- src/librustc_parse/parser/item.rs | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d07fe358272..3fc4cafc0da 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -698,7 +698,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_impl_assoc_ty()? + self.parse_assoc_ty()? } else if self.is_const_item() { self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { @@ -750,31 +750,6 @@ impl<'a> Parser<'a> { !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) } - /// Parses the following grammar: - /// - /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_impl_assoc_ty(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - - // 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 default = if self.eat(&token::Eq) { - Some(self.parse_ty()?) - } else { - None - }; - self.expect_semi()?; - - Ok((ident, ImplItemKind::TyAlias(bounds, default), generics)) - } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -894,7 +869,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_trait_item_assoc_ty()? + self.parse_assoc_ty()? } else if self.is_const_item() { self.parse_assoc_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { @@ -937,7 +912,7 @@ impl<'a> Parser<'a> { /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { + fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -956,7 +931,7 @@ impl<'a> Parser<'a> { }; self.expect_semi()?; - Ok((ident, TraitItemKind::TyAlias(bounds, default), generics)) + Ok((ident, AssocItemKind::TyAlias(bounds, default), generics)) } /// Parses a `UseTree`. -- cgit 1.4.1-3-g733a5 From 7672bff3780ef0e7ba5313bf23644465644e19e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:07:49 +0100 Subject: Unify associated function parsing. --- src/librustc_parse/parser/item.rs | 65 ++++++++++++++------------------------- src/libsyntax/ast.rs | 1 + 2 files changed, 24 insertions(+), 42 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3fc4cafc0da..32cc156783c 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -6,7 +6,7 @@ use crate::maybe_whole; use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey}; use rustc_error_codes::*; use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; -use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; +use syntax::ast::{ItemKind, ImplItem, TraitItem, TraitItemKind, UseTree, UseTreeKind}; use syntax::ast::{AssocItemKind}; use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; @@ -705,7 +705,7 @@ impl<'a> Parser<'a> { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) } else { - self.parse_impl_method(at_end, &mut attrs)? + self.parse_assoc_fn(at_end, &mut attrs, |_| true)? }; Ok(ImplItem { @@ -876,7 +876,11 @@ impl<'a> Parser<'a> { // trait item macro. (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) } else { - self.parse_trait_item_method(at_end, &mut attrs)? + // This is somewhat dubious; We don't want to allow + // param names to be left off if there is a definition... + // + // We don't allow param names to be left off in edition 2018. + self.parse_assoc_fn(at_end, &mut attrs, |t| t.span.rust_2018())? }; Ok(TraitItem { @@ -1823,48 +1827,40 @@ impl<'a> Parser<'a> { }) } - /// Parses a method or a macro invocation in a trait impl. - fn parse_impl_method( - &mut self, - at_end: &mut bool, - attrs: &mut Vec, - ) -> PResult<'a, (Ident, ImplItemKind, Generics)> { - let (ident, sig, generics) = self.parse_method_sig(|_| true)?; - let body = self.parse_trait_method_body(at_end, attrs)?; - Ok((ident, ast::ImplItemKind::Method(sig, body), generics)) - } - - fn parse_trait_item_method( + fn parse_assoc_fn( &mut self, at_end: &mut bool, attrs: &mut Vec, - ) -> PResult<'a, (Ident, TraitItemKind, Generics)> { - // This is somewhat dubious; We don't want to allow - // argument names to be left off if there is a definition... - // - // We don't allow argument names to be left off in edition 2018. - let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; - let body = self.parse_trait_method_body(at_end, attrs)?; - Ok((ident, TraitItemKind::Method(sig, body), generics)) + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, (Ident, AssocItemKind, Generics)> { + let header = self.parse_fn_front_matter()?; + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: true, + allow_c_variadic: false, + is_name_required, + })?; + let sig = FnSig { header, decl }; + let body = self.parse_assoc_fn_body(at_end, attrs)?; + Ok((ident, AssocItemKind::Method(sig, body), generics)) } - /// Parse the "body" of a method in a trait item definition. + /// Parse the "body" of a method in an associated item definition. /// This can either be `;` when there's no body, /// or e.g. a block when the method is a provided one. - fn parse_trait_method_body( + fn parse_assoc_fn_body( &mut self, at_end: &mut bool, attrs: &mut Vec, ) -> PResult<'a, Option>> { Ok(match self.token.kind { token::Semi => { - debug!("parse_trait_method_body(): parsing required method"); + debug!("parse_assoc_fn_body(): parsing required method"); self.bump(); *at_end = true; None } token::OpenDelim(token::Brace) => { - debug!("parse_trait_method_body(): parsing provided method"); + debug!("parse_assoc_fn_body(): parsing provided method"); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(inner_attrs.iter().cloned()); @@ -1885,21 +1881,6 @@ impl<'a> Parser<'a> { }) } - /// Parse the "signature", including the identifier, parameters, and generics - /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. - fn parse_method_sig( - &mut self, - is_name_required: fn(&token::Token) -> bool, - ) -> PResult<'a, (Ident, FnSig, Generics)> { - let header = self.parse_fn_front_matter()?; - let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { - is_self_allowed: true, - allow_c_variadic: false, - is_name_required, - })?; - Ok((ident, FnSig { header, decl }, generics)) - } - /// Parses all the "front matter" for a `fn` declaration, up to /// and including the `fn` keyword: /// diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dd8a7fa8665..5866f9db078 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1640,6 +1640,7 @@ pub enum AssocItemKind { Const(P, Option>), /// An associated function. + /// FIXME(Centril): Rename to `Fn`. Method(FnSig, Option>), /// An associated type. -- cgit 1.4.1-3-g733a5 From 63a9030e7b75312261733187f827df66db55cb1b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:30:04 +0100 Subject: Unify associated item parsing. An exception is `fn` params. --- src/librustc_parse/parser/item.rs | 70 +++++++++-------------------- src/test/ui/did_you_mean/issue-40006.rs | 4 +- src/test/ui/did_you_mean/issue-40006.stderr | 12 ++--- src/test/ui/parser/issue-21153.stderr | 2 +- 4 files changed, 29 insertions(+), 59 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 32cc156783c..3fbdbb4cb22 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -6,8 +6,7 @@ use crate::maybe_whole; use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey}; use rustc_error_codes::*; use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; -use syntax::ast::{ItemKind, ImplItem, TraitItem, TraitItemKind, UseTree, UseTreeKind}; -use syntax::ast::{AssocItemKind}; +use syntax::ast::{AssocItem, AssocItemKind, ItemKind, UseTree, UseTreeKind}; use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField}; @@ -649,7 +648,7 @@ impl<'a> Parser<'a> { Ok((Ident::invalid(), item_kind, Some(attrs))) } - fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { + fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { self.expect(&token::OpenDelim(token::Brace))?; let attrs = self.parse_inner_attributes()?; @@ -671,12 +670,12 @@ impl<'a> Parser<'a> { } /// Parses an impl item. - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { + pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { maybe_whole!(self, NtImplItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_impl_item_(at_end, attrs); + let item = this.parse_assoc_item(at_end, attrs, |_| true); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -689,38 +688,6 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_impl_item_( - &mut self, - at_end: &mut bool, - mut attrs: Vec, - ) -> PResult<'a, ImplItem> { - let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - let defaultness = self.parse_defaultness(); - let (name, kind, generics) = if self.eat_keyword(kw::Type) { - self.parse_assoc_ty()? - } else if self.is_const_item() { - self.parse_assoc_const()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { - // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! - (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) - } else { - self.parse_assoc_fn(at_end, &mut attrs, |_| true)? - }; - - Ok(ImplItem { - id: DUMMY_NODE_ID, - span: lo.to(self.prev_span), - ident: name, - attrs, - vis, - defaultness, - generics, - kind, - tokens: None, - }) - } - /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { // `pub` is included for better error messages @@ -843,12 +810,19 @@ impl<'a> Parser<'a> { } /// Parses the items in a trait declaration. - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { + pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { maybe_whole!(self, NtTraitItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_trait_item_(at_end, attrs); + // This is somewhat dubious; We don't want to allow + // param names to be left off if there is a definition... + // + // We don't allow param names to be left off in edition 2018. + // + // FIXME(Centril): bake closure into param parsing. + // Also add semantic restrictions and add tests. + let item = this.parse_assoc_item(at_end, attrs, |t| t.span.rust_2018()); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -860,11 +834,12 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_trait_item_( + fn parse_assoc_item( &mut self, at_end: &mut bool, mut attrs: Vec, - ) -> PResult<'a, TraitItem> { + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, AssocItem> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); @@ -872,18 +847,13 @@ impl<'a> Parser<'a> { self.parse_assoc_ty()? } else if self.is_const_item() { self.parse_assoc_const()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { - // trait item macro. - (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) + } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? { + (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { - // This is somewhat dubious; We don't want to allow - // param names to be left off if there is a definition... - // - // We don't allow param names to be left off in edition 2018. - self.parse_assoc_fn(at_end, &mut attrs, |t| t.span.rust_2018())? + self.parse_assoc_fn(at_end, &mut attrs, is_name_required)? }; - Ok(TraitItem { + Ok(AssocItem { id: DUMMY_NODE_ID, span: lo.to(self.prev_span), ident: name, diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index b3c1f60b7eb..ea21592997b 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -18,10 +18,10 @@ trait A { //~ ERROR missing trait B { fn xxx() { ### } //~ ERROR expected } -trait C { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration +trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration L = M; } -trait D { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration +trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration Z = { 2 + 3 }; } trait E { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 30ae6ed4c6d..d1e995013cb 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,4 +1,4 @@ -error: missing `fn`, `type`, or `const` for impl-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:1:13 | LL | impl dyn A { @@ -6,7 +6,7 @@ LL | impl dyn A { LL | | Y | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:7:10 | LL | trait X { @@ -14,7 +14,7 @@ LL | trait X { LL | | X() {} | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:15:10 | LL | trait A { @@ -28,7 +28,7 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:21:10 | LL | trait C { @@ -36,7 +36,7 @@ LL | trait C { LL | | L = M; | |____^ missing `fn`, `type`, or `const` -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:24:10 | LL | trait D { @@ -50,7 +50,7 @@ error: expected one of `!` or `::`, found `(` LL | ::Y (); | ^ expected one of `!` or `::` -error: missing `fn`, `type`, or `const` for impl-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-40006.rs:32:8 | LL | pub hello_method(&self) { diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index 70f55f0aeb9..6e20a9ce3c4 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,4 +1,4 @@ -error: missing `fn`, `type`, or `const` for trait-item declaration +error: missing `fn`, `type`, or `const` for associated-item declaration --> $DIR/issue-21153.rs:1:29 | LL | trait MyTrait: Iterator { -- cgit 1.4.1-3-g733a5 From fa828d7a0567cf833a8da9b10cc9936b3e9423dd Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 11:34:25 +0100 Subject: Relocate `is_const_item`. --- src/librustc_parse/parser/item.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3fbdbb4cb22..dbc0163eef6 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -710,13 +710,6 @@ impl<'a> Parser<'a> { } } - /// Returns `true` if we are looking at `const ID` - /// (returns `false` for things like `const fn`, etc.). - fn is_const_item(&self) -> bool { - self.token.is_keyword(kw::Const) && - !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) - } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -866,6 +859,13 @@ impl<'a> Parser<'a> { }) } + /// Returns `true` if we are looking at `const ID` + /// (returns `false` for things like `const fn`, etc.). + fn is_const_item(&self) -> bool { + self.token.is_keyword(kw::Const) && + !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) + } + /// This parses the grammar: /// /// AssocConst = "const" Ident ":" Ty "=" Expr ";" -- cgit 1.4.1-3-g733a5 From 404013e015d9a9f4835cda47e56aab5223f278ed Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 12:52:59 +0100 Subject: Leave a FIXME re. `allow_plus`. --- src/librustc_parse/parser/ty.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 84ffef68e9a..33d7c878e88 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -42,11 +42,12 @@ impl<'a> Parser<'a> { /// Parses an optional return type `[ -> TY ]` in a function declaration. pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { - if self.eat(&token::RArrow) { - Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?)) + Ok(if self.eat(&token::RArrow) { + // FIXME(Centril): Can we unconditionally `allow_plus`? + FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?) } else { - Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo())) - } + FunctionRetTy::Default(self.token.span.shrink_to_lo()) + }) } pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool, -- cgit 1.4.1-3-g733a5 From 34d91709b672d91ea9623ae4bc2275e8b003fc2c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:00:08 +0100 Subject: parse: refactor fun ret ty & param ty --- src/librustc/hir/lowering.rs | 34 +++++--------- src/librustc_interface/util.rs | 8 ++-- src/librustc_parse/parser/expr.rs | 2 +- src/librustc_parse/parser/item.rs | 6 +-- src/librustc_parse/parser/path.rs | 6 +-- src/librustc_parse/parser/ty.rs | 26 +++++++++-- src/librustc_passes/ast_validation.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 9 ++-- src/libsyntax/ast.rs | 4 +- src/libsyntax/mut_visit.rs | 8 +++- src/libsyntax/print/pprust.rs | 75 ++++++++---------------------- src/libsyntax/visit.rs | 2 +- 12 files changed, 77 insertions(+), 107 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 54ff1f56eec..e2c99f456e9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2092,29 +2092,19 @@ impl<'a> LoweringContext<'a> { .iter() .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())) .collect(); + let output_ty = match output { + FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()), + FunctionRetTy::Default(_) => P(this.ty_tup(span, hir::HirVec::new())), + }; + let args = hir_vec![GenericArg::Type(this.ty_tup(span, inputs))]; + let binding = hir::TypeBinding { + hir_id: this.next_id(), + ident: Ident::with_dummy_span(FN_OUTPUT_NAME), + span: output_ty.span, + kind: hir::TypeBindingKind::Equality { ty: output_ty }, + }; ( - hir::GenericArgs { - args: hir_vec![GenericArg::Type(this.ty_tup(span, inputs))], - bindings: hir_vec![ - hir::TypeBinding { - hir_id: this.next_id(), - ident: Ident::with_dummy_span(FN_OUTPUT_NAME), - kind: hir::TypeBindingKind::Equality { - ty: output - .as_ref() - .map(|ty| this.lower_ty( - &ty, - ImplTraitContext::disallowed() - )) - .unwrap_or_else(|| - P(this.ty_tup(span, hir::HirVec::new())) - ), - }, - span: output.as_ref().map_or(span, |ty| ty.span), - } - ], - parenthesized: true, - }, + hir::GenericArgs { args, bindings: hir_vec![binding], parenthesized: true }, false, ) } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8c225b83f40..ca7c4ba8786 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -712,8 +712,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { ret } - fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool { - if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output { + fn should_ignore_fn(ret_ty: &ast::FunctionRetTy) -> bool { + if let ast::FunctionRetTy::Ty(ref ty) = ret_ty { fn involves_impl_trait(ty: &ast::Ty) -> bool { match ty.kind { ast::TyKind::ImplTrait(..) => true, @@ -742,7 +742,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { }, Some(&ast::GenericArgs::Parenthesized(ref data)) => { any_involves_impl_trait(data.inputs.iter()) || - any_involves_impl_trait(data.output.iter()) + ReplaceBodyWithLoop::should_ignore_fn(&data.output) } } }), @@ -762,7 +762,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { fn is_sig_const(sig: &ast::FnSig) -> bool { sig.header.constness.node == ast::Constness::Const || - ReplaceBodyWithLoop::should_ignore_fn(&sig.decl) + ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output) } } diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3cd4988ce0b..e4dff07e92c 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1381,7 +1381,7 @@ impl<'a> Parser<'a> { args } }; - let output = self.parse_ret_ty(true)?; + let output = self.parse_ret_ty(true, true)?; Ok(P(FnDecl { inputs: inputs_captures, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index dbc0163eef6..f391eda976c 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1900,7 +1900,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { Ok(P(FnDecl { inputs: self.parse_fn_params(cfg)?, - output: self.parse_ret_ty(ret_allow_plus)?, + output: self.parse_ret_ty(ret_allow_plus, true)?, })) } @@ -2002,12 +2002,12 @@ impl<'a> Parser<'a> { } self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?) + (pat, self.parse_ty_for_param(cfg.allow_c_variadic)?) } else { debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic); + let mut ty = self.parse_ty_for_param(cfg.allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 5334fc485e7..aeba6dd2f67 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -182,11 +182,7 @@ impl<'a> Parser<'a> { // `(T, U) -> R` let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let span = ident.span.to(self.prev_span); - let output = if self.eat(&token::RArrow) { - Some(self.parse_ty_common(false, false, false)?) - } else { - None - }; + let output = self.parse_ret_ty(false, false)?; ParenthesizedArgs { inputs, output, span }.into() }; diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 33d7c878e88..1dffa6c94a8 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -30,6 +30,13 @@ impl<'a> Parser<'a> { self.parse_ty_common(true, true, false) } + /// Parse a type suitable for a function or function pointer parameter. + /// The difference from `parse_ty` is that this version allows `...` + /// (`CVarArgs`) at the top level of the the type. + pub(super) fn parse_ty_for_param(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { + self.parse_ty_common(true, true, allow_c_variadic) + } + /// Parses a type in restricted contexts where `+` is not permitted. /// /// Example 1: `&'a TYPE` @@ -41,17 +48,26 @@ impl<'a> Parser<'a> { } /// Parses an optional return type `[ -> TY ]` in a function declaration. - pub(super) fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { + pub(super) fn parse_ret_ty( + &mut self, + allow_plus: bool, + allow_qpath_recovery: bool, + ) -> PResult<'a, FunctionRetTy> { Ok(if self.eat(&token::RArrow) { // FIXME(Centril): Can we unconditionally `allow_plus`? - FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?) + FunctionRetTy::Ty(self.parse_ty_common(allow_plus, allow_qpath_recovery, false)?) } else { FunctionRetTy::Default(self.token.span.shrink_to_lo()) }) } - pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool, - allow_c_variadic: bool) -> PResult<'a, P> { + fn parse_ty_common( + &mut self, + allow_plus: bool, + allow_qpath_recovery: bool, + // Is `...` (`CVarArgs`) legal in the immediate top level call? + allow_c_variadic: bool, + ) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); maybe_whole!(self, NtTy, |x| x); @@ -198,6 +214,8 @@ impl<'a> Parser<'a> { self.eat(&token::DotDotDot); TyKind::CVarArgs } else { + // FIXME(Centril): Should we just allow `...` syntactically + // anywhere in a type and use semantic restrictions instead? return Err(struct_span_fatal!( self.sess.span_diagnostic, self.token.span, diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index f4b28077e9f..8be97155d8c 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -674,10 +674,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } GenericArgs::Parenthesized(ref data) => { walk_list!(self, visit_ty, &data.inputs); - if let Some(ref type_) = data.output { + if let FunctionRetTy::Ty(ty) = &data.output { // `-> Foo` syntax is essentially an associated type binding, // so it is also allowed to contain nested `impl Trait`. - self.with_impl_trait(None, |this| this.visit_ty(type_)); + self.with_impl_trait(None, |this| this.visit_ty(ty)); } } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index d63a9df8d9b..cc0f3c512f5 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -811,9 +811,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { match **generic_args { ast::GenericArgs::AngleBracketed(ref data) => { for arg in &data.args { - match arg { - ast::GenericArg::Type(ty) => self.visit_ty(ty), - _ => {} + if let ast::GenericArg::Type(ty) = arg { + self.visit_ty(ty); } } } @@ -821,8 +820,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { for t in &data.inputs { self.visit_ty(t); } - if let Some(ref t) = data.output { - self.visit_ty(t); + if let ast::FunctionRetTy::Ty(ty) = &data.output { + self.visit_ty(ty); } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5866f9db078..d90d74d7a26 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -254,7 +254,7 @@ pub struct ParenthesizedArgs { pub inputs: Vec>, /// `C` - pub output: Option>, + pub output: FunctionRetTy, } impl ParenthesizedArgs { @@ -2185,7 +2185,7 @@ impl fmt::Debug for ImplPolarity { } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum FunctionRetTy { +pub enum FunctionRetTy { // FIXME(Centril): Rename to `FnRetTy` and in HIR also. /// Returns type is not specified. /// /// Functions default to `()` and closures default to inference. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index bb0462c19cd..97a85b0fe7e 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -553,7 +553,7 @@ pub fn noop_visit_parenthesized_parameter_data(args: &mut Parenth vis: &mut T) { let ParenthesizedArgs { inputs, output, span } = args; visit_vec(inputs, |input| vis.visit_ty(input)); - visit_opt(output, |output| vis.visit_ty(output)); + noop_visit_fn_ret_ty(output, vis); vis.visit_span(span); } @@ -742,7 +742,11 @@ pub fn noop_visit_asyncness(asyncness: &mut IsAsync, vis: &mut T) pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { let FnDecl { inputs, output } = decl.deref_mut(); inputs.flat_map_in_place(|param| vis.flat_map_param(param)); - match output { + noop_visit_fn_ret_ty(output, vis); +} + +pub fn noop_visit_fn_ret_ty(fn_ret_ty: &mut FunctionRetTy, vis: &mut T) { + match fn_ret_ty { FunctionRetTy::Default(span) => vis.visit_span(span), FunctionRetTy::Ty(ty) => vis.visit_ty(ty), } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 03e394b8c7e..a141d4d71bb 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -887,17 +887,9 @@ impl<'a> PrintState<'a> for State<'a> { ast::GenericArgs::Parenthesized(ref data) => { self.s.word("("); - self.commasep( - Inconsistent, - &data.inputs, - |s, ty| s.print_type(ty)); + self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty)); self.s.word(")"); - - if let Some(ref ty) = data.output { - self.space_if_not_bol(); - self.word_space("->"); - self.print_type(ty); - } + self.print_fn_ret_ty(&data.output); } } } @@ -1579,6 +1571,7 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::SubItem(ti.id)) } + // FIXME(Centril): merge with function above. crate fn print_impl_item(&mut self, ii: &ast::ImplItem) { self.ann.pre(self, AnnNode::SubItem(ii.id)); self.hardbreak_if_not_bol(); @@ -2104,7 +2097,7 @@ impl<'a> State<'a> { self.print_asyncness(asyncness); self.print_capture_clause(capture_clause); - self.print_fn_block_params(decl); + self.print_fn_params_and_ret(decl, true); self.s.space(); self.print_expr(body); self.end(); // need to close a box @@ -2535,36 +2528,16 @@ impl<'a> State<'a> { self.print_ident(name); } self.print_generic_params(&generics.params); - self.print_fn_params_and_ret(decl); + self.print_fn_params_and_ret(decl, false); self.print_where_clause(&generics.where_clause) } - crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl) { - self.popen(); - self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, false)); - self.pclose(); - - self.print_fn_output(decl) - } - - crate fn print_fn_block_params(&mut self, decl: &ast::FnDecl) { - self.s.word("|"); - self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, true)); - self.s.word("|"); - - if let ast::FunctionRetTy::Default(..) = decl.output { - return; - } - - self.space_if_not_bol(); - self.word_space("->"); - match decl.output { - ast::FunctionRetTy::Ty(ref ty) => { - self.print_type(ty); - self.maybe_print_comment(ty.span.lo()) - } - ast::FunctionRetTy::Default(..) => unreachable!(), - } + crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) { + let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") }; + self.word(open); + self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure)); + self.word(close); + self.print_fn_ret_ty(&decl.output) } crate fn print_movability(&mut self, movability: ast::Movability) { @@ -2786,24 +2759,14 @@ impl<'a> State<'a> { self.end(); } - crate fn print_fn_output(&mut self, decl: &ast::FnDecl) { - if let ast::FunctionRetTy::Default(..) = decl.output { - return; - } - - self.space_if_not_bol(); - self.ibox(INDENT_UNIT); - self.word_space("->"); - match decl.output { - ast::FunctionRetTy::Default(..) => unreachable!(), - ast::FunctionRetTy::Ty(ref ty) => - self.print_type(ty), - } - self.end(); - - match decl.output { - ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo()), - _ => {} + crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FunctionRetTy) { + if let ast::FunctionRetTy::Ty(ty) = fn_ret_ty { + self.space_if_not_bol(); + self.ibox(INDENT_UNIT); + self.word_space("->"); + self.print_type(ty); + self.end(); + self.maybe_print_comment(ty.span.lo()); } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7cc1a769e52..74df808b37e 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -420,7 +420,7 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V, } GenericArgs::Parenthesized(ref data) => { walk_list!(visitor, visit_ty, &data.inputs); - walk_list!(visitor, visit_ty, &data.output); + walk_fn_ret_ty(visitor, &data.output); } } } -- cgit 1.4.1-3-g733a5 From 51ccdebe0b07f38e7e371a80424285539811c048 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 17:29:13 +0100 Subject: Unify associated item parsing more. --- src/librustc_parse/parser/item.rs | 49 ++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 29 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f391eda976c..0126297a358 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -669,25 +669,6 @@ impl<'a> Parser<'a> { Ok((impl_items, attrs)) } - /// Parses an impl item. - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { - maybe_whole!(self, NtImplItem, |x| x); - let attrs = self.parse_outer_attributes()?; - let mut unclosed_delims = vec![]; - let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_assoc_item(at_end, attrs, |_| true); - unclosed_delims.append(&mut this.unclosed_delims); - item - })?; - self.unclosed_delims.append(&mut unclosed_delims); - - // See `parse_item` for why this clause is here. - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - Ok(item) - } - /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { // `pub` is included for better error messages @@ -802,20 +783,30 @@ impl<'a> Parser<'a> { } } - /// Parses the items in a trait declaration. + pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { + maybe_whole!(self, NtImplItem, |x| x); + self.parse_assoc_item(at_end, |_| true) + } + pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> { maybe_whole!(self, NtTraitItem, |x| x); + // This is somewhat dubious; We don't want to allow + // param names to be left off if there is a definition... + // + // We don't allow param names to be left off in edition 2018. + self.parse_assoc_item(at_end, |t| t.span.rust_2018()) + } + + /// Parses associated items. + fn parse_assoc_item( + &mut self, + at_end: &mut bool, + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, AssocItem> { let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - // This is somewhat dubious; We don't want to allow - // param names to be left off if there is a definition... - // - // We don't allow param names to be left off in edition 2018. - // - // FIXME(Centril): bake closure into param parsing. - // Also add semantic restrictions and add tests. - let item = this.parse_assoc_item(at_end, attrs, |t| t.span.rust_2018()); + let item = this.parse_assoc_item_(at_end, attrs, is_name_required); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -827,7 +818,7 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_assoc_item( + fn parse_assoc_item_( &mut self, at_end: &mut bool, mut attrs: Vec, -- cgit 1.4.1-3-g733a5 From 0d41d0fe1423b4d21d6a9a2778419d399da1a13a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 02:38:33 +0100 Subject: Move `allow_c_varadic` logic to `ast_validation`. --- src/librustc_parse/parser/item.rs | 16 ++------- src/librustc_parse/parser/ty.rs | 5 ++- src/librustc_passes/ast_validation.rs | 26 +++++++++++++++ src/test/ui/invalid/invalid-variadic-function.rs | 3 -- .../ui/invalid/invalid-variadic-function.stderr | 15 --------- src/test/ui/parser/variadic-ffi-3.rs | 5 --- src/test/ui/parser/variadic-ffi-3.stderr | 9 ----- src/test/ui/parser/variadic-ffi-4.rs | 5 --- src/test/ui/parser/variadic-ffi-4.stderr | 9 ----- .../parser/variadic-ffi-semantic-restrictions.rs | 26 +++++++++++++++ .../variadic-ffi-semantic-restrictions.stderr | 38 ++++++++++++++++++++++ src/test/ui/parser/variadic-ffi-syntactic-pass.rs | 25 ++++++++++++++ 12 files changed, 119 insertions(+), 63 deletions(-) delete mode 100644 src/test/ui/invalid/invalid-variadic-function.rs delete mode 100644 src/test/ui/invalid/invalid-variadic-function.stderr delete mode 100644 src/test/ui/parser/variadic-ffi-3.rs delete mode 100644 src/test/ui/parser/variadic-ffi-3.stderr delete mode 100644 src/test/ui/parser/variadic-ffi-4.rs delete mode 100644 src/test/ui/parser/variadic-ffi-4.stderr create mode 100644 src/test/ui/parser/variadic-ffi-semantic-restrictions.rs create mode 100644 src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr create mode 100644 src/test/ui/parser/variadic-ffi-syntactic-pass.rs (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0126297a358..d4b62e8ebba 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1727,8 +1727,6 @@ impl<'a> Parser<'a> { pub(super) struct ParamCfg { /// Is `self` is allowed as the first parameter? pub is_self_allowed: bool, - /// Is `...` allowed as the tail of the parameter list? - pub allow_c_variadic: bool, /// `is_name_required` decides if, per-parameter, /// the parameter must have a pattern or just a type. pub is_name_required: fn(&token::Token) -> bool, @@ -1744,16 +1742,8 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { - let is_c_abi = match header.ext { - ast::Extern::None => false, - ast::Extern::Implicit => true, - ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C, - }; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - // FIXME: Parsing should not depend on ABI or unsafety and - // the variadic parameter should always be parsed. - allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe, is_name_required: |_| true, })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; @@ -1772,7 +1762,6 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Fn)?; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - allow_c_variadic: true, is_name_required: |_| true, })?; let span = lo.to(self.token.span); @@ -1797,7 +1786,6 @@ impl<'a> Parser<'a> { let header = self.parse_fn_front_matter()?; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: true, - allow_c_variadic: false, is_name_required, })?; let sig = FnSig { header, decl }; @@ -1993,12 +1981,12 @@ impl<'a> Parser<'a> { } self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_for_param(cfg.allow_c_variadic)?) + (pat, self.parse_ty_for_param()?) } else { debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_for_param(cfg.allow_c_variadic); + let mut ty = self.parse_ty_for_param(); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 1dffa6c94a8..3ab290d1cbb 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -33,8 +33,8 @@ impl<'a> Parser<'a> { /// Parse a type suitable for a function or function pointer parameter. /// The difference from `parse_ty` is that this version allows `...` /// (`CVarArgs`) at the top level of the the type. - pub(super) fn parse_ty_for_param(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { - self.parse_ty_common(true, true, allow_c_variadic) + pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P> { + self.parse_ty_common(true, true, true) } /// Parses a type in restricted contexts where `+` is not permitted. @@ -306,7 +306,6 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Fn)?; let cfg = ParamCfg { is_self_allowed: false, - allow_c_variadic: true, is_name_required: |_| false, }; let decl = self.parse_fn_decl(cfg, false)?; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index ad6c99494a6..a26c991c9cf 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -306,6 +306,19 @@ impl<'a> AstValidator<'a> { .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect") .emit(); } + + fn check_c_varadic_type(&self, decl: &FnDecl) { + for Param { ty, span, .. } in &decl.inputs { + if let TyKind::CVarArgs = ty.kind { + self.err_handler() + .struct_span_err( + *span, + "only foreign or `unsafe extern \"C\" functions may be C-variadic", + ) + .emit(); + } + } + } } enum GenericPosition { @@ -554,6 +567,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } + // Reject C-varadic type unless the function is `unsafe extern "C"` semantically. + match sig.header.ext { + Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | + Extern::Implicit if sig.header.unsafety == Unsafety::Unsafe => {} + _ => self.check_c_varadic_type(&sig.decl), + } } ItemKind::ForeignMod(..) => { self.invalid_visibility( @@ -795,6 +814,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(ti.span, ti.defaultness); visit::walk_trait_item(self, ti); } + + fn visit_assoc_item(&mut self, item: &'a AssocItem) { + if let AssocItemKind::Method(sig, _) = &item.kind { + self.check_c_varadic_type(&sig.decl); + } + visit::walk_assoc_item(self, item); + } } pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool { diff --git a/src/test/ui/invalid/invalid-variadic-function.rs b/src/test/ui/invalid/invalid-variadic-function.rs deleted file mode 100644 index 8d23f0e4770..00000000000 --- a/src/test/ui/invalid/invalid-variadic-function.rs +++ /dev/null @@ -1,3 +0,0 @@ -extern "C" fn foo(x: u8, ...); -//~^ ERROR only foreign functions are allowed to be C-variadic -//~| ERROR expected one of `->`, `where`, or `{`, found `;` diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr deleted file mode 100644 index 7e58b17e7db..00000000000 --- a/src/test/ui/invalid/invalid-variadic-function.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/invalid-variadic-function.rs:1:26 - | -LL | extern "C" fn foo(x: u8, ...); - | ^^^ - -error: expected one of `->`, `where`, or `{`, found `;` - --> $DIR/invalid-variadic-function.rs:1:30 - | -LL | extern "C" fn foo(x: u8, ...); - | ^ expected one of `->`, `where`, or `{` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-3.rs b/src/test/ui/parser/variadic-ffi-3.rs deleted file mode 100644 index ce83cc87abe..00000000000 --- a/src/test/ui/parser/variadic-ffi-3.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn foo(x: isize, ...) { - //~^ ERROR: only foreign functions are allowed to be C-variadic -} - -fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr deleted file mode 100644 index aeeebdb9914..00000000000 --- a/src/test/ui/parser/variadic-ffi-3.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/variadic-ffi-3.rs:1:18 - | -LL | fn foo(x: isize, ...) { - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-4.rs b/src/test/ui/parser/variadic-ffi-4.rs deleted file mode 100644 index 5f8b3f8f539..00000000000 --- a/src/test/ui/parser/variadic-ffi-4.rs +++ /dev/null @@ -1,5 +0,0 @@ -extern "C" fn foo(x: isize, ...) { - //~^ ERROR: only foreign functions are allowed to be C-variadic -} - -fn main() {} diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr deleted file mode 100644 index da83276c72d..00000000000 --- a/src/test/ui/parser/variadic-ffi-4.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0743]: only foreign functions are allowed to be C-variadic - --> $DIR/variadic-ffi-4.rs:1:29 - | -LL | extern "C" fn foo(x: isize, ...) { - | ^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0743`. diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs new file mode 100644 index 00000000000..57086bca2f4 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -0,0 +1,26 @@ +#![feature(c_variadic)] + +fn main() {} + +fn f1(x: isize, ...) {} +//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + +extern "C" fn f2(x: isize, ...) {} +//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + +extern fn f3(x: isize, ...) {} +//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + +struct X; + +impl X { + fn f4(x: isize, ...) {} + //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +} + +trait T { + fn f5(x: isize, ...) {} + //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + fn f6(x: isize, ...); + //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +} diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr new file mode 100644 index 00000000000..69244d92ee3 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -0,0 +1,38 @@ +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:5:17 + | +LL | fn f1(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:28 + | +LL | extern "C" fn f2(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:11:24 + | +LL | extern fn f3(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:17:21 + | +LL | fn f4(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:22:21 + | +LL | fn f5(x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:24:21 + | +LL | fn f6(x: isize, ...); + | ^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs new file mode 100644 index 00000000000..f8fcce6ba73 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs @@ -0,0 +1,25 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn f1(x: isize, ...) {} + +#[cfg(FALSE)] +extern "C" fn f2(x: isize, ...) {} + +#[cfg(FALSE)] +extern fn f3(x: isize, ...) {} + +struct X; + +#[cfg(FALSE)] +impl X { + fn f4(x: isize, ...) {} +} + +#[cfg(FALSE)] +trait T { + fn f5(x: isize, ...) {} + fn f6(x: isize, ...); +} -- cgit 1.4.1-3-g733a5 From 35e9e097e7c7e977f36795c0febceb327e1fa33f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Dec 2019 03:16:12 +0100 Subject: More c-variadic errors as semantic restrictions. --- src/librustc/hir/lowering.rs | 8 +- src/librustc_parse/parser/item.rs | 55 +----- src/librustc_passes/ast_validation.rs | 23 ++- .../c-variadic/variadic-ffi-no-fixed-args.stderr | 4 +- .../parser/variadic-ffi-semantic-restrictions.rs | 74 ++++++-- .../variadic-ffi-semantic-restrictions.stderr | 204 +++++++++++++++++++-- src/test/ui/parser/variadic-ffi-syntactic-pass.rs | 40 +++- 7 files changed, 322 insertions(+), 86 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e2c99f456e9..58225e87f26 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1426,7 +1426,13 @@ impl<'a> LoweringContext<'a> { } } TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"), - TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"), + TyKind::CVarArgs => { + self.sess.delay_span_bug( + t.span, + "`TyKind::CVarArgs` should have been handled elsewhere", + ); + hir::TyKind::Err + } }; hir::Ty { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d4b62e8ebba..a7c98886622 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1885,58 +1885,23 @@ impl<'a> Parser<'a> { /// Parses the parameter list of a function, including the `(` and `)` delimiters. fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { - let sp = self.token.span; let is_trait_item = cfg.is_self_allowed; - let mut c_variadic = false; // Parse the arguments, starting out with `self` being possibly allowed... - let (params, _) = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(&cfg, is_trait_item); + let (mut params, _) = self.parse_paren_comma_seq(|p| { + let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| { + e.emit(); + let lo = p.prev_span; + // Skip every token until next possible arg or end. + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + // Create a placeholder argument for proper arg count (issue #34264). + Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span)))) + }); // ...now that we've parsed the first argument, `self` is no longer allowed. cfg.is_self_allowed = false; - - match param { - Ok(param) => Ok( - if let TyKind::CVarArgs = param.ty.kind { - c_variadic = true; - if p.token != token::CloseDelim(token::Paren) { - p.span_err( - p.token.span, - "`...` must be the last argument of a C-variadic function", - ); - // FIXME(eddyb) this should probably still push `CVarArgs`. - // Maybe AST validation/HIR lowering should emit the above error? - None - } else { - Some(param) - } - } else { - Some(param) - } - ), - Err(mut e) => { - e.emit(); - let lo = p.prev_span; - // Skip every token until next possible arg or end. - p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); - // Create a placeholder argument for proper arg count (issue #34264). - let span = lo.to(p.prev_span); - Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) - } - } + param })?; - - let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); - // Replace duplicated recovered params with `_` pattern to avoid unnecessary errors. self.deduplicate_recovered_params_names(&mut params); - - if c_variadic && params.len() <= 1 { - self.span_err( - sp, - "C-variadic function must be declared with at least one named argument", - ); - } - Ok(params) } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 884af188ed6..c75bd996e10 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -250,6 +250,26 @@ impl<'a> AstValidator<'a> { } fn check_fn_decl(&self, fn_decl: &FnDecl) { + match &*fn_decl.inputs { + [Param { ty, span, .. }] => if let TyKind::CVarArgs = ty.kind { + self.err_handler() + .span_err( + *span, + "C-variadic function must be declared with at least one named argument", + ); + }, + [ps @ .., _] => for Param { ty, span, .. } in ps { + if let TyKind::CVarArgs = ty.kind { + self.err_handler() + .span_err( + *span, + "`...` must be the last argument of a C-variadic function", + ); + } + } + _ => {} + } + fn_decl .inputs .iter() @@ -265,8 +285,7 @@ impl<'a> AstValidator<'a> { ) .span_label(attr.span, "doc comments are not allowed here") .emit(); - } - else { + } else { self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \ forbid, and warn are the only allowed built-in attributes in function parameters") }); diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr index cb6060525fc..7af38c88f43 100644 --- a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -1,8 +1,8 @@ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-no-fixed-args.rs:2:11 + --> $DIR/variadic-ffi-no-fixed-args.rs:2:12 | LL | fn foo(...); - | ^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs index 57086bca2f4..aa85f6d6b52 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -2,25 +2,75 @@ fn main() {} -fn f1(x: isize, ...) {} -//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +fn f1_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic -extern "C" fn f2(x: isize, ...) {} -//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +fn f1_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument -extern fn f3(x: isize, ...) {} -//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic +extern "C" fn f2_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +extern "C" fn f2_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f2_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern fn f3_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + +extern fn f3_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern fn f3_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern { + fn e_f1(...); + //~^ ERROR C-variadic function must be declared with at least one named argument + fn e_f2(..., x: isize); + //~^ ERROR `...` must be the last argument of a C-variadic function +} struct X; impl X { - fn f4(x: isize, ...) {} - //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + fn i_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn i_f2(...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn i_f3(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn i_f4(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function } trait T { - fn f5(x: isize, ...) {} - //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic - fn f6(x: isize, ...); - //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f2(x: isize, ...); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + fn t_f3(...) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f4(...); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f5(..., x: isize) {} + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn t_f6(..., x: isize); + //~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function } diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr index 69244d92ee3..21992a29670 100644 --- a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,38 +1,206 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:5:17 + --> $DIR/variadic-ffi-semantic-restrictions.rs:5:19 | -LL | fn f1(x: isize, ...) {} - | ^^^^ +LL | fn f1_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + | +LL | fn f1_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:8:9 + | +LL | fn f1_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 + | +LL | extern "C" fn f2_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:19:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:8:28 + --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26 | -LL | extern "C" fn f2(x: isize, ...) {} +LL | extern fn f3_1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16 + | +LL | extern fn f3_2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:26:16 + | +LL | extern fn f3_2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16 + | +LL | extern fn f3_3(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:30:16 + | +LL | extern fn f3_3(..., x: isize) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:35:13 + | +LL | fn e_f1(...); + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:37:13 + | +LL | fn e_f2(..., x: isize); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:23 + | +LL | fn i_f1(x: isize, ...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + | +LL | fn i_f2(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:46:13 + | +LL | fn i_f2(...) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:49:28 + | +LL | fn i_f3(..., x: isize, ...) {} | ^^^^ +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:11:24 + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13 | -LL | extern fn f3(x: isize, ...) {} - | ^^^^ +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:53:28 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:17:21 + --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23 | -LL | fn f4(x: isize, ...) {} - | ^^^^ +LL | fn t_f1(x: isize, ...) {} + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:22:21 + --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23 + | +LL | fn t_f2(x: isize, ...); + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + | +LL | fn t_f3(...) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 + | +LL | fn t_f3(...) {} + | ^^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + | +LL | fn t_f4(...); + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 + | +LL | fn t_f4(...); + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^^ + +error: only foreign or `unsafe extern "C" functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 | -LL | fn f5(x: isize, ...) {} - | ^^^^ +LL | fn t_f6(..., x: isize); + | ^^^^ error: only foreign or `unsafe extern "C" functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:24:21 + --> $DIR/variadic-ffi-semantic-restrictions.rs:73:13 | -LL | fn f6(x: isize, ...); - | ^^^^ +LL | fn t_f6(..., x: isize); + | ^^^^ -error: aborting due to 6 previous errors +error: aborting due to 34 previous errors diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs index f8fcce6ba73..3875d6af137 100644 --- a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs +++ b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs @@ -3,23 +3,51 @@ fn main() {} #[cfg(FALSE)] -fn f1(x: isize, ...) {} +fn f1_1(x: isize, ...) {} #[cfg(FALSE)] -extern "C" fn f2(x: isize, ...) {} +fn f1_2(...) {} #[cfg(FALSE)] -extern fn f3(x: isize, ...) {} +extern "C" fn f2_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern "C" fn f2_2(...) {} + +#[cfg(FALSE)] +extern "C" fn f2_3(..., x: isize) {} + +#[cfg(FALSE)] +extern fn f3_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern fn f3_2(...) {} + +#[cfg(FALSE)] +extern fn f3_3(..., x: isize) {} + +#[cfg(FALSE)] +extern { + fn e_f1(...); + fn e_f2(..., x: isize); +} struct X; #[cfg(FALSE)] impl X { - fn f4(x: isize, ...) {} + fn i_f1(x: isize, ...) {} + fn i_f2(...) {} + fn i_f3(..., x: isize, ...) {} + fn i_f4(..., x: isize, ...) {} } #[cfg(FALSE)] trait T { - fn f5(x: isize, ...) {} - fn f6(x: isize, ...); + fn t_f1(x: isize, ...) {} + fn t_f2(x: isize, ...); + fn t_f3(...) {} + fn t_f4(...); + fn t_f5(..., x: isize) {} + fn t_f6(..., x: isize); } -- cgit 1.4.1-3-g733a5 From e52f902a8ab3a1abbb200607db4766d95b27bc8e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 00:13:59 +0100 Subject: `AssocImplKind::{Method -> Fn}`. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/lowering/item.rs | 10 +++++----- src/librustc_interface/util.rs | 2 +- src/librustc_lint/builtin.rs | 4 ++-- src/librustc_parse/parser/item.rs | 2 +- src/librustc_passes/ast_validation.rs | 8 ++++---- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/def_collector.rs | 11 ++++------- src/librustc_resolve/late.rs | 4 ++-- src/librustc_save_analysis/dump_visitor.rs | 4 ++-- src/libsyntax/ast.rs | 3 +-- src/libsyntax/feature_gate/check.rs | 4 ++-- src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 4 ++-- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- 16 files changed, 31 insertions(+), 35 deletions(-) (limited to 'src/librustc_parse/parser') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 78df14adc5d..50733512fae 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -481,7 +481,7 @@ impl<'a> LoweringContext<'a> { self.lctx.allocate_hir_id_counter(item.id); match item.kind { - AssocItemKind::Method(_, None) => { + AssocItemKind::Fn(_, None) => { // Ignore patterns in trait methods without bodies self.with_hir_id_owner(None, |this| { visit::walk_trait_item(this, item) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index f25714f741b..f0543b9057d 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -826,7 +826,7 @@ impl LoweringContext<'_> { .map(|x| self.lower_const_body(i.span, Some(x))), ), ), - AssocItemKind::Method(ref sig, None) => { + AssocItemKind::Fn(ref sig, None) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( &i.generics, @@ -837,7 +837,7 @@ impl LoweringContext<'_> { ); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } - AssocItemKind::Method(ref sig, Some(ref body)) => { + AssocItemKind::Fn(ref sig, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig( &i.generics, @@ -880,7 +880,7 @@ impl LoweringContext<'_> { AssocItemKind::TyAlias(_, ref default) => { (hir::AssocItemKind::Type, default.is_some()) } - AssocItemKind::Method(ref sig, ref default) => ( + AssocItemKind::Fn(ref sig, ref default) => ( hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, @@ -913,7 +913,7 @@ impl LoweringContext<'_> { self.lower_const_body(i.span, expr.as_deref()), ), ), - AssocItemKind::Method(ref sig, ref body) => { + AssocItemKind::Fn(ref sig, ref body) => { self.current_item = Some(i.span); let body_id = self.lower_maybe_async_body( i.span, @@ -984,7 +984,7 @@ impl LoweringContext<'_> { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, }, - AssocItemKind::Method(sig, _) => hir::AssocItemKind::Method { + AssocItemKind::Fn(sig, _) => hir::AssocItemKind::Method { has_self: sig.decl.has_self(), }, AssocItemKind::Macro(..) => unimplemented!(), diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index da8eae6028e..e84ac82942c 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -779,7 +779,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: ast::AssocItem) -> SmallVec<[ast::AssocItem; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Method(ref sig, _) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8916fc08838..1fc89961889 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -269,7 +269,7 @@ impl EarlyLintPass for UnsafeCode { } fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &ast::AssocItem) { - if let ast::AssocItemKind::Method(ref sig, None) = item.kind { + if let ast::AssocItemKind::Fn(ref sig, None) = item.kind { if sig.header.unsafety == ast::Unsafety::Unsafe { self.report_unsafe(cx, item.span, "declaration of an `unsafe` method") } @@ -617,7 +617,7 @@ declare_lint_pass!( impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { match it.kind { - ast::AssocItemKind::Method(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _) => { for arg in sig.decl.inputs.iter() { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index a7c98886622..0840a1551db 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1790,7 +1790,7 @@ impl<'a> Parser<'a> { })?; let sig = FnSig { header, decl }; let body = self.parse_assoc_fn_body(at_end, attrs)?; - Ok((ident, AssocItemKind::Method(sig, body), generics)) + Ok((ident, AssocItemKind::Fn(sig, body), generics)) } /// Parse the "body" of a method in an associated item definition. diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 609885cb254..e90231f984b 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -544,7 +544,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } for impl_item in impl_items { self.invalid_visibility(&impl_item.vis, None); - if let AssocItemKind::Method(ref sig, _) = impl_item.kind { + if let AssocItemKind::Fn(ref sig, _) = impl_item.kind { self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node); } @@ -795,7 +795,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { AssocItemKind::Const(_, body) => { self.check_impl_item_provided(ii.span, body, "constant", " = ;"); } - AssocItemKind::Method(sig, body) => { + AssocItemKind::Fn(sig, body) => { self.check_impl_item_provided(ii.span, body, "function", " { }"); self.check_fn_decl(&sig.decl); } @@ -812,7 +812,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.invalid_visibility(&ti.vis, None); self.check_defaultness(ti.span, ti.defaultness); - if let AssocItemKind::Method(sig, block) = &ti.kind { + if let AssocItemKind::Fn(sig, block) = &ti.kind { self.check_fn_decl(&sig.decl); self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); @@ -838,7 +838,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_assoc_item(&mut self, item: &'a AssocItem) { - if let AssocItemKind::Method(sig, _) = &item.kind { + if let AssocItemKind::Fn(sig, _) = &item.kind { self.check_c_varadic_type(&sig.decl); } visit::walk_assoc_item(self, item); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index dc301375440..e94e0dc695c 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1176,7 +1176,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), - AssocItemKind::Method(ref sig, _) => { + AssocItemKind::Fn(ref sig, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 6e26553d82f..9bae339f80e 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -214,11 +214,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a AssocItem) { let def_data = match ti.kind { - AssocItemKind::Method(..) | AssocItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.name), - AssocItemKind::TyAlias(..) => { - DefPathData::TypeNs(ti.ident.name) - }, + AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ti.ident.name), + AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ti.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; @@ -228,7 +225,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a AssocItem) { let def_data = match ii.kind { - AssocItemKind::Method(FnSig { + AssocItemKind::Fn(FnSig { ref header, ref decl, }, ref body) if header.asyncness.node.is_async() => { @@ -242,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body.as_deref(), ) } - AssocItemKind::Method(..) | + AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), AssocItemKind::TyAlias(..) => DefPathData::TypeNs(ii.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ad29fd9e1db..ec9c2a5b75d 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -818,7 +818,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { }); } } - AssocItemKind::Method(_, _) => { + AssocItemKind::Fn(_, _) => { visit::walk_assoc_item(this, trait_item) } AssocItemKind::TyAlias(..) => { @@ -1109,7 +1109,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { visit::walk_assoc_item(this, impl_item) }); } - AssocItemKind::Method(..) => { + AssocItemKind::Fn(..) => { // If this is a trait impl, ensure the method // exists in trait this.check_trait_item(impl_item.ident, diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 3b36c1c70f9..df6ad51d104 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1044,7 +1044,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &trait_item.attrs, ); } - ast::AssocItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref body) => { self.process_method( sig, body.as_ref().map(|x| &**x), @@ -1115,7 +1115,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &impl_item.attrs, ); } - ast::AssocItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref body) => { self.process_method( sig, body.as_deref(), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1b729ebaf43..f7f84333857 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1634,8 +1634,7 @@ pub enum AssocItemKind { Const(P, Option>), /// An associated function. - /// FIXME(Centril): Rename to `Fn`. - Method(FnSig, Option>), + Fn(FnSig, Option>), /// An associated type. TyAlias(GenericBounds, Option>), diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index fcce9d4e95f..871ec2c008e 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -573,7 +573,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_trait_item(&mut self, ti: &'a ast::AssocItem) { match ti.kind { - ast::AssocItemKind::Method(ref sig, ref block) => { + ast::AssocItemKind::Fn(ref sig, ref block) => { if block.is_none() { self.check_extern(sig.header.ext); } @@ -600,7 +600,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } match ii.kind { - ast::AssocItemKind::Method(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _) => { if sig.decl.c_variadic() { gate_feature_post!( &self, c_variadic, ii.span, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 18d42f9dd66..2a6cff5971c 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -955,7 +955,7 @@ pub fn noop_flat_map_assoc_item(mut item: AssocItem, visitor: &mu visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - AssocItemKind::Method(sig, body) => { + AssocItemKind::Fn(sig, body) => { visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 9e4615f60c0..87f6ae85b69 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1528,7 +1528,7 @@ impl<'a> State<'a> { ast::AssocItemKind::Const(ty, expr) => { self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis); } - ast::AssocItemKind::Method(sig, body) => { + ast::AssocItemKind::Fn(sig, body) => { if body.is_some() { self.head(""); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e2c0ee61467..51e7fa1eb38 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -600,11 +600,11 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Method(ref sig, None) => { + AssocItemKind::Fn(ref sig, None) => { visitor.visit_fn_header(&sig.header); walk_fn_decl(visitor, &sig.decl); } - AssocItemKind::Method(ref sig, Some(ref body)) => { + AssocItemKind::Fn(ref sig, Some(ref body)) => { visitor.visit_fn(FnKind::Method(item.ident, sig, &item.vis, body), &sig.decl, item.span, item.id); } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1c1fcc4f301..b7707bfb8e5 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -958,7 +958,7 @@ impl<'a> MethodDef<'a> { vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::AssocItemKind::Method(sig, Some(body_block)), + kind: ast::AssocItemKind::Fn(sig, Some(body_block)), tokens: None, } } -- cgit 1.4.1-3-g733a5 From 74d4fbc5f5f68212d01a78738c207d5976fe13e4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Dec 2019 06:32:58 +0100 Subject: De-fatalize `...` parsing. Also fix error the code description. --- src/librustc_error_codes/error_codes/E0743.md | 16 ++++++++++----- src/librustc_parse/parser/ty.rs | 16 ++++++++------- .../parser/variadic-ffi-nested-syntactic-fail.rs | 9 ++++++++ .../variadic-ffi-nested-syntactic-fail.stderr | 24 ++++++++++++++++++++++ 4 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs create mode 100644 src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr (limited to 'src/librustc_parse/parser') diff --git a/src/librustc_error_codes/error_codes/E0743.md b/src/librustc_error_codes/error_codes/E0743.md index aaf19d8478c..1780fe59cbd 100644 --- a/src/librustc_error_codes/error_codes/E0743.md +++ b/src/librustc_error_codes/error_codes/E0743.md @@ -1,11 +1,17 @@ -C-variadic has been used on a non-foreign function. +The C-variadic type `...` has been nested inside another type. Erroneous code example: ```compile_fail,E0743 -fn foo2(x: u8, ...) {} // error! +#![feature(c_variadic)] + +fn foo2(x: u8, y: &...) {} // error! ``` -Only foreign functions can use C-variadic (`...`). It is used to give an -undefined number of parameters to a given function (like `printf` in C). The -equivalent in Rust would be to use macros directly. +Only foreign functions can use the C-variadic type (`...`). +In such functions, `...` may only occur non-nested. +That is, `y: &'a ...` is not allowed. + +A C-variadic type is used to give an undefined number +of parameters to a given function (like `printf` in C). +The equivalent in Rust would be to use macros directly. diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 3ab290d1cbb..6f7ab0542d5 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -10,7 +10,7 @@ use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef}; use syntax::ast::{Mutability, AnonConst, Mac}; use syntax::token::{self, Token}; -use syntax::struct_span_fatal; +use syntax::struct_span_err; use syntax_pos::source_map::Span; use syntax_pos::symbol::kw; @@ -209,19 +209,21 @@ impl<'a> Parser<'a> { TyKind::Path(None, path) } } - } else if self.check(&token::DotDotDot) { + } else if self.eat(&token::DotDotDot) { if allow_c_variadic { - self.eat(&token::DotDotDot); TyKind::CVarArgs } else { // FIXME(Centril): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? - return Err(struct_span_fatal!( + struct_span_err!( self.sess.span_diagnostic, - self.token.span, + lo.to(self.prev_span), E0743, - "only foreign functions are allowed to be C-variadic", - )); + "C-variadic type `...` may not be nested inside another type", + ) + .emit(); + + TyKind::Err } } else { let msg = format!("expected type, found {}", self.this_token_descr()); diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs new file mode 100644 index 00000000000..9eeee195e56 --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.rs @@ -0,0 +1,9 @@ +fn f1<'a>(x: u8, y: &'a ...) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn f2<'a>(x: u8, y: Vec<&'a ...>) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr new file mode 100644 index 00000000000..8b9d676a45d --- /dev/null +++ b/src/test/ui/parser/variadic-ffi-nested-syntactic-fail.stderr @@ -0,0 +1,24 @@ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:1:25 + | +LL | fn f1<'a>(x: u8, y: &'a ...) {} + | ^^^ + +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:4:29 + | +LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0743. +For more information about an error, try `rustc --explain E0308`. -- cgit 1.4.1-3-g733a5