@@ -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
@@ -1059,6 +1084,14 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: P<ast::FnDecl>, block: P<ast::Bl
1059
1084
/// A tree-folder that performs macro expansion
1060
1085
pub struct MacroExpander < ' a , ' b : ' a > {
1061
1086
pub cx : & ' a mut ExtCtxt < ' b > ,
1087
+ // The type of the impl currently being expanded.
1088
+ current_impl_type : Option < P < ast:: Ty > > ,
1089
+ }
1090
+
1091
+ impl < ' a , ' b > MacroExpander < ' a , ' b > {
1092
+ pub fn new ( cx : & ' a mut ExtCtxt < ' b > ) -> MacroExpander < ' a , ' b > {
1093
+ MacroExpander { cx : cx, current_impl_type : None }
1094
+ }
1062
1095
}
1063
1096
1064
1097
impl < ' a , ' b > Folder for MacroExpander < ' a , ' b > {
@@ -1071,7 +1104,14 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
1071
1104
}
1072
1105
1073
1106
fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
1074
- expand_item ( item, self )
1107
+ let prev_type = self . current_impl_type . clone ( ) ;
1108
+ if let ast:: Item_ :: ItemImpl ( _, _, _, ref ty, _) = item. node {
1109
+ self . current_impl_type = Some ( ty. clone ( ) ) ;
1110
+ }
1111
+
1112
+ let result = expand_item ( item, self ) ;
1113
+ self . current_impl_type = prev_type;
1114
+ result
1075
1115
}
1076
1116
1077
1117
fn fold_item_underscore ( & mut self , item : ast:: Item_ ) -> ast:: Item_ {
@@ -1094,6 +1134,11 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
1094
1134
expand_method ( method, self )
1095
1135
}
1096
1136
1137
+ fn fold_ty ( & mut self , t : P < ast:: Ty > ) -> P < ast:: Ty > {
1138
+ let impl_type = self . current_impl_type . clone ( ) ;
1139
+ expand_type ( t, self , impl_type)
1140
+ }
1141
+
1097
1142
fn new_span ( & mut self , span : Span ) -> Span {
1098
1143
new_span ( self . cx , span)
1099
1144
}
@@ -1138,9 +1183,7 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
1138
1183
user_exts : Vec < NamedSyntaxExtension > ,
1139
1184
c : Crate ) -> Crate {
1140
1185
let mut cx = ExtCtxt :: new ( parse_sess, c. config . clone ( ) , cfg) ;
1141
- let mut expander = MacroExpander {
1142
- cx : & mut cx,
1143
- } ;
1186
+ let mut expander = MacroExpander :: new ( & mut cx) ;
1144
1187
1145
1188
for ExportedMacros { crate_name, macros } in imported_macros. into_iter ( ) {
1146
1189
let name = format ! ( "<{} macros>" , token:: get_ident( crate_name) )
0 commit comments