@@ -11,12 +11,15 @@ use syntax::{
1111
1212#[ derive( Default ) ]
1313struct AstSubsts {
14- // ast::TypeArgs stands in fact for both type and const params
15- // as consts declared elsewhere look just like type params.
16- types_and_consts : Vec < ast:: TypeArg > ,
14+ types_and_consts : Vec < TypeOrConst > ,
1715 lifetimes : Vec < ast:: LifetimeArg > ,
1816}
1917
18+ enum TypeOrConst {
19+ Either ( ast:: TypeArg ) , // indistinguishable type or const param
20+ Const ( ast:: ConstArg ) ,
21+ }
22+
2023type LifetimeName = String ;
2124
2225/// `PathTransform` substitutes path in SyntaxNodes in bulk.
@@ -125,27 +128,38 @@ impl<'a> PathTransform<'a> {
125128 // the resulting change can be applied correctly.
126129 . zip ( self . substs . types_and_consts . iter ( ) . map ( Some ) . chain ( std:: iter:: repeat ( None ) ) )
127130 . for_each ( |( k, v) | match ( k. split ( db) , v) {
128- ( Either :: Right ( t ) , Some ( v ) ) => {
131+ ( Either :: Right ( k ) , Some ( TypeOrConst :: Either ( v ) ) ) => {
129132 if let Some ( ty) = v. ty ( ) {
130- type_substs. insert ( t , ty. clone ( ) ) ;
133+ type_substs. insert ( k , ty. clone ( ) ) ;
131134 }
132135 }
133- ( Either :: Right ( t ) , None ) => {
134- if let Some ( default) = t . default ( db) {
136+ ( Either :: Right ( k ) , None ) => {
137+ if let Some ( default) = k . default ( db) {
135138 if let Some ( default) =
136139 & default. display_source_code ( db, source_module. into ( ) , false ) . ok ( )
137140 {
138- type_substs. insert ( t , ast:: make:: ty ( default) . clone_for_update ( ) ) ;
139- default_types. push ( t ) ;
141+ type_substs. insert ( k , ast:: make:: ty ( default) . clone_for_update ( ) ) ;
142+ default_types. push ( k ) ;
140143 }
141144 }
142145 }
143- ( Either :: Left ( c ) , Some ( v ) ) => {
146+ ( Either :: Left ( k ) , Some ( TypeOrConst :: Either ( v ) ) ) => {
144147 if let Some ( ty) = v. ty ( ) {
145- const_substs. insert ( c, ty. syntax ( ) . clone ( ) ) ;
148+ const_substs. insert ( k, ty. syntax ( ) . clone ( ) ) ;
149+ }
150+ }
151+ ( Either :: Left ( k) , Some ( TypeOrConst :: Const ( v) ) ) => {
152+ if let Some ( expr) = v. expr ( ) {
153+ // FIXME: expressions in curly brackets can cause ambiguity after insertion
154+ // (e.g. `N * 2` -> `{1 + 1} * 2`; it's unclear whether `{1 + 1}`
155+ // is a standalone statement or a part of another expresson)
156+ // and sometimes require slight modifications; see
157+ // https://doc.rust-lang.org/reference/statements.html#expression-statements
158+ const_substs. insert ( k, expr. syntax ( ) . clone ( ) ) ;
146159 }
147160 }
148161 ( Either :: Left ( _) , None ) => ( ) , // FIXME: get default const value
162+ _ => ( ) , // ignore mismatching params
149163 } ) ;
150164 let lifetime_substs: FxHashMap < _ , _ > = self
151165 . generic_def
@@ -201,6 +215,9 @@ impl<'a> Ctx<'a> {
201215 fn transform_default_type_substs ( & self , default_types : Vec < hir:: TypeParam > ) {
202216 for k in default_types {
203217 let v = self . type_substs . get ( & k) . unwrap ( ) ;
218+ // `transform_path` may update a node's parent and that would break the
219+ // tree traversal. Thus all paths in the tree are collected into a vec
220+ // so that such operation is safe.
204221 let paths = postorder ( & v. syntax ( ) ) . filter_map ( ast:: Path :: cast) . collect :: < Vec < _ > > ( ) ;
205222 for path in paths {
206223 self . transform_path ( path) ;
@@ -326,8 +343,12 @@ fn get_type_args_from_arg_list(generic_arg_list: ast::GenericArgList) -> Option<
326343 // Const params are marked as consts on definition only,
327344 // being passed to the trait they are indistguishable from type params;
328345 // anyway, we don't really need to distinguish them here.
329- ast:: GenericArg :: TypeArg ( type_or_const_arg) => {
330- result. types_and_consts . push ( type_or_const_arg)
346+ ast:: GenericArg :: TypeArg ( type_arg) => {
347+ result. types_and_consts . push ( TypeOrConst :: Either ( type_arg) )
348+ }
349+ // Some const values are recognized correctly.
350+ ast:: GenericArg :: ConstArg ( const_arg) => {
351+ result. types_and_consts . push ( TypeOrConst :: Const ( const_arg) ) ;
331352 }
332353 ast:: GenericArg :: LifetimeArg ( l_arg) => result. lifetimes . push ( l_arg) ,
333354 _ => ( ) ,
0 commit comments