@@ -39,6 +39,7 @@ pub(super) fn mangle<'tcx>(
39
39
consts : FxHashMap :: default ( ) ,
40
40
binders : vec ! [ ] ,
41
41
out : String :: from ( prefix) ,
42
+ wrapper_level : GrammarFeatureLevel :: BASE_LINE ,
42
43
} ;
43
44
44
45
// Append `::{shim:...#0}` to shims that can coexist with a non-shim instance.
@@ -79,11 +80,13 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
79
80
consts : FxHashMap :: default ( ) ,
80
81
binders : vec ! [ ] ,
81
82
out : String :: new ( ) ,
83
+ wrapper_level : GrammarFeatureLevel :: BASE_LINE ,
82
84
} ;
83
85
cx. print_def_path ( trait_ref. def_id ( ) , & [ ] ) . unwrap ( ) ;
84
86
std:: mem:: take ( & mut cx. out )
85
87
}
86
88
89
+ #[ derive( Clone ) ]
87
90
struct BinderLevel {
88
91
/// The range of distances from the root of what's
89
92
/// being printed, to the lifetimes in a binder.
@@ -98,6 +101,15 @@ struct BinderLevel {
98
101
lifetime_depths : Range < u32 > ,
99
102
}
100
103
104
+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
105
+ struct GrammarFeatureLevel ( usize ) ;
106
+
107
+ impl GrammarFeatureLevel {
108
+ const BASE_LINE : GrammarFeatureLevel = GrammarFeatureLevel ( 0 ) ;
109
+ const COMPLEX_CONST_GENERICS : GrammarFeatureLevel = GrammarFeatureLevel ( 1 ) ;
110
+ }
111
+
112
+ #[ derive( Clone ) ]
101
113
struct SymbolMangler < ' tcx > {
102
114
tcx : TyCtxt < ' tcx > ,
103
115
binders : Vec < BinderLevel > ,
@@ -109,6 +121,8 @@ struct SymbolMangler<'tcx> {
109
121
paths : FxHashMap < ( DefId , & ' tcx [ GenericArg < ' tcx > ] ) , usize > ,
110
122
types : FxHashMap < Ty < ' tcx > , usize > ,
111
123
consts : FxHashMap < ty:: Const < ' tcx > , usize > ,
124
+
125
+ wrapper_level : GrammarFeatureLevel ,
112
126
}
113
127
114
128
impl < ' tcx > SymbolMangler < ' tcx > {
@@ -192,6 +206,75 @@ impl<'tcx> SymbolMangler<'tcx> {
192
206
193
207
Ok ( ( ) )
194
208
}
209
+
210
+ fn required_feature_level_for_const ( & self , ct : ty:: Const < ' tcx > ) -> GrammarFeatureLevel {
211
+ let ct = ct. normalize ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
212
+ match ct. kind ( ) {
213
+ ty:: ConstKind :: Value ( _) => { }
214
+
215
+ ty:: ConstKind :: Unevaluated ( _)
216
+ | ty:: ConstKind :: Expr ( _)
217
+ | ty:: ConstKind :: Param ( _)
218
+ | ty:: ConstKind :: Infer ( _)
219
+ | ty:: ConstKind :: Bound ( ..)
220
+ | ty:: ConstKind :: Placeholder ( _)
221
+ | ty:: ConstKind :: Error ( _) => {
222
+ return GrammarFeatureLevel :: BASE_LINE ;
223
+ }
224
+ }
225
+
226
+ let ty = ct. ty ( ) ;
227
+
228
+ match ty. kind ( ) {
229
+ ty:: Uint ( _) | ty:: Int ( _) | ty:: Bool | ty:: Char => GrammarFeatureLevel :: BASE_LINE ,
230
+ _ => GrammarFeatureLevel :: COMPLEX_CONST_GENERICS ,
231
+ }
232
+ }
233
+
234
+ fn wrapped (
235
+ & mut self ,
236
+ level : GrammarFeatureLevel ,
237
+ f : & mut dyn FnMut ( & mut Self ) -> Result < ( ) , PrintError > ,
238
+ ) -> Result < ( ) , PrintError > {
239
+ if self . wrapper_level >= level {
240
+ return f ( self ) ;
241
+ }
242
+
243
+ self . out . push ( 'C' ) ;
244
+ let backup = self . clone ( ) ;
245
+
246
+ let mut digit_count = 2 ;
247
+
248
+ for _iteration in 0 ..10 {
249
+ self . wrapper_level = level;
250
+ let digit_range = self . out . len ( ) ..self . out . len ( ) + digit_count;
251
+ for _ in 0 ..digit_count {
252
+ self . out . push ( '#' ) ;
253
+ }
254
+
255
+ self . out . push ( '_' ) ;
256
+
257
+ let start = self . out . len ( ) ;
258
+
259
+ f ( self ) ?;
260
+
261
+ let end = self . out . len ( ) ;
262
+ let fragment_length = format ! ( "{}" , end - start) ;
263
+
264
+ // FIXME: Add check if any back references to interior were made. If
265
+ // not, we can just shift everything without remangling.
266
+ if fragment_length. len ( ) == digit_count {
267
+ self . out . replace_range ( digit_range, & fragment_length) ;
268
+ self . wrapper_level = backup. wrapper_level ;
269
+ return Ok ( ( ) ) ;
270
+ }
271
+
272
+ * self = backup. clone ( ) ;
273
+ digit_count = fragment_length. len ( ) ;
274
+ }
275
+
276
+ Err ( PrintError :: default ( ) )
277
+ }
195
278
}
196
279
197
280
impl < ' tcx > Printer < ' tcx > for SymbolMangler < ' tcx > {
@@ -813,8 +896,12 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
813
896
ty. print ( self ) ?;
814
897
}
815
898
GenericArgKind :: Const ( c) => {
816
- self . push ( "K" ) ;
817
- c. print ( self ) ?;
899
+ let required_feature_level = self . required_feature_level_for_const ( c) ;
900
+
901
+ self . wrapped ( required_feature_level, & mut |this| {
902
+ this. push ( "K" ) ;
903
+ c. print ( this)
904
+ } ) ?;
818
905
}
819
906
}
820
907
}
0 commit comments