1
- use proc_macro:: { Diagnostic , Span } ;
2
- use proc_macro2:: { Span as Span2 , TokenStream as TokenStream2 } ;
1
+ use proc_macro:: Span ;
2
+ use proc_macro2:: TokenStream as TokenStream2 ;
3
3
use quote:: { ToTokens , TokenStreamExt } ;
4
4
use syn:: {
5
5
FnArg , Ident , ItemTrait , Lifetime , MethodSig , Pat , PatIdent , TraitItem , TraitItemMethod ,
6
6
TraitItemType , TraitItemConst ,
7
7
} ;
8
8
9
- use crate :: { proxy:: ProxyType , spanned:: Spanned } ;
10
-
11
- /// The type parameter used in the proxy type. Usually, one would just use `T`,
12
- /// but this could conflict with type parameters on the trait.
13
- ///
14
- /// Why do we have to care about this? Why about hygiene? In the first version
15
- /// of stable proc_macros, only call site spans are included. That means that
16
- /// we cannot generate spans that do not conflict with any other ident the user
17
- /// wrote. Once proper hygiene is available to proc_macros, this should be
18
- /// changed.
19
- const PROXY_TY_PARAM_NAME : & str = "__AutoImplProxyT" ;
9
+ use crate :: {
10
+ analyze:: { find_suitable_param_names} ,
11
+ diag:: DiagnosticExt ,
12
+ proxy:: ProxyType ,
13
+ spanned:: Spanned
14
+ } ;
20
15
21
- /// The lifetime parameter used in the proxy type if the proxy type is `&` or
22
- /// `&mut`. For more information see `PROXY_TY_PARAM_NAME`.
23
- const PROXY_LT_PARAM_NAME : & str = "'__auto_impl_proxy_lifetime" ;
24
16
25
17
26
18
/// Generates one complete impl of the given trait for each of the given proxy
@@ -31,10 +23,12 @@ pub(crate) fn gen_impls(
31
23
) -> Result < :: proc_macro:: TokenStream , ( ) > {
32
24
let mut tokens = TokenStream2 :: new ( ) ;
33
25
26
+ let ( proxy_ty_param, proxy_lt_param) = find_suitable_param_names ( trait_def) ;
27
+
34
28
// One impl for each proxy type
35
29
for proxy_type in proxy_types {
36
- let header = header ( proxy_type, trait_def) ?;
37
- let items = gen_items ( proxy_type, trait_def) ?;
30
+ let header = header ( proxy_type, trait_def, & proxy_ty_param , & proxy_lt_param ) ?;
31
+ let items = gen_items ( proxy_type, trait_def, & proxy_ty_param ) ?;
38
32
39
33
tokens. append_all ( quote ! {
40
34
#header { #( #items ) * }
@@ -46,10 +40,12 @@ pub(crate) fn gen_impls(
46
40
47
41
/// Generates the header of the impl of the given trait for the given proxy
48
42
/// type.
49
- fn header ( proxy_type : & ProxyType , trait_def : & ItemTrait ) -> Result < TokenStream2 , ( ) > {
50
- let proxy_ty_param = Ident :: new ( PROXY_TY_PARAM_NAME , Span2 :: call_site ( ) ) ;
51
- let proxy_lt_param = & Lifetime :: new ( PROXY_LT_PARAM_NAME , Span2 :: call_site ( ) ) ;
52
-
43
+ fn header (
44
+ proxy_type : & ProxyType ,
45
+ trait_def : & ItemTrait ,
46
+ proxy_ty_param : & Ident ,
47
+ proxy_lt_param : & Lifetime ,
48
+ ) -> Result < TokenStream2 , ( ) > {
53
49
// Generate generics for impl positions from trait generics.
54
50
let ( impl_generics, trait_generics, where_clause) = trait_def. generics . split_for_impl ( ) ;
55
51
@@ -63,10 +59,10 @@ fn header(proxy_type: &ProxyType, trait_def: &ItemTrait) -> Result<TokenStream2,
63
59
// one or two parameters added. For a trait `trait Foo<'x, 'y, A, B>`,
64
60
// it will look like this:
65
61
//
66
- // '__auto_impl_proxy_lifetime , 'x, 'y, A, B, __AutoImplProxyT
62
+ // '{proxy_lt_param} , 'x, 'y, A, B, {proxy_ty_param}
67
63
//
68
- // The `'__auto_impl_proxy_lifetime ` in the beginning is only added when
69
- // the proxy type is `&` or `&mut`.
64
+ // The `'{proxy_lt_param} ` in the beginning is only added when the proxy
65
+ // type is `&` or `&mut`.
70
66
let impl_generics = {
71
67
// Determine if our proxy type needs a lifetime parameter
72
68
let ( mut params, ty_bounds) = match proxy_type {
@@ -297,12 +293,19 @@ fn gen_fn_type_for_trait(
297
293
fn gen_items (
298
294
proxy_type : & ProxyType ,
299
295
trait_def : & ItemTrait ,
296
+ proxy_ty_param : & Ident ,
300
297
) -> Result < Vec < TokenStream2 > , ( ) > {
301
298
trait_def. items . iter ( ) . map ( |item| {
302
299
match item {
303
- TraitItem :: Const ( c) => gen_const_item ( proxy_type, c, trait_def) ,
304
- TraitItem :: Method ( method) => gen_method_item ( proxy_type, method, trait_def) ,
305
- TraitItem :: Type ( ty) => gen_type_item ( proxy_type, ty, trait_def) ,
300
+ TraitItem :: Const ( c) => {
301
+ gen_const_item ( proxy_type, c, trait_def, proxy_ty_param)
302
+ }
303
+ TraitItem :: Method ( method) => {
304
+ gen_method_item ( proxy_type, method, trait_def, proxy_ty_param)
305
+ }
306
+ TraitItem :: Type ( ty) => {
307
+ gen_type_item ( proxy_type, ty, trait_def, proxy_ty_param)
308
+ }
306
309
TraitItem :: Macro ( mac) => {
307
310
// We cannot resolve the macro invocation and thus cannot know
308
311
// if it adds additional items to the trait. Thus, we have to
@@ -334,6 +337,7 @@ fn gen_const_item(
334
337
proxy_type : & ProxyType ,
335
338
item : & TraitItemConst ,
336
339
trait_def : & ItemTrait ,
340
+ proxy_ty_param : & Ident ,
337
341
) -> Result < TokenStream2 , ( ) > {
338
342
// A trait with associated consts cannot be implemented for Fn* types.
339
343
if proxy_type. is_fn ( ) {
@@ -350,7 +354,6 @@ fn gen_const_item(
350
354
// We simply use the associated const from our type parameter.
351
355
let const_name = & item. ident ;
352
356
let const_ty = & item. ty ;
353
- let proxy_ty_param = Ident :: new ( PROXY_TY_PARAM_NAME , Span2 :: call_site ( ) ) ;
354
357
355
358
Ok ( quote ! {
356
359
const #const_name: #const_ty = #proxy_ty_param:: #const_name;
@@ -366,6 +369,7 @@ fn gen_type_item(
366
369
proxy_type : & ProxyType ,
367
370
item : & TraitItemType ,
368
371
trait_def : & ItemTrait ,
372
+ proxy_ty_param : & Ident ,
369
373
) -> Result < TokenStream2 , ( ) > {
370
374
// A trait with associated types cannot be implemented for Fn* types.
371
375
if proxy_type. is_fn ( ) {
@@ -381,7 +385,6 @@ fn gen_type_item(
381
385
382
386
// We simply use the associated type from our type parameter.
383
387
let assoc_name = & item. ident ;
384
- let proxy_ty_param = Ident :: new ( PROXY_TY_PARAM_NAME , Span2 :: call_site ( ) ) ;
385
388
386
389
Ok ( quote ! {
387
390
type #assoc_name = #proxy_ty_param:: #assoc_name;
@@ -398,6 +401,7 @@ fn gen_method_item(
398
401
proxy_type : & ProxyType ,
399
402
item : & TraitItemMethod ,
400
403
trait_def : & ItemTrait ,
404
+ proxy_ty_param : & Ident ,
401
405
) -> Result < TokenStream2 , ( ) > {
402
406
// Determine the kind of the method, determined by the self type.
403
407
let sig = & item. sig ;
@@ -421,7 +425,6 @@ fn gen_method_item(
421
425
// No receiver
422
426
SelfType :: None => {
423
427
// The proxy type is a reference, smartpointer or Box.
424
- let proxy_ty_param = Ident :: new ( PROXY_TY_PARAM_NAME , Span2 :: call_site ( ) ) ;
425
428
quote ! { #proxy_ty_param:: #name( #args) }
426
429
}
427
430
@@ -588,19 +591,3 @@ fn get_arg_list(inputs: impl Iterator<Item = &'a FnArg>) -> Result<TokenStream2,
588
591
589
592
Ok ( args)
590
593
}
591
-
592
- trait DiagnosticExt {
593
- /// Helper function to add a note to the diagnostic (with a span pointing
594
- /// to the `auto_impl` attribute) and emit the error. Additionally,
595
- /// `Err(())` is always returned.
596
- fn emit_with_attr_note < T > ( self ) -> Result < T , ( ) > ;
597
- }
598
-
599
- impl DiagnosticExt for Diagnostic {
600
- fn emit_with_attr_note < T > ( self ) -> Result < T , ( ) > {
601
- self . span_note ( Span :: call_site ( ) , "auto-impl requested here" )
602
- . emit ( ) ;
603
-
604
- Err ( ( ) )
605
- }
606
- }
0 commit comments