@@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
131
131
parse_error ( tcx, item. span ,
132
132
"this attribute must have a valid value" ,
133
133
"expected value here" ,
134
- Some ( r#"eg `#[rustc_on_unimplemented = "foo"]`"# ) ) ;
134
+ Some ( r#"eg `#[rustc_on_unimplemented(message= "foo") ]`"# ) ) ;
135
135
}
136
136
137
137
if errored {
@@ -170,7 +170,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
170
170
return Err ( parse_error ( tcx, attr. span ,
171
171
"`#[rustc_on_unimplemented]` requires a value" ,
172
172
"value required here" ,
173
- Some ( r#"eg `#[rustc_on_unimplemented = "foo"]`"# ) ) ) ;
173
+ Some ( r#"eg `#[rustc_on_unimplemented(message= "foo") ]`"# ) ) ) ;
174
174
} ;
175
175
debug ! ( "of_item({:?}/{:?}) = {:?}" , trait_def_id, impl_def_id, result) ;
176
176
result
@@ -213,10 +213,13 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
213
213
}
214
214
}
215
215
216
+ let options: FxHashMap < String , String > = options. into_iter ( )
217
+ . filter_map ( |( k, v) | v. as_ref ( ) . map ( |v| ( k. to_owned ( ) , v. to_owned ( ) ) ) )
218
+ . collect ( ) ;
216
219
OnUnimplementedNote {
217
- label : label. map ( |l| l. format ( tcx, trait_ref) ) ,
218
- message : message. map ( |m| m. format ( tcx, trait_ref) ) ,
219
- note : note. map ( |n| n. format ( tcx, trait_ref) ) ,
220
+ label : label. map ( |l| l. format ( tcx, trait_ref, & options ) ) ,
221
+ message : message. map ( |m| m. format ( tcx, trait_ref, & options ) ) ,
222
+ note : note. map ( |n| n. format ( tcx, trait_ref, & options ) ) ,
220
223
}
221
224
}
222
225
}
@@ -251,24 +254,25 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
251
254
Position :: ArgumentNamed ( s) if s == "Self" => ( ) ,
252
255
// `{ThisTraitsName}` is allowed
253
256
Position :: ArgumentNamed ( s) if s == name => ( ) ,
257
+ // `{from_method}` is allowed
258
+ Position :: ArgumentNamed ( s) if s == "from_method" => ( ) ,
259
+ // `{from_desugaring}` is allowed
260
+ Position :: ArgumentNamed ( s) if s == "from_desugaring" => ( ) ,
254
261
// So is `{A}` if A is a type parameter
255
262
Position :: ArgumentNamed ( s) => match generics. params . iter ( ) . find ( |param| {
256
263
param. name == s
257
264
} ) {
258
265
Some ( _) => ( ) ,
259
266
None => {
260
267
span_err ! ( tcx. sess, span, E0230 ,
261
- "there is no parameter \
262
- {} on trait {}",
263
- s, name) ;
268
+ "there is no parameter `{}` on trait `{}`" , s, name) ;
264
269
result = Err ( ErrorReported ) ;
265
270
}
266
271
} ,
267
272
// `{:1}` and `{}` are not to be used
268
273
Position :: ArgumentIs ( _) | Position :: ArgumentImplicitlyIs ( _) => {
269
274
span_err ! ( tcx. sess, span, E0231 ,
270
- "only named substitution \
271
- parameters are allowed") ;
275
+ "only named substitution parameters are allowed" ) ;
272
276
result = Err ( ErrorReported ) ;
273
277
}
274
278
}
@@ -280,7 +284,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
280
284
281
285
pub fn format ( & self ,
282
286
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
283
- trait_ref : ty:: TraitRef < ' tcx > )
287
+ trait_ref : ty:: TraitRef < ' tcx > ,
288
+ options : & FxHashMap < String , String > )
284
289
-> String
285
290
{
286
291
let name = tcx. item_name ( trait_ref. def_id ) ;
@@ -296,6 +301,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
296
301
let name = param. name . to_string ( ) ;
297
302
Some ( ( name, value) )
298
303
} ) . collect :: < FxHashMap < String , String > > ( ) ;
304
+ let empty_string = String :: new ( ) ;
299
305
300
306
let parser = Parser :: new ( & self . 0 , None ) ;
301
307
parser. map ( |p| {
@@ -308,14 +314,20 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
308
314
& trait_str
309
315
}
310
316
None => {
311
- bug ! ( "broken on_unimplemented {:?} for {:?}: \
312
- no argument matching {:?}",
313
- self . 0 , trait_ref, s)
317
+ if let Some ( val) = options. get ( s) {
318
+ val
319
+ } else if s == "from_desugaring" || s == "from_method" {
320
+ // don't break messages using these two arguments incorrectly
321
+ & empty_string
322
+ } else {
323
+ bug ! ( "broken on_unimplemented {:?} for {:?}: \
324
+ no argument matching {:?}",
325
+ self . 0 , trait_ref, s)
326
+ }
314
327
}
315
328
} ,
316
329
_ => {
317
- bug ! ( "broken on_unimplemented {:?} - bad \
318
- format arg", self . 0 )
330
+ bug ! ( "broken on_unimplemented {:?} - bad format arg" , self . 0 )
319
331
}
320
332
}
321
333
}
0 commit comments