From 34d91709b672d91ea9623ae4bc2275e8b003fc2c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Dec 2019 16:00:08 +0100 Subject: [PATCH] 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(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 54ff1f56eec0..e2c99f456e98 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 8c225b83f40e..ca7c4ba87863 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 3cd4988ce0be..e4dff07e92cb 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 dbc0163eef6a..f391eda976ce 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 5334fc485e7a..aeba6dd2f67c 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 33d7c878e888..1dffa6c94a89 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 f4b28077e9f0..8be97155d8c6 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 d63a9df8d9bc..cc0f3c512f53 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 5866f9db078f..d90d74d7a262 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 bb0462c19cdf..97a85b0fe7e3 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 03e394b8c7e9..a141d4d71bbd 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 7cc1a769e52b..74df808b37e3 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); } } }