Auto merge of #110994 - matthiaskrgr:rollup-wv4u5yi, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #105848 (rustdoc: Add a new lint for broken inline code)
 - #110644 (Update tests for libtest `--format json`)
 - #110950 (Deny the `unsafe_op_in_unsafe_fn` lint in `rustc_arena`.)
 - #110951 (Add support for LibreSSL 3.7.x)
 - #110964 (rustdoc: fix weird margins between Deref impl items)
 - #110979 (windows: kill rust-analyzer-proc-macro-srv before deleting stage0 directory)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-04-29 16:17:35 +00:00
commit eb62877597
30 changed files with 1954 additions and 40 deletions

View File

@ -2370,9 +2370,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.84"
version = "0.9.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa"
checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [
"cc",
"libc",

View File

@ -20,6 +20,7 @@
#![feature(rustc_attrs)]
#![cfg_attr(test, feature(test))]
#![feature(strict_provenance)]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine.
@ -74,19 +75,27 @@ impl<T> ArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
ArenaChunk {
storage: NonNull::new_unchecked(Box::into_raw(Box::new_uninit_slice(capacity))),
storage: NonNull::from(Box::leak(Box::new_uninit_slice(capacity))),
entries: 0,
}
}
/// Destroys this arena chunk.
///
/// # Safety
///
/// The caller must ensure that `len` elements of this chunk have been initialized.
#[inline]
unsafe fn destroy(&mut self, len: usize) {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
// Without the branch, dropping TypedArena<T> takes linear time.
if mem::needs_drop::<T>() {
let slice = self.storage.as_mut();
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
// SAFETY: The caller must ensure that `len` elements of this chunk have
// been initialized.
unsafe {
let slice = self.storage.as_mut();
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
}
}
}
@ -255,7 +264,9 @@ impl<T> TypedArena<T> {
self.ensure_capacity(len);
let start_ptr = self.ptr.get();
self.ptr.set(start_ptr.add(len));
// SAFETY: `self.ensure_capacity` makes sure that there is enough space
// for `len` elements.
unsafe { self.ptr.set(start_ptr.add(len)) };
start_ptr
}
@ -483,6 +494,10 @@ impl DroplessArena {
}
}
/// # Safety
///
/// The caller must ensure that `mem` is valid for writes up to
/// `size_of::<T>() * len`.
#[inline]
unsafe fn write_from_iter<T, I: Iterator<Item = T>>(
&self,
@ -494,13 +509,18 @@ impl DroplessArena {
// Use a manual loop since LLVM manages to optimize it better for
// slice iterators
loop {
let value = iter.next();
if i >= len || value.is_none() {
// We only return as many items as the iterator gave us, even
// though it was supposed to give us `len`
return slice::from_raw_parts_mut(mem, i);
// SAFETY: The caller must ensure that `mem` is valid for writes up to
// `size_of::<T>() * len`.
unsafe {
match iter.next() {
Some(value) if i < len => mem.add(i).write(value),
Some(_) | None => {
// We only return as many items as the iterator gave us, even
// though it was supposed to give us `len`
return slice::from_raw_parts_mut(mem, i);
}
}
}
ptr::write(mem.add(i), value.unwrap());
i += 1;
}
}

View File

@ -19,7 +19,10 @@ try:
except ImportError:
lzma = None
if sys.platform == 'win32':
def platform_is_win32():
return sys.platform == 'win32'
if platform_is_win32():
EXE_SUFFIX = ".exe"
else:
EXE_SUFFIX = ""
@ -78,7 +81,6 @@ def _download(path, url, probably_big, verbose, exception):
if probably_big or verbose:
print("downloading {}".format(url))
platform_is_win32 = sys.platform == 'win32'
try:
if probably_big or verbose:
option = "-#"
@ -86,7 +88,7 @@ def _download(path, url, probably_big, verbose, exception):
option = "-s"
# If curl is not present on Win32, we should not sys.exit
# but raise `CalledProcessError` or `OSError` instead
require(["curl", "--version"], exception=platform_is_win32)
require(["curl", "--version"], exception=platform_is_win32())
with open(path, "wb") as outfile:
run(["curl", option,
"-L", # Follow redirect.
@ -99,8 +101,8 @@ def _download(path, url, probably_big, verbose, exception):
)
except (subprocess.CalledProcessError, OSError, RuntimeError):
# see http://serverfault.com/questions/301128/how-to-download
if platform_is_win32:
run(["PowerShell.exe", "/nologo", "-Command",
if platform_is_win32():
run_powershell([
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
verbose=verbose,
@ -174,6 +176,10 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
else:
sys.exit(err)
def run_powershell(script, *args, **kwargs):
"""Run a powershell script"""
run(["PowerShell.exe", "/nologo", "-Command"] + script, *args, **kwargs)
def require(cmd, exit=True, exception=False):
'''Run a command, returning its output.
@ -229,7 +235,7 @@ def default_build_triple(verbose):
print("pre-installed rustc not detected: {}".format(e))
print("falling back to auto-detect")
required = sys.platform != 'win32'
required = not platform_is_win32()
ostype = require(["uname", "-s"], exit=required)
cputype = require(['uname', '-m'], exit=required)
@ -434,6 +440,23 @@ class RustBuild(object):
(not os.path.exists(self.rustc()) or
self.program_out_of_date(self.rustc_stamp(), key)):
if os.path.exists(bin_root):
# HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's
# running. Kill it.
if platform_is_win32():
print("Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain")
regex = '{}\\\\(host|{})\\\\stage0\\\\libexec'.format(
os.path.basename(self.build_dir),
self.build
)
script = (
# NOTE: can't use `taskkill` or `Get-Process -Name` because they error if
# the server isn't running.
'Get-Process | ' +
'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' +
'Where-Object {{$_.Path -match "{}"}} |'.format(regex) +
'Stop-Process'
)
run_powershell([script])
shutil.rmtree(bin_root)
tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
filename = "rust-std-{}-{}{}".format(

View File

@ -374,3 +374,41 @@ warning: this URL is not a hyperlink
warning: 2 warnings emitted
```
## `unescaped_backticks`
This lint is **allowed by default**. It detects backticks (\`) that are not escaped.
This usually means broken inline code. For example:
```rust
#![warn(rustdoc::unescaped_backticks)]
/// `add(a, b) is the same as `add(b, a)`.
pub fn add(a: i32, b: i32) -> i32 { a + b }
```
Which will give:
```text
warning: unescaped backtick
--> src/lib.rs:3:41
|
3 | /// `add(a, b) is the same as `add(b, a)`.
| ^
|
note: the lint level is defined here
--> src/lib.rs:1:9
|
1 | #![warn(rustdoc::unescaped_backticks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: a previous inline code might be longer than expected
|
3 | /// `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
3 | /// `add(a, b) is the same as `add(b, a)\`.
| +
warning: 1 warning emitted
```

View File

@ -1155,10 +1155,10 @@ fn render_assoc_items_inner(
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
let mut tmp_buf = Buffer::html();
let (render_mode, id) = match what {
let (render_mode, id, class_html) = match what {
AssocItemRender::All => {
write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations");
(RenderMode::Normal, "implementations-list".to_owned())
(RenderMode::Normal, "implementations-list".to_owned(), "")
}
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
let id =
@ -1175,7 +1175,11 @@ fn render_assoc_items_inner(
),
&id,
);
(RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id))
(
RenderMode::ForDeref { mut_: deref_mut_ },
cx.derive_id(id),
r#" class="impl-items""#,
)
}
};
let mut impls_buf = Buffer::html();
@ -1199,7 +1203,7 @@ fn render_assoc_items_inner(
}
if !impls_buf.is_empty() {
write!(w, "{}", tmp_buf.into_inner()).unwrap();
write!(w, "<div id=\"{}\">", id).unwrap();
write!(w, "<div id=\"{id}\"{class_html}>").unwrap();
write!(w, "{}", impls_buf.into_inner()).unwrap();
w.write_str("</div>").unwrap();
}
@ -1788,12 +1792,14 @@ fn render_impl(
.into_string()
);
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.write_str("<div class=\"impl-items\">");
close_tags.insert_str(0, "</div>");
}
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.write_str("<div class=\"impl-items\">");
w.push_buffer(default_impl_items);
w.push_buffer(impl_items);
close_tags.insert_str(0, "</div>");
}
w.write_str(&close_tags);
}

View File

@ -7,14 +7,15 @@
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(let_chains)]
#![feature(test)]
#![feature(never_type)]
#![feature(lazy_cell)]
#![feature(type_ascription)]
#![feature(iter_intersperse)]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)]
#![feature(lazy_cell)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(round_char_boundary)]
#![feature(test)]
#![feature(type_alias_impl_trait)]
#![feature(type_ascription)]
#![recursion_limit = "256"]
#![warn(rustc::internal)]
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]

View File

@ -174,6 +174,17 @@ declare_rustdoc_lint! {
"codeblock could not be parsed as valid Rust or is empty"
}
declare_rustdoc_lint! {
/// The `unescaped_backticks` lint detects unescaped backticks (\`), which usually
/// mean broken inline code. This is a `rustdoc` only lint, see the documentation
/// in the [rustdoc book].
///
/// [rustdoc book]: ../../../rustdoc/lints.html#unescaped_backticks
UNESCAPED_BACKTICKS,
Allow,
"detects unescaped backticks in doc comments"
}
pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
vec![
BROKEN_INTRA_DOC_LINKS,
@ -185,6 +196,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
INVALID_HTML_TAGS,
BARE_URLS,
MISSING_CRATE_LEVEL_DOCS,
UNESCAPED_BACKTICKS,
]
});

View File

@ -4,6 +4,7 @@
mod bare_urls;
mod check_code_block_syntax;
mod html_tags;
mod unescaped_backticks;
use super::Pass;
use crate::clean::*;
@ -27,6 +28,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> {
bare_urls::visit_item(self.cx, item);
check_code_block_syntax::visit_item(self.cx, item);
html_tags::visit_item(self.cx, item);
unescaped_backticks::visit_item(self.cx, item);
self.visit_item_recur(item)
}

View File

@ -0,0 +1,416 @@
//! Detects unescaped backticks (\`) in doc comments.
use crate::clean::Item;
use crate::core::DocContext;
use crate::html::markdown::main_body_opts;
use crate::passes::source_span_for_markdown_range;
use pulldown_cmark::{BrokenLink, Event, Parser};
use rustc_errors::DiagnosticBuilder;
use rustc_lint_defs::Applicability;
use std::ops::Range;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
let tcx = cx.tcx;
let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else {
// If non-local, no need to check anything.
return;
};
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
if dox.is_empty() {
return;
}
let link_names = item.link_names(&cx.cache);
let mut replacer = |broken_link: BrokenLink<'_>| {
link_names
.iter()
.find(|link| *link.original_text == *broken_link.reference)
.map(|link| ((*link.href).into(), (*link.new_text).into()))
};
let parser = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer))
.into_offset_iter();
let mut element_stack = Vec::new();
let mut prev_text_end = 0;
for (event, event_range) in parser {
match event {
Event::Start(_) => {
element_stack.push(Element::new(event_range));
}
Event::End(_) => {
let element = element_stack.pop().unwrap();
let Some(backtick_index) = element.backtick_index else {
continue;
};
// If we can't get a span of the backtick, because it is in a `#[doc = ""]` attribute,
// use the span of the entire attribute as a fallback.
let span = source_span_for_markdown_range(
tcx,
&dox,
&(backtick_index..backtick_index + 1),
&item.attrs,
)
.unwrap_or_else(|| item.attr_span(tcx));
cx.tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| {
let mut help_emitted = false;
match element.prev_code_guess {
PrevCodeGuess::None => {}
PrevCodeGuess::Start { guess, .. } => {
// "foo` `bar`" -> "`foo` `bar`"
if let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges)
&& can_suggest_backtick(&dox, suggest_index)
{
suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the opening backtick of a previous inline code may be missing");
help_emitted = true;
}
}
PrevCodeGuess::End { guess, .. } => {
// "`foo `bar`" -> "`foo` `bar`"
// Don't `clamp_end` here, because the suggestion is guaranteed to be inside
// an inline code node and we intentionally "break" the inline code here.
let suggest_index = guess;
if can_suggest_backtick(&dox, suggest_index) {
suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "a previous inline code might be longer than expected");
help_emitted = true;
}
}
}
if !element.prev_code_guess.is_confident() {
// "`foo` bar`" -> "`foo` `bar`"
if let Some(guess) = guess_start_of_code(&dox, element.element_range.start..backtick_index)
&& let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges)
&& can_suggest_backtick(&dox, suggest_index)
{
suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the opening backtick of an inline code may be missing");
help_emitted = true;
}
// "`foo` `bar" -> "`foo` `bar`"
// Don't suggest closing backtick after single trailing char,
// if we already suggested opening backtick. For example:
// "foo`." -> "`foo`." or "foo`s" -> "`foo`s".
if let Some(guess) = guess_end_of_code(&dox, backtick_index + 1..element.element_range.end)
&& let Some(suggest_index) = clamp_end(guess, &element.suggestible_ranges)
&& can_suggest_backtick(&dox, suggest_index)
&& (!help_emitted || suggest_index - backtick_index > 2)
{
suggest_insertion(cx, item, &dox, lint, suggest_index, '`', "the closing backtick of an inline code may be missing");
help_emitted = true;
}
}
if !help_emitted {
lint.help("the opening or closing backtick of an inline code may be missing");
}
suggest_insertion(cx, item, &dox, lint, backtick_index, '\\', "if you meant to use a literal backtick, escape it");
lint
});
}
Event::Code(_) => {
let element = element_stack
.last_mut()
.expect("expected inline code node to be inside of an element");
assert!(
event_range.start >= element.element_range.start
&& event_range.end <= element.element_range.end
);
// This inline code might be longer than it's supposed to be.
// Only check single backtick inline code for now.
if !element.prev_code_guess.is_confident()
&& dox.as_bytes().get(event_range.start) == Some(&b'`')
&& dox.as_bytes().get(event_range.start + 1) != Some(&b'`')
{
let range_inside = event_range.start + 1..event_range.end - 1;
let text_inside = &dox[range_inside.clone()];
let is_confident = text_inside.starts_with(char::is_whitespace)
|| text_inside.ends_with(char::is_whitespace);
if let Some(guess) = guess_end_of_code(&dox, range_inside) {
// Find earlier end of code.
element.prev_code_guess = PrevCodeGuess::End { guess, is_confident };
} else {
// Find alternate start of code.
let range_before = element.element_range.start..event_range.start;
if let Some(guess) = guess_start_of_code(&dox, range_before) {
element.prev_code_guess = PrevCodeGuess::Start { guess, is_confident };
}
}
}
}
Event::Text(text) => {
let element = element_stack
.last_mut()
.expect("expected inline text node to be inside of an element");
assert!(
event_range.start >= element.element_range.start
&& event_range.end <= element.element_range.end
);
// The first char is escaped if the prev char is \ and not part of a text node.
let is_escaped = prev_text_end < event_range.start
&& dox.as_bytes()[event_range.start - 1] == b'\\';
// Don't lint backslash-escaped (\`) or html-escaped (&#96;) backticks.
if *text == *"`" && !is_escaped && *text == dox[event_range.clone()] {
// We found a stray backtick.
assert!(
element.backtick_index.is_none(),
"expected at most one unescaped backtick per element",
);
element.backtick_index = Some(event_range.start);
}
prev_text_end = event_range.end;
if is_escaped {
// Ensure that we suggest "`\x" and not "\`x".
element.suggestible_ranges.push(event_range.start - 1..event_range.end);
} else {
element.suggestible_ranges.push(event_range);
}
}
_ => {}
}
}
}
/// A previous inline code node, that looks wrong.
///
/// `guess` is the position, where we want to suggest a \` and the guess `is_confident` if an
/// inline code starts or ends with a whitespace.
#[derive(Debug)]
enum PrevCodeGuess {
None,
/// Missing \` at start.
///
/// ```markdown
/// foo` `bar`
/// ```
Start {
guess: usize,
is_confident: bool,
},
/// Missing \` at end.
///
/// ```markdown
/// `foo `bar`
/// ```
End {
guess: usize,
is_confident: bool,
},
}
impl PrevCodeGuess {
fn is_confident(&self) -> bool {
match *self {
PrevCodeGuess::None => false,
PrevCodeGuess::Start { is_confident, .. } | PrevCodeGuess::End { is_confident, .. } => {
is_confident
}
}
}
}
/// A markdown [tagged element], which may or may not contain an unescaped backtick.
///
/// [tagged element]: https://docs.rs/pulldown-cmark/0.9/pulldown_cmark/enum.Tag.html
#[derive(Debug)]
struct Element {
/// The full range (span) of the element in the doc string.
element_range: Range<usize>,
/// The ranges where we're allowed to put backticks.
/// This is used to prevent breaking markdown elements like links or lists.
suggestible_ranges: Vec<Range<usize>>,
/// The unescaped backtick.
backtick_index: Option<usize>,
/// Suggest a different start or end of an inline code.
prev_code_guess: PrevCodeGuess,
}
impl Element {
const fn new(element_range: Range<usize>) -> Self {
Self {
element_range,
suggestible_ranges: Vec::new(),
backtick_index: None,
prev_code_guess: PrevCodeGuess::None,
}
}
}
/// Given a potentially unclosed inline code, attempt to find the start.
fn guess_start_of_code(dox: &str, range: Range<usize>) -> Option<usize> {
assert!(dox.as_bytes()[range.end] == b'`');
let mut braces = 0;
let mut guess = 0;
for (idx, ch) in dox[range.clone()].char_indices().rev() {
match ch {
')' | ']' | '}' => braces += 1,
'(' | '[' | '{' => {
if braces == 0 {
guess = idx + 1;
break;
}
braces -= 1;
}
ch if ch.is_whitespace() && braces == 0 => {
guess = idx + 1;
break;
}
_ => (),
}
}
guess += range.start;
// Don't suggest empty inline code or duplicate backticks.
can_suggest_backtick(dox, guess).then_some(guess)
}
/// Given a potentially unclosed inline code, attempt to find the end.
fn guess_end_of_code(dox: &str, range: Range<usize>) -> Option<usize> {
// Punctuation that should be outside of the inline code.
const TRAILING_PUNCTUATION: &[u8] = b".,";
assert!(dox.as_bytes()[range.start - 1] == b'`');
let text = dox[range.clone()].trim_end();
let mut braces = 0;
let mut guess = text.len();
for (idx, ch) in text.char_indices() {
match ch {
'(' | '[' | '{' => braces += 1,
')' | ']' | '}' => {
if braces == 0 {
guess = idx;
break;
}
braces -= 1;
}
ch if ch.is_whitespace() && braces == 0 => {
guess = idx;
break;
}
_ => (),
}
}
// Strip a single trailing punctuation.
if guess >= 1
&& TRAILING_PUNCTUATION.contains(&text.as_bytes()[guess - 1])
&& (guess < 2 || !TRAILING_PUNCTUATION.contains(&text.as_bytes()[guess - 2]))
{
guess -= 1;
}
guess += range.start;
// Don't suggest empty inline code or duplicate backticks.
can_suggest_backtick(dox, guess).then_some(guess)
}
/// Returns whether inserting a backtick at `dox[index]` will not produce double backticks.
fn can_suggest_backtick(dox: &str, index: usize) -> bool {
(index == 0 || dox.as_bytes()[index - 1] != b'`')
&& (index == dox.len() || dox.as_bytes()[index] != b'`')
}
/// Increase the index until it is inside or one past the end of one of the ranges.
///
/// The ranges must be sorted for this to work correctly.
fn clamp_start(index: usize, ranges: &[Range<usize>]) -> Option<usize> {
for range in ranges {
if range.start >= index {
return Some(range.start);
}
if index <= range.end {
return Some(index);
}
}
None
}
/// Decrease the index until it is inside or one past the end of one of the ranges.
///
/// The ranges must be sorted for this to work correctly.
fn clamp_end(index: usize, ranges: &[Range<usize>]) -> Option<usize> {
for range in ranges.iter().rev() {
if range.end <= index {
return Some(range.end);
}
if index >= range.start {
return Some(index);
}
}
None
}
/// Try to emit a span suggestion and fall back to help messages if we can't find a suitable span.
///
/// This helps finding backticks in huge macro-generated docs.
fn suggest_insertion(
cx: &DocContext<'_>,
item: &Item,
dox: &str,
lint: &mut DiagnosticBuilder<'_, ()>,
insert_index: usize,
suggestion: char,
message: &str,
) {
/// Maximum bytes of context to show around the insertion.
const CONTEXT_MAX_LEN: usize = 80;
if let Some(span) =
source_span_for_markdown_range(cx.tcx, &dox, &(insert_index..insert_index), &item.attrs)
{
lint.span_suggestion(span, message, suggestion, Applicability::MaybeIncorrect);
} else {
let line_start = dox[..insert_index].rfind('\n').map_or(0, |idx| idx + 1);
let line_end = dox[insert_index..].find('\n').map_or(dox.len(), |idx| idx + insert_index);
let context_before_max_len = if insert_index - line_start < CONTEXT_MAX_LEN / 2 {
insert_index - line_start
} else if line_end - insert_index < CONTEXT_MAX_LEN / 2 {
CONTEXT_MAX_LEN - (line_end - insert_index)
} else {
CONTEXT_MAX_LEN / 2
};
let context_after_max_len = CONTEXT_MAX_LEN - context_before_max_len;
let (prefix, context_start) = if insert_index - line_start <= context_before_max_len {
("", line_start)
} else {
("...", dox.ceil_char_boundary(insert_index - context_before_max_len))
};
let (suffix, context_end) = if line_end - insert_index <= context_after_max_len {
("", line_end)
} else {
("...", dox.floor_char_boundary(insert_index + context_after_max_len))
};
let context_full = &dox[context_start..context_end].trim_end();
let context_before = &dox[context_start..insert_index];
let context_after = &dox[insert_index..context_end].trim_end();
lint.help(format!(
"{message}\n change: {prefix}{context_full}{suffix}\nto this: {prefix}{context_before}{suggestion}{context_after}{suffix}"
));
}
}

View File

@ -90,6 +90,9 @@ pub struct TestProps {
pub unset_rustc_env: Vec<String>,
// Environment settings to use during execution
pub exec_env: Vec<(String, String)>,
// Environment variables to unset prior to execution.
// Variables are unset before applying 'exec_env'
pub unset_exec_env: Vec<String>,
// Build documentation for all specified aux-builds as well
pub build_aux_docs: bool,
// Flag to force a crate to be built with the host architecture
@ -198,6 +201,7 @@ mod directives {
pub const AUX_CRATE: &'static str = "aux-crate";
pub const EXEC_ENV: &'static str = "exec-env";
pub const RUSTC_ENV: &'static str = "rustc-env";
pub const UNSET_EXEC_ENV: &'static str = "unset-exec-env";
pub const UNSET_RUSTC_ENV: &'static str = "unset-rustc-env";
pub const FORBID_OUTPUT: &'static str = "forbid-output";
pub const CHECK_TEST_LINE_NUMBERS_MATCH: &'static str = "check-test-line-numbers-match";
@ -231,6 +235,7 @@ impl TestProps {
rustc_env: vec![],
unset_rustc_env: vec![],
exec_env: vec![],
unset_exec_env: vec![],
build_aux_docs: false,
force_host: false,
check_stdout: false,
@ -382,6 +387,12 @@ impl TestProps {
&mut self.exec_env,
Config::parse_env,
);
config.push_name_value_directive(
ln,
UNSET_EXEC_ENV,
&mut self.unset_exec_env,
|r| r,
);
config.push_name_value_directive(
ln,
RUSTC_ENV,

View File

@ -165,11 +165,15 @@ pub(super) fn parse_cfg_name_directive<'a>(
message: "when the architecture is part of the Thumb family"
}
// Technically the locally built compiler uses the "dev" channel rather than the "nightly"
// channel, even though most people don't know or won't care about it. To avoid confusion, we
// treat the "dev" channel as the "nightly" channel when processing the directive.
condition! {
name: &config.channel,
name: if config.channel == "dev" { "nightly" } else { &config.channel },
allowed_names: &["stable", "beta", "nightly"],
message: "when the release channel is {name}",
}
condition! {
name: "cross-compile",
condition: config.target != config.host,

View File

@ -1614,8 +1614,13 @@ impl<'test> TestCx<'test> {
test_client
.args(&["run", &support_libs.len().to_string(), &prog])
.args(support_libs)
.args(args)
.envs(env.clone());
.args(args);
for key in &self.props.unset_exec_env {
test_client.env_remove(key);
}
test_client.envs(env.clone());
self.compose_and_run(
test_client,
self.config.run_lib_path.to_str().unwrap(),
@ -1627,7 +1632,13 @@ impl<'test> TestCx<'test> {
let aux_dir = self.aux_output_dir_name();
let ProcArgs { prog, args } = self.make_run_args();
let mut wr_run = Command::new("wr-run");
wr_run.args(&[&prog]).args(args).envs(env.clone());
wr_run.args(&[&prog]).args(args);
for key in &self.props.unset_exec_env {
wr_run.env_remove(key);
}
wr_run.envs(env.clone());
self.compose_and_run(
wr_run,
self.config.run_lib_path.to_str().unwrap(),
@ -1639,7 +1650,13 @@ impl<'test> TestCx<'test> {
let aux_dir = self.aux_output_dir_name();
let ProcArgs { prog, args } = self.make_run_args();
let mut program = Command::new(&prog);
program.args(args).current_dir(&self.output_base_dir()).envs(env.clone());
program.args(args).current_dir(&self.output_base_dir());
for key in &self.props.unset_exec_env {
program.env_remove(key);
}
program.envs(env.clone());
self.compose_and_run(
program,
self.config.run_lib_path.to_str().unwrap(),

View File

@ -0,0 +1,342 @@
#![deny(rustdoc::unescaped_backticks)]
#![allow(rustdoc::broken_intra_doc_links)]
#![allow(rustdoc::invalid_html_tags)]
///
pub fn empty() {}
#[doc = ""]
pub fn empty2() {}
/// `
//~^ ERROR unescaped backtick
pub fn single() {}
/// \`
pub fn escaped() {}
/// \\`
//~^ ERROR unescaped backtick
pub fn not_escaped() {}
/// \\\`
pub fn not_not_escaped() {}
/// [`link1]
//~^ ERROR unescaped backtick
pub fn link1() {}
/// [link2`]
//~^ ERROR unescaped backtick
pub fn link2() {}
/// [`link_long](link_long)
//~^ ERROR unescaped backtick
pub fn link_long() {}
/// [`broken-link]
//~^ ERROR unescaped backtick
pub fn broken_link() {}
/// <xx:`>
pub fn url() {}
/// <x:`>
//~^ ERROR unescaped backtick
pub fn not_url() {}
/// <h1>`</h1>
pub fn html_tag() {}
/// &#96;
pub fn html_escape() {}
/// 🦀`🦀
//~^ ERROR unescaped backtick
pub fn unicode() {}
/// `foo(
//~^ ERROR unescaped backtick
///
/// paragraph
pub fn paragraph() {}
/// `foo `bar`
//~^ ERROR unescaped backtick
///
/// paragraph
pub fn paragraph2() {}
/// `foo(
//~^ ERROR unescaped backtick
/// not paragraph
pub fn not_paragraph() {}
/// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
//~^ ERROR unescaped backtick
///
/// You could use this function to add 42 to a number `n` (add(n, 42)`),
/// or even to add a number `n` to 42 (`add(42, b)`)!
//~^ ERROR unescaped backtick
pub fn add1(a: i32, b: i32) -> i32 { a + b }
/// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
//~^ ERROR unescaped backtick
///
/// You could use this function to add 42 to a number `n` (`add(n, 42)),
/// or even to add a number `n` to 42 (`add(42, n)`)!
//~^ ERROR unescaped backtick
pub fn add2(a: i32, b: i32) -> i32 { a + b }
/// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
//~^ ERROR unescaped backtick
///
/// You could use this function to add 42 to a number `n` (`add(n, 42)`),
/// or even to add a number `n` to 42 (add(42, n)`)!
//~^ ERROR unescaped backtick
pub fn add3(a: i32, b: i32) -> i32 { a + b }
/// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
//~^ ERROR unescaped backtick
///
/// You could use this function to add 42 to a number `n` (`add(n, 42)),
/// or even to add a number `n` to 42 (`add(42, n)`)!
//~^ ERROR unescaped backtick
pub fn add4(a: i32, b: i32) -> i32 { a + b }
#[doc = "`"]
//~^ ERROR unescaped backtick
pub fn attr() {}
#[doc = concat!("\\", "`")]
pub fn attr_escaped() {}
#[doc = concat!("\\\\", "`")]
//~^ ERROR unescaped backtick
pub fn attr_not_escaped() {}
#[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
//~^ ERROR unescaped backtick
pub fn attr_add1(a: i32, b: i32) -> i32 { a + b }
#[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
//~^ ERROR unescaped backtick
pub fn attr_add2(a: i32, b: i32) -> i32 { a + b }
#[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
//~^ ERROR unescaped backtick
pub fn attr_add3(a: i32, b: i32) -> i32 { a + b }
#[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
//~^ ERROR unescaped backtick
pub fn attr_add4(a: i32, b: i32) -> i32 { a + b }
/// ``double backticks``
/// `foo
//~^ ERROR unescaped backtick
pub fn double_backticks() {}
/// # `(heading
//~^ ERROR unescaped backtick
/// ## heading2)`
//~^ ERROR unescaped backtick
///
/// multi `(
//~^ ERROR unescaped backtick
/// line
/// ) heading
/// =
///
/// para)`(graph
//~^ ERROR unescaped backtick
///
/// para)`(graph2
//~^ ERROR unescaped backtick
///
/// 1. foo)`
//~^ ERROR unescaped backtick
/// 2. `(bar
//~^ ERROR unescaped backtick
/// * baz)`
//~^ ERROR unescaped backtick
/// * `(quux
//~^ ERROR unescaped backtick
///
/// `#![this_is_actually_an_image(and(not), an = "attribute")]
//~^ ERROR unescaped backtick
///
/// #![this_is_actually_an_image(and(not), an = "attribute")]`
//~^ ERROR unescaped backtick
///
/// [this_is_actually_an_image(and(not), an = "attribute")]: `.png
///
/// | `table( | )head` |
//~^ ERROR unescaped backtick
//~| ERROR unescaped backtick
/// |---------|--------|
/// | table`( | )`body |
//~^ ERROR unescaped backtick
//~| ERROR unescaped backtick
pub fn complicated_markdown() {}
/// The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
/// attribute only works on functions - there is no way to insert custom MIR into the middle of
/// another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
/// docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
/// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
//~^ ERROR unescaped backtick
/// "runtime", phase = "optimized")] if you don't.
pub mod mir {}
pub mod rustc {
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
//~^ ERROR unescaped backtick
/// ensure it gets used.
pub fn ty_error_with_message() {}
pub struct WhereClause {
/// `true` if we ate a `where` token: this can happen
/// if we parsed no predicates (e.g. `struct Foo where {}
/// This allows us to accurately pretty-print
/// in `nt_to_tokenstream`
//~^ ERROR unescaped backtick
pub has_where_token: bool,
}
/// A symbol is an interned or gensymed string. The use of `newtype_index!` means
/// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
//~^ ERROR unescaped backtick
/// the last 256 values for tagging purposes.
pub struct Symbol();
/// It is equivalent to `OpenOptions::new()` but allows you to write more
/// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")`
/// you can write `File::with_options().read(true).open("foo.txt"). This
/// also avoids the need to import `OpenOptions`.
//~^ ERROR unescaped backtick
pub fn with_options() {}
/// Subtracts `set from `row`. `set` can be either `BitSet` or
/// `HybridBitSet`. Has no effect if `row` does not exist.
//~^ ERROR unescaped backtick
///
/// Returns true if the row was changed.
pub fn subtract_row() {}
pub mod assert_module_sources {
//! The reason that we use `cfg=...` and not `#[cfg_attr]` is so that
//! the HIR doesn't change as a result of the annotations, which might
//! perturb the reuse results.
//!
//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
//~^ ERROR unescaped backtick
//! allows for doing a more fine-grained check to see if pre- or post-lto data
//! was re-used.
/// `cfg=...
//~^ ERROR unescaped backtick
pub fn foo() {}
/// `cfg=... and not `#[cfg_attr]`
//~^ ERROR unescaped backtick
pub fn bar() {}
}
/// Conceptually, this is like a `Vec<Vec<RWU>>`. But the number of
/// RWU`s can get very large, so it uses a more compact representation.
//~^ ERROR unescaped backtick
pub struct RWUTable {}
/// Like [Self::canonicalize_query], but preserves distinct universes. For
/// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
/// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1`
/// in `U2`.
//~^ ERROR unescaped backtick
///
/// This is used for Chalk integration.
pub fn canonicalize_query_preserving_universes() {}
/// Note that we used to return `Error` here, but that was quite
/// dubious -- the premise was that an error would *eventually* be
/// reported, when the obligation was processed. But in general once
/// you see an `Error` you are supposed to be able to assume that an
/// error *has been* reported, so that you can take whatever heuristic
/// paths you want to take. To make things worse, it was possible for
/// cycles to arise, where you basically had a setup like `<MyType<$0>
/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
/// Trait>::Foo> to `[type error]` would lead to an obligation of
/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
/// an error for this obligation, but we legitimately should not,
/// because it contains `[type error]`. Yuck! (See issue #29857 for
//~^ ERROR unescaped backtick
/// one case where this arose.)
pub fn normalize_to_error() {}
/// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
/// is `EvaluatedToOk`; this is because they were only considered
/// ok on the premise that if `A: AutoTrait` held, but we indeed
/// encountered a problem (later on) with `A: AutoTrait. So we
/// currently set a flag on the stack node for `B: AutoTrait` (as
/// well as the second instance of `A: AutoTrait`) to suppress
//~^ ERROR unescaped backtick
/// caching.
pub struct TraitObligationStack;
/// Extend `scc` so that it can outlive some placeholder region
/// from a universe it can't name; at present, the only way for
/// this to be true is if `scc` outlives `'static`. This is
/// actually stricter than necessary: ideally, we'd support bounds
/// like `for<'a: 'b`>` that might then allow us to approximate
/// `'a` with `'b` and not `'static`. But it will have to do for
//~^ ERROR unescaped backtick
/// now.
pub fn add_incompatible_universe(){}
}
/// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
/// which returns an `Option<Dispatch>`. If all [`Dispatch`] clones that point
/// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return
/// `None`. Otherwise, it will return `Some(Dispatch)`.
//~^ ERROR unescaped backtick
///
/// Returns some reference to this `[`Subscriber`] value if it is of type `T`,
/// or `None` if it isn't.
//~^ ERROR unescaped backtick
///
/// Called before the filtered [`Layer]'s [`on_event`], to determine if
/// `on_event` should be called.
//~^ ERROR unescaped backtick
///
/// Therefore, if the `Filter will change the value returned by this
/// method, it is responsible for ensuring that
/// [`rebuild_interest_cache`][rebuild] is called after the value of the max
//~^ ERROR unescaped backtick
/// level changes.
pub mod tracing {}
macro_rules! id {
($($tt:tt)*) => { $($tt)* }
}
id! {
/// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
//~^ ERROR unescaped backtick
//~| ERROR unescaped backtick
//~| ERROR unescaped backtick
//~| ERROR unescaped backtick
/// which returns an `Option<Dispatch>`. If all [`Dispatch`] clones that point
/// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return
/// `None`. Otherwise, it will return `Some(Dispatch)`.
///
/// Returns some reference to this `[`Subscriber`] value if it is of type `T`,
/// or `None` if it isn't.
///
/// Called before the filtered [`Layer]'s [`on_event`], to determine if
/// `on_event` should be called.
///
/// Therefore, if the `Filter will change the value returned by this
/// method, it is responsible for ensuring that
/// [`rebuild_interest_cache`][rebuild] is called after the value of the max
/// level changes.
pub mod tracing_macro {}
}

View File

@ -0,0 +1,959 @@
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:186:70
|
LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
| ^
|
note: the lint level is defined here
--> $DIR/unescaped_backticks.rs:1:9
|
LL | #![deny(rustdoc::unescaped_backticks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the closing backtick of an inline code may be missing
|
LL | /// "runtime", phase = "optimized")]` if you don't.
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![custom_mir(dialect =
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:231:13
|
LL | //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]`
| +
help: if you meant to use a literal backtick, escape it
|
LL | //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:236:13
|
LL | /// `cfg=...
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// `cfg=...`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// \`cfg=...
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:240:42
|
LL | /// `cfg=... and not `#[cfg_attr]`
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// `cfg=...` and not `#[cfg_attr]`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// `cfg=... and not `#[cfg_attr]\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:192:91
|
LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given \`msg to
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:201:34
|
LL | /// in `nt_to_tokenstream`
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// if we parsed no predicates (e.g. `struct` Foo where {}
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// in `nt_to_tokenstream\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:207:62
|
LL | /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index!` reserves
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_index! reserves
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:215:52
|
LL | /// also avoids the need to import `OpenOptions`.
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// you can write `File::with_options().read(true).open("foo.txt")`. This
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// also avoids the need to import `OpenOptions\`.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:220:46
|
LL | /// `HybridBitSet`. Has no effect if `row` does not exist.
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// Subtracts `set` from `row`. `set` can be either `BitSet` or
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// `HybridBitSet`. Has no effect if `row\` does not exist.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:246:12
|
LL | /// RWU`s can get very large, so it uses a more compact representation.
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `RWU`s can get very large, so it uses a more compact representation.
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// RWU\`s can get very large, so it uses a more compact representation.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:253:15
|
LL | /// in `U2`.
| ^
|
help: the opening backtick of a previous inline code may be missing
|
LL | /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// in `U2\`.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:270:42
|
LL | /// because it contains `[type error]`. Yuck! (See issue #29857 for
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0>` as
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// because it contains `[type error]\`. Yuck! (See issue #29857 for
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:280:53
|
LL | /// well as the second instance of `A: AutoTrait`) to suppress
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// encountered a problem (later on) with `A:` AutoTrait. So we
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// well as the second instance of `A: AutoTrait\`) to suppress
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:290:40
|
LL | /// `'a` with `'b` and not `'static`. But it will have to do for
| ^
|
= help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
|
LL | /// `'a` with `'b` and not `'static\`. But it will have to do for
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:299:54
|
LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
| ^
|
help: the opening backtick of a previous inline code may be missing
|
LL | /// The `Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:303:13
|
LL | /// or `None` if it isn't.
| ^
|
= help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
|
LL | /// or `None\` if it isn't.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:307:14
|
LL | /// `on_event` should be called.
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// Called before the filtered [`Layer`]'s [`on_event`], to determine if
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// `on_event\` should be called.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:312:29
|
LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// Therefore, if the `Filter` will change the value returned by this
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the max
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:322:5
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |
LL | |
LL | |
... |
LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | | /// level changes.
| |______________________^
|
= help: the opening backtick of a previous inline code may be missing
change: The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
to this: The `Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
= help: if you meant to use a literal backtick, escape it
change: `None`. Otherwise, it will return `Some(Dispatch)`.
to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:322:5
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |
LL | |
LL | |
... |
LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | | /// level changes.
| |______________________^
|
= help: the opening or closing backtick of an inline code may be missing
= help: if you meant to use a literal backtick, escape it
change: or `None` if it isn't.
to this: or `None\` if it isn't.
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:322:5
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |
LL | |
LL | |
... |
LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | | /// level changes.
| |______________________^
|
= help: a previous inline code might be longer than expected
change: Called before the filtered [`Layer]'s [`on_event`], to determine if
to this: Called before the filtered [`Layer`]'s [`on_event`], to determine if
= help: if you meant to use a literal backtick, escape it
change: `on_event` should be called.
to this: `on_event\` should be called.
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:322:5
|
LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |
LL | |
LL | |
... |
LL | | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | | /// level changes.
| |______________________^
|
= help: a previous inline code might be longer than expected
change: Therefore, if the `Filter will change the value returned by this
to this: Therefore, if the `Filter` will change the value returned by this
= help: if you meant to use a literal backtick, escape it
change: [`rebuild_interest_cache`][rebuild] is called after the value of the max
to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:11:5
|
LL | /// `
| ^
|
= help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
|
LL | /// \`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:18:7
|
LL | /// \`
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `\`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// \\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:25:6
|
LL | /// [`link1]
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// [`link1`]
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// [\`link1]
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:29:11
|
LL | /// [link2`]
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// [`link2`]
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// [link2\`]
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:33:6
|
LL | /// [`link_long](link_long)
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// [`link_long`](link_long)
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// [\`link_long](link_long)
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:37:6
|
LL | /// [`broken-link]
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// [`broken-link`]
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// [\`broken-link]
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:44:8
|
LL | /// <x:`>
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `<x:`>
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// <x:\`>
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:54:6
|
LL | /// 🦀`🦀
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `🦀`🦀
| +
help: the closing backtick of an inline code may be missing
|
LL | /// 🦀`🦀`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// 🦀\`🦀
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:58:5
|
LL | /// `foo(
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// `foo(`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// \`foo(
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:64:14
|
LL | /// `foo `bar`
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// `foo` `bar`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// `foo `bar\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:70:5
|
LL | /// `foo(
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// not paragraph`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// \`foo(
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:75:83
|
LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
| ^
|
help: the opening backtick of a previous inline code may be missing
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:79:51
|
LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
| ^
|
help: the opening backtick of a previous inline code may be missing
|
LL | /// You could use this function to add 42 to a number `n` (`add(n, 42)`),
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// or even to add a number `n` to 42 (`add(42, b)\`)!
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:83:83
|
LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:87:51
|
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// You could use this function to add 42 to a number `n` (`add(n, 42)`),
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:91:83
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:95:50
|
LL | /// or even to add a number `n` to 42 (add(42, n)`)!
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// or even to add a number `n` to 42 (add(42, n)\`)!
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:99:74
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:103:51
|
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
| ^
|
help: a previous inline code might be longer than expected
|
LL | /// You could use this function to add 42 to a number `n` (`add(n, 42)`),
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:107:1
|
LL | #[doc = "`"]
| ^^^^^^^^^^^^
|
= help: the opening or closing backtick of an inline code may be missing
= help: if you meant to use a literal backtick, escape it
change: `
to this: \`
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:114:1
|
LL | #[doc = concat!("\\", "`")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: the opening backtick of an inline code may be missing
change: \`
to this: `\`
= help: if you meant to use a literal backtick, escape it
change: \`
to this: \\`
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:118:1
|
LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: the opening backtick of a previous inline code may be missing
change: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
= help: if you meant to use a literal backtick, escape it
change: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:122:1
|
LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: a previous inline code might be longer than expected
change: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
= help: if you meant to use a literal backtick, escape it
change: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:126:1
|
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: the opening backtick of an inline code may be missing
change: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
= help: if you meant to use a literal backtick, escape it
change: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:130:1
|
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: the closing backtick of an inline code may be missing
change: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
= help: if you meant to use a literal backtick, escape it
change: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:135:5
|
LL | /// `foo
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// `foo`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// \`foo
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:139:7
|
LL | /// # `(heading
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// # `(heading`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// # \`(heading
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:141:17
|
LL | /// ## heading2)`
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// ## `heading2)`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// ## heading2)\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:144:11
|
LL | /// multi `(
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// )` heading
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// multi \`(
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:150:10
|
LL | /// para)`(graph
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `para)`(graph
| +
help: the closing backtick of an inline code may be missing
|
LL | /// para)`(graph`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// para)\`(graph
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:153:10
|
LL | /// para)`(graph2
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `para)`(graph2
| +
help: the closing backtick of an inline code may be missing
|
LL | /// para)`(graph2`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// para)\`(graph2
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:156:12
|
LL | /// 1. foo)`
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// 1. `foo)`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// 1. foo)\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:158:8
|
LL | /// 2. `(bar
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// 2. `(bar`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// 2. \`(bar
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:160:11
|
LL | /// * baz)`
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// * `baz)`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// * baz)\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:162:7
|
LL | /// * `(quux
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// * `(quux`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// * \`(quux
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:165:5
|
LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// `#`![this_is_actually_an_image(and(not), an = "attribute")]
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")]
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:168:62
|
LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]`
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\`
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:173:7
|
LL | /// | `table( | )head` |
| ^
|
help: the closing backtick of an inline code may be missing
|
LL | /// | `table(` | )head` |
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// | \`table( | )head` |
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:173:22
|
LL | /// | `table( | )head` |
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// | `table( | `)head` |
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// | `table( | )head\` |
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:177:12
|
LL | /// | table`( | )`body |
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// | `table`( | )`body |
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// | table\`( | )`body |
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:177:18
|
LL | /// | table`( | )`body |
| ^
|
help: the opening backtick of an inline code may be missing
|
LL | /// | table`( | `)`body |
| +
help: the closing backtick of an inline code may be missing
|
LL | /// | table`( | )`body` |
| +
help: if you meant to use a literal backtick, escape it
|
LL | /// | table`( | )\`body |
| +
error: aborting due to 63 previous errors

View File

@ -0,0 +1,43 @@
#![crate_name="foo"]
use std::ops::{Deref, DerefMut};
// @has foo/struct.Vec.html
// @count - '//h2[@id="deref-methods-Slice"]' 1
// @count - '//div[@id="deref-methods-Slice-1"]' 1
// @count - '//div[@id="deref-methods-Slice-1"][@class="impl-items"]' 1
// @count - '//div[@id="deref-methods-Slice-1"]/div[@class="impl-items"]' 0
pub struct Vec;
pub struct Slice;
impl Deref for Vec {
type Target = Slice;
fn deref(&self) -> &Slice {
&Slice
}
}
impl DerefMut for Vec {
fn deref_mut(&mut self) -> &mut Slice {
&mut Slice
}
}
impl Slice {
pub fn sort_floats(&mut self) {
todo!();
}
}
impl Slice {
pub fn sort(&mut self) {
todo!();
}
}
impl Slice {
pub fn len(&self) {
todo!();
}
}

View File

@ -0,0 +1,18 @@
// no-prefer-dynamic
// compile-flags: --test
// run-flags: --list --format json -Zunstable-options
// run-fail
// check-run-results
// ignore-nightly
// unset-exec-env:RUSTC_BOOTSTRAP
#![cfg(test)]
#[test]
fn m_test() {}
#[test]
#[ignore = "not yet implemented"]
fn z_test() {}
#[test]
fn a_test() {}

View File

@ -0,0 +1 @@
error: the option `Z` is only accepted on the nightly compiler

View File

@ -3,6 +3,7 @@
// run-flags: --list --format json -Zunstable-options
// run-pass
// check-run-results
// only-nightly
// normalize-stdout-test: "fake-test-src-base/test-attrs/" -> "$$DIR/"
// normalize-stdout-test: "fake-test-src-base\\test-attrs\\" -> "$$DIR/"

View File

@ -1,5 +1,5 @@
{ "type": "suite", "event": "discovery" }
{ "type": "test", "event": "discovered", "name": "a_test", "ignore": false, "ignore_message": "", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 20, "start_col": 4, "end_line": 20, "end_col": 10 }
{ "type": "test", "event": "discovered", "name": "m_test", "ignore": false, "ignore_message": "", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 13, "start_col": 4, "end_line": 13, "end_col": 10 }
{ "type": "test", "event": "discovered", "name": "z_test", "ignore": true, "ignore_message": "not yet implemented", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 17, "start_col": 4, "end_line": 17, "end_col": 10 }
{ "type": "test", "event": "discovered", "name": "a_test", "ignore": false, "ignore_message": "", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 21, "start_col": 4, "end_line": 21, "end_col": 10 }
{ "type": "test", "event": "discovered", "name": "m_test", "ignore": false, "ignore_message": "", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 14, "start_col": 4, "end_line": 14, "end_col": 10 }
{ "type": "test", "event": "discovered", "name": "z_test", "ignore": true, "ignore_message": "not yet implemented", "source_path": "$DIR/tests-listing-format-json.rs", "start_line": 18, "start_col": 4, "end_line": 18, "end_col": 10 }
{ "type": "suite", "event": "completed", "tests": 3, "benchmarks": 0, "total": 3, "ignored": 1 }