Skip to content

Commit ab2561a

Browse files
committed
Use more Rust-like syntax for variadic fns
1 parent 6152b77 commit ab2561a

File tree

4 files changed

+78
-19
lines changed

4 files changed

+78
-19
lines changed

chalk-parse/src/ast.rs

+48
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,51 @@ pub enum ClosureKind {
466466
FnMut,
467467
FnOnce,
468468
}
469+
470+
#[derive(Clone, Eq, PartialEq, Debug)]
471+
pub enum FnArg {
472+
NonVariadic(Ty),
473+
Variadic,
474+
}
475+
#[derive(Clone, Eq, PartialEq, Debug)]
476+
pub enum FnArgs {
477+
NonVariadic(Vec<Ty>),
478+
Variadic(Vec<Ty>),
479+
}
480+
481+
impl FnArgs {
482+
pub fn is_variadic(&self) -> bool {
483+
match self {
484+
Self::Variadic(..) => true,
485+
_ => false,
486+
}
487+
}
488+
489+
pub fn to_tys(self) -> Vec<Ty> {
490+
match self {
491+
Self::NonVariadic(tys) | Self::Variadic(tys) => tys,
492+
}
493+
}
494+
495+
pub fn from_vec(mut args: Vec<FnArg>) -> Result<Self, &'static str> {
496+
let mut tys = Vec::with_capacity(args.len());
497+
let last = args.pop();
498+
for arg in args {
499+
match arg {
500+
FnArg::NonVariadic(ty) => tys.push(ty),
501+
FnArg::Variadic => {
502+
return Err("a variadic argument must be the last parameter in a function");
503+
}
504+
}
505+
}
506+
507+
Ok(match last {
508+
Some(FnArg::NonVariadic(ty)) => {
509+
tys.push(ty);
510+
FnArgs::NonVariadic(tys)
511+
}
512+
Some(FnArg::Variadic) => FnArgs::Variadic(tys),
513+
None => FnArgs::NonVariadic(tys),
514+
})
515+
}
516+
}

chalk-parse/src/parser.lalrpop

+24-13
Original file line numberDiff line numberDiff line change
@@ -140,28 +140,31 @@ FnReturn: Ty = {
140140
};
141141

142142
FnDefn: FnDefn = {
143-
<var:Variadic?> <safety:Safety?> <abi:FnAbi?> "fn" <n:Id> <p:Angle<VariableKind>>"(" <args:FnArgs> ")"
143+
<safety:Safety?> <abi:FnAbi?> "fn" <n:Id> <p:Angle<VariableKind>>"(" <args:FnArgs> ")"
144144
<ret_ty:FnReturn?> <w:QuantifiedWhereClauses> ";" => FnDefn
145145
{
146146
name: n,
147147
variable_kinds: p,
148148
where_clauses: w,
149-
argument_types: args,
149+
variadic: args.is_variadic(),
150+
argument_types: args.to_tys(),
150151
return_type: ret_ty.unwrap_or_else(|| Ty::Tuple { types: Vec::new() }),
151152
abi: abi.unwrap_or_default(),
152153
safety: safety.unwrap_or_default(),
153-
variadic: var.unwrap_or(false),
154154
}
155155
};
156156

157157
FnAbi: FnAbi = "extern" "\"" <id:Id> "\"" => FnAbi(id.str);
158158

159-
FnArg: Ty = {
160-
Id ":" <arg_ty: Ty> => arg_ty
159+
FnArg: FnArg = {
160+
Id ":" "..." => FnArg::Variadic,
161+
Id ":" <arg_ty: Ty> => FnArg::NonVariadic(arg_ty),
161162
};
162163

163-
FnArgs: Vec<Ty> = {
164-
<Comma<FnArg>>
164+
FnArgs: FnArgs = {
165+
<Comma<FnArg>> =>? FnArgs::from_vec(<>).map_err(|e| lalrpop_util::ParseError::User {
166+
error: e,
167+
})
165168
};
166169

167170
ClosureDefn: ClosureDefn = {
@@ -183,7 +186,7 @@ ClosureSelf: ClosureKind = {
183186
}
184187

185188
ClosureArgs: Vec<Ty> = {
186-
"," <args:FnArgs> => args,
189+
"," <args:FnArgs> => args.to_tys(),
187190
}
188191

189192
TraitDefn: TraitDefn = {
@@ -317,20 +320,28 @@ Safety: Safety = {
317320
"unsafe" => Safety::Unsafe,
318321
};
319322

320-
Variadic: bool = {
321-
"variadic" => true,
322-
}
323+
FnArgTy: FnArg = {
324+
"..." => FnArg::Variadic,
325+
<arg_ty: Ty> => FnArg::NonVariadic(arg_ty),
326+
};
327+
328+
FnArgTys: FnArgs = {
329+
<Comma<FnArgTy>> =>? FnArgs::from_vec(<>).map_err(|e| lalrpop_util::ParseError::User {
330+
error: e,
331+
})
332+
};
323333

324334
TyWithoutId: Ty = {
325-
<l:ForLifetimes?> <var:Variadic?> <safety:Safety?> <abi:FnAbi?> "fn" "(" <types:Comma<Ty>> ")" <ret_ty:FnReturn?> => Ty::ForAll {
335+
<l:ForLifetimes?> <safety:Safety?> <abi:FnAbi?> "fn" "(" <types:FnArgTys> ")" <ret_ty:FnReturn?> => Ty::ForAll {
326336
lifetime_names: l.unwrap_or_default(),
337+
variadic: types.is_variadic(),
327338
types: types
339+
.to_tys()
328340
.into_iter()
329341
.chain(std::iter::once(ret_ty.unwrap_or_else(|| Ty::Tuple { types: Vec::new() })))
330342
.map(Box::new).collect(),
331343
safety: safety.unwrap_or_default(),
332344
abi: abi.unwrap_or_default(),
333-
variadic: var.unwrap_or(false)
334345
},
335346
<ScalarType> => Ty::Scalar { ty: <> },
336347
"str" => Ty::Str,

tests/lowering/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -731,15 +731,15 @@ fn extern_functions() {
731731
fn unsafe_variadic_functions() {
732732
lowering_success! {
733733
program {
734-
unsafe fn foo();
735-
variadic unsafe fn bar();
734+
unsafe fn foo(_: u8);
735+
unsafe fn bar(_: u8, _: ...);
736736
unsafe extern "C" fn baz();
737737
}
738738
}
739739
lowering_success! {
740740
program {
741-
variadic fn foo();
742-
variadic extern "C" fn bar();
741+
fn foo(_: u8, _: ...);
742+
extern "C" fn bar(_: u8, _: ...);
743743
}
744744
}
745745
}

tests/test/unify.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ fn forall_equality() {
109109

110110
goal {
111111
// Variadic function pointers should not be equal to non-variadic fn pointers.
112-
variadic fn(): Eq<fn()>
112+
fn(u8, ...): Eq<fn(u8)>
113113
} yields {
114114
"No possible solution"
115115
}
116116

117117
goal {
118118
// Variadic function pointers should be equal to variadic fn pointers.
119-
variadic fn(): Eq<variadic fn()>
119+
fn(u8, ...): Eq<fn(u8, ...)>
120120
} yields {
121121
"Unique; substitution [], lifetime constraints []"
122122
}

0 commit comments

Comments
 (0)