Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
78a83b0d
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
78a83b0d
编写于
5月 27, 2022
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
proc_macro: don't pass a client-side function pointer through the server.
上级
56fd680c
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
217 addition
and
134 deletion
+217
-134
compiler/rustc_builtin_macros/src/proc_macro_harness.rs
compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+39
-32
compiler/rustc_expand/src/proc_macro.rs
compiler/rustc_expand/src/proc_macro.rs
+3
-3
library/proc_macro/src/bridge/client.rs
library/proc_macro/src/bridge/client.rs
+46
-35
library/proc_macro/src/bridge/mod.rs
library/proc_macro/src/bridge/mod.rs
+2
-0
library/proc_macro/src/bridge/selfless_reify.rs
library/proc_macro/src/bridge/selfless_reify.rs
+83
-0
library/proc_macro/src/bridge/server.rs
library/proc_macro/src/bridge/server.rs
+32
-55
src/test/ui/proc-macro/signature.rs
src/test/ui/proc-macro/signature.rs
+1
-1
src/test/ui/proc-macro/signature.stderr
src/test/ui/proc-macro/signature.stderr
+11
-8
未找到文件。
compiler/rustc_builtin_macros/src/proc_macro_harness.rs
浏览文件 @
78a83b0d
...
...
@@ -294,50 +294,57 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
// that we generate expressions. The position of each NodeId
// in the 'proc_macros' Vec corresponds to its position
// in the static array that will be generated
let
decls
=
{
let
local_path
=
|
cx
:
&
ExtCtxt
<
'_
>
,
sp
:
Span
,
name
|
{
cx
.expr_path
(
cx
.path
(
sp
.with_ctxt
(
span
.ctxt
()),
vec!
[
name
]))
};
let
proc_macro_ty_method_path
=
|
cx
:
&
ExtCtxt
<
'_
>
,
method
|
{
cx
.expr_path
(
cx
.path
(
span
,
vec!
[
proc_macro
,
bridge
,
client
,
proc_macro_ty
,
method
]))
};
let
attr_or_bang
=
|
cx
:
&
mut
ExtCtxt
<
'_
>
,
ca
:
&
ProcMacroDef
,
ident
|
{
cx
.resolver
.declare_proc_macro
(
ca
.id
);
cx
.expr_call
(
span
,
proc_macro_ty_method_path
(
cx
,
ident
),
vec!
[
cx
.expr_str
(
ca
.span
,
ca
.function_name.name
),
local_path
(
cx
,
ca
.span
,
ca
.function_name
),
],
)
};
macros
.iter
()
.map
(|
m
|
match
m
{
let
decls
=
macros
.iter
()
.map
(|
m
|
{
let
harness_span
=
span
;
let
span
=
match
m
{
ProcMacro
::
Derive
(
m
)
=>
m
.span
,
ProcMacro
::
Attr
(
m
)
|
ProcMacro
::
Bang
(
m
)
=>
m
.span
,
};
let
local_path
=
|
cx
:
&
ExtCtxt
<
'_
>
,
name
|
cx
.expr_path
(
cx
.path
(
span
,
vec!
[
name
]));
let
proc_macro_ty_method_path
=
|
cx
:
&
ExtCtxt
<
'_
>
,
method
|
{
cx
.expr_path
(
cx
.path
(
span
.with_ctxt
(
harness_span
.ctxt
()),
vec!
[
proc_macro
,
bridge
,
client
,
proc_macro_ty
,
method
],
))
};
match
m
{
ProcMacro
::
Derive
(
cd
)
=>
{
cx
.resolver
.declare_proc_macro
(
cd
.id
);
cx
.expr_call
(
span
,
proc_macro_ty_method_path
(
cx
,
custom_derive
),
vec!
[
cx
.expr_str
(
cd
.
span
,
cd
.trait_name
),
cx
.expr_str
(
span
,
cd
.trait_name
),
cx
.expr_vec_slice
(
span
,
cd
.attrs
.iter
()
.map
(|
&
s
|
cx
.expr_str
(
cd
.span
,
s
))
.collect
::
<
Vec
<
_
>>
(),
cd
.attrs
.iter
()
.map
(|
&
s
|
cx
.expr_str
(
span
,
s
))
.collect
::
<
Vec
<
_
>>
(),
),
local_path
(
cx
,
cd
.
span
,
cd
.
function_name
),
local_path
(
cx
,
cd
.function_name
),
],
)
}
ProcMacro
::
Attr
(
ca
)
=>
attr_or_bang
(
cx
,
&
ca
,
attr
),
ProcMacro
::
Bang
(
ca
)
=>
attr_or_bang
(
cx
,
&
ca
,
bang
),
})
.collect
()
};
ProcMacro
::
Attr
(
ca
)
|
ProcMacro
::
Bang
(
ca
)
=>
{
cx
.resolver
.declare_proc_macro
(
ca
.id
);
let
ident
=
match
m
{
ProcMacro
::
Attr
(
_
)
=>
attr
,
ProcMacro
::
Bang
(
_
)
=>
bang
,
ProcMacro
::
Derive
(
_
)
=>
unreachable!
(),
};
cx
.expr_call
(
span
,
proc_macro_ty_method_path
(
cx
,
ident
),
vec!
[
cx
.expr_str
(
span
,
ca
.function_name.name
),
local_path
(
cx
,
ca
.function_name
),
],
)
}
}
})
.collect
();
let
decls_static
=
cx
.item_static
(
...
...
compiler/rustc_expand/src/proc_macro.rs
浏览文件 @
78a83b0d
...
...
@@ -14,7 +14,7 @@
const
EXEC_STRATEGY
:
pm
::
bridge
::
server
::
SameThread
=
pm
::
bridge
::
server
::
SameThread
;
pub
struct
BangProcMacro
{
pub
client
:
pm
::
bridge
::
client
::
Client
<
fn
(
pm
::
TokenStream
)
->
pm
::
TokenStream
>
,
pub
client
:
pm
::
bridge
::
client
::
Client
<
pm
::
TokenStream
,
pm
::
TokenStream
>
,
}
impl
base
::
BangProcMacro
for
BangProcMacro
{
...
...
@@ -42,7 +42,7 @@ fn expand<'cx>(
}
pub
struct
AttrProcMacro
{
pub
client
:
pm
::
bridge
::
client
::
Client
<
fn
(
pm
::
TokenStream
,
pm
::
TokenStream
)
->
pm
::
TokenStream
>
,
pub
client
:
pm
::
bridge
::
client
::
Client
<
(
pm
::
TokenStream
,
pm
::
TokenStream
),
pm
::
TokenStream
>
,
}
impl
base
::
AttrProcMacro
for
AttrProcMacro
{
...
...
@@ -73,7 +73,7 @@ fn expand<'cx>(
}
pub
struct
DeriveProcMacro
{
pub
client
:
pm
::
bridge
::
client
::
Client
<
fn
(
pm
::
TokenStream
)
->
pm
::
TokenStream
>
,
pub
client
:
pm
::
bridge
::
client
::
Client
<
pm
::
TokenStream
,
pm
::
TokenStream
>
,
}
impl
MultiItemModifier
for
DeriveProcMacro
{
...
...
library/proc_macro/src/bridge/client.rs
浏览文件 @
78a83b0d
...
...
@@ -357,22 +357,33 @@ fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
}
}
/// A client-side "global object" (usually a function pointer),
/// which may be using a different `proc_macro` from the one
/// used by the server, but can be interacted with compatibly.
/// A client-side RPC entry-point, which may be using a different `proc_macro`
/// from the one used by the server, but can be invoked compatibly.
///
/// N.B., `F` must have FFI-friendly memory layout (e.g., a pointer).
/// The call ABI of function pointers used for `F` doesn't
/// need to match between server and client, since it's only
/// passed between them and (eventually) called by the client.
/// Note that the (phantom) `I` ("input") and `O` ("output") type parameters
/// decorate the `Client<I, O>` with the RPC "interface" of the entry-point, but
/// do not themselves participate in ABI, at all, only facilitate type-checking.
///
/// E.g. `Client<TokenStream, TokenStream>` is the common proc macro interface,
/// used for `#[proc_macro] fn foo(input: TokenStream) -> TokenStream`,
/// indicating that the RPC input and output will be serialized token streams,
/// and forcing the use of APIs that take/return `S::TokenStream`, server-side.
#[repr(C)]
#[derive(Copy,
Clone)]
pub
struct
Client
<
F
>
{
pub
struct
Client
<
I
,
O
>
{
// FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
// a wrapper `fn` pointer, once `const fn` can reference `static`s.
pub
(
super
)
get_handle_counters
:
extern
"C"
fn
()
->
&
'static
HandleCounters
,
pub
(
super
)
run
:
extern
"C"
fn
(
Bridge
<
'_
>
,
F
)
->
Buffer
,
pub
(
super
)
f
:
F
,
pub
(
super
)
run
:
extern
"C"
fn
(
Bridge
<
'_
>
)
->
Buffer
,
pub
(
super
)
_
marker
:
PhantomData
<
fn
(
I
)
->
O
>
,
}
impl
<
I
,
O
>
Copy
for
Client
<
I
,
O
>
{}
impl
<
I
,
O
>
Clone
for
Client
<
I
,
O
>
{
fn
clone
(
&
self
)
->
Self
{
*
self
}
}
/// Client-side helper for handling client panics, entering the bridge,
...
...
@@ -419,31 +430,31 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
buf
}
impl
Client
<
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
>
{
pub
const
fn
expand1
(
f
:
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
)
->
Self
{
extern
"C"
fn
run
(
bridge
:
Bridge
<
'_
>
,
f
:
impl
FnOnce
(
crate
::
TokenStream
)
->
crate
::
TokenStream
,
)
->
Buffer
{
run_client
(
bridge
,
|
input
|
f
(
crate
::
TokenStream
(
input
))
.0
)
impl
Client
<
crate
::
TokenStream
,
crate
::
TokenStream
>
{
pub
const
fn
expand1
(
f
:
impl
Fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
+
Copy
)
->
Self
{
Client
{
get_handle_counters
:
HandleCounters
::
get
,
run
:
super
::
selfless_reify
::
reify_to_extern_c_fn_hrt_bridge
(
move
|
bridge
|
{
run_client
(
bridge
,
|
input
|
f
(
crate
::
TokenStream
(
input
))
.0
)
}),
_
marker
:
PhantomData
,
}
Client
{
get_handle_counters
:
HandleCounters
::
get
,
run
,
f
}
}
}
impl
Client
<
fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
>
{
impl
Client
<
(
crate
::
TokenStream
,
crate
::
TokenStream
),
crate
::
TokenStream
>
{
pub
const
fn
expand2
(
f
:
fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
,
f
:
impl
Fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
+
Copy
,
)
->
Self
{
extern
"C"
fn
run
(
bridge
:
Bridge
<
'_
>
,
f
:
impl
FnOnce
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
,
)
->
Buffer
{
run_client
(
bridge
,
|(
input
,
input2
)|
{
f
(
crate
::
TokenStream
(
input
),
crate
::
TokenStream
(
input2
))
.0
})
Client
{
get_handle_counters
:
HandleCounters
::
get
,
run
:
super
::
selfless_reify
::
reify_to_extern_c_fn_hrt_bridge
(
move
|
bridge
|
{
run_client
(
bridge
,
|(
input
,
input2
)|
{
f
(
crate
::
TokenStream
(
input
),
crate
::
TokenStream
(
input2
))
.0
})
}),
_
marker
:
PhantomData
,
}
Client
{
get_handle_counters
:
HandleCounters
::
get
,
run
,
f
}
}
}
...
...
@@ -453,17 +464,17 @@ pub enum ProcMacro {
CustomDerive
{
trait_name
:
&
'static
str
,
attributes
:
&
'static
[
&
'static
str
],
client
:
Client
<
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
>
,
client
:
Client
<
crate
::
TokenStream
,
crate
::
TokenStream
>
,
},
Attr
{
name
:
&
'static
str
,
client
:
Client
<
fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
>
,
client
:
Client
<
(
crate
::
TokenStream
,
crate
::
TokenStream
),
crate
::
TokenStream
>
,
},
Bang
{
name
:
&
'static
str
,
client
:
Client
<
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
>
,
client
:
Client
<
crate
::
TokenStream
,
crate
::
TokenStream
>
,
},
}
...
...
@@ -479,21 +490,21 @@ pub fn name(&self) -> &'static str {
pub
const
fn
custom_derive
(
trait_name
:
&
'static
str
,
attributes
:
&
'static
[
&
'static
str
],
expand
:
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
,
expand
:
impl
Fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
+
Copy
,
)
->
Self
{
ProcMacro
::
CustomDerive
{
trait_name
,
attributes
,
client
:
Client
::
expand1
(
expand
)
}
}
pub
const
fn
attr
(
name
:
&
'static
str
,
expand
:
fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
,
expand
:
impl
Fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
+
Copy
,
)
->
Self
{
ProcMacro
::
Attr
{
name
,
client
:
Client
::
expand2
(
expand
)
}
}
pub
const
fn
bang
(
name
:
&
'static
str
,
expand
:
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
,
expand
:
impl
Fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
+
Copy
,
)
->
Self
{
ProcMacro
::
Bang
{
name
,
client
:
Client
::
expand1
(
expand
)
}
}
...
...
library/proc_macro/src/bridge/mod.rs
浏览文件 @
78a83b0d
...
...
@@ -208,6 +208,8 @@ fn sub(
mod
rpc
;
#[allow(unsafe_code)]
mod
scoped_cell
;
#[allow(unsafe_code)]
mod
selfless_reify
;
#[forbid(unsafe_code)]
pub
mod
server
;
...
...
library/proc_macro/src/bridge/selfless_reify.rs
0 → 100644
浏览文件 @
78a83b0d
//! Abstraction for creating `fn` pointers from any callable that *effectively*
//! has the equivalent of implementing `Default`, even if the compiler neither
//! provides `Default` nor allows reifying closures (i.e. creating `fn` pointers)
//! other than those with absolutely no captures.
//!
//! More specifically, for a closure-like type to be "effectively `Default`":
//! * it must be a ZST (zero-sized type): no information contained within, so
//! that `Default`'s return value (if it were implemented) is unambiguous
//! * it must be `Copy`: no captured "unique ZST tokens" or any other similar
//! types that would make duplicating values at will unsound
//! * combined with the ZST requirement, this confers a kind of "telecopy"
//! ability: similar to `Copy`, but without keeping the value around, and
//! instead "reconstructing" it (a noop given it's a ZST) when needed
//! * it must be *provably* inhabited: no captured uninhabited types or any
//! other types that cannot be constructed by the user of this abstraction
//! * the proof is a value of the closure-like type itself, in a sense the
//! "seed" for the "telecopy" process made possible by ZST + `Copy`
//! * this requirement is the only reason an abstraction limited to a specific
//! usecase is required: ZST + `Copy` can be checked with *at worst* a panic
//! at the "attempted `::default()` call" time, but that doesn't guarantee
//! that the value can be soundly created, and attempting to use the typical
//! "proof ZST token" approach leads yet again to having a ZST + `Copy` type
//! that is not proof of anything without a value (i.e. isomorphic to a
//! newtype of the type it's trying to prove the inhabitation of)
//!
//! A more flexible (and safer) solution to the general problem could exist once
//! `const`-generic parameters can have type parameters in their types:
//!
//! ```rust,ignore (needs future const-generics)
//! extern "C" fn ffi_wrapper<
//! A, R,
//! F: Fn(A) -> R,
//! const f: F, // <-- this `const`-generic is not yet allowed
//! >(arg: A) -> R {
//! f(arg)
//! }
//! ```
use
std
::
mem
;
// FIXME(eddyb) this could be `trait` impls except for the `const fn` requirement.
macro_rules!
define_reify_functions
{
(
$
(
fn
$name:ident
$
(
<
$
(
$param:ident
),
*>
)
?
for
$
(
extern
$abi:tt
)
?
fn
(
$
(
$arg:ident
:
$arg_ty:ty
),
*
)
->
$ret_ty:ty
;
)
+
)
=>
{
$
(
pub
const
fn
$name
<
$
(
$
(
$param
,)
*
)
?
F
:
Fn
(
$
(
$arg_ty
),
*
)
->
$ret_ty
+
Copy
>
(
f
:
F
)
->
$
(
extern
$abi
)
?
fn
(
$
(
$arg_ty
),
*
)
->
$ret_ty
{
// FIXME(eddyb) describe the `F` type (e.g. via `type_name::<F>`) once panic
// formatting becomes possible in `const fn`.
assert!
(
mem
::
size_of
::
<
F
>
()
==
0
,
"selfless_reify: closure must be zero-sized"
);
$
(
extern
$abi
)
?
fn
wrapper
<
$
(
$
(
$param
,)
*
)
?
F
:
Fn
(
$
(
$arg_ty
),
*
)
->
$ret_ty
+
Copy
>
(
$
(
$arg
:
$arg_ty
),
*
)
->
$ret_ty
{
let
f
=
unsafe
{
// SAFETY: `F` satisfies all criteria for "out of thin air"
// reconstructability (see module-level doc comment).
mem
::
MaybeUninit
::
<
F
>
::
uninit
()
.assume_init
()
};
f
(
$
(
$arg
),
*
)
}
let
_
f_proof
=
f
;
wrapper
::
<
$
(
$
(
$param
,)
*
)
?
F
>
})
+
}
}
define_reify_functions!
{
fn
_
reify_to_extern_c_fn_unary
<
A
,
R
>
for
extern
"C"
fn
(
arg
:
A
)
->
R
;
// HACK(eddyb) this abstraction is used with `for<'a> fn(Bridge<'a>) -> T`
// but that doesn't work with just `reify_to_extern_c_fn_unary` because of
// the `fn` pointer type being "higher-ranked" (i.e. the `for<'a>` binder).
// FIXME(eddyb) try to remove the lifetime from `Bridge`, that'd help.
fn
reify_to_extern_c_fn_hrt_bridge
<
R
>
for
extern
"C"
fn
(
bridge
:
super
::
Bridge
<
'_
>
)
->
R
;
}
library/proc_macro/src/bridge/server.rs
浏览文件 @
78a83b0d
...
...
@@ -118,12 +118,11 @@ fn dispatch(&mut self, mut buf: Buffer) -> Buffer {
with_api!
(
Self
,
self_
,
define_dispatcher_impl
);
pub
trait
ExecutionStrategy
{
fn
run_bridge_and_client
<
D
:
Copy
+
Send
+
'static
>
(
fn
run_bridge_and_client
(
&
self
,
dispatcher
:
&
mut
impl
DispatcherTrait
,
input
:
Buffer
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
,
D
)
->
Buffer
,
client_data
:
D
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
)
->
Buffer
,
force_show_panics
:
bool
,
)
->
Buffer
;
}
...
...
@@ -131,25 +130,21 @@ fn run_bridge_and_client<D: Copy + Send + 'static>(
pub
struct
SameThread
;
impl
ExecutionStrategy
for
SameThread
{
fn
run_bridge_and_client
<
D
:
Copy
+
Send
+
'static
>
(
fn
run_bridge_and_client
(
&
self
,
dispatcher
:
&
mut
impl
DispatcherTrait
,
input
:
Buffer
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
,
D
)
->
Buffer
,
client_data
:
D
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
)
->
Buffer
,
force_show_panics
:
bool
,
)
->
Buffer
{
let
mut
dispatch
=
|
buf
|
dispatcher
.dispatch
(
buf
);
run_client
(
Bridge
{
cached_buffer
:
input
,
dispatch
:
(
&
mut
dispatch
)
.into
(),
force_show_panics
,
_
marker
:
marker
::
PhantomData
,
},
client_data
,
)
run_client
(
Bridge
{
cached_buffer
:
input
,
dispatch
:
(
&
mut
dispatch
)
.into
(),
force_show_panics
,
_
marker
:
marker
::
PhantomData
,
})
}
}
...
...
@@ -159,12 +154,11 @@ fn run_bridge_and_client<D: Copy + Send + 'static>(
pub
struct
CrossThread1
;
impl
ExecutionStrategy
for
CrossThread1
{
fn
run_bridge_and_client
<
D
:
Copy
+
Send
+
'static
>
(
fn
run_bridge_and_client
(
&
self
,
dispatcher
:
&
mut
impl
DispatcherTrait
,
input
:
Buffer
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
,
D
)
->
Buffer
,
client_data
:
D
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
)
->
Buffer
,
force_show_panics
:
bool
,
)
->
Buffer
{
use
std
::
sync
::
mpsc
::
channel
;
...
...
@@ -178,15 +172,12 @@ fn run_bridge_and_client<D: Copy + Send + 'static>(
res_rx
.recv
()
.unwrap
()
};
run_client
(
Bridge
{
cached_buffer
:
input
,
dispatch
:
(
&
mut
dispatch
)
.into
(),
force_show_panics
,
_
marker
:
marker
::
PhantomData
,
},
client_data
,
)
run_client
(
Bridge
{
cached_buffer
:
input
,
dispatch
:
(
&
mut
dispatch
)
.into
(),
force_show_panics
,
_
marker
:
marker
::
PhantomData
,
})
});
for
b
in
req_rx
{
...
...
@@ -200,12 +191,11 @@ fn run_bridge_and_client<D: Copy + Send + 'static>(
pub
struct
CrossThread2
;
impl
ExecutionStrategy
for
CrossThread2
{
fn
run_bridge_and_client
<
D
:
Copy
+
Send
+
'static
>
(
fn
run_bridge_and_client
(
&
self
,
dispatcher
:
&
mut
impl
DispatcherTrait
,
input
:
Buffer
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
,
D
)
->
Buffer
,
client_data
:
D
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
)
->
Buffer
,
force_show_panics
:
bool
,
)
->
Buffer
{
use
std
::
sync
::{
Arc
,
Mutex
};
...
...
@@ -231,15 +221,12 @@ enum State<T> {
}
};
let
r
=
run_client
(
Bridge
{
cached_buffer
:
input
,
dispatch
:
(
&
mut
dispatch
)
.into
(),
force_show_panics
,
_
marker
:
marker
::
PhantomData
,
},
client_data
,
);
let
r
=
run_client
(
Bridge
{
cached_buffer
:
input
,
dispatch
:
(
&
mut
dispatch
)
.into
(),
force_show_panics
,
_
marker
:
marker
::
PhantomData
,
});
// Wake up the server so it can exit the dispatch loop.
drop
(
state2
);
...
...
@@ -268,14 +255,12 @@ fn run_server<
S
:
Server
,
I
:
Encode
<
HandleStore
<
MarkedTypes
<
S
>>>
,
O
:
for
<
'a
,
's
>
DecodeMut
<
'a
,
's
,
HandleStore
<
MarkedTypes
<
S
>>>
,
D
:
Copy
+
Send
+
'static
,
>
(
strategy
:
&
impl
ExecutionStrategy
,
handle_counters
:
&
'static
client
::
HandleCounters
,
server
:
S
,
input
:
I
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
,
D
)
->
Buffer
,
client_data
:
D
,
run_client
:
extern
"C"
fn
(
Bridge
<
'_
>
)
->
Buffer
,
force_show_panics
:
bool
,
)
->
Result
<
O
,
PanicMessage
>
{
let
mut
dispatcher
=
...
...
@@ -284,18 +269,12 @@ fn run_server<
let
mut
buf
=
Buffer
::
new
();
input
.encode
(
&
mut
buf
,
&
mut
dispatcher
.handle_store
);
buf
=
strategy
.run_bridge_and_client
(
&
mut
dispatcher
,
buf
,
run_client
,
client_data
,
force_show_panics
,
);
buf
=
strategy
.run_bridge_and_client
(
&
mut
dispatcher
,
buf
,
run_client
,
force_show_panics
);
Result
::
decode
(
&
mut
&
buf
[
..
],
&
mut
dispatcher
.handle_store
)
}
impl
client
::
Client
<
fn
(
crate
::
TokenStream
)
->
crate
::
TokenStream
>
{
impl
client
::
Client
<
crate
::
TokenStream
,
crate
::
TokenStream
>
{
pub
fn
run
<
S
:
Server
>
(
&
self
,
strategy
:
&
impl
ExecutionStrategy
,
...
...
@@ -303,21 +282,20 @@ pub fn run<S: Server>(
input
:
S
::
TokenStream
,
force_show_panics
:
bool
,
)
->
Result
<
S
::
TokenStream
,
PanicMessage
>
{
let
client
::
Client
{
get_handle_counters
,
run
,
f
}
=
*
self
;
let
client
::
Client
{
get_handle_counters
,
run
,
_
marker
}
=
*
self
;
run_server
(
strategy
,
get_handle_counters
(),
server
,
<
MarkedTypes
<
S
>
as
Types
>
::
TokenStream
::
mark
(
input
),
run
,
f
,
force_show_panics
,
)
.map
(
<
MarkedTypes
<
S
>
as
Types
>
::
TokenStream
::
unmark
)
}
}
impl
client
::
Client
<
fn
(
crate
::
TokenStream
,
crate
::
TokenStream
)
->
crate
::
TokenStream
>
{
impl
client
::
Client
<
(
crate
::
TokenStream
,
crate
::
TokenStream
),
crate
::
TokenStream
>
{
pub
fn
run
<
S
:
Server
>
(
&
self
,
strategy
:
&
impl
ExecutionStrategy
,
...
...
@@ -326,7 +304,7 @@ pub fn run<S: Server>(
input2
:
S
::
TokenStream
,
force_show_panics
:
bool
,
)
->
Result
<
S
::
TokenStream
,
PanicMessage
>
{
let
client
::
Client
{
get_handle_counters
,
run
,
f
}
=
*
self
;
let
client
::
Client
{
get_handle_counters
,
run
,
_
marker
}
=
*
self
;
run_server
(
strategy
,
get_handle_counters
(),
...
...
@@ -336,7 +314,6 @@ pub fn run<S: Server>(
<
MarkedTypes
<
S
>
as
Types
>
::
TokenStream
::
mark
(
input2
),
),
run
,
f
,
force_show_panics
,
)
.map
(
<
MarkedTypes
<
S
>
as
Types
>
::
TokenStream
::
unmark
)
...
...
src/test/ui/proc-macro/signature.rs
浏览文件 @
78a83b0d
...
...
@@ -8,6 +8,6 @@
#[proc_macro_derive(A)]
pub
unsafe
extern
"C"
fn
foo
(
a
:
i32
,
b
:
u32
)
->
u32
{
//~^ ERROR:
mismatched types
//~^ ERROR:
expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn
loop
{}
}
src/test/ui/proc-macro/signature.stderr
浏览文件 @
78a83b0d
error[E0
308]: mismatched types
error[E0
277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
--> $DIR/signature.rs:10:1
|
LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
LL | |
LL | | loop {}
LL | | }
| |_^ expected normal fn, found unsafe fn
| | ^
| | |
| |_call the function in a closure: `|| unsafe { /* code */ }`
| required by a bound introduced by this call
|
=
note: expected fn pointer `fn(proc_macro::TokenStream) -> proc_macro::TokenStream
`
found fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
note:
associated function defined here
=
help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}
`
= note: unsafe function cannot be called generically without an unsafe block
note:
required by a bound in `ProcMacro::custom_derive`
--> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
|
LL |
pub const fn custom_derive(
|
^^^^^^^^^^^^^
LL |
expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0
308
`.
For more information about this error, try `rustc --explain E0
277
`.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录