unsafe {
let _b = (*a)[3];
}
}
```
We want to ensure this shows "index out of bounds", but we cannot use the `ERROR`
annotation since the runtime error doesn't have any span. Then it's time to use the
`error-pattern` directive:
```rust,ignore
//@ error-pattern: index out of bounds
fn main() {
let a: *const [_] = &[1, 2, 3];
unsafe {
let _b = (*a)[3];
}
}
```
Use of `error-pattern` is not recommended in general.
For strict testing of compile time output, try to use the line annotations `//~` as much as
possible, including `//~?` annotations for diagnostics without spans.
If the compile time output is target dependent or too verbose, use directive
`//@ dont-require-annotations: <diagnostic-kind>` to make the line annotation checking
non-exhaustive.
Some of the compiler messages can stay uncovered by annotations in this mode.
For checking runtime output, `//@ check-run-results` may be preferable.
Only use `error-pattern` if none of the above works.
Line annotations `//~` and `error-pattern` are compatible and can be used in the same test.
### Diagnostic kinds (error levels)
The diagnostic kinds that you can have are:
- `ERROR`
- `WARN` (or `WARNING`)
- `NOTE`
- `HELP`
- `SUGGESTION`
- `RAW`
The `SUGGESTION` kind is used for specifying what the expected replacement text
should be for a diagnostic suggestion.
The `RAW` kind can be used for matching on lines from non-structured output sometimes emitted
by the compiler instead of or in addition to structured json.
`ERROR` and `WARN` kinds are required to be exhaustively covered by line annotations
`//~` by default.
Other kinds only need to be line-annotated if at least one annotation of that kind appears
in the test file. For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file
to be written out explicitly.
Use directive `//@ dont-require-annotations` to opt out of exhaustive annotations.
E.g. use `//@ dont-require-annotations: NOTE` to annotate notes selectively.
Avoid using this directive for `ERROR`s and `WARN`ings, unless there's a serious reason, like
target-dependent compiler output.
Some diagnostics are never required to be line-annotated, regardless of their kind or directives,
for example secondary lines of multiline diagnostics,
or ubiquitous diagnostics like `aborting due to N previous errors`.
UI tests use the `-A unused` flag by default to ignore all unused warnings, as
unused warnings are usually not the focus of a test. However, simple code
samples often have unused warnings. If the test is specifically testing an
unused warning, just add the appropriate `#![warn(unused)]` attribute as needed.
### `cfg` revisions
When using [revisions](compiletest.md#revisions), different messages can be
conditionally checked based on the current revision. This is done by placing the
revision cfg name in brackets like this:
```rust,ignore
//@ edition:2018
//@ revisions: mir thir
//@[thir] compile-flags: -Z thir-unsafeck
async unsafe fn f() {}
async fn g() {
f(); //~ ERROR call to unsafe function is unsafe
}
fn main() {
f(); //[mir]~ ERROR call to unsafe function is unsafe
}
```
In this example, the second error message is only emitted in the `mir` revision.
The `thir` revision only emits the first error.
If the `cfg` causes the compiler to emit different output, then a test can have
multiple `.stderr` files for the different outputs. In the example above, there
would be a `.mir.stderr` and `.thir.stderr` file with the different outputs of
the different revisions.
> Note: cfg revisions also work inside the source code with `#[cfg]` attributes.
>
> By convention, the `FALSE` cfg is used to have an always-false config.
## Controlling pass/fail expectations
By default, a UI test is expected to **generate a compile error** because most
of the tests are checking for invalid input and error diagnostics. However, you
can also make UI tests where compilation is expected to succeed, and you can
even run the resulting program. Just add one of the following