parse: refactor fun ret ty & param ty
This commit is contained in:
parent
404013e015
commit
34d91709b6
12 changed files with 77 additions and 107 deletions
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1900,7 +1900,7 @@ impl<'a> Parser<'a> {
|
|||
) -> PResult<'a, P<FnDecl>> {
|
||||
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,
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
||||
|
|
|
@ -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<Ty>> {
|
||||
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<Ty>> {
|
||||
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<Ty>> {
|
||||
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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,7 +254,7 @@ pub struct ParenthesizedArgs {
|
|||
pub inputs: Vec<P<Ty>>,
|
||||
|
||||
/// `C`
|
||||
pub output: Option<P<Ty>>,
|
||||
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.
|
||||
|
|
|
@ -553,7 +553,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(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<T: MutVisitor>(asyncness: &mut IsAsync, 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();
|
||||
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::Ty(ty) => vis.visit_ty(ty),
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue