about summary refs log tree commit diff
path: root/src/test/ui/lint
AgeCommit message (Collapse)AuthorLines
2021-10-11Add enum_intrinsics_non_enums lintFlying-Toast-0/+162
2021-10-04Rollup merge of #89473 - FabianWolff:issue-89469, r=joshtriplettJubilee-0/+20
Fix extra `non_snake_case` warning for shorthand field bindings Fixes #89469. The problem is the innermost `if` condition here: https://github.com/rust-lang/rust/blob/d14731cb3ced8318d7fc83cbe838f0e7f2fb3b40/compiler/rustc_lint/src/nonstandard_style.rs#L435-L452 This code runs for every `PatKind::Binding`, so if a struct has multiple fields, say A and B, and both are bound in a pattern using shorthands, the call to `self.check_snake_case()` will indeed be skipped in the `check_pat()` call for `A`; but when `check_pat()` is called for `B`, the loop will still iterate over `A`, and `field.ident (= A) != ident (= B)` will be true. I have fixed this by only looking at non-shorthand bindings, and only the binding that `check_pat()` was actually called for.
2021-10-04Rollup merge of #89500 - FabianWolff:issue-87308, r=petrochenkovJubilee-0/+26
Fix ICE with buffered lint referring to AST node deleted by everybody_loops Fixes #87308. Note the following comment: https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_lint/src/early.rs#L415-L417 As it turns out, this is not _always_ a bug, because `-Zunpretty=everybody_loops` causes a lot of AST nodes to be deleted, and thus some buffered lints will refer to non-existent node ids. To fix this, my changes simply ignore buffered lints if `-Zunpretty=everybody_loops` is enabled, which, from my understanding, shouldn't be a big issue because it only affects pretty-printing. Of course, a more elegant solution would only ignore buffered lints that actually point at deleted node ids, but I haven't figured out an easy way of achieving this. For the concrete example in #87308, the buffered lint is created [here](https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_expand/src/mbe/macro_rules.rs#L145-L151) with the `lint_node_id` from [here](https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_expand/src/mbe/macro_rules.rs#L319), i.e. it points at the macro _expansion_, which then gets deleted by `ReplaceBodyWithLoop` [here](https://github.com/rust-lang/rust/blob/08759c691e2e9799a3c6780ffdf910240ebd4a6b/compiler/rustc_interface/src/passes.rs#L377).
2021-10-03Fix ICE with buffered lint referring to AST node deleted by everybody_loopsFabian Wolff-0/+26
2021-10-03Fix extra `non_snake_case` warning for shorthand field bindingsFabian Wolff-0/+20
2021-10-03Practice diagnostic message conventionHirochika Matsumoto-13/+13
2021-10-03Auto merge of #84267 - dtolnay:ptrunit, r=nagisabors-45/+60
Make *const (), *mut () okay for FFI Pointer-to-() is used occasionally in the standard library to mean "pointer to none-of-your-business". Examples: - `RawWakerVTable::new` https://doc.rust-lang.org/1.51.0/std/task/struct.RawWakerVTable.html#method.new - `<*const T>::to_raw_parts` https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.to_raw_parts I believe it's useful for the same purpose in FFI signatures, even while `()` itself is not FFI safe. The following should be allowed: ```rust extern "C" { fn demo(pc: *const (), pm: *mut ()); } ``` Prior to this PR, those pointers were not considered okay for an extern signature. ```console warning: `extern` block uses type `()`, which is not FFI-safe --> src/main.rs:2:17 | 2 | fn demo(pc: *const (), pm: *mut ()); | ^^^^^^^^^ not FFI-safe | = note: `#[warn(improper_ctypes)]` on by default = help: consider using a struct instead = note: tuples have unspecified layout warning: `extern` block uses type `()`, which is not FFI-safe --> src/main.rs:2:32 | 2 | fn demo(pc: *const (), pm: *mut ()); | ^^^^^^^ not FFI-safe | = help: consider using a struct instead = note: tuples have unspecified layout ```
2021-09-30Rollup merge of #89303 - guswynn:std_suspend, r=dtolnayManish Goregaokar-0/+38
Add `#[must_not_suspend]` to some types in std I am not sure what else should have it? `Ref`?
2021-09-30Auto merge of #89110 - Aaron1011:adjustment-span, r=estebankbors-1/+1
Use larger span for adjustment THIR expressions Currently, we use a relatively 'small' span for THIR expressions generated by an 'adjustment' (e.g. an autoderef, autoborrow, unsizing). As a result, if a borrow generated by an adustment ends up causing a borrowcheck error, for example: ```rust let mut my_var = String::new(); let my_ref = &my_var my_var.push('a'); my_ref; ``` then the span for the mutable borrow may end up referring to only the base expression (e.g. `my_var`), rather than the method call which triggered the mutable borrow (e.g. `my_var.push('a')`) Due to a quirk of the MIR borrowck implementation, this doesn't always get exposed in migration mode, but it does in many cases. This commit makes THIR building consistently use 'larger' spans for adjustment expressions. These spans are recoded when we first create the adjustment during typecheck. For example, an autoref adjustment triggered by a method call will record the span of the entire method call. The intent of this change it make it clearer to users when it's the specific way in which a variable is used (for example, in a method call) that produdes a borrowcheck error. For example, an error message claiming that a 'mutable borrow occurs here' might be confusing if it just points at a usage of a variable (e.g. `my_var`), when no `&mut` is in sight. Pointing at the entire expression should help to emphasize that the method call itself is responsible for the mutable borrow. In several cases, this makes the `#![feature(nll)]` diagnostic output match up exactly with the default (migration mode) output. As a result, several `.nll.stderr` files end up getting removed entirely.
2021-09-28ref/refmutGus Wynn-1/+1
2021-09-27Auto merge of #89214 - smoelius:register_tool, r=petrochenkovbors-0/+14
Pass real crate-level attributes to `pre_expansion_lint` The PR concerns the unstable feature `register_tool` (#66079). The feature's implementation requires the attributes of the crate being compiled, so that when attributes like `allow(foo::bar)` are encountered, it can be verified that `register_tool(foo)` appears in the crate root. However, the crate's attributes are not readily available during early lint passes. Specifically, on this line, `krate.attrs` appears to be the attributes of the current source file, not the attributes of the whole crate: https://github.com/rust-lang/rust/blob/bf642323d621dcefeef1d8ab4711aae36e357615/compiler/rustc_lint/src/context.rs#L815 Consequently, "unknown tool" errors were being produced when `allow(foo::bar)` appeared in a submodule, even though `register_tool(foo)` appeared in the crate root. EDITED: The proposed fix is to obtain the real crate-level attributes in `configure_and_expand` and pass them to `pre_expansion_lint`. (See `@petrochenkov's` [comment](https://github.com/rust-lang/rust/pull/89214#issuecomment-926927072) below.) The original "prosed fix" text follows. --- The proposed fix is to add an `error_on_unknown_tool` flag to `LintLevelsBuilder`. The flag controls whether "unknown tool" errors are emitted. The flag is set during late passes, but not earlier. More specifically, this PR contains two commits: * The first adds a `known-tool-in-submodule` UI test that does not currently pass. * The second adds the `error_on_unknown_tool` flag. The new test passes with the addition of this flag. This change has the added benefit of eliminating some errors that were duplicated in existing tests. To the reviewer: please check that I implemented the UI test correctly.
2021-09-27#[feature] not required for lint resultGus Wynn-5/+4
2021-09-27lock typesGus Wynn-0/+39
2021-09-26Auto merge of #88316 - est31:remove_box_tests, r=Mark-Simulacrumbors-6/+6
Remove most box syntax uses from the testsuite except for src/test/ui/issues Removes most box syntax uses from the testsuite outside of the src/test/ui/issues directory. The goal was to only change tests where box syntax is an implementation detail instead of the actual feature being tested. So some tests were left out, like the regression test for #87935, or tests where the obtained error message changed significantly. Mostly this replaces box syntax with `Box::new`, but there are some minor drive by improvements, like formatting improvements or `assert_eq` instead of `assert!( == )`. Prior PR that removed box syntax from the compiler and tools: #87781
2021-09-26Remove box syntax from most places in src/test outside of the issues direst31-6/+6
2021-09-25Move malformed attribute code to a function and fix inner attribute suggestion.Eric Huss-1/+1
Moving to a dedicated function in preparation for other validation. The suggestion given didn't consider if it was an inner attribute.
2021-09-25Use larger span for adjustments on method callsAaron Hill-1/+1
Currently, we use a relatively 'small' span for THIR expressions generated by an 'adjustment' (e.g. an autoderef, autoborrow, unsizing). As a result, if a borrow generated by an adustment ends up causing a borrowcheck error, for example: ```rust let mut my_var = String::new(); let my_ref = &my_var my_var.push('a'); my_ref; ``` then the span for the mutable borrow may end up referring to only the base expression (e.g. `my_var`), rather than the method call which triggered the mutable borrow (e.g. `my_var.push('a')`) Due to a quirk of the MIR borrowck implementation, this doesn't always get exposed in migration mode, but it does in many cases. This commit makes THIR building consistently use 'larger' spans for adjustment expressions The intent of this change it make it clearer to users when it's the specific way in which a variable is used (for example, in a method call) that produdes a borrowcheck error. For example, an error message claiming that a 'mutable borrow occurs here' might be confusing if it just points at a usage of a variable (e.g. `my_var`), when no `&mut` is in sight. Pointing at the entire expression should help to emphasize that the method call itself is responsible for the mutable borrow. In several cases, this makes the `#![feature(nll)]` diagnostic output match up exactly with the default (migration mode) output. As a result, several `.nll.stderr` files end up getting removed entirely.
2021-09-23Add known-tool-in-submodule testSamuel E. Moelius III-0/+14
The test currently fails. The next commit fixes it.
2021-09-22Rollup merge of #89133 - FabianWolff:issue-79546, r=michaelwoeristerthe8472-0/+8
Fix ICE with `--cap-lints=allow` and `-Zfuel=...=0` Fixes #79546.
2021-09-22Auto merge of #88865 - guswynn:must_not_suspend, r=oli-obkbors-0/+417
Implement `#[must_not_suspend]` implements #83310 Some notes on the impl: 1. The code that searches for the attribute on the ADT is basically copied from the `must_use` lint. It's not shared, as the logic did diverge 2. The RFC does specify that the attribute can be placed on fn's (and fn-like objects), like `must_use`. I think this is a direct copy from the `must_use` reference definition. This implementation does NOT support this, as I felt that ADT's (+ `impl Trait` + `dyn Trait`) cover the usecase's people actually want on the RFC, and adding an imp for the fn call case would be significantly harder. The `must_use` impl can do a single check at fn call stmt time, but `must_not_suspend` would need to answer the question: "for some value X with type T, find any fn call that COULD have produced this value". That would require significant changes to `generator_interior.rs`, and I would need mentorship on that. `@eholk` and I are discussing it. 3. `@estebank` do you know a way I can make the user-provided `reason` note pop out? right now it seems quite hidden Also, I am not sure if we should run perf on this r? `@nikomatsakis`
2021-09-21Fix ICE with `--cap-lints=allow` and `-Zfuel=...=0`Fabian Wolff-0/+8
2021-09-18deduplicationGus Wynn-59/+45
2021-09-18generic testGus Wynn-0/+52
2021-09-15factor into struct, and commentsGus Wynn-21/+49
2021-09-15Move some tests to more reasonable directoriesCaio-0/+69
2021-09-13error formatting and fix buildGus Wynn-26/+39
2021-09-11array comment + test for referencesGus Wynn-0/+71
2021-09-11skip the uninhabitated check and commentsGus Wynn-9/+27
2021-09-11must_not_suspend implGus Wynn-0/+249
2021-09-09Use more accurate spans for "unused delimiter" lintEsteban Kuber-74/+448
2021-09-06Auto merge of #88493 - chenyukang:fix-duplicated-diagnostic, r=estebankbors-31/+5
Fix #88256 remove duplicated diagnostics Fix #88256
2021-09-04Fix #88256, remove duplicated diagnosticyukang-31/+5
2021-08-31fix(rustc_lint): better detect when parens are necessaryMichael Howell-0/+94
Fixes #88519
2021-08-28Update testsinquisitivecrystal-4/+38
2021-08-24Update testsinquisitivecrystal-18/+14
This updates tests to reflect that `force-warn` is now stable.
2021-08-24Auto merge of #87739 - Aaron1011:remove-used-attrs, r=wesleywiserbors-179/+11
Remove `Session.used_attrs` and move logic to `CheckAttrVisitor` Instead of updating global state to mark attributes as used, we now explicitly emit a warning when an attribute is used in an unsupported position. As a side effect, we are to emit more detailed warning messages (instead of just a generic "unused" message). `Session.check_name` is removed, since its only purpose was to mark the attribute as used. All of the callers are modified to use `Attribute.has_name` Additionally, `AttributeType::AssumedUsed` is removed - an 'assumed used' attribute is implemented by simply not performing any checks in `CheckAttrVisitor` for a particular attribute. We no longer emit unused attribute warnings for the `#[rustc_dummy]` attribute - it's an internal attribute used for tests, so it doesn't mark sense to treat it as 'unused'. With this commit, a large source of global untracked state is removed.
2021-08-24Auto merge of #85556 - FabianWolff:issue-85071, r=estebank,jackh726bors-0/+109
Warn about unreachable code following an expression with an uninhabited type This pull request fixes #85071. The issue is that liveness analysis currently is "smarter" than reachability analysis when it comes to detecting uninhabited types: Unreachable code is detected during type checking, where full type information is not yet available. Therefore, the check for type inhabitedness is quite crude: https://github.com/rust-lang/rust/blob/fc81ad22c453776de16acf9938976930cf8c9401/compiler/rustc_typeck/src/check/expr.rs#L202-L205 i.e. it only checks for `!`, but not other, non-trivially uninhabited types, such as empty enums, structs containing an uninhabited type, etc. By contrast, liveness analysis, which runs after type checking, can benefit from the more sophisticated `tcx.is_ty_uninhabited_from()`: https://github.com/rust-lang/rust/blob/fc81ad22c453776de16acf9938976930cf8c9401/compiler/rustc_passes/src/liveness.rs#L981 https://github.com/rust-lang/rust/blob/fc81ad22c453776de16acf9938976930cf8c9401/compiler/rustc_passes/src/liveness.rs#L996 This can lead to confusing warnings when a variable is reported as unused, but the use of the variable is not reported as unreachable. For instance: ```rust enum Foo {} fn f() -> Foo {todo!()} fn main() { let x = f(); let _ = x; } ``` currently leads to ``` warning: unused variable: `x` --> t1.rs:5:9 | 5 | let x = f(); | ^ help: if this is intentional, prefix it with an underscore: `_x` | = note: `#[warn(unused_variables)]` on by default warning: 1 warning emitted ``` which is confusing, because `x` _appears_ to be used in line 6. With my changes, I get: ``` warning: unreachable expression --> t1.rs:6:13 | 5 | let x = f(); | --- any code following this expression is unreachable 6 | let _ = x; | ^ unreachable expression | = note: `#[warn(unreachable_code)]` on by default note: this expression has type `Foo`, which is uninhabited --> t1.rs:5:13 | 5 | let x = f(); | ^^^ warning: unused variable: `x` --> t1.rs:5:9 | 5 | let x = f(); | ^ help: if this is intentional, prefix it with an underscore: `_x` | = note: `#[warn(unused_variables)]` on by default warning: 2 warnings emitted ``` My implementation is slightly inelegant because unreachable code warnings can now be issued in two different places (during type checking and during liveness analysis), but I think it is the solution with the least amount of unnecessary code duplication, given that the new warning integrates nicely with liveness analysis, where unreachable code is already implicitly detected for the purpose of finding unused variables.
2021-08-22Fix more “a”/“an” typosFrank Steffahn-1/+1
2021-08-21Remove `Session.used_attrs` and move logic to `CheckAttrVisitor`Aaron Hill-179/+11
Instead of updating global state to mark attributes as used, we now explicitly emit a warning when an attribute is used in an unsupported position. As a side effect, we are to emit more detailed warning messages (instead of just a generic "unused" message). `Session.check_name` is removed, since its only purpose was to mark the attribute as used. All of the callers are modified to use `Attribute.has_name` Additionally, `AttributeType::AssumedUsed` is removed - an 'assumed used' attribute is implemented by simply not performing any checks in `CheckAttrVisitor` for a particular attribute. We no longer emit unused attribute warnings for the `#[rustc_dummy]` attribute - it's an internal attribute used for tests, so it doesn't mark sense to treat it as 'unused'. With this commit, a large source of global untracked state is removed.
2021-08-21Auto merge of #88134 - rylev:force-warn-improvements, r=nikomatsakisbors-11/+128
Force warn improvements As part of stablization of the `--force-warn` option (#86516) I've made the following changes: * Error when the `warnings` lint group is based to the `--force-warn` option * Tests have been updated to make it easier to understand the semantics of `--force-warn` r? `@nikomatsakis`
2021-08-18Rollup merge of #88036 - nbdd0121:const3, r=petrochenkovGuillaume Gomez-0/+45
Fix dead code warning when inline const is used in pattern Fixes #78171
2021-08-18Error when warnings lint group is used with force-warnRyan Levick-0/+14
2021-08-18Improve force-warn testsRyan Levick-11/+114
2021-08-16Auto merge of #84039 - jyn514:uplift-atomic-ordering, r=wesleywiserbors-0/+1346
Uplift the invalid_atomic_ordering lint from clippy to rustc This is mostly just a rebase of https://github.com/rust-lang/rust/pull/79654; I've copy/pasted the text from that PR below. r? `@lcnr` since you reviewed the last one, but feel free to reassign. --- This is an implementation of https://github.com/rust-lang/compiler-team/issues/390. As mentioned, in general this turns an unconditional runtime panic into a (compile time) lint failure. It has no false positives, and the only false negatives I'm aware of are if `Ordering` isn't specified directly and is comes from an argument/constant/whatever. As a result of it having no false positives, and the alternative always being strictly wrong, it's on as deny by default. This seems right. In the [zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Uplift.20the.20.60invalid_atomic_ordering.60.20lint.20from.20clippy/near/218483957) `@joshtriplett` suggested that lang team should FCP this before landing it. Perhaps libs team cares too? --- Some notes on the code for reviewers / others below ## Changes from clippy The code is changed from [the implementation in clippy](https://github.com/rust-lang/rust-clippy/blob/68cf94f6a66e47234e3adefc6dfbe806cd6ad164/clippy_lints/src/atomic_ordering.rs) in the following ways: 1. Uses `Symbols` and `rustc_diagnostic_item`s instead of string literals. - It's possible I should have just invoked Symbol::intern for some of these instead? Seems better to use symbol, but it did require adding several. 2. The functions are moved to static methods inside the lint struct, as a way to namespace them. - There's a lot of other code in that file — which I picked as the location for this lint because `@jyn514` told me that seemed reasonable. 3. Supports unstable AtomicU128/AtomicI128. - I did this because it was almost easier to support them than not — not supporting them would have (ideally) required finding a way not to give them a `rustc_diagnostic_item`, which would have complicated an already big macro. - These don't have tests since I wasn't sure if/how I should make tests conditional on whether or not the target has the atomic... This is to a certain extent an issue of 64bit atomics too, but 128-bit atomics are much less common. Regardless, the existing tests should be *more* than thorough enough here. 4. Minor changes like: - grammar tweaks ("loads cannot have `Release` **and** `AcqRel` ordering" => "loads cannot have `Release` **or** `AcqRel` ordering") - function renames (`match_ordering_def_path` => `matches_ordering_def_path`), - avoiding clippy-specific helper methods that don't exist in rustc_lint and didn't seem worth adding for this case (for example `cx.struct_span_lint` vs clippy's `span_lint_and_help` helper). ## Potential issues (This is just about the code in this PR, not conceptual issues with the lint or anything) 1. I'm not sure if I should have used a diagnostic item for `Ordering` and its variants (I couldn't figure out how really, so if I should do this some pointers would be appreciated). - It seems possible that failing to do this might possibly mean there are more cases this lint would miss, but I don't really know how `match_def_path` works and if it has any pitfalls like that, so maybe not. 2. I *think* I deprecated the lint in clippy (CC `@flip1995` who asked to be notified about clippy changes in the future in [this comment](https://github.com/rust-lang/rust/pull/75671#issuecomment-718731659)) but I'm not sure if I need to do anything else there. - I'm kind of hoping CI will catch if I missed anything, since `x.py test src/tools/clippy` fails with a lot of errors with and without my changes (and is probably a nonsense command regardless). Running `cargo test` from src/tools/clippy also fails with unrelated errors that seem like refactorings that didnt update clippy? So, honestly no clue. 3. I wasn't sure if the description/example I gave good. Hopefully it is. The example is less thorough than the one from clippy here: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering. Let me know if/how I should change it if it needs changing. 4. It pulls in the `if_chain` crate. This crate was already used in clippy, and seems like it's used elsewhere in rustc, but I'm willing to rewrite it to not use this if needed (I'd prefer not to, all things being equal).
2021-08-16Uplift the `invalid_atomic_ordering` lint from clippy to rustcThom Chiovoloni-0/+1346
- Deprecate clippy::invalid_atomic_ordering - Use rustc_diagnostic_item for the orderings in the invalid_atomic_ordering lint - Reduce code duplication - Give up on making enum variants diagnostic items and just look for `Ordering` instead I ran into tons of trouble with this because apparently the change to store HIR attrs in a side table also gave the DefIds of the constructor instead of the variant itself. So I had to change `matches_ordering` to also check the grandparent of the defid as well. - Rename `atomic_ordering_x` symbols to just the name of the variant - Fix typos in checks - there were a few places that said "may not be Release" in the diagnostic but actually checked for SeqCst in the lint. - Make constant items const - Use fewer diagnostic items - Only look at arguments after making sure the method matches This prevents an ICE when there aren't enough arguments. - Ignore trait methods - Only check Ctors instead of going through `qpath_res` The functions take values, so this couldn't ever be anything else. - Add if_chain to allowed dependencies - Fix grammar - Remove unnecessary allow
2021-08-15Add a dead code test for using anon const in patternGary Guo-0/+45
2021-08-13Auto merge of #86492 - hyd-dev:no-mangle-method, r=petrochenkovbors-16/+79
Associated functions that contain extern indicator or have `#[rustc_std_internal_symbol]` are reachable Previously these fails to link with ``undefined reference to `foo'``: <details> <summary>Example 1</summary> ```rs struct AssocFn; impl AssocFn { #[no_mangle] fn foo() {} } fn main() { extern "Rust" { fn foo(); } unsafe { foo() } } ``` ([Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=f1244afcdd26e2a28445f6e82ca46b50)) </details> <details> <summary>Example 2</summary> ```rs #![crate_name = "lib"] #![crate_type = "lib"] struct AssocFn; impl AssocFn { #[no_mangle] fn foo() {} } ``` ```rs extern crate lib; fn main() { extern "Rust" { fn foo(); } unsafe { foo() } } ``` </details> But I believe they should link successfully, because this works: <details> ```rs #[no_mangle] fn foo() {} fn main() { extern "Rust" { fn foo(); } unsafe { foo() } } ``` ([Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=789b3f283ee6126f53939429103ed98d)) </details> This PR fixes the problem, by adding associated functions that have "custom linkage" to `reachable_set`, just like normal functions. I haven't tested whether #76211 and [Miri](https://github.com/rust-lang/miri/issues/1837) are fixed by this PR yet, but I'm submitting this anyway since this fixes the examples above. I added a `run-pass` test that combines my two examples above, but I'm not sure if that's the right way to test this. Maybe I should add / modify an existing codegen test (`src/test/codegen/export-no-mangle.rs`?) instead?
2021-08-12Rollup merge of #87885 - m-ou-se:edition-guide-links, r=rylevGuillaume Gomez-10/+10
Link to edition guide instead of issues for 2021 lints. This changes the 2021 lints to not link to github issues, but to the edition guide instead. Fixes #86996
2021-08-12Adjust `#[no_mangle]`-related checks and lints for `impl` itemshyd-dev-16/+79
2021-08-11Modify structured suggestion outputEsteban Küber-44/+45
* On suggestions that include deletions, use a diff inspired output format * When suggesting addition, use `+` as underline * Color highlight modified span