Skip to content

Commit

Permalink
Merge #196
Browse files Browse the repository at this point in the history
196: API: Use patterns in `ClosureExpr` parameters r=xFrednet a=xFrednet

This also removes the implementation of `CallableData` from `ClosureExpr`

Closes #181

Co-authored-by: xFrednet <xFrednet@gmail.com>
  • Loading branch information
bors[bot] and xFrednet authored Jul 26, 2023
2 parents 41eaf5b + 28b4301 commit dd8ba60
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 162 deletions.
2 changes: 1 addition & 1 deletion marker_api/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ mod test {
assert_eq!(24, size_of::<CharLitExpr<'_>>(), "CharLitExpr<'_>");
assert_eq!(24, size_of::<BoolLitExpr<'_>>(), "BoolLitExpr<'_>");
assert_eq!(88, size_of::<BlockExpr<'_>>(), "BlockExpr<'_>");
assert_eq!(88, size_of::<ClosureExpr<'_>>(), "ClosureExpr<'_>");
assert_eq!(72, size_of::<ClosureExpr<'_>>(), "ClosureExpr<'_>");
assert_eq!(40, size_of::<UnaryOpExpr<'_>>(), "UnaryOpExpr<'_>");
assert_eq!(40, size_of::<RefExpr<'_>>(), "RefExpr<'_>");
assert_eq!(56, size_of::<BinaryOpExpr<'_>>(), "BinaryOpExpr<'_>");
Expand Down
80 changes: 70 additions & 10 deletions marker_api/src/ast/expr/block_expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
ast::{impl_callable_data_trait, stmt::StmtKind, BodyId, CommonCallableData, Ident},
ast::{pat::PatKind, stmt::StmtKind, ty::SynTyKind, BodyId, Ident, Span, SpanId},
context::with_cx,
ffi::{FfiOption, FfiSlice},
};

Expand Down Expand Up @@ -101,38 +102,47 @@ impl<'ast> BlockExpr<'ast> {
#[derive(Debug)]
pub struct ClosureExpr<'ast> {
data: CommonExprData<'ast>,
callable_data: CommonCallableData<'ast>,
capture_kind: CaptureKind,
body: BodyId,
params: FfiSlice<'ast, ClosureParam<'ast>>,
return_ty: FfiOption<SynTyKind<'ast>>,
body_id: BodyId,
}

impl<'ast> ClosureExpr<'ast> {
pub fn capture_kind(&self) -> CaptureKind {
self.capture_kind
}

pub fn params(&self) -> &'ast [ClosureParam<'ast>] {
self.params.get()
}

pub fn return_ty(&self) -> Option<SynTyKind<'_>> {
self.return_ty.copy()
}

pub fn body_id(&self) -> BodyId {
self.body
self.body_id
}
}

super::impl_expr_data!(ClosureExpr<'ast>, Closure);

impl_callable_data_trait!(ClosureExpr<'ast>);

#[cfg(feature = "driver-api")]
impl<'ast> ClosureExpr<'ast> {
pub fn new(
data: CommonExprData<'ast>,
callable_data: CommonCallableData<'ast>,
capture_kind: CaptureKind,
body: BodyId,
params: &'ast [ClosureParam<'ast>],
return_ty: Option<SynTyKind<'ast>>,
body_id: BodyId,
) -> Self {
Self {
data,
callable_data,
capture_kind,
body,
params: params.into(),
return_ty: return_ty.into(),
body_id,
}
}
}
Expand All @@ -144,3 +154,53 @@ pub enum CaptureKind {
Default,
Move,
}

/// A parameter for a [`ClosureExpr`], with a pattern and an optional type, like:
///
/// ```
/// # let _: fn(u32) -> () =
/// // A simple parameter
/// // v
/// |x| { /*...*/ };
///
/// // A parameter with a type
/// // vvvvvv
/// |y: u32| { /*...*/ };
///
/// # let _: fn((u32, u32, u32)) -> () =
/// // A parameter with a complex pattern
/// // vvvvvvvv
/// |(a, b, c)| { /*...*/ };
/// ```
#[repr(C)]
#[derive(Debug)]
pub struct ClosureParam<'ast> {
span: SpanId,
pat: PatKind<'ast>,
ty: FfiOption<SynTyKind<'ast>>,
}

impl<'ast> ClosureParam<'ast> {
pub fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}

pub fn pat(&self) -> PatKind<'ast> {
self.pat
}

pub fn ty(&self) -> Option<SynTyKind<'ast>> {
self.ty.copy()
}
}

#[cfg(feature = "driver-api")]
impl<'ast> ClosureParam<'ast> {
pub fn new(span: SpanId, pat: PatKind<'ast>, ty: Option<SynTyKind<'ast>>) -> Self {
Self {
span,
pat,
ty: ty.into(),
}
}
}
46 changes: 24 additions & 22 deletions marker_rustc_driver/src/conversion/marker/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use marker_api::{
ast::{
expr::{
ArrayExpr, AsExpr, AssignExpr, BinaryOpExpr, BinaryOpKind, BlockExpr, BoolLitExpr, BreakExpr, CallExpr,
CaptureKind, CharLitExpr, ClosureExpr, CommonExprData, ConstExpr, ContinueExpr, CtorExpr, CtorField,
ExprKind, ExprPrecedence, FieldExpr, FloatLitExpr, FloatSuffix, ForExpr, IfExpr, IndexExpr, IntLitExpr,
IntSuffix, LetExpr, LoopExpr, MatchArm, MatchExpr, MethodExpr, PathExpr, QuestionMarkExpr, RangeExpr,
RefExpr, ReturnExpr, StrLitData, StrLitExpr, TupleExpr, UnaryOpExpr, UnaryOpKind, UnstableExpr, WhileExpr,
CaptureKind, CharLitExpr, ClosureExpr, ClosureParam, CommonExprData, ConstExpr, ContinueExpr, CtorExpr,
CtorField, ExprKind, ExprPrecedence, FieldExpr, FloatLitExpr, FloatSuffix, ForExpr, IfExpr, IndexExpr,
IntLitExpr, IntSuffix, LetExpr, LoopExpr, MatchArm, MatchExpr, MethodExpr, PathExpr, QuestionMarkExpr,
RangeExpr, RefExpr, ReturnExpr, StrLitData, StrLitExpr, TupleExpr, UnaryOpExpr, UnaryOpKind, UnstableExpr,
WhileExpr,
},
pat::PatKind,
CommonCallableData, Constness, Ident, Parameter, Safety, Syncness,
Ident,
},
CtorBlocker,
};
Expand Down Expand Up @@ -395,32 +396,33 @@ impl<'ast, 'tcx> MarkerConverterInner<'ast, 'tcx> {
fn to_closure_expr(&self, data: CommonExprData<'ast>, closure: &hir::Closure<'tcx>) -> ClosureExpr<'ast> {
let fn_decl = closure.fn_decl;

let params = self.alloc_slice(fn_decl.inputs.iter().map(|ty| {
// FIXME(xFrednet): The name should be a pattern retrieved from the body, but
// that requires adjustments in `Parameter`. rust-marker/marker#181
Parameter::new(None, Some(self.to_syn_ty(ty)), None)
}));
let body_id = closure.body;
let params;
let body = self.rustc_cx.hir().body(body_id);
super::with_body!(self, body_id, {
params = self.alloc_slice(body.params.iter().zip(fn_decl.inputs.iter()).map(|(param, ty)| {
// Rustc automatically substitutes the infer type, if a closure
// parameter has no type declaration.
let param_ty = if matches!(ty.kind, hir::TyKind::Infer) && param.pat.span.contains(ty.span) {
None
} else {
Some(self.to_syn_ty(ty))
};
ClosureParam::new(self.to_span_id(param.span), self.to_pat(param.pat), param_ty)
}));
});

let return_ty = if let hir::FnRetTy::Return(rust_ty) = fn_decl.output {
Some(self.to_syn_ty(rust_ty))
} else {
None
};

let call = CommonCallableData::new(
Constness::NotConst,
Syncness::Sync,
Safety::Safe,
false,
marker_api::ast::Abi::Default,
false,
params,
return_ty,
);

ClosureExpr::new(
data,
call,
self.to_capture_kind(closure.capture_clause),
params,
return_ty,
self.to_body_id(closure.body),
)
}
Expand Down
13 changes: 13 additions & 0 deletions marker_uilints/tests/ui/expr/print_closure_expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fn main() {
let a = "Hey".to_string();

let _print_simple_closure = || {
1 + 1;
};
let _print_no_type: fn(u32) -> () = |x| { /*...*/ };
let _print_with_args = |x: u32, y: u32| x + y;
let _print_move = move || a;
let _print_pattern_in_arg: fn((u32, u32, u32)) -> () = |(a, b, c)| { /*...*/ };
// Make sure the infer type stays, if it originates from the source code
let _print_infer_ty: fn(u32) -> () = |x: _| { /*...*/ };
}
Loading

0 comments on commit dd8ba60

Please sign in to comment.