Skip to content

Commit da5c538

Browse files
committed
strip out proc-macro-hack
1 parent 28ed854 commit da5c538

File tree

11 files changed

+188
-105
lines changed

11 files changed

+188
-105
lines changed

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ all-features = true
2929

3030
[features]
3131
default = [ "macros" ]
32-
macros = [ "sqlx-macros", "proc-macro-hack" ]
32+
macros = [ "sqlx-macros" ]
3333
tls = ["sqlx-core/tls"]
3434

3535
# database
@@ -43,7 +43,6 @@ uuid = [ "sqlx-core/uuid", "sqlx-macros/uuid" ]
4343
[dependencies]
4444
sqlx-core = { version = "=0.1.4", path = "sqlx-core" }
4545
sqlx-macros = { version = "0.1.1", path = "sqlx-macros", optional = true }
46-
proc-macro-hack = { version = "0.5.11", optional = true }
4746

4847
[dev-dependencies]
4948
anyhow = "1.0.26"

sqlx-macros/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ uuid = [ "sqlx/uuid" ]
3333
async-std = { version = "1.4.0", default-features = false }
3434
dotenv = { version = "0.15.0", default-features = false }
3535
futures = { version = "0.3.1", default-features = false }
36-
proc-macro-hack = { version = "0.5.11", default-features = false }
3736
proc-macro2 = { version = "1.0.6", default-features = false }
3837
sqlx = { version = "0.1.1", default-features = false, path = "../sqlx-core", package = "sqlx-core" }
3938
syn = { version = "1.0.11", default-features = false, features = [ "full" ] }

sqlx-macros/src/lib.rs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ extern crate proc_macro;
66

77
use proc_macro::TokenStream;
88

9-
use proc_macro_hack::proc_macro_hack;
10-
119
use quote::quote;
1210

1311
use syn::parse_macro_input;
@@ -26,8 +24,22 @@ mod query_macros;
2624

2725
use query_macros::*;
2826

27+
fn macro_result(tokens: proc_macro2::TokenStream) -> TokenStream {
28+
quote!(
29+
macro_rules! macro_result {
30+
($($args:tt)*) => (#tokens)
31+
}
32+
)
33+
.into()
34+
}
35+
2936
macro_rules! async_macro (
30-
($db:ident => $expr:expr) => {{
37+
($db:ident, $input:ident: $ty:ty => $expr:expr) => {{
38+
let $input = match syn::parse::<$ty>($input) {
39+
Ok(input) => input,
40+
Err(e) => return macro_result(e.to_compile_error()),
41+
};
42+
3143
let res: Result<proc_macro2::TokenStream> = task::block_on(async {
3244
use sqlx::Connection;
3345

@@ -70,40 +82,36 @@ macro_rules! async_macro (
7082
Ok(ts) => ts.into(),
7183
Err(e) => {
7284
if let Some(parse_err) = e.downcast_ref::<syn::Error>() {
73-
return dbg!(parse_err).to_compile_error().into();
85+
macro_result(parse_err.to_compile_error())
86+
} else {
87+
let msg = format!("{:?}", e);
88+
macro_result(quote!(compile_error(#msg)))
7489
}
75-
76-
let msg = format!("{:?}", e);
77-
quote!(compile_error!(#msg);).into()
7890
}
7991
}
8092
}}
8193
);
8294

83-
#[proc_macro_hack]
95+
#[proc_macro]
8496
pub fn query(input: TokenStream) -> TokenStream {
8597
#[allow(unused_variables)]
86-
let input = parse_macro_input!(input as QueryMacroInput);
87-
async_macro!(db => expand_query(input, db))
98+
async_macro!(db, input: QueryMacroInput => expand_query(input, db))
8899
}
89100

90-
#[proc_macro_hack]
101+
#[proc_macro]
91102
pub fn query_file(input: TokenStream) -> TokenStream {
92103
#[allow(unused_variables)]
93-
let input = parse_macro_input!(input as QueryMacroInput);
94-
async_macro!(db => expand_query_file(input, db))
104+
async_macro!(db, input: QueryMacroInput => expand_query_file(input, db))
95105
}
96106

97-
#[proc_macro_hack]
107+
#[proc_macro]
98108
pub fn query_as(input: TokenStream) -> TokenStream {
99109
#[allow(unused_variables)]
100-
let input = parse_macro_input!(input as QueryAsMacroInput);
101-
async_macro!(db => expand_query_as(input, db))
110+
async_macro!(db, input: QueryAsMacroInput => expand_query_as(input, db))
102111
}
103112

104-
#[proc_macro_hack]
113+
#[proc_macro]
105114
pub fn query_file_as(input: TokenStream) -> TokenStream {
106115
#[allow(unused_variables)]
107-
let input = parse_macro_input!(input as QueryAsMacroInput);
108-
async_macro!(db => expand_query_file_as(input, db))
116+
async_macro!(db, input: QueryAsMacroInput => expand_query_file_as(input, db))
109117
}

sqlx-macros/src/query_macros/args.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn quote_args<DB: DatabaseExt>(
1212
input: &QueryMacroInput,
1313
describe: &Describe<DB>,
1414
) -> crate::Result<TokenStream> {
15-
if input.args.is_empty() {
15+
if input.arg_names.is_empty() {
1616
return Ok(quote! {
1717
let args = ();
1818
});
@@ -22,7 +22,7 @@ pub fn quote_args<DB: DatabaseExt>(
2222
let param_types = describe
2323
.param_types
2424
.iter()
25-
.zip(&*input.args)
25+
.zip(&*input.arg_exprs)
2626
.map(|(type_, expr)| {
2727
get_type_override(expr)
2828
.or_else(|| {
@@ -36,7 +36,7 @@ pub fn quote_args<DB: DatabaseExt>(
3636
})
3737
.collect::<crate::Result<Vec<_>>>()?;
3838

39-
let args_ty_cons = input.args.iter().enumerate().map(|(i, expr)| {
39+
let args_ty_cons = input.arg_names.iter().enumerate().map(|(i, expr)| {
4040
// required or `quote!()` emits it as `Nusize`
4141
let i = syn::Index::from(i);
4242
quote_spanned!( expr.span() => {
@@ -56,10 +56,10 @@ pub fn quote_args<DB: DatabaseExt>(
5656
TokenStream::new()
5757
};
5858

59-
let args = input.args.iter();
59+
let args = input.arg_names.iter();
6060

6161
Ok(quote! {
62-
let args = (#(&#args),*,);
62+
let args = (#(&$#args),*,);
6363
#args_check
6464
})
6565
}

sqlx-macros/src/query_macros/input.rs

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
use std::env;
22

33
use async_std::fs;
4-
use proc_macro2::Span;
4+
use proc_macro2::{Ident, Span, TokenStream};
55
use syn::parse::{Parse, ParseStream};
66
use syn::punctuated::Punctuated;
7-
use syn::Token;
7+
use syn::spanned::Spanned;
8+
use syn::token::Group;
89
use syn::{Expr, ExprLit, ExprPath, Lit};
10+
use syn::{ExprGroup, Token};
11+
12+
use quote::{format_ident, quote, ToTokens};
913

1014
use sqlx::describe::Describe;
1115
use sqlx::Connection;
@@ -14,28 +18,55 @@ use sqlx::Connection;
1418
pub struct QueryMacroInput {
1519
pub(super) source: String,
1620
pub(super) source_span: Span,
17-
pub(super) args: Vec<Expr>,
21+
// `arg0 .. argN` for N arguments
22+
pub(super) arg_names: Vec<Ident>,
23+
pub(super) arg_exprs: Vec<Expr>,
1824
}
1925

2026
impl QueryMacroInput {
2127
fn from_exprs(input: ParseStream, mut args: impl Iterator<Item = Expr>) -> syn::Result<Self> {
22-
let sql = match args.next() {
28+
fn lit_err<T>(span: Span, unexpected: Expr) -> syn::Result<T> {
29+
Err(syn::Error::new(
30+
span,
31+
format!(
32+
"expected string literal, got {}",
33+
unexpected.to_token_stream()
34+
),
35+
))
36+
}
37+
38+
let (source, source_span) = match args.next() {
2339
Some(Expr::Lit(ExprLit {
2440
lit: Lit::Str(sql), ..
25-
})) => sql,
26-
Some(other_expr) => {
27-
return Err(syn::Error::new_spanned(
28-
other_expr,
29-
"expected string literal",
30-
));
41+
})) => (sql.value(), sql.span()),
42+
Some(Expr::Group(ExprGroup {
43+
expr,
44+
group_token: Group { span },
45+
..
46+
})) => {
47+
// this duplication with the above is necessary because `expr` is `Box<Expr>` here
48+
// which we can't directly pattern-match without `box_patterns`
49+
match *expr {
50+
Expr::Lit(ExprLit {
51+
lit: Lit::Str(sql), ..
52+
}) => (sql.value(), span),
53+
other_expr => return lit_err(span, other_expr),
54+
}
3155
}
56+
Some(other_expr) => return lit_err(other_expr.span(), other_expr),
3257
None => return Err(input.error("expected SQL string literal")),
3358
};
3459

60+
let arg_exprs: Vec<_> = args.collect();
61+
let arg_names = (0..arg_exprs.len())
62+
.map(|i| format_ident!("arg{}", i))
63+
.collect();
64+
3565
Ok(Self {
36-
source: sql.value(),
37-
source_span: sql.span(),
38-
args: args.collect(),
66+
source,
67+
source_span,
68+
arg_exprs,
69+
arg_names,
3970
})
4071
}
4172

@@ -56,13 +87,13 @@ impl QueryMacroInput {
5687
.await
5788
.map_err(|e| syn::Error::new(self.source_span, e))?;
5889

59-
if self.args.len() != describe.param_types.len() {
90+
if self.arg_names.len() != describe.param_types.len() {
6091
return Err(syn::Error::new(
6192
Span::call_site(),
6293
format!(
6394
"expected {} parameters, got {}",
6495
describe.param_types.len(),
65-
self.args.len()
96+
self.arg_names.len()
6697
),
6798
)
6899
.into());
@@ -97,16 +128,33 @@ impl QueryAsMacroInput {
97128

98129
impl Parse for QueryAsMacroInput {
99130
fn parse(input: ParseStream) -> syn::Result<Self> {
131+
fn path_err<T>(span: Span, unexpected: Expr) -> syn::Result<T> {
132+
Err(syn::Error::new(
133+
span,
134+
format!(
135+
"expected path to a type, got {}",
136+
unexpected.to_token_stream()
137+
),
138+
))
139+
}
140+
100141
let mut args = Punctuated::<Expr, Token![,]>::parse_terminated(input)?.into_iter();
101142

102143
let as_ty = match args.next() {
103144
Some(Expr::Path(path)) => path,
104-
Some(other_expr) => {
105-
return Err(syn::Error::new_spanned(
106-
other_expr,
107-
"expected path to a type",
108-
));
145+
Some(Expr::Group(ExprGroup {
146+
expr,
147+
group_token: Group { span },
148+
..
149+
})) => {
150+
// this duplication with the above is necessary because `expr` is `Box<Expr>` here
151+
// which we can't directly pattern-match without `box_patterns`
152+
match *expr {
153+
Expr::Path(path) => path,
154+
other_expr => return path_err(span, other_expr),
155+
}
109156
}
157+
Some(other_expr) => return path_err(other_expr.span(), other_expr),
110158
None => return Err(input.error("expected path to SQL file")),
111159
};
112160

sqlx-macros/src/query_macros/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ where
4646
}
4747

4848
let args_tokens = args::quote_args(&input.query_input, &describe)?;
49+
let arg_names = &input.query_input.arg_names;
4950

5051
let columns = output::columns_to_rust(&describe)?;
5152
let output = output::quote_query_as::<C::Database>(
@@ -54,10 +55,14 @@ where
5455
&columns,
5556
);
5657

57-
Ok(quote! {{
58-
#args_tokens
59-
#output.bind_all(args)
60-
}})
58+
Ok(quote! {
59+
macro_rules! macro_result {
60+
(#($#arg_names:expr),*) => {{
61+
#args_tokens
62+
#output.bind_all(args)
63+
}}
64+
}
65+
})
6166
}
6267

6368
pub async fn expand_query_file_as<C: Connection>(

sqlx-macros/src/query_macros/query.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,20 @@ where
5050
.collect::<TokenStream>();
5151

5252
let output = output::quote_query_as::<C::Database>(sql, &record_type, &columns);
53+
let arg_names = &input.arg_names;
5354

54-
Ok(quote! {{
55-
#[derive(Debug)]
56-
struct #record_type {
57-
#record_fields
58-
}
55+
Ok(quote! {
56+
macro_rules! macro_result {
57+
(#($#arg_names:expr),*) => {{
58+
#[derive(Debug)]
59+
struct #record_type {
60+
#record_fields
61+
}
5962

60-
#args
63+
#args
6164

62-
#output.bind_all(args)
63-
}})
65+
#output.bind_all(args)
66+
}
67+
}}
68+
})
6469
}

src/lib.rs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,13 @@ pub use sqlx_core::mysql::{self, MySql, MySqlConnection, MySqlPool};
2020
#[cfg(feature = "postgres")]
2121
pub use sqlx_core::postgres::{self, PgConnection, PgPool, Postgres};
2222

23-
#[allow(unused_attributes)]
24-
#[macro_export]
25-
mod macros;
26-
27-
#[cfg(feature = "macros")]
28-
#[doc(hidden)]
29-
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
30-
#[allow(dead_code)]
31-
pub use sqlx_macros::query as query_;
32-
3323
#[cfg(feature = "macros")]
3424
#[doc(hidden)]
35-
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
36-
#[allow(dead_code)]
37-
pub use sqlx_macros::query_as as query_as_;
25+
pub extern crate sqlx_macros;
3826

3927
#[cfg(feature = "macros")]
40-
#[doc(hidden)]
41-
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
42-
#[allow(dead_code)]
43-
pub use sqlx_macros::query_file as query_file_;
44-
45-
#[cfg(feature = "macros")]
46-
#[doc(hidden)]
47-
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
48-
#[allow(dead_code)]
49-
pub use sqlx_macros::query_file_as as query_file_as_;
28+
#[macro_export]
29+
mod macros;
5030

5131
// macro support
5232
#[cfg(feature = "macros")]

0 commit comments

Comments
 (0)