@@ -321,7 +321,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
321
321
}
322
322
323
323
#[derive(Clone, Debug)]
324
- pub struct OnUnimplementedFormatString(Symbol);
324
+ pub struct OnUnimplementedFormatString(Symbol, Span );
325
325
326
326
#[derive(Debug)]
327
327
pub struct OnUnimplementedDirective {
@@ -350,7 +350,7 @@ pub struct OnUnimplementedNote {
350
350
pub enum AppendConstMessage {
351
351
#[default]
352
352
Default,
353
- Custom(Symbol),
353
+ Custom(Symbol, Span ),
354
354
}
355
355
356
356
#[derive(LintDiagnostic)]
@@ -372,6 +372,35 @@ impl MalformedOnUnimplementedAttrLint {
372
372
#[help]
373
373
pub struct MissingOptionsForOnUnimplementedAttr;
374
374
375
+ #[derive(LintDiagnostic)]
376
+ #[diag(trait_selection_ignored_diagnostic_option)]
377
+ pub struct IgnoredDiagnosticOption {
378
+ pub option_name: &'static str,
379
+ #[label]
380
+ pub span: Span,
381
+ #[label(trait_selection_other_label)]
382
+ pub prev_span: Span,
383
+ }
384
+
385
+ impl IgnoredDiagnosticOption {
386
+ fn maybe_emit_warning<'tcx>(
387
+ tcx: TyCtxt<'tcx>,
388
+ item_def_id: DefId,
389
+ new: Option<Span>,
390
+ old: Option<Span>,
391
+ option_name: &'static str,
392
+ ) {
393
+ if let (Some(new_item), Some(old_item)) = (new, old) {
394
+ tcx.emit_spanned_lint(
395
+ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
396
+ tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local()),
397
+ new_item,
398
+ IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
399
+ );
400
+ }
401
+ }
402
+ }
403
+
375
404
impl<'tcx> OnUnimplementedDirective {
376
405
fn parse(
377
406
tcx: TyCtxt<'tcx>,
@@ -384,8 +413,9 @@ impl<'tcx> OnUnimplementedDirective {
384
413
let mut errored = None;
385
414
let mut item_iter = items.iter();
386
415
387
- let parse_value = |value_str| {
388
- OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span).map(Some)
416
+ let parse_value = |value_str, value_span| {
417
+ OnUnimplementedFormatString::try_parse(tcx, item_def_id, value_str, span, value_span)
418
+ .map(Some)
389
419
};
390
420
391
421
let condition = if is_root {
@@ -398,7 +428,7 @@ impl<'tcx> OnUnimplementedDirective {
398
428
.ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
399
429
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
400
430
if let Some(value) = cfg.value
401
- && let Err(guar) = parse_value(value)
431
+ && let Err(guar) = parse_value(value, cfg.span )
402
432
{
403
433
errored = Some(guar);
404
434
}
@@ -417,17 +447,17 @@ impl<'tcx> OnUnimplementedDirective {
417
447
for item in item_iter {
418
448
if item.has_name(sym::message) && message.is_none() {
419
449
if let Some(message_) = item.value_str() {
420
- message = parse_value(message_)?;
450
+ message = parse_value(message_, item.span() )?;
421
451
continue;
422
452
}
423
453
} else if item.has_name(sym::label) && label.is_none() {
424
454
if let Some(label_) = item.value_str() {
425
- label = parse_value(label_)?;
455
+ label = parse_value(label_, item.span() )?;
426
456
continue;
427
457
}
428
458
} else if item.has_name(sym::note) {
429
459
if let Some(note_) = item.value_str() {
430
- if let Some(note) = parse_value(note_)? {
460
+ if let Some(note) = parse_value(note_, item.span() )? {
431
461
notes.push(note);
432
462
continue;
433
463
}
@@ -437,7 +467,7 @@ impl<'tcx> OnUnimplementedDirective {
437
467
&& !is_diagnostic_namespace_variant
438
468
{
439
469
if let Some(parent_label_) = item.value_str() {
440
- parent_label = parse_value(parent_label_)?;
470
+ parent_label = parse_value(parent_label_, item.span() )?;
441
471
continue;
442
472
}
443
473
} else if item.has_name(sym::on)
@@ -470,7 +500,7 @@ impl<'tcx> OnUnimplementedDirective {
470
500
&& !is_diagnostic_namespace_variant
471
501
{
472
502
if let Some(msg) = item.value_str() {
473
- append_const_msg = Some(AppendConstMessage::Custom(msg));
503
+ append_const_msg = Some(AppendConstMessage::Custom(msg, item.span() ));
474
504
continue;
475
505
} else if item.is_word() {
476
506
append_const_msg = Some(AppendConstMessage::Default);
@@ -519,6 +549,54 @@ impl<'tcx> OnUnimplementedDirective {
519
549
subcommands.extend(directive.subcommands);
520
550
let mut notes = aggr.notes;
521
551
notes.extend(directive.notes);
552
+ IgnoredDiagnosticOption::maybe_emit_warning(
553
+ tcx,
554
+ item_def_id,
555
+ directive.message.as_ref().map(|f| f.1),
556
+ aggr.message.as_ref().map(|f| f.1),
557
+ "message",
558
+ );
559
+ IgnoredDiagnosticOption::maybe_emit_warning(
560
+ tcx,
561
+ item_def_id,
562
+ directive.label.as_ref().map(|f| f.1),
563
+ aggr.label.as_ref().map(|f| f.1),
564
+ "label",
565
+ );
566
+ IgnoredDiagnosticOption::maybe_emit_warning(
567
+ tcx,
568
+ item_def_id,
569
+ directive.condition.as_ref().map(|i| i.span),
570
+ aggr.condition.as_ref().map(|i| i.span),
571
+ "condition",
572
+ );
573
+ IgnoredDiagnosticOption::maybe_emit_warning(
574
+ tcx,
575
+ item_def_id,
576
+ directive.parent_label.as_ref().map(|f| f.1),
577
+ aggr.parent_label.as_ref().map(|f| f.1),
578
+ "parent_label",
579
+ );
580
+ IgnoredDiagnosticOption::maybe_emit_warning(
581
+ tcx,
582
+ item_def_id,
583
+ directive.append_const_msg.as_ref().and_then(|c| {
584
+ if let AppendConstMessage::Custom(_, s) = c {
585
+ Some(*s)
586
+ } else {
587
+ None
588
+ }
589
+ }),
590
+ aggr.append_const_msg.as_ref().and_then(|c| {
591
+ if let AppendConstMessage::Custom(_, s) = c {
592
+ Some(*s)
593
+ } else {
594
+ None
595
+ }
596
+ }),
597
+ "append_const_msg",
598
+ );
599
+
522
600
Ok(Some(Self {
523
601
condition: aggr.condition.or(directive.condition),
524
602
subcommands,
@@ -556,6 +634,7 @@ impl<'tcx> OnUnimplementedDirective {
556
634
item_def_id,
557
635
value,
558
636
attr.span,
637
+ attr.span,
559
638
)?),
560
639
notes: Vec::new(),
561
640
parent_label: None,
@@ -633,7 +712,11 @@ impl<'tcx> OnUnimplementedDirective {
633
712
// `with_no_visible_paths` is also used when generating the options,
634
713
// so we need to match it here.
635
714
ty::print::with_no_visible_paths!(
636
- OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
715
+ OnUnimplementedFormatString(v, cfg.span).format(
716
+ tcx,
717
+ trait_ref,
718
+ &options_map
719
+ )
637
720
)
638
721
});
639
722
@@ -678,8 +761,9 @@ impl<'tcx> OnUnimplementedFormatString {
678
761
item_def_id: DefId,
679
762
from: Symbol,
680
763
err_sp: Span,
764
+ value_span: Span,
681
765
) -> Result<Self, ErrorGuaranteed> {
682
- let result = OnUnimplementedFormatString(from);
766
+ let result = OnUnimplementedFormatString(from, value_span );
683
767
result.verify(tcx, item_def_id, err_sp)?;
684
768
Ok(result)
685
769
}
0 commit comments