@@ -139,10 +139,11 @@ use an error-level lint instead of a fixed error.
139
139
flag. That said, don't make it so terse that it's hard to understand.
140
140
- The word "illegal" is illegal. Prefer "invalid" or a more specific word
141
141
instead.
142
- - Errors should document the span of code where they occur – the
143
- [ ` rustc_errors::diagnostic_builder::DiagnosticBuilder ` ] [ diagbuild ] ` span_* `
144
- methods allow to easily do this. Also ` note ` other spans that have
145
- contributed to the error if the span isn't too large.
142
+ - Errors should document the span of code where they occur (use
143
+ [ ` rustc_errors::diagnostic_builder::DiagnosticBuilder ` ] [ diagbuild ] 's
144
+ ` span_* ` methods or a diagnostic struct's ` #[primary_span] ` to easily do
145
+ this). Also ` note ` other spans that have contributed to the error if the span
146
+ isn't too large.
146
147
- When emitting a message with span, try to reduce the span to the smallest
147
148
amount possible that still signifies the issue
148
149
- Try not to emit multiple error messages for the same error. This may require
@@ -312,6 +313,15 @@ reporting errors.
312
313
313
314
[ errors ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html
314
315
316
+ Diagnostics can be implemented as types which implement the ` SessionDiagnostic `
317
+ trait. This is preferred for new diagnostics as it enforces a separation
318
+ between diagnostic emitting logic and the main code paths. For less-complex
319
+ diagnostics, the ` SessionDiagnostic ` trait can be derived -- see [ Diagnostic
320
+ structs] [ diagnostic-structs ] . Within the trait implementation, the APIs
321
+ described below can be used as normal.
322
+
323
+ [ diagnostic-structs ] : ./diagnostics/diagnostic-structs.md
324
+
315
325
[ ` Session ` ] [ session ] and [ ` ParseSess ` ] [ parsesses ] have
316
326
methods (or fields with methods) that allow reporting errors. These methods
317
327
usually have names like ` span_err ` or ` struct_span_err ` or ` span_warn ` , etc...
@@ -327,6 +337,12 @@ directly and ones that allow finer control over what to emit. For example,
327
337
[ ` struct_span_err ` ] [ strspanerr ] instead returns a
328
338
[ ` DiagnosticBuilder ` ] [ diagbuild ] .
329
339
340
+ Most of these methods will accept strings, but it is recommended that typed
341
+ identifiers for translatable diagnostics be used for new diagnostics (see
342
+ [ Translation] [ translation ] ).
343
+
344
+ [ translation ] : ./diagnostics/translation.md
345
+
330
346
` DiagnosticBuilder ` allows you to add related notes and suggestions to an error
331
347
before emitting it by calling the [ ` emit ` ] [ emit ] method. (Failing to either
332
348
emit or [ cancel] [ cancel ] a ` DiagnosticBuilder ` will result in an ICE.) See the
@@ -340,30 +356,30 @@ emit or [cancel][cancel] a `DiagnosticBuilder` will result in an ICE.) See the
340
356
341
357
``` rust,ignore
342
358
// Get a DiagnosticBuilder. This does _not_ emit an error yet.
343
- let mut err = sess.struct_span_err(sp, "oh no! this is an error!" );
359
+ let mut err = sess.struct_span_err(sp, fluent::example::example_error );
344
360
345
361
// In some cases, you might need to check if `sp` is generated by a macro to
346
362
// avoid printing weird errors about macro-generated code.
347
363
348
364
if let Ok(snippet) = sess.source_map().span_to_snippet(sp) {
349
365
// Use the snippet to generate a suggested fix
350
- err.span_suggestion(suggestion_sp, "try using a qux here" , format!("qux {}", snippet));
366
+ err.span_suggestion(suggestion_sp, fluent::example::try_qux_suggestion , format!("qux {}", snippet));
351
367
} else {
352
368
// If we weren't able to generate a snippet, then emit a "help" message
353
369
// instead of a concrete "suggestion". In practice this is unlikely to be
354
370
// reached.
355
- err.span_help(suggestion_sp, "you could use a qux here instead" );
371
+ err.span_help(suggestion_sp, fluent::example::qux_suggestion );
356
372
}
357
373
358
374
// emit the error
359
375
err.emit();
360
376
```
361
377
362
- Alternatively, for less-complex diagnostics, the ` SessionDiagnostic ` derive
363
- macro can be used -- see [ Creating Errors With SessionDiagnostic ] [ sessiondiagnostic ] .
364
-
365
- [ sessiondiagnostic ] : ./diagnostics/sessiondiagnostic.md
366
-
378
+ ``` fluent
379
+ example-example-error = oh no! this is an error!
380
+ .try-qux-suggestion = try using a qux here
381
+ .qux-suggestion = you could use a qux here instead
382
+ ```
367
383
368
384
## Suggestions
369
385
@@ -405,17 +421,17 @@ apply them)
405
421
For example, to make our ` qux ` suggestion machine-applicable, we would do:
406
422
407
423
``` rust,ignore
408
- let mut err = sess.struct_span_err(sp, "oh no! this is an error!" );
424
+ let mut err = sess.struct_span_err(sp, fluent::example::message );
409
425
410
426
if let Ok(snippet) = sess.source_map().span_to_snippet(sp) {
411
427
err.span_suggestion(
412
428
suggestion_sp,
413
- "try using a qux here" ,
429
+ fluent::example::try_qux_suggestion ,
414
430
format!("qux {}", snippet),
415
431
Applicability::MachineApplicable,
416
432
);
417
433
} else {
418
- err.span_help(suggestion_sp, "you could use a qux here instead" );
434
+ err.span_help(suggestion_sp, fluent::example::qux_suggestion );
419
435
}
420
436
421
437
err.emit();
@@ -504,9 +520,9 @@ much faster to work on.
504
520
505
521
Every lint is implemented via a ` struct ` that implements the ` LintPass ` ` trait `
506
522
(you can also implement one of the more specific lint pass traits, either
507
- ` EarlyLintPass ` or ` LateLintPass ` depending on when is best for your lint to run).
508
- The trait implementation allows you to check certain syntactic constructs
509
- as the linter walks the AST. You can then choose to emit lints in a
523
+ ` EarlyLintPass ` or ` LateLintPass ` depending on when is best for your lint to run).
524
+ The trait implementation allows you to check certain syntactic constructs
525
+ as the linter walks the AST. You can then choose to emit lints in a
510
526
very similar way to compile errors.
511
527
512
528
You also declare the metadata of a particular lint via the ` declare_lint! `
@@ -557,13 +573,12 @@ impl EarlyLintPass for WhileTrue {
557
573
if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
558
574
if let ast::LitKind::Bool(true) = lit.kind {
559
575
if !lit.span.from_expansion() {
560
- let msg = "denote infinite loops with `loop { ... }`";
561
576
let condition_span = cx.sess.source_map().guess_head_span(e.span);
562
577
cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
563
- lint.build(msg )
578
+ lint.build(fluent::example::use_loop )
564
579
.span_suggestion_short(
565
580
condition_span,
566
- "use `loop`" ,
581
+ fluent::example::suggestion ,
567
582
"loop".to_owned(),
568
583
Applicability::MachineApplicable,
569
584
)
@@ -577,6 +592,11 @@ impl EarlyLintPass for WhileTrue {
577
592
}
578
593
```
579
594
595
+ ``` fluent
596
+ example-use-loop = denote infinite loops with `loop {"{"} ... {"}"}`
597
+ .suggestion = use `loop`
598
+ ```
599
+
580
600
### Edition-gated lints
581
601
582
602
Sometimes we want to change the behavior of a lint in a new edition. To do this,
@@ -613,15 +633,15 @@ declare_lint! {
613
633
The use of the term ` future-incompatible ` within the compiler has a slightly
614
634
broader meaning than what rustc exposes to users of the compiler.
615
635
616
- Inside rustc, future-incompatible lints are for signalling to the user that code they have
636
+ Inside rustc, future-incompatible lints are for signalling to the user that code they have
617
637
written may not compile in the future. In general, future-incompatible code
618
638
exists for two reasons:
619
- * the user has written unsound code that the compiler mistakenly accepted. While
620
- it is within Rust's backwards compatibility guarantees to fix the soundness hole
621
- (breaking the user's code), the lint is there to warn the user that this will happen
622
- in some upcoming version of rustc * regardless of which edition the code uses* . This is the
639
+ * the user has written unsound code that the compiler mistakenly accepted. While
640
+ it is within Rust's backwards compatibility guarantees to fix the soundness hole
641
+ (breaking the user's code), the lint is there to warn the user that this will happen
642
+ in some upcoming version of rustc * regardless of which edition the code uses* . This is the
623
643
meaning that rustc exclusively exposes to users as "future incompatible".
624
- * the user has written code that will either no longer compiler * or* will change
644
+ * the user has written code that will either no longer compiler * or* will change
625
645
meaning in an upcoming * edition* . These are often called "edition lints" and can be
626
646
typically seen in the various "edition compatibility" lint groups (e.g., ` rust_2021_compatibility ` )
627
647
that are used to lint against code that will break if the user updates the crate's edition.
@@ -644,11 +664,11 @@ declare_lint! {
644
664
Notice the ` reason ` field which describes why the future incompatible change is happening.
645
665
This will change the diagnostic message the user receives as well as determine which
646
666
lint groups the lint is added to. In the example above, the lint is an "edition lint"
647
- (since it's "reason" is ` EditionError ` ) signifying to the user that the use of anonymous
667
+ (since it's "reason" is ` EditionError ` ) signifying to the user that the use of anonymous
648
668
parameters will no longer compile in Rust 2018 and beyond.
649
669
650
- Inside [ LintStore::register_lints] [ fi-lint-groupings ] , lints with ` future_incompatible `
651
- fields get placed into either edition-based lint groups (if their ` reason ` is tied to
670
+ Inside [ LintStore::register_lints] [ fi-lint-groupings ] , lints with ` future_incompatible `
671
+ fields get placed into either edition-based lint groups (if their ` reason ` is tied to
652
672
an edition) or into the ` future_incompatibility ` lint group.
653
673
654
674
[ fi-lint-groupings ] : https://github.com/rust-lang/rust/blob/51fd129ac12d5bfeca7d216c47b0e337bf13e0c2/compiler/rustc_lint/src/context.rs#L212-L237
@@ -659,7 +679,7 @@ to support this.
659
679
660
680
### Renaming or removing a lint
661
681
662
- If it is determined that a lint is either improperly named or no longer needed,
682
+ If it is determined that a lint is either improperly named or no longer needed,
663
683
the lint must be registered for renaming or removal, which will trigger a warning if a user tries
664
684
to use the old lint name. To declare a rename/remove, add a line with
665
685
[ ` store.register_renamed ` ] or [ ` store.register_removed ` ] to the code of the
@@ -695,11 +715,11 @@ This defines the `nonstandard_style` group which turns on the listed lints. A
695
715
user can turn on these lints with a ` !#[warn(nonstandard_style)] ` attribute in
696
716
the source code, or by passing ` -W nonstandard-style ` on the command line.
697
717
698
- Some lint groups are created automatically in ` LintStore::register_lints ` . For instance,
699
- any lint declared with ` FutureIncompatibleInfo ` where the reason is
700
- ` FutureIncompatibilityReason::FutureReleaseError ` (the default when
718
+ Some lint groups are created automatically in ` LintStore::register_lints ` . For instance,
719
+ any lint declared with ` FutureIncompatibleInfo ` where the reason is
720
+ ` FutureIncompatibilityReason::FutureReleaseError ` (the default when
701
721
` @future_incompatible ` is used in ` declare_lint! ` ), will be added to
702
- the ` future_incompatible ` lint group. Editions also have their own lint groups
722
+ the ` future_incompatible ` lint group. Editions also have their own lint groups
703
723
(e.g., ` rust_2021_compatibility ` ) automatically generated for any lints signaling
704
724
future-incompatible code that will break in the specified edition.
705
725
0 commit comments