parse: refactor fun ret ty & param ty

This commit is contained in:
Mazdak Farrokhzad 2019-12-01 16:00:08 +01:00
parent 404013e015
commit 34d91709b6
12 changed files with 77 additions and 107 deletions

View file

@ -2092,29 +2092,19 @@ impl<'a> LoweringContext<'a> {
.iter() .iter()
.map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())) .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed()))
.collect(); .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 { hir::GenericArgs { args, bindings: hir_vec![binding], parenthesized: true },
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,
},
false, false,
) )
} }

View file

@ -712,8 +712,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
ret ret
} }
fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool { fn should_ignore_fn(ret_ty: &ast::FunctionRetTy) -> bool {
if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output { if let ast::FunctionRetTy::Ty(ref ty) = ret_ty {
fn involves_impl_trait(ty: &ast::Ty) -> bool { fn involves_impl_trait(ty: &ast::Ty) -> bool {
match ty.kind { match ty.kind {
ast::TyKind::ImplTrait(..) => true, ast::TyKind::ImplTrait(..) => true,
@ -742,7 +742,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
}, },
Some(&ast::GenericArgs::Parenthesized(ref data)) => { Some(&ast::GenericArgs::Parenthesized(ref data)) => {
any_involves_impl_trait(data.inputs.iter()) || 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 { fn is_sig_const(sig: &ast::FnSig) -> bool {
sig.header.constness.node == ast::Constness::Const || sig.header.constness.node == ast::Constness::Const ||
ReplaceBodyWithLoop::should_ignore_fn(&sig.decl) ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output)
} }
} }

View file

@ -1381,7 +1381,7 @@ impl<'a> Parser<'a> {
args args
} }
}; };
let output = self.parse_ret_ty(true)?; let output = self.parse_ret_ty(true, true)?;
Ok(P(FnDecl { Ok(P(FnDecl {
inputs: inputs_captures, inputs: inputs_captures,

View file

@ -1900,7 +1900,7 @@ impl<'a> Parser<'a> {
) -> PResult<'a, P<FnDecl>> { ) -> PResult<'a, P<FnDecl>> {
Ok(P(FnDecl { Ok(P(FnDecl {
inputs: self.parse_fn_params(cfg)?, 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(); 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 { } else {
debug!("parse_param_general ident_to_pat"); debug!("parse_param_general ident_to_pat");
let parser_snapshot_before_ty = self.clone(); let parser_snapshot_before_ty = self.clone();
self.eat_incorrect_doc_comment_for_param_type(); 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 && if ty.is_ok() && self.token != token::Comma &&
self.token != token::CloseDelim(token::Paren) { self.token != token::CloseDelim(token::Paren) {
// This wasn't actually a type, but a pattern looking like a type, // This wasn't actually a type, but a pattern looking like a type,

View file

@ -182,11 +182,7 @@ impl<'a> Parser<'a> {
// `(T, U) -> R` // `(T, U) -> R`
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
let span = ident.span.to(self.prev_span); let span = ident.span.to(self.prev_span);
let output = if self.eat(&token::RArrow) { let output = self.parse_ret_ty(false, false)?;
Some(self.parse_ty_common(false, false, false)?)
} else {
None
};
ParenthesizedArgs { inputs, output, span }.into() ParenthesizedArgs { inputs, output, span }.into()
}; };

View file

@ -30,6 +30,13 @@ impl<'a> Parser<'a> {
self.parse_ty_common(true, true, false) 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<Ty>> {
self.parse_ty_common(true, true, allow_c_variadic)
}
/// Parses a type in restricted contexts where `+` is not permitted. /// Parses a type in restricted contexts where `+` is not permitted.
/// ///
/// Example 1: `&'a TYPE` /// Example 1: `&'a TYPE`
@ -41,17 +48,26 @@ impl<'a> Parser<'a> {
} }
/// Parses an optional return type `[ -> TY ]` in a function declaration. /// 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) { Ok(if self.eat(&token::RArrow) {
// FIXME(Centril): Can we unconditionally `allow_plus`? // 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 { } else {
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, fn parse_ty_common(
allow_c_variadic: bool) -> PResult<'a, P<Ty>> { &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<Ty>> {
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
maybe_whole!(self, NtTy, |x| x); maybe_whole!(self, NtTy, |x| x);
@ -198,6 +214,8 @@ impl<'a> Parser<'a> {
self.eat(&token::DotDotDot); self.eat(&token::DotDotDot);
TyKind::CVarArgs TyKind::CVarArgs
} else { } else {
// FIXME(Centril): Should we just allow `...` syntactically
// anywhere in a type and use semantic restrictions instead?
return Err(struct_span_fatal!( return Err(struct_span_fatal!(
self.sess.span_diagnostic, self.sess.span_diagnostic,
self.token.span, self.token.span,

View file

@ -674,10 +674,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
GenericArgs::Parenthesized(ref data) => { GenericArgs::Parenthesized(ref data) => {
walk_list!(self, visit_ty, &data.inputs); 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, // `-> Foo` syntax is essentially an associated type binding,
// so it is also allowed to contain nested `impl Trait`. // 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));
} }
} }
} }

View file

@ -811,9 +811,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
match **generic_args { match **generic_args {
ast::GenericArgs::AngleBracketed(ref data) => { ast::GenericArgs::AngleBracketed(ref data) => {
for arg in &data.args { for arg in &data.args {
match arg { if let ast::GenericArg::Type(ty) = arg {
ast::GenericArg::Type(ty) => self.visit_ty(ty), self.visit_ty(ty);
_ => {}
} }
} }
} }
@ -821,8 +820,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
for t in &data.inputs { for t in &data.inputs {
self.visit_ty(t); self.visit_ty(t);
} }
if let Some(ref t) = data.output { if let ast::FunctionRetTy::Ty(ty) = &data.output {
self.visit_ty(t); self.visit_ty(ty);
} }
} }
} }

View file

@ -254,7 +254,7 @@ pub struct ParenthesizedArgs {
pub inputs: Vec<P<Ty>>, pub inputs: Vec<P<Ty>>,
/// `C` /// `C`
pub output: Option<P<Ty>>, pub output: FunctionRetTy,
} }
impl ParenthesizedArgs { impl ParenthesizedArgs {
@ -2185,7 +2185,7 @@ impl fmt::Debug for ImplPolarity {
} }
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] #[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. /// Returns type is not specified.
/// ///
/// Functions default to `()` and closures default to inference. /// Functions default to `()` and closures default to inference.

View file

@ -553,7 +553,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(args: &mut Parenth
vis: &mut T) { vis: &mut T) {
let ParenthesizedArgs { inputs, output, span } = args; let ParenthesizedArgs { inputs, output, span } = args;
visit_vec(inputs, |input| vis.visit_ty(input)); 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); vis.visit_span(span);
} }
@ -742,7 +742,11 @@ pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T)
pub fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) { pub fn noop_visit_fn_decl<T: MutVisitor>(decl: &mut P<FnDecl>, vis: &mut T) {
let FnDecl { inputs, output } = decl.deref_mut(); let FnDecl { inputs, output } = decl.deref_mut();
inputs.flat_map_in_place(|param| vis.flat_map_param(param)); 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<T: MutVisitor>(fn_ret_ty: &mut FunctionRetTy, vis: &mut T) {
match fn_ret_ty {
FunctionRetTy::Default(span) => vis.visit_span(span), FunctionRetTy::Default(span) => vis.visit_span(span),
FunctionRetTy::Ty(ty) => vis.visit_ty(ty), FunctionRetTy::Ty(ty) => vis.visit_ty(ty),
} }

View file

@ -887,17 +887,9 @@ impl<'a> PrintState<'a> for State<'a> {
ast::GenericArgs::Parenthesized(ref data) => { ast::GenericArgs::Parenthesized(ref data) => {
self.s.word("("); self.s.word("(");
self.commasep( self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty));
Inconsistent,
&data.inputs,
|s, ty| s.print_type(ty));
self.s.word(")"); self.s.word(")");
self.print_fn_ret_ty(&data.output);
if let Some(ref ty) = data.output {
self.space_if_not_bol();
self.word_space("->");
self.print_type(ty);
}
} }
} }
} }
@ -1579,6 +1571,7 @@ impl<'a> State<'a> {
self.ann.post(self, AnnNode::SubItem(ti.id)) self.ann.post(self, AnnNode::SubItem(ti.id))
} }
// FIXME(Centril): merge with function above.
crate fn print_impl_item(&mut self, ii: &ast::ImplItem) { crate fn print_impl_item(&mut self, ii: &ast::ImplItem) {
self.ann.pre(self, AnnNode::SubItem(ii.id)); self.ann.pre(self, AnnNode::SubItem(ii.id));
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
@ -2104,7 +2097,7 @@ impl<'a> State<'a> {
self.print_asyncness(asyncness); self.print_asyncness(asyncness);
self.print_capture_clause(capture_clause); self.print_capture_clause(capture_clause);
self.print_fn_block_params(decl); self.print_fn_params_and_ret(decl, true);
self.s.space(); self.s.space();
self.print_expr(body); self.print_expr(body);
self.end(); // need to close a box self.end(); // need to close a box
@ -2535,36 +2528,16 @@ impl<'a> State<'a> {
self.print_ident(name); self.print_ident(name);
} }
self.print_generic_params(&generics.params); 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) self.print_where_clause(&generics.where_clause)
} }
crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl) { crate fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
self.popen(); let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") };
self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, false)); self.word(open);
self.pclose(); self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure));
self.word(close);
self.print_fn_output(decl) self.print_fn_ret_ty(&decl.output)
}
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_movability(&mut self, movability: ast::Movability) { crate fn print_movability(&mut self, movability: ast::Movability) {
@ -2786,24 +2759,14 @@ impl<'a> State<'a> {
self.end(); self.end();
} }
crate fn print_fn_output(&mut self, decl: &ast::FnDecl) { crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FunctionRetTy) {
if let ast::FunctionRetTy::Default(..) = decl.output { if let ast::FunctionRetTy::Ty(ty) = fn_ret_ty {
return; self.space_if_not_bol();
} self.ibox(INDENT_UNIT);
self.word_space("->");
self.space_if_not_bol(); self.print_type(ty);
self.ibox(INDENT_UNIT); self.end();
self.word_space("->"); self.maybe_print_comment(ty.span.lo());
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()),
_ => {}
} }
} }

View file

@ -420,7 +420,7 @@ pub fn walk_generic_args<'a, V>(visitor: &mut V,
} }
GenericArgs::Parenthesized(ref data) => { GenericArgs::Parenthesized(ref data) => {
walk_list!(visitor, visit_ty, &data.inputs); walk_list!(visitor, visit_ty, &data.inputs);
walk_list!(visitor, visit_ty, &data.output); walk_fn_ret_ty(visitor, &data.output);
} }
} }
} }