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()
|
.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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()),
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue