diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-06 16:08:26 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-06 16:08:26 +0100 |
commit | f6d688d13070a54b288486900a30680d013c66ca (patch) | |
tree | 39262a1e6cb34897723c4c36b7503fc1483c5a9f /crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs | |
parent | 2603a9e628d304c8cb8fd08979e2f9c9afeac69e (diff) | |
parent | 4f70162f54ceaa4ff68a5ab74e31b5dda7ac9444 (diff) |
Merge #3842
3842: Add lib-proc-macro mod in ra_proc_macro_srv r=matklad a=edwin0cheng
This PR add a module in ra_proc_macro_srv, which is just copy & paste from rustc lib_proc_macro and remove all unstable features in it.
The main idea here is by doing that, we could build the `ra_proc_macro_srv` without nightly compiler and remain ABI compatibility.
Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs')
-rw-r--r-- | crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs b/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs new file mode 100644 index 000000000..6ae3926b2 --- /dev/null +++ b/crates/ra_proc_macro_srv/src/proc_macro/bridge/mod.rs | |||
@@ -0,0 +1,404 @@ | |||
1 | //! lib-proc-macro Internal interface for communicating between a `proc_macro` client | ||
2 | //! | ||
3 | //! Copy from https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/bridge/mod.rs | ||
4 | //! augmented with removing unstable features | ||
5 | //! | ||
6 | //! Internal interface for communicating between a `proc_macro` client | ||
7 | //! (a proc macro crate) and a `proc_macro` server (a compiler front-end). | ||
8 | //! | ||
9 | //! Serialization (with C ABI buffers) and unique integer handles are employed | ||
10 | //! to allow safely interfacing between two copies of `proc_macro` built | ||
11 | //! (from the same source) by different compilers with potentially mismatching | ||
12 | //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap). | ||
13 | |||
14 | #![deny(unsafe_code)] | ||
15 | |||
16 | pub use crate::proc_macro::{Delimiter, Level, LineColumn, Spacing}; | ||
17 | use std::fmt; | ||
18 | use std::hash::Hash; | ||
19 | use std::marker; | ||
20 | use std::mem; | ||
21 | use std::ops::Bound; | ||
22 | use std::panic; | ||
23 | use std::sync::atomic::AtomicUsize; | ||
24 | use std::sync::Once; | ||
25 | use std::thread; | ||
26 | |||
27 | /// Higher-order macro describing the server RPC API, allowing automatic | ||
28 | /// generation of type-safe Rust APIs, both client-side and server-side. | ||
29 | /// | ||
30 | /// `with_api!(MySelf, my_self, my_macro)` expands to: | ||
31 | /// ```rust,ignore (pseudo-code) | ||
32 | /// my_macro! { | ||
33 | /// // ... | ||
34 | /// Literal { | ||
35 | /// // ... | ||
36 | /// fn character(ch: char) -> MySelf::Literal; | ||
37 | /// // ... | ||
38 | /// fn span(my_self: &MySelf::Literal) -> MySelf::Span; | ||
39 | /// fn set_span(my_self: &mut MySelf::Literal, span: MySelf::Span); | ||
40 | /// }, | ||
41 | /// // ... | ||
42 | /// } | ||
43 | /// ``` | ||
44 | /// | ||
45 | /// The first two arguments serve to customize the arguments names | ||
46 | /// and argument/return types, to enable several different usecases: | ||
47 | /// | ||
48 | /// If `my_self` is just `self`, then each `fn` signature can be used | ||
49 | /// as-is for a method. If it's anything else (`self_` in practice), | ||
50 | /// then the signatures don't have a special `self` argument, and | ||
51 | /// can, therefore, have a different one introduced. | ||
52 | /// | ||
53 | /// If `MySelf` is just `Self`, then the types are only valid inside | ||
54 | /// a trait or a trait impl, where the trait has associated types | ||
55 | /// for each of the API types. If non-associated types are desired, | ||
56 | /// a module name (`self` in practice) can be used instead of `Self`. | ||
57 | macro_rules! with_api { | ||
58 | ($S:ident, $self:ident, $m:ident) => { | ||
59 | $m! { | ||
60 | TokenStream { | ||
61 | fn drop($self: $S::TokenStream); | ||
62 | fn clone($self: &$S::TokenStream) -> $S::TokenStream; | ||
63 | fn new() -> $S::TokenStream; | ||
64 | fn is_empty($self: &$S::TokenStream) -> bool; | ||
65 | fn from_str(src: &str) -> $S::TokenStream; | ||
66 | fn to_string($self: &$S::TokenStream) -> String; | ||
67 | fn from_token_tree( | ||
68 | tree: TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>, | ||
69 | ) -> $S::TokenStream; | ||
70 | fn into_iter($self: $S::TokenStream) -> $S::TokenStreamIter; | ||
71 | }, | ||
72 | TokenStreamBuilder { | ||
73 | fn drop($self: $S::TokenStreamBuilder); | ||
74 | fn new() -> $S::TokenStreamBuilder; | ||
75 | fn push($self: &mut $S::TokenStreamBuilder, stream: $S::TokenStream); | ||
76 | fn build($self: $S::TokenStreamBuilder) -> $S::TokenStream; | ||
77 | }, | ||
78 | TokenStreamIter { | ||
79 | fn drop($self: $S::TokenStreamIter); | ||
80 | fn clone($self: &$S::TokenStreamIter) -> $S::TokenStreamIter; | ||
81 | fn next( | ||
82 | $self: &mut $S::TokenStreamIter, | ||
83 | ) -> Option<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>; | ||
84 | }, | ||
85 | Group { | ||
86 | fn drop($self: $S::Group); | ||
87 | fn clone($self: &$S::Group) -> $S::Group; | ||
88 | fn new(delimiter: Delimiter, stream: $S::TokenStream) -> $S::Group; | ||
89 | fn delimiter($self: &$S::Group) -> Delimiter; | ||
90 | fn stream($self: &$S::Group) -> $S::TokenStream; | ||
91 | fn span($self: &$S::Group) -> $S::Span; | ||
92 | fn span_open($self: &$S::Group) -> $S::Span; | ||
93 | fn span_close($self: &$S::Group) -> $S::Span; | ||
94 | fn set_span($self: &mut $S::Group, span: $S::Span); | ||
95 | }, | ||
96 | Punct { | ||
97 | fn new(ch: char, spacing: Spacing) -> $S::Punct; | ||
98 | fn as_char($self: $S::Punct) -> char; | ||
99 | fn spacing($self: $S::Punct) -> Spacing; | ||
100 | fn span($self: $S::Punct) -> $S::Span; | ||
101 | fn with_span($self: $S::Punct, span: $S::Span) -> $S::Punct; | ||
102 | }, | ||
103 | Ident { | ||
104 | fn new(string: &str, span: $S::Span, is_raw: bool) -> $S::Ident; | ||
105 | fn span($self: $S::Ident) -> $S::Span; | ||
106 | fn with_span($self: $S::Ident, span: $S::Span) -> $S::Ident; | ||
107 | }, | ||
108 | Literal { | ||
109 | fn drop($self: $S::Literal); | ||
110 | fn clone($self: &$S::Literal) -> $S::Literal; | ||
111 | // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. | ||
112 | fn debug($self: &$S::Literal) -> String; | ||
113 | fn integer(n: &str) -> $S::Literal; | ||
114 | fn typed_integer(n: &str, kind: &str) -> $S::Literal; | ||
115 | fn float(n: &str) -> $S::Literal; | ||
116 | fn f32(n: &str) -> $S::Literal; | ||
117 | fn f64(n: &str) -> $S::Literal; | ||
118 | fn string(string: &str) -> $S::Literal; | ||
119 | fn character(ch: char) -> $S::Literal; | ||
120 | fn byte_string(bytes: &[u8]) -> $S::Literal; | ||
121 | fn span($self: &$S::Literal) -> $S::Span; | ||
122 | fn set_span($self: &mut $S::Literal, span: $S::Span); | ||
123 | fn subspan( | ||
124 | $self: &$S::Literal, | ||
125 | start: Bound<usize>, | ||
126 | end: Bound<usize>, | ||
127 | ) -> Option<$S::Span>; | ||
128 | }, | ||
129 | SourceFile { | ||
130 | fn drop($self: $S::SourceFile); | ||
131 | fn clone($self: &$S::SourceFile) -> $S::SourceFile; | ||
132 | fn eq($self: &$S::SourceFile, other: &$S::SourceFile) -> bool; | ||
133 | fn path($self: &$S::SourceFile) -> String; | ||
134 | fn is_real($self: &$S::SourceFile) -> bool; | ||
135 | }, | ||
136 | MultiSpan { | ||
137 | fn drop($self: $S::MultiSpan); | ||
138 | fn new() -> $S::MultiSpan; | ||
139 | fn push($self: &mut $S::MultiSpan, span: $S::Span); | ||
140 | }, | ||
141 | Diagnostic { | ||
142 | fn drop($self: $S::Diagnostic); | ||
143 | fn new(level: Level, msg: &str, span: $S::MultiSpan) -> $S::Diagnostic; | ||
144 | fn sub( | ||
145 | $self: &mut $S::Diagnostic, | ||
146 | level: Level, | ||
147 | msg: &str, | ||
148 | span: $S::MultiSpan, | ||
149 | ); | ||
150 | fn emit($self: $S::Diagnostic); | ||
151 | }, | ||
152 | Span { | ||
153 | fn debug($self: $S::Span) -> String; | ||
154 | fn def_site() -> $S::Span; | ||
155 | fn call_site() -> $S::Span; | ||
156 | fn mixed_site() -> $S::Span; | ||
157 | fn source_file($self: $S::Span) -> $S::SourceFile; | ||
158 | fn parent($self: $S::Span) -> Option<$S::Span>; | ||
159 | fn source($self: $S::Span) -> $S::Span; | ||
160 | fn start($self: $S::Span) -> LineColumn; | ||
161 | fn end($self: $S::Span) -> LineColumn; | ||
162 | fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>; | ||
163 | fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span; | ||
164 | fn source_text($self: $S::Span) -> Option<String>; | ||
165 | }, | ||
166 | } | ||
167 | }; | ||
168 | } | ||
169 | |||
170 | // FIXME(eddyb) this calls `encode` for each argument, but in reverse, | ||
171 | // to avoid borrow conflicts from borrows started by `&mut` arguments. | ||
172 | macro_rules! reverse_encode { | ||
173 | ($writer:ident;) => {}; | ||
174 | ($writer:ident; $first:ident $(, $rest:ident)*) => { | ||
175 | reverse_encode!($writer; $($rest),*); | ||
176 | $first.encode(&mut $writer, &mut ()); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | // FIXME(eddyb) this calls `decode` for each argument, but in reverse, | ||
181 | // to avoid borrow conflicts from borrows started by `&mut` arguments. | ||
182 | macro_rules! reverse_decode { | ||
183 | ($reader:ident, $s:ident;) => {}; | ||
184 | ($reader:ident, $s:ident; $first:ident: $first_ty:ty $(, $rest:ident: $rest_ty:ty)*) => { | ||
185 | reverse_decode!($reader, $s; $($rest: $rest_ty),*); | ||
186 | let $first = <$first_ty>::decode(&mut $reader, $s); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | #[allow(unsafe_code)] | ||
191 | mod buffer; | ||
192 | #[forbid(unsafe_code)] | ||
193 | pub mod client; | ||
194 | #[allow(unsafe_code)] | ||
195 | mod closure; | ||
196 | #[forbid(unsafe_code)] | ||
197 | mod handle; | ||
198 | #[macro_use] | ||
199 | #[forbid(unsafe_code)] | ||
200 | mod rpc; | ||
201 | #[allow(unsafe_code)] | ||
202 | mod scoped_cell; | ||
203 | #[forbid(unsafe_code)] | ||
204 | pub mod server; | ||
205 | |||
206 | use buffer::Buffer; | ||
207 | pub use rpc::PanicMessage; | ||
208 | use rpc::{Decode, DecodeMut, Encode, Reader, Writer}; | ||
209 | |||
210 | /// An active connection between a server and a client. | ||
211 | /// The server creates the bridge (`Bridge::run_server` in `server.rs`), | ||
212 | /// then passes it to the client through the function pointer in the `run` | ||
213 | /// field of `client::Client`. The client holds its copy of the `Bridge` | ||
214 | /// in TLS during its execution (`Bridge::{enter, with}` in `client.rs`). | ||
215 | #[repr(C)] | ||
216 | pub struct Bridge<'a> { | ||
217 | /// Reusable buffer (only `clear`-ed, never shrunk), primarily | ||
218 | /// used for making requests, but also for passing input to client. | ||
219 | cached_buffer: Buffer<u8>, | ||
220 | |||
221 | /// Server-side function that the client uses to make requests. | ||
222 | dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>, | ||
223 | } | ||
224 | |||
225 | #[forbid(unsafe_code)] | ||
226 | #[allow(non_camel_case_types)] | ||
227 | mod api_tags { | ||
228 | use super::rpc::{DecodeMut, Encode, Reader, Writer}; | ||
229 | |||
230 | macro_rules! declare_tags { | ||
231 | ($($name:ident { | ||
232 | $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* | ||
233 | }),* $(,)?) => { | ||
234 | $( | ||
235 | pub(super) enum $name { | ||
236 | $($method),* | ||
237 | } | ||
238 | rpc_encode_decode!(enum $name { $($method),* }); | ||
239 | )* | ||
240 | |||
241 | |||
242 | pub(super) enum Method { | ||
243 | $($name($name)),* | ||
244 | } | ||
245 | rpc_encode_decode!(enum Method { $($name(m)),* }); | ||
246 | } | ||
247 | } | ||
248 | with_api!(self, self, declare_tags); | ||
249 | } | ||
250 | |||
251 | /// Helper to wrap associated types to allow trait impl dispatch. | ||
252 | /// That is, normally a pair of impls for `T::Foo` and `T::Bar` | ||
253 | /// can overlap, but if the impls are, instead, on types like | ||
254 | /// `Marked<T::Foo, Foo>` and `Marked<T::Bar, Bar>`, they can't. | ||
255 | trait Mark { | ||
256 | type Unmarked; | ||
257 | fn mark(unmarked: Self::Unmarked) -> Self; | ||
258 | } | ||
259 | |||
260 | /// Unwrap types wrapped by `Mark::mark` (see `Mark` for details). | ||
261 | trait Unmark { | ||
262 | type Unmarked; | ||
263 | fn unmark(self) -> Self::Unmarked; | ||
264 | } | ||
265 | |||
266 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | ||
267 | struct Marked<T, M> { | ||
268 | value: T, | ||
269 | _marker: marker::PhantomData<M>, | ||
270 | } | ||
271 | |||
272 | impl<T, M> Mark for Marked<T, M> { | ||
273 | type Unmarked = T; | ||
274 | fn mark(unmarked: Self::Unmarked) -> Self { | ||
275 | Marked { value: unmarked, _marker: marker::PhantomData } | ||
276 | } | ||
277 | } | ||
278 | impl<T, M> Unmark for Marked<T, M> { | ||
279 | type Unmarked = T; | ||
280 | fn unmark(self) -> Self::Unmarked { | ||
281 | self.value | ||
282 | } | ||
283 | } | ||
284 | impl<'a, T, M> Unmark for &'a Marked<T, M> { | ||
285 | type Unmarked = &'a T; | ||
286 | fn unmark(self) -> Self::Unmarked { | ||
287 | &self.value | ||
288 | } | ||
289 | } | ||
290 | impl<'a, T, M> Unmark for &'a mut Marked<T, M> { | ||
291 | type Unmarked = &'a mut T; | ||
292 | fn unmark(self) -> Self::Unmarked { | ||
293 | &mut self.value | ||
294 | } | ||
295 | } | ||
296 | |||
297 | impl<T: Mark> Mark for Option<T> { | ||
298 | type Unmarked = Option<T::Unmarked>; | ||
299 | fn mark(unmarked: Self::Unmarked) -> Self { | ||
300 | unmarked.map(T::mark) | ||
301 | } | ||
302 | } | ||
303 | impl<T: Unmark> Unmark for Option<T> { | ||
304 | type Unmarked = Option<T::Unmarked>; | ||
305 | fn unmark(self) -> Self::Unmarked { | ||
306 | self.map(T::unmark) | ||
307 | } | ||
308 | } | ||
309 | |||
310 | macro_rules! mark_noop { | ||
311 | ($($ty:ty),* $(,)?) => { | ||
312 | $( | ||
313 | impl Mark for $ty { | ||
314 | type Unmarked = Self; | ||
315 | fn mark(unmarked: Self::Unmarked) -> Self { | ||
316 | unmarked | ||
317 | } | ||
318 | } | ||
319 | impl Unmark for $ty { | ||
320 | type Unmarked = Self; | ||
321 | fn unmark(self) -> Self::Unmarked { | ||
322 | self | ||
323 | } | ||
324 | } | ||
325 | )* | ||
326 | } | ||
327 | } | ||
328 | mark_noop! { | ||
329 | (), | ||
330 | bool, | ||
331 | char, | ||
332 | &'_ [u8], | ||
333 | &'_ str, | ||
334 | String, | ||
335 | Delimiter, | ||
336 | Level, | ||
337 | LineColumn, | ||
338 | Spacing, | ||
339 | Bound<usize>, | ||
340 | } | ||
341 | |||
342 | rpc_encode_decode!( | ||
343 | enum Delimiter { | ||
344 | Parenthesis, | ||
345 | Brace, | ||
346 | Bracket, | ||
347 | None, | ||
348 | } | ||
349 | ); | ||
350 | rpc_encode_decode!( | ||
351 | enum Level { | ||
352 | Error, | ||
353 | Warning, | ||
354 | Note, | ||
355 | Help, | ||
356 | } | ||
357 | ); | ||
358 | rpc_encode_decode!(struct LineColumn { line, column }); | ||
359 | rpc_encode_decode!( | ||
360 | enum Spacing { | ||
361 | Alone, | ||
362 | Joint, | ||
363 | } | ||
364 | ); | ||
365 | |||
366 | #[derive(Clone)] | ||
367 | pub enum TokenTree<G, P, I, L> { | ||
368 | Group(G), | ||
369 | Punct(P), | ||
370 | Ident(I), | ||
371 | Literal(L), | ||
372 | } | ||
373 | |||
374 | impl<G: Mark, P: Mark, I: Mark, L: Mark> Mark for TokenTree<G, P, I, L> { | ||
375 | type Unmarked = TokenTree<G::Unmarked, P::Unmarked, I::Unmarked, L::Unmarked>; | ||
376 | fn mark(unmarked: Self::Unmarked) -> Self { | ||
377 | match unmarked { | ||
378 | TokenTree::Group(tt) => TokenTree::Group(G::mark(tt)), | ||
379 | TokenTree::Punct(tt) => TokenTree::Punct(P::mark(tt)), | ||
380 | TokenTree::Ident(tt) => TokenTree::Ident(I::mark(tt)), | ||
381 | TokenTree::Literal(tt) => TokenTree::Literal(L::mark(tt)), | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | impl<G: Unmark, P: Unmark, I: Unmark, L: Unmark> Unmark for TokenTree<G, P, I, L> { | ||
386 | type Unmarked = TokenTree<G::Unmarked, P::Unmarked, I::Unmarked, L::Unmarked>; | ||
387 | fn unmark(self) -> Self::Unmarked { | ||
388 | match self { | ||
389 | TokenTree::Group(tt) => TokenTree::Group(tt.unmark()), | ||
390 | TokenTree::Punct(tt) => TokenTree::Punct(tt.unmark()), | ||
391 | TokenTree::Ident(tt) => TokenTree::Ident(tt.unmark()), | ||
392 | TokenTree::Literal(tt) => TokenTree::Literal(tt.unmark()), | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | |||
397 | rpc_encode_decode!( | ||
398 | enum TokenTree<G, P, I, L> { | ||
399 | Group(tt), | ||
400 | Punct(tt), | ||
401 | Ident(tt), | ||
402 | Literal(tt), | ||
403 | } | ||
404 | ); | ||