Skip to content

Commit

Permalink
Auto merge of rust-lang#101736 - GuillaumeGomez:rollup-f71kjdb, r=Gui…
Browse files Browse the repository at this point in the history
…llaumeGomez

Rollup of 8 pull requests

Successful merges:

 - rust-lang#100185 (Fix `ReErased` leaking into typeck due to `typeof(...)` recovery)
 - rust-lang#100291 (constify some `CStr` methods)
 - rust-lang#101677 (Add test for rust-lang#101211)
 - rust-lang#101723 (Impove diagnostic for `.await`ing non-futures)
 - rust-lang#101724 (Allow unauthenticated users to add the `const-hack` label)
 - rust-lang#101731 (rustdoc: improve rustdoc HTML suggestions handling of nested generics)
 - rust-lang#101732 (Feature gate the `rustdoc::missing_doc_code_examples` lint)
 - rust-lang#101735 (rustdoc: fix treatment of backslash-escaped HTML)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Sep 12, 2022
2 parents fa6ee93 + 031a2f8 commit 089584d
Show file tree
Hide file tree
Showing 40 changed files with 592 additions and 87 deletions.
12 changes: 9 additions & 3 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
),
ExprKind::Await(ref expr) => {
let span = if expr.span.hi() < e.span.hi() {
expr.span.shrink_to_hi().with_hi(e.span.hi())
let dot_await_span = if expr.span.hi() < e.span.hi() {
let span_with_whitespace = self
.tcx
.sess
.source_map()
.span_extend_while(expr.span, char::is_whitespace)
.unwrap_or(expr.span);
span_with_whitespace.shrink_to_hi().with_hi(e.span.hi())
} else {
// this is a recovered `await expr`
e.span
};
self.lower_expr_await(span, expr)
self.lower_expr_await(dot_await_span, expr)
}
ExprKind::Closure(
ref binder,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ declare_features! (
(active, rustc_private, "1.0.0", Some(27812), None),
/// Allows using internal rustdoc features like `doc(primitive)` or `doc(keyword)`.
(active, rustdoc_internals, "1.58.0", Some(90418), None),
/// Allows using the `rustdoc::missing_doc_code_examples` lint
(active, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730), None),
/// Allows using `#[start]` on a function indicating that it is the program entrypoint.
(active, start, "1.0.0", Some(29633), None),
/// Allows using `#[structural_match]` which indicates that a type is structurally matchable.
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_lint/src/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,10 @@ impl<'s> LintLevelsBuilder<'s> {
sp,
reason,
);
for id in ids {
self.insert_spec(*id, (level, src));
for &id in ids {
if self.check_gated_lint(id, attr.span) {
self.insert_spec(id, (level, src));
}
}
if let Level::Expect(expect_id) = level {
self.lint_expectations.push((
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,18 +658,21 @@ macro_rules! declare_lint {
macro_rules! declare_tool_lint {
(
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
$(, @feature_gate = $gate:expr;)?
) => (
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false $(, @feature_gate = $gate;)?}
);
(
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
report_in_external_macro: $rep:expr
$(, @feature_gate = $gate:expr;)?
) => (
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep $(, @feature_gate = $gate;)?}
);
(
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
$external:expr
$(, @feature_gate = $gate:expr;)?
) => (
$(#[$attr])*
$vis static $NAME: &$crate::Lint = &$crate::Lint {
Expand All @@ -680,8 +683,9 @@ macro_rules! declare_tool_lint {
report_in_external_macro: $external,
future_incompatible: None,
is_plugin: true,
feature_gate: None,
$(feature_gate: Some($gate),)?
crate_level_only: false,
..$crate::Lint::default_fields_for_macro()
};
);
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,7 @@ symbols! {
rustc_variance,
rustdoc,
rustdoc_internals,
rustdoc_missing_doc_code_examples,
rustfmt,
rvalue_static_promotion,
s,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1160,8 +1160,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// and if not maybe suggest doing something else? If we kept the expression around we
// could also check if it is an fn call (very likely) and suggest changing *that*, if
// it is from the local crate.
err.span_suggestion_verbose(
expr.span.shrink_to_hi().with_hi(span.hi()),
err.span_suggestion(
span,
"remove the `.await`",
"",
Applicability::MachineApplicable,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2672,7 +2672,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.normalize_ty(ast_ty.span, array_ty)
}
hir::TyKind::Typeof(ref e) => {
let ty = tcx.type_of(tcx.hir().local_def_id(e.hir_id));
let ty_erased = tcx.type_of(tcx.hir().local_def_id(e.hir_id));
let ty = tcx.fold_regions(ty_erased, |r, _| {
if r.is_erased() { tcx.lifetimes.re_static } else { r }
});
let span = ast_ty.span;
tcx.sess.emit_err(TypeofReservedKeywordUsed {
span,
Expand Down
19 changes: 12 additions & 7 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ enum FromBytesWithNulErrorKind {
}

impl FromBytesWithNulError {
fn interior_nul(pos: usize) -> FromBytesWithNulError {
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
}
fn not_nul_terminated() -> FromBytesWithNulError {
const fn not_nul_terminated() -> FromBytesWithNulError {
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
}

Expand Down Expand Up @@ -294,7 +294,8 @@ impl CStr {
/// ```
///
#[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
pub fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> {
#[rustc_const_unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> {
let nul_pos = memchr::memchr(0, bytes);
match nul_pos {
Some(nul_pos) => {
Expand Down Expand Up @@ -343,7 +344,8 @@ impl CStr {
/// assert!(cstr.is_err());
/// ```
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
let nul_pos = memchr::memchr(0, bytes);
match nul_pos {
Some(nul_pos) if nul_pos + 1 == bytes.len() => {
Expand Down Expand Up @@ -493,7 +495,8 @@ impl CStr {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes(&self) -> &[u8] {
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
pub const fn to_bytes(&self) -> &[u8] {
let bytes = self.to_bytes_with_nul();
// SAFETY: to_bytes_with_nul returns slice with length at least 1
unsafe { bytes.get_unchecked(..bytes.len() - 1) }
Expand All @@ -520,7 +523,8 @@ impl CStr {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
pub const fn to_bytes_with_nul(&self) -> &[u8] {
// SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
// is safe on all supported targets.
unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
Expand All @@ -543,7 +547,8 @@ impl CStr {
/// assert_eq!(cstr.to_str(), Ok("foo"));
/// ```
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
// instead of in `from_ptr()`, it may be worth considering if this should
// be rewritten to do the UTF-8 check inline with the length calculation
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
#![feature(const_slice_from_ref)]
#![feature(const_slice_index)]
#![feature(const_is_char_boundary)]
#![feature(const_cstr_methods)]
//
// Language features:
#![feature(abi_unadjusted)]
Expand Down
29 changes: 24 additions & 5 deletions library/core/src/slice/memchr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch

use crate::cmp;
use crate::intrinsics;
use crate::mem;

const LO_USIZE: usize = usize::repeat_u8(0x01);
Expand Down Expand Up @@ -35,13 +36,31 @@ fn repeat_byte(b: u8) -> usize {
/// Returns the first index matching the byte `x` in `text`.
#[must_use]
#[inline]
pub fn memchr(x: u8, text: &[u8]) -> Option<usize> {
// Fast path for small slices
if text.len() < 2 * USIZE_BYTES {
return text.iter().position(|elt| *elt == x);
pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> {
#[inline]
fn rt_impl(x: u8, text: &[u8]) -> Option<usize> {
// Fast path for small slices
if text.len() < 2 * USIZE_BYTES {
return text.iter().position(|elt| *elt == x);
}

memchr_general_case(x, text)
}

const fn const_impl(x: u8, bytes: &[u8]) -> Option<usize> {
let mut i = 0;
while i < bytes.len() {
if bytes[i] == x {
return Some(i);
}
i += 1;
}

None
}

memchr_general_case(x, text)
// SAFETY: The const and runtime versions have identical behavior
unsafe { intrinsics::const_eval_select((x, text), const_impl, rt_impl) }
}

fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
Expand Down
9 changes: 7 additions & 2 deletions src/librustdoc/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,13 @@ where
}

macro_rules! declare_rustdoc_lint {
($(#[$attr:meta])* $name: ident, $level: ident, $descr: literal $(,)?) => {
(
$(#[$attr:meta])* $name: ident, $level: ident, $descr: literal $(,)?
$(@feature_gate = $gate:expr;)?
) => {
declare_tool_lint! {
$(#[$attr])* pub rustdoc::$name, $level, $descr
$(, @feature_gate = $gate;)?
}
}
}
Expand Down Expand Up @@ -123,7 +127,8 @@ declare_rustdoc_lint! {
/// [rustdoc book]: ../../../rustdoc/lints.html#missing_doc_code_examples
MISSING_DOC_CODE_EXAMPLES,
Allow,
"detects publicly-exported items without code samples in their documentation"
"detects publicly-exported items without code samples in their documentation",
@feature_gate = rustc_span::symbol::sym::rustdoc_missing_doc_code_examples;
}

declare_rustdoc_lint! {
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/passes/check_doc_test_visibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item

find_testable_code(dox, &mut tests, ErrorCodes::No, false, None);

if tests.found_tests == 0 && cx.tcx.sess.is_nightly_build() {
if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples {
if should_have_doc_example(cx, item) {
debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
let sp = item.attr_span(cx.tcx);
Expand Down
85 changes: 81 additions & 4 deletions src/librustdoc/passes/html_tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,34 @@ fn extract_path_backwards(text: &str, end_pos: usize) -> Option<usize> {
if current_pos == end_pos { None } else { Some(current_pos) }
}

fn extract_path_forward(text: &str, start_pos: usize) -> Option<usize> {
use rustc_lexer::{is_id_continue, is_id_start};
let mut current_pos = start_pos;
loop {
if current_pos < text.len() && text[current_pos..].starts_with("::") {
current_pos += 2;
} else {
break;
}
let mut chars = text[current_pos..].chars();
if let Some(c) = chars.next() {
if is_id_start(c) {
current_pos += c.len_utf8();
} else {
break;
}
}
while let Some(c) = chars.next() {
if is_id_continue(c) {
current_pos += c.len_utf8();
} else {
break;
}
}
}
if current_pos == start_pos { None } else { Some(current_pos) }
}

fn is_valid_for_html_tag_name(c: char, is_empty: bool) -> bool {
// https://spec.commonmark.org/0.30/#raw-html
//
Expand Down Expand Up @@ -218,19 +246,68 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
// If a tag looks like `<this>`, it might actually be a generic.
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
if let Some(Some(generics_start)) = (is_open_tag
&& dox[..range.end].ends_with('>'))
let mut generics_end = range.end;
if let Some(Some(mut generics_start)) = (is_open_tag
&& dox[..generics_end].ends_with('>'))
.then(|| extract_path_backwards(&dox, range.start))
{
while generics_start != 0
&& generics_end < dox.len()
&& dox.as_bytes()[generics_start - 1] == b'<'
&& dox.as_bytes()[generics_end] == b'>'
{
generics_end += 1;
generics_start -= 1;
if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
generics_start = new_start;
}
if let Some(new_end) = extract_path_forward(&dox, generics_end) {
generics_end = new_end;
}
}
if let Some(new_end) = extract_path_forward(&dox, generics_end) {
generics_end = new_end;
}
let generics_sp = match super::source_span_for_markdown_range(
tcx,
&dox,
&(generics_start..range.end),
&(generics_start..generics_end),
&item.attrs,
) {
Some(sp) => sp,
None => item.attr_span(tcx),
};
// Sometimes, we only extract part of a path. For example, consider this:
//
// <[u32] as IntoIter<u32>>::Item
// ^^^^^ unclosed HTML tag `u32`
//
// We don't have any code for parsing fully-qualified trait paths.
// In theory, we could add it, but doing it correctly would require
// parsing the entire path grammar, which is problematic because of
// overlap between the path grammar and Markdown.
//
// The example above shows that ambiguity. Is `[u32]` intended to be an
// intra-doc link to the u32 primitive, or is it intended to be a slice?
//
// If the below conditional were removed, we would suggest this, which is
// not what the user probably wants.
//
// <[u32] as `IntoIter<u32>`>::Item
//
// We know that the user actually wants to wrap the whole thing in a code
// block, but the only reason we know that is because `u32` does not, in
// fact, implement IntoIter. If the example looks like this:
//
// <[Vec<i32>] as IntoIter<i32>::Item
//
// The ideal fix would be significantly different.
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
{
diag.emit();
return;
}
// multipart form is chosen here because ``Vec<i32>`` would be confusing.
diag.multipart_suggestion(
"try marking as source code",
Expand Down Expand Up @@ -278,7 +355,7 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
for (event, range) in p {
match event {
Event::Start(Tag::CodeBlock(_)) => in_code_block = true,
Event::Html(text) | Event::Text(text) if !in_code_block => {
Event::Html(text) if !in_code_block => {
extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag)
}
Event::End(Tag::CodeBlock(_)) => in_code_block = false,
Expand Down
1 change: 1 addition & 0 deletions src/test/rustdoc-ui/check-fail.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// compile-flags: -Z unstable-options --check

#![feature(rustdoc_missing_doc_code_examples)]
#![deny(missing_docs)]
#![deny(rustdoc::all)]

Expand Down
Loading

0 comments on commit 089584d

Please sign in to comment.