Skip to content

Commit a07ccb1

Browse files
committed
Auto merge of #573 - nathanwhit:fn-refactor, r=jackh726
Refactor and flesh out Fn pointers Closes #507. This PR does a few things: - Renames `Fn` -> `FnPointer` - Adds ABI to `FnPointer` - Adds support for unsafe functions to both `FnPointer` and `FnDef` - Adds a variadic flag to both `FnPointer` and `FnDef` (cc [this comment](#507 (comment)))
2 parents 863be95 + ab2561a commit a07ccb1

File tree

19 files changed

+271
-44
lines changed

19 files changed

+271
-44
lines changed

chalk-integration/src/lowering.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,8 @@ impl LowerFnDefn for FnDefn {
12101210
id: fn_def_id,
12111211
abi: self.abi.lower()?,
12121212
binders,
1213+
safety: ast_safety_to_chalk_safety(self.safety),
1214+
variadic: self.variadic,
12131215
})
12141216
}
12151217
}
@@ -1647,6 +1649,9 @@ impl LowerTy for Ty {
16471649
Ty::ForAll {
16481650
lifetime_names,
16491651
types,
1652+
abi,
1653+
safety,
1654+
variadic,
16501655
} => {
16511656
let quantified_env = env.introduce(lifetime_names.iter().map(|id| {
16521657
chalk_ir::WithKind::new(chalk_ir::VariableKind::Lifetime, id.str.clone())
@@ -1657,9 +1662,12 @@ impl LowerTy for Ty {
16571662
lowered_tys.push(ty.lower(&quantified_env)?.cast(interner));
16581663
}
16591664

1660-
let function = chalk_ir::Fn {
1665+
let function = chalk_ir::FnPointer {
16611666
num_binders: lifetime_names.len(),
16621667
substitution: Substitution::from_iter(interner, lowered_tys),
1668+
abi: abi.lower()?,
1669+
safety: ast_safety_to_chalk_safety(*safety),
1670+
variadic: *variadic,
16631671
};
16641672
Ok(chalk_ir::TyData::Function(function).intern(interner))
16651673
}
@@ -2192,3 +2200,10 @@ fn ast_mutability_to_chalk_mutability(mutability: Mutability) -> chalk_ir::Mutab
21922200
Mutability::Not => chalk_ir::Mutability::Not,
21932201
}
21942202
}
2203+
2204+
fn ast_safety_to_chalk_safety(safety: Safety) -> chalk_ir::Safety {
2205+
match safety {
2206+
Safety::Safe => chalk_ir::Safety::Safe,
2207+
Safety::Unsafe => chalk_ir::Safety::Unsafe,
2208+
}
2209+
}

chalk-integration/src/test_macros.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ macro_rules! ty {
1313
};
1414

1515
(function $n:tt $($arg:tt)*) => {
16-
chalk_ir::TyData::Function(chalk_ir::Fn {
16+
chalk_ir::TyData::Function(chalk_ir::FnPointer {
1717
num_binders: $n,
1818
substitution: chalk_ir::Substitution::from_iter(
1919
&chalk_integration::interner::ChalkIr,
2020
vec![$(arg!($arg)),*] as Vec<chalk_ir::GenericArg<_>>
2121
),
22+
safety: chalk_ir::Safety::Safe,
23+
abi: <chalk_integration::interner::ChalkIr as chalk_ir::interner::Interner>::FnAbi::Rust,
24+
variadic: false,
2225
}).intern(&chalk_integration::interner::ChalkIr)
2326
};
2427

chalk-ir/src/debug.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,21 @@ impl Debug for InferenceVar {
232232
}
233233
}
234234

235-
impl<I: Interner> Debug for Fn<I> {
235+
impl<I: Interner> Debug for FnPointer<I> {
236236
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
237237
// FIXME -- we should introduce some names or something here
238-
let Fn {
238+
let FnPointer {
239239
num_binders,
240240
substitution,
241+
abi,
242+
safety,
243+
variadic: _,
241244
} = self;
242-
write!(fmt, "for<{}> {:?}", num_binders, substitution)
245+
write!(
246+
fmt,
247+
"for<{}> {:?} {:?} {:?}",
248+
num_binders, safety, abi, substitution
249+
)
243250
}
244251
}
245252

chalk-ir/src/fold/binder_impls.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
use crate::interner::TargetInterner;
77
use crate::*;
88

9-
impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for Fn<I> {
10-
type Result = Fn<TI>;
9+
impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for FnPointer<I> {
10+
type Result = FnPointer<TI>;
1111
fn fold_with<'i>(
1212
&self,
1313
folder: &mut dyn Folder<'i, I, TI>,
@@ -17,13 +17,19 @@ impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for Fn<I> {
1717
I: 'i,
1818
TI: 'i,
1919
{
20-
let Fn {
20+
let FnPointer {
2121
num_binders,
2222
substitution,
23+
abi,
24+
safety,
25+
variadic,
2326
} = self;
24-
Ok(Fn {
27+
Ok(FnPointer {
2528
num_binders: *num_binders,
2629
substitution: substitution.fold_with(folder, outer_binder.shifted_in())?,
30+
abi: TI::transfer_abi(*abi),
31+
safety: *safety,
32+
variadic: *variadic,
2733
})
2834
}
2935
}

chalk-ir/src/fold/boring_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ copy_fold!(FloatTy);
267267
copy_fold!(Scalar);
268268
copy_fold!(ClausePriority);
269269
copy_fold!(Mutability);
270+
copy_fold!(Safety);
270271

271272
#[doc(hidden)]
272273
#[macro_export]

chalk-ir/src/interner.rs

+7
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,9 @@ pub trait TargetInterner<I: Interner>: Interner {
633633
&self,
634634
const_evaluated: &I::InternedConcreteConst,
635635
) -> Self::InternedConcreteConst;
636+
637+
/// Transfer function ABI to the target interner.
638+
fn transfer_abi(abi: I::FnAbi) -> Self::FnAbi;
636639
}
637640

638641
impl<I: Interner> TargetInterner<I> for I {
@@ -662,6 +665,10 @@ impl<I: Interner> TargetInterner<I> for I {
662665
) -> Self::InternedConcreteConst {
663666
const_evaluated.clone()
664667
}
668+
669+
fn transfer_abi(abi: I::FnAbi) -> Self::FnAbi {
670+
abi
671+
}
665672
}
666673

667674
/// Implemented by types that have an associated interner (which

chalk-ir/src/lib.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ pub enum Scalar {
193193
Float(FloatTy),
194194
}
195195

196+
/// Whether a function is safe or not.
197+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
198+
pub enum Safety {
199+
/// Safe
200+
Safe,
201+
/// Unsafe
202+
Unsafe,
203+
}
204+
196205
/// Whether a type is mutable or not.
197206
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
198207
pub enum Mutability {
@@ -503,7 +512,7 @@ pub enum TyData<I: Interner> {
503512
/// Note that "higher-ranked" types (starting with `for<>`) are either
504513
/// function types or dyn types, and do not appear otherwise in Rust
505514
/// surface syntax.
506-
Function(Fn<I>),
515+
Function(FnPointer<I>),
507516

508517
/// References the binding at the given depth. The index is a [de
509518
/// Bruijn index], so it counts back through the in-scope binders.
@@ -860,12 +869,15 @@ impl InferenceVar {
860869
/// and we use deBruijn indices within `self.ty`
861870
#[derive(Clone, PartialEq, Eq, Hash, HasInterner)]
862871
#[allow(missing_docs)]
863-
pub struct Fn<I: Interner> {
872+
pub struct FnPointer<I: Interner> {
864873
pub num_binders: usize,
874+
pub abi: I::FnAbi,
875+
pub safety: Safety,
876+
pub variadic: bool,
865877
pub substitution: Substitution<I>,
866878
}
867879

868-
impl<I: Interner> Copy for Fn<I> where I::InternedSubstitution: Copy {}
880+
impl<I: Interner> Copy for FnPointer<I> where I::InternedSubstitution: Copy {}
869881

870882
/// Constants.
871883
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)]

chalk-ir/src/visit/binder_impls.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
//! The more interesting impls of `Visit` remain in the `visit` module.
55
66
use crate::interner::HasInterner;
7-
use crate::{Binders, Canonical, DebruijnIndex, Fn, Interner, Visit, VisitResult, Visitor};
7+
use crate::{Binders, Canonical, DebruijnIndex, FnPointer, Interner, Visit, VisitResult, Visitor};
88

9-
impl<I: Interner> Visit<I> for Fn<I> {
9+
impl<I: Interner> Visit<I> for FnPointer<I> {
1010
fn visit_with<'i, R: VisitResult>(
1111
&self,
1212
visitor: &mut dyn Visitor<'i, I, Result = R>,

chalk-ir/src/visit/boring_impls.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
use crate::{
88
AdtId, AssocTypeId, ClausePriority, ClosureId, Constraints, DebruijnIndex, FloatTy, FnDefId,
99
GenericArg, Goals, ImplId, IntTy, Interner, Mutability, OpaqueTyId, PlaceholderIndex,
10-
ProgramClause, ProgramClauses, QuantifiedWhereClauses, QuantifierKind, Scalar, Substitution,
11-
SuperVisit, TraitId, UintTy, UniverseIndex, Visit, VisitResult, Visitor,
10+
ProgramClause, ProgramClauses, QuantifiedWhereClauses, QuantifierKind, Safety, Scalar,
11+
Substitution, SuperVisit, TraitId, UintTy, UniverseIndex, Visit, VisitResult, Visitor,
1212
};
1313
use std::{marker::PhantomData, sync::Arc};
1414

@@ -211,6 +211,7 @@ const_visit!(UintTy);
211211
const_visit!(IntTy);
212212
const_visit!(FloatTy);
213213
const_visit!(Mutability);
214+
const_visit!(Safety);
214215

215216
#[doc(hidden)]
216217
#[macro_export]

chalk-parse/src/ast.rs

+65
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ pub struct FnDefn {
7474
pub argument_types: Vec<Ty>,
7575
pub return_type: Ty,
7676
pub abi: FnAbi,
77+
pub safety: Safety,
78+
pub variadic: bool,
7779
}
7880

7981
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -259,6 +261,9 @@ pub enum Ty {
259261
ForAll {
260262
lifetime_names: Vec<Identifier>,
261263
types: Vec<Box<Ty>>,
264+
abi: FnAbi,
265+
safety: Safety,
266+
variadic: bool,
262267
},
263268
Tuple {
264269
types: Vec<Box<Ty>>,
@@ -327,6 +332,18 @@ pub enum Mutability {
327332
Not,
328333
}
329334

335+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
336+
pub enum Safety {
337+
Safe,
338+
Unsafe,
339+
}
340+
341+
impl Default for Safety {
342+
fn default() -> Self {
343+
Self::Safe
344+
}
345+
}
346+
330347
#[derive(Clone, PartialEq, Eq, Debug)]
331348
pub enum Lifetime {
332349
Id { name: Identifier },
@@ -450,3 +467,51 @@ pub enum ClosureKind {
450467
FnMut,
451468
FnOnce,
452469
}
470+
471+
#[derive(Clone, Eq, PartialEq, Debug)]
472+
pub enum FnArg {
473+
NonVariadic(Ty),
474+
Variadic,
475+
}
476+
#[derive(Clone, Eq, PartialEq, Debug)]
477+
pub enum FnArgs {
478+
NonVariadic(Vec<Ty>),
479+
Variadic(Vec<Ty>),
480+
}
481+
482+
impl FnArgs {
483+
pub fn is_variadic(&self) -> bool {
484+
match self {
485+
Self::Variadic(..) => true,
486+
_ => false,
487+
}
488+
}
489+
490+
pub fn to_tys(self) -> Vec<Ty> {
491+
match self {
492+
Self::NonVariadic(tys) | Self::Variadic(tys) => tys,
493+
}
494+
}
495+
496+
pub fn from_vec(mut args: Vec<FnArg>) -> Result<Self, &'static str> {
497+
let mut tys = Vec::with_capacity(args.len());
498+
let last = args.pop();
499+
for arg in args {
500+
match arg {
501+
FnArg::NonVariadic(ty) => tys.push(ty),
502+
FnArg::Variadic => {
503+
return Err("a variadic argument must be the last parameter in a function");
504+
}
505+
}
506+
}
507+
508+
Ok(match last {
509+
Some(FnArg::NonVariadic(ty)) => {
510+
tys.push(ty);
511+
FnArgs::NonVariadic(tys)
512+
}
513+
Some(FnArg::Variadic) => FnArgs::Variadic(tys),
514+
None => FnArgs::NonVariadic(tys),
515+
})
516+
}
517+
}

chalk-parse/src/parser.lalrpop

+33-9
Original file line numberDiff line numberDiff line change
@@ -140,26 +140,31 @@ FnReturn: Ty = {
140140
};
141141

142142
FnDefn: FnDefn = {
143-
<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(),
153+
safety: safety.unwrap_or_default(),
152154
}
153155
};
154156

155157
FnAbi: FnAbi = "extern" "\"" <id:Id> "\"" => FnAbi(id.str);
156158

157-
FnArg: Ty = {
158-
Id ":" <arg_ty: Ty> => arg_ty
159+
FnArg: FnArg = {
160+
Id ":" "..." => FnArg::Variadic,
161+
Id ":" <arg_ty: Ty> => FnArg::NonVariadic(arg_ty),
159162
};
160163

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

165170
ClosureDefn: ClosureDefn = {
@@ -181,7 +186,7 @@ ClosureSelf: ClosureKind = {
181186
}
182187

183188
ClosureArgs: Vec<Ty> = {
184-
"," <args:FnArgs> => args,
189+
"," <args:FnArgs> => args.to_tys(),
185190
}
186191

187192
TraitDefn: TraitDefn = {
@@ -313,13 +318,32 @@ pub Ty: Ty = {
313318
TyWithoutId,
314319
};
315320

321+
Safety: Safety = {
322+
"unsafe" => Safety::Unsafe,
323+
};
324+
325+
FnArgTy: FnArg = {
326+
"..." => FnArg::Variadic,
327+
<arg_ty: Ty> => FnArg::NonVariadic(arg_ty),
328+
};
329+
330+
FnArgTys: FnArgs = {
331+
<Comma<FnArgTy>> =>? FnArgs::from_vec(<>).map_err(|e| lalrpop_util::ParseError::User {
332+
error: e,
333+
})
334+
};
335+
316336
TyWithoutId: Ty = {
317-
<l:ForLifetimes?> "fn" "(" <types:Comma<Ty>> ")" <ret_ty:FnReturn?> => Ty::ForAll {
337+
<l:ForLifetimes?> <safety:Safety?> <abi:FnAbi?> "fn" "(" <types:FnArgTys> ")" <ret_ty:FnReturn?> => Ty::ForAll {
318338
lifetime_names: l.unwrap_or_default(),
339+
variadic: types.is_variadic(),
319340
types: types
341+
.to_tys()
320342
.into_iter()
321343
.chain(std::iter::once(ret_ty.unwrap_or_else(|| Ty::Tuple { types: Vec::new() })))
322-
.map(Box::new).collect()
344+
.map(Box::new).collect(),
345+
safety: safety.unwrap_or_default(),
346+
abi: abi.unwrap_or_default(),
323347
},
324348
<ScalarType> => Ty::Scalar { ty: <> },
325349
"str" => Ty::Str,

0 commit comments

Comments
 (0)