@@ -15,6 +15,7 @@ use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
15
15
use ast:: { StmtExpr , StmtSemi } ;
16
16
use ast:: TokenTree ;
17
17
use ast;
18
+ use ast_util:: path_to_ident;
18
19
use ext:: mtwt;
19
20
use ext:: build:: AstBuilder ;
20
21
use attr;
@@ -37,6 +38,30 @@ enum Either<L,R> {
37
38
Right ( R )
38
39
}
39
40
41
+ pub fn expand_type ( t : P < ast:: Ty > ,
42
+ fld : & mut MacroExpander ,
43
+ impl_ty : Option < P < ast:: Ty > > )
44
+ -> P < ast:: Ty > {
45
+ debug ! ( "expanding type {} with impl_ty {}" , t, impl_ty) ;
46
+ let t = match ( t. node . clone ( ) , impl_ty) {
47
+ // Expand uses of `Self` in impls to the concrete type.
48
+ ( ast:: Ty_ :: TyPath ( ref path, _) , Some ( ref impl_ty) ) => {
49
+ let path_as_ident = path_to_ident ( path) ;
50
+ // Note unhygenic comparison here. I think this is correct, since
51
+ // even though `Self` is almost just a type parameter, the treatment
52
+ // for this expansion is as if it were a keyword.
53
+ if path_as_ident. is_some ( ) &&
54
+ path_as_ident. unwrap ( ) . name == token:: special_idents:: type_self. name {
55
+ impl_ty. clone ( )
56
+ } else {
57
+ t
58
+ }
59
+ }
60
+ _ => t
61
+ } ;
62
+ fold:: noop_fold_ty ( t, fld)
63
+ }
64
+
40
65
pub fn expand_expr ( e : P < ast:: Expr > , fld : & mut MacroExpander ) -> P < ast:: Expr > {
41
66
e. and_then ( |ast:: Expr { id, node, span} | match node {
42
67
// expr_mac should really be expr_ext or something; it's the
@@ -1065,6 +1090,14 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: P<ast::FnDecl>, block: P<ast::Bl
1065
1090
/// A tree-folder that performs macro expansion
1066
1091
pub struct MacroExpander < ' a , ' b : ' a > {
1067
1092
pub cx : & ' a mut ExtCtxt < ' b > ,
1093
+ // The type of the impl currently being expanded.
1094
+ current_impl_type : Option < P < ast:: Ty > > ,
1095
+ }
1096
+
1097
+ impl < ' a , ' b > MacroExpander < ' a , ' b > {
1098
+ pub fn new ( cx : & ' a mut ExtCtxt < ' b > ) -> MacroExpander < ' a , ' b > {
1099
+ MacroExpander { cx : cx, current_impl_type : None }
1100
+ }
1068
1101
}
1069
1102
1070
1103
impl < ' a , ' b > Folder for MacroExpander < ' a , ' b > {
@@ -1077,7 +1110,14 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
1077
1110
}
1078
1111
1079
1112
fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
1080
- expand_item ( item, self )
1113
+ let prev_type = self . current_impl_type . clone ( ) ;
1114
+ if let ast:: Item_ :: ItemImpl ( _, _, _, ref ty, _) = item. node {
1115
+ self . current_impl_type = Some ( ty. clone ( ) ) ;
1116
+ }
1117
+
1118
+ let result = expand_item ( item, self ) ;
1119
+ self . current_impl_type = prev_type;
1120
+ result
1081
1121
}
1082
1122
1083
1123
fn fold_item_underscore ( & mut self , item : ast:: Item_ ) -> ast:: Item_ {
@@ -1100,6 +1140,11 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
1100
1140
expand_method ( method, self )
1101
1141
}
1102
1142
1143
+ fn fold_ty ( & mut self , t : P < ast:: Ty > ) -> P < ast:: Ty > {
1144
+ let impl_type = self . current_impl_type . clone ( ) ;
1145
+ expand_type ( t, self , impl_type)
1146
+ }
1147
+
1103
1148
fn new_span ( & mut self , span : Span ) -> Span {
1104
1149
new_span ( self . cx , span)
1105
1150
}
@@ -1144,9 +1189,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
1144
1189
user_exts : Vec < NamedSyntaxExtension > ,
1145
1190
c : Crate ) -> Crate {
1146
1191
let mut cx = ExtCtxt :: new ( parse_sess, c. config . clone ( ) , cfg) ;
1147
- let mut expander = MacroExpander {
1148
- cx : & mut cx,
1149
- } ;
1192
+ let mut expander = MacroExpander :: new ( & mut cx) ;
1150
1193
1151
1194
for ExportedMacros { crate_name, macros } in imported_macros. into_iter ( ) {
1152
1195
let name = format ! ( "<{} macros>" , token:: get_ident( crate_name) )
0 commit comments