@@ -139,10 +139,11 @@ use an error-level lint instead of a fixed error.
139139 flag. That said, don't make it so terse that it's hard to understand.
140140- The word "illegal" is illegal. Prefer "invalid" or a more specific word
141141 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.
146147- When emitting a message with span, try to reduce the span to the smallest
147148 amount possible that still signifies the issue
148149- Try not to emit multiple error messages for the same error. This may require
@@ -312,6 +313,15 @@ reporting errors.
312313
313314[ errors ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html
314315
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+
315325[ ` Session ` ] [ session ] and [ ` ParseSess ` ] [ parsesses ] have
316326methods (or fields with methods) that allow reporting errors. These methods
317327usually 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,
327337[ ` struct_span_err ` ] [ strspanerr ] instead returns a
328338[ ` DiagnosticBuilder ` ] [ diagbuild ] .
329339
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+
330346` DiagnosticBuilder ` allows you to add related notes and suggestions to an error
331347before emitting it by calling the [ ` emit ` ] [ emit ] method. (Failing to either
332348emit 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
340356
341357``` rust,ignore
342358// 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 );
344360
345361// In some cases, you might need to check if `sp` is generated by a macro to
346362// avoid printing weird errors about macro-generated code.
347363
348364if let Ok(snippet) = sess.source_map().span_to_snippet(sp) {
349365 // 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));
351367} else {
352368 // If we weren't able to generate a snippet, then emit a "help" message
353369 // instead of a concrete "suggestion". In practice this is unlikely to be
354370 // reached.
355- err.span_help(suggestion_sp, "you could use a qux here instead" );
371+ err.span_help(suggestion_sp, fluent::example::qux_suggestion );
356372}
357373
358374// emit the error
359375err.emit();
360376```
361377
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+ ```
367383
368384## Suggestions
369385
@@ -405,17 +421,17 @@ apply them)
405421For example, to make our ` qux ` suggestion machine-applicable, we would do:
406422
407423``` 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 );
409425
410426if let Ok(snippet) = sess.source_map().span_to_snippet(sp) {
411427 err.span_suggestion(
412428 suggestion_sp,
413- "try using a qux here" ,
429+ fluent::example::try_qux_suggestion ,
414430 format!("qux {}", snippet),
415431 Applicability::MachineApplicable,
416432 );
417433} else {
418- err.span_help(suggestion_sp, "you could use a qux here instead" );
434+ err.span_help(suggestion_sp, fluent::example::qux_suggestion );
419435}
420436
421437err.emit();
@@ -504,9 +520,9 @@ much faster to work on.
504520
505521Every lint is implemented via a ` struct ` that implements the ` LintPass ` ` trait `
506522(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
510526very similar way to compile errors.
511527
512528You also declare the metadata of a particular lint via the ` declare_lint! `
@@ -557,13 +573,12 @@ impl EarlyLintPass for WhileTrue {
557573 if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
558574 if let ast::LitKind::Bool(true) = lit.kind {
559575 if !lit.span.from_expansion() {
560- let msg = "denote infinite loops with `loop { ... }`";
561576 let condition_span = cx.sess.source_map().guess_head_span(e.span);
562577 cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
563- lint.build(msg )
578+ lint.build(fluent::example::use_loop )
564579 .span_suggestion_short(
565580 condition_span,
566- "use `loop`" ,
581+ fluent::example::suggestion ,
567582 "loop".to_owned(),
568583 Applicability::MachineApplicable,
569584 )
@@ -577,6 +592,11 @@ impl EarlyLintPass for WhileTrue {
577592}
578593```
579594
595+ ``` fluent
596+ example-use-loop = denote infinite loops with `loop {"{"} ... {"}"}`
597+ .suggestion = use `loop`
598+ ```
599+
580600### Edition-gated lints
581601
582602Sometimes we want to change the behavior of a lint in a new edition. To do this,
@@ -613,15 +633,15 @@ declare_lint! {
613633The use of the term ` future-incompatible ` within the compiler has a slightly
614634broader meaning than what rustc exposes to users of the compiler.
615635
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
617637written may not compile in the future. In general, future-incompatible code
618638exists 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
623643meaning 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
625645meaning in an upcoming * edition* . These are often called "edition lints" and can be
626646typically seen in the various "edition compatibility" lint groups (e.g., ` rust_2021_compatibility ` )
627647that are used to lint against code that will break if the user updates the crate's edition.
@@ -644,11 +664,11 @@ declare_lint! {
644664Notice the ` reason ` field which describes why the future incompatible change is happening.
645665This will change the diagnostic message the user receives as well as determine which
646666lint 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
648668parameters will no longer compile in Rust 2018 and beyond.
649669
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
652672an edition) or into the ` future_incompatibility ` lint group.
653673
654674[ 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.
659679
660680### Renaming or removing a lint
661681
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,
663683the lint must be registered for renaming or removal, which will trigger a warning if a user tries
664684to use the old lint name. To declare a rename/remove, add a line with
665685[ ` 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
695715user can turn on these lints with a ` !#[warn(nonstandard_style)] ` attribute in
696716the source code, or by passing ` -W nonstandard-style ` on the command line.
697717
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
701721` @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
703723(e.g., ` rust_2021_compatibility ` ) automatically generated for any lints signaling
704724future-incompatible code that will break in the specified edition.
705725
0 commit comments