Auto merge of #86379 - JohnTitor:rollup-mkz9x36, r=JohnTitor
Rollup of 10 pull requests Successful merges: - #85870 (Allow whitespace in dump_mir filter) - #86104 (Fix span calculation in format strings) - #86140 (Mention the `Borrow` guarantee on the `Hash` implementations for Arrays and `Vec`) - #86141 (Link reference in `dyn` keyword documentation) - #86260 (Open trait implementations' toggles by default.) - #86339 (Mention #79078 on compatibility notes of 1.52) - #86341 (Stop returning a value from `report_assert_as_lint`) - #86353 (Remove `projection_ty_from_predicates`) - #86361 (Add missing backslashes to prevent unwanted newlines in rustdoc HTML) - #86372 (Typo correction: s/is/its) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
444a85ac38
@ -306,6 +306,7 @@ Compatibility Notes
|
||||
- [Rustc now catches more cases of `pub_use_of_private_extern_crate`][80763]
|
||||
- [Changes in how proc macros handle whitespace may lead to panics when used
|
||||
with older `proc-macro-hack` versions. A `cargo update` should be sufficient to fix this in all cases.][84136]
|
||||
- [Turn `#[derive]` into a regular macro attribute][79078]
|
||||
|
||||
[84136]: https://github.com/rust-lang/rust/issues/84136
|
||||
[80763]: https://github.com/rust-lang/rust/pull/80763
|
||||
@ -332,6 +333,7 @@ Compatibility Notes
|
||||
[78429]: https://github.com/rust-lang/rust/pull/78429
|
||||
[82733]: https://github.com/rust-lang/rust/pull/82733
|
||||
[82594]: https://github.com/rust-lang/rust/pull/82594
|
||||
[79078]: https://github.com/rust-lang/rust/pull/79078
|
||||
[cargo/9181]: https://github.com/rust-lang/cargo/pull/9181
|
||||
[`char::MAX`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.MAX
|
||||
[`char::REPLACEMENT_CHARACTER`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.REPLACEMENT_CHARACTER
|
||||
|
@ -939,6 +939,7 @@ pub fn expand_preparsed_format_args(
|
||||
|
||||
let msg = "format argument must be a string literal";
|
||||
let fmt_sp = efmt.span;
|
||||
let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_));
|
||||
let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
|
||||
Ok(mut fmt) if append_newline => {
|
||||
fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
|
||||
@ -989,7 +990,19 @@ pub fn expand_preparsed_format_args(
|
||||
|
||||
if !parser.errors.is_empty() {
|
||||
let err = parser.errors.remove(0);
|
||||
let sp = fmt_span.from_inner(err.span);
|
||||
let sp = if efmt_kind_is_lit {
|
||||
fmt_span.from_inner(err.span)
|
||||
} else {
|
||||
// The format string could be another macro invocation, e.g.:
|
||||
// format!(concat!("abc", "{}"), 4);
|
||||
// However, `err.span` is an inner span relative to the *result* of
|
||||
// the macro invocation, which is why we would get a nonsensical
|
||||
// result calling `fmt_span.from_inner(err.span)` as above, and
|
||||
// might even end up inside a multibyte character (issue #86085).
|
||||
// Therefore, we conservatively report the error for the entire
|
||||
// argument span here.
|
||||
fmt_span
|
||||
};
|
||||
let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description));
|
||||
e.span_label(sp, err.label + " in format string");
|
||||
if let Some(note) = err.note {
|
||||
|
@ -285,7 +285,7 @@ pub mod label_strs {
|
||||
// required that their size stay the same, but we don't want to change
|
||||
// it inadvertently. This assert just ensures we're aware of any change.
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
static_assert_size!(DepNode, 18);
|
||||
static_assert_size!(DepNode, 17);
|
||||
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
static_assert_size!(DepNode, 24);
|
||||
|
@ -191,10 +191,6 @@
|
||||
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
query projection_ty_from_predicates(key: (DefId, DefId)) -> Option<ty::ProjectionTy<'tcx>> {
|
||||
desc { |tcx| "finding projection type inside predicates of `{}`", tcx.def_path_str(key.0) }
|
||||
}
|
||||
|
||||
query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
|
||||
desc { "looking up the native libraries of a linked crate" }
|
||||
}
|
||||
|
@ -528,14 +528,14 @@ fn report_assert_as_lint(
|
||||
source_info: SourceInfo,
|
||||
message: &'static str,
|
||||
panic: AssertKind<impl std::fmt::Debug>,
|
||||
) -> Option<()> {
|
||||
let lint_root = self.lint_root(source_info)?;
|
||||
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
||||
let mut err = lint.build(message);
|
||||
err.span_label(source_info.span, format!("{:?}", panic));
|
||||
err.emit()
|
||||
});
|
||||
None
|
||||
) {
|
||||
if let Some(lint_root) = self.lint_root(source_info) {
|
||||
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
|
||||
let mut err = lint.build(message);
|
||||
err.span_label(source_info.span, format!("{:?}", panic));
|
||||
err.emit()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_unary_op(
|
||||
@ -557,7 +557,8 @@ fn check_unary_op(
|
||||
source_info,
|
||||
"this arithmetic operation will overflow",
|
||||
AssertKind::OverflowNeg(val.to_const_int()),
|
||||
)?;
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(())
|
||||
@ -602,7 +603,8 @@ fn check_binary_op(
|
||||
},
|
||||
r.to_const_int(),
|
||||
),
|
||||
)?;
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
@ -617,7 +619,8 @@ fn check_binary_op(
|
||||
source_info,
|
||||
"this arithmetic operation will overflow",
|
||||
AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
|
||||
)?;
|
||||
);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(())
|
||||
|
@ -99,7 +99,10 @@ pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) ->
|
||||
});
|
||||
filters.split('|').any(|or_filter| {
|
||||
or_filter.split('&').all(|and_filter| {
|
||||
and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter)
|
||||
let and_filter_trimmed = and_filter.trim();
|
||||
and_filter_trimmed == "all"
|
||||
|| pass_name.contains(and_filter_trimmed)
|
||||
|| node_path.contains(and_filter_trimmed)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -77,7 +77,6 @@ pub fn provide(providers: &mut Providers) {
|
||||
generics_of,
|
||||
predicates_of,
|
||||
predicates_defined_on,
|
||||
projection_ty_from_predicates,
|
||||
explicit_predicates_of,
|
||||
super_predicates_of,
|
||||
super_predicates_that_define_assoc_type,
|
||||
@ -2352,29 +2351,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
|
||||
}
|
||||
}
|
||||
|
||||
fn projection_ty_from_predicates(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: (
|
||||
// ty_def_id
|
||||
DefId,
|
||||
// def_id of `N` in `<T as Trait>::N`
|
||||
DefId,
|
||||
),
|
||||
) -> Option<ty::ProjectionTy<'tcx>> {
|
||||
let (ty_def_id, item_def_id) = key;
|
||||
let mut projection_ty = None;
|
||||
for (predicate, _) in tcx.predicates_of(ty_def_id).predicates {
|
||||
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder()
|
||||
{
|
||||
if item_def_id == projection_predicate.projection_ty.item_def_id {
|
||||
projection_ty = Some(projection_predicate.projection_ty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
projection_ty
|
||||
}
|
||||
|
||||
/// Converts a specific `GenericBound` from the AST into a set of
|
||||
/// predicates that apply to the self type. A vector is returned
|
||||
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
|
||||
|
@ -2407,6 +2407,23 @@ fn clone_from(&mut self, other: &Self) {
|
||||
}
|
||||
}
|
||||
|
||||
/// The hash of a vector is the same as that of the corresponding slice,
|
||||
/// as required by the `core::borrow::Borrow` implementation.
|
||||
///
|
||||
/// ```
|
||||
/// use std::hash::{BuildHasher, Hash, Hasher};
|
||||
///
|
||||
/// fn hash_of(x: impl Hash, b: &impl BuildHasher) -> u64 {
|
||||
/// let mut h = b.build_hasher();
|
||||
/// x.hash(&mut h);
|
||||
/// h.finish()
|
||||
/// }
|
||||
///
|
||||
/// let b = std::collections::hash_map::RandomState::new();
|
||||
/// let v: Vec<u8> = vec![0xa8, 0x3c, 0x09];
|
||||
/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
|
||||
/// assert_eq!(hash_of(v, &b), hash_of(s, &b));
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Hash, A: Allocator> Hash for Vec<T, A> {
|
||||
#[inline]
|
||||
|
@ -139,6 +139,23 @@ fn borrow_mut(&mut self) -> &mut [T] {
|
||||
}
|
||||
}
|
||||
|
||||
/// The hash of an array is the same as that of the corresponding slice,
|
||||
/// as required by the `Borrow` implementation.
|
||||
///
|
||||
/// ```
|
||||
/// use std::hash::{BuildHasher, Hash, Hasher};
|
||||
///
|
||||
/// fn hash_of(x: impl Hash, b: &impl BuildHasher) -> u64 {
|
||||
/// let mut h = b.build_hasher();
|
||||
/// x.hash(&mut h);
|
||||
/// h.finish()
|
||||
/// }
|
||||
///
|
||||
/// let b = std::collections::hash_map::RandomState::new();
|
||||
/// let a: [u8; 3] = [0xa8, 0x3c, 0x09];
|
||||
/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
|
||||
/// assert_eq!(hash_of(a, &b), hash_of(s, &b));
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Hash, const N: usize> Hash for [T; N] {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
|
@ -194,7 +194,7 @@ pub const fn from_raw_parts(
|
||||
}
|
||||
}
|
||||
|
||||
/// Decompose a (possibly wide) pointer into is address and metadata components.
|
||||
/// Decompose a (possibly wide) pointer into its address and metadata components.
|
||||
///
|
||||
/// The pointer can be later reconstructed with [`NonNull::from_raw_parts`].
|
||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||
|
@ -2256,6 +2256,9 @@ mod await_keyword {}
|
||||
/// At run-time, when a method needs to be called on the `dyn Trait`, the vtable is consulted to get
|
||||
/// the function pointer and then that function pointer is called.
|
||||
///
|
||||
/// See the Reference for more information on [trait objects][ref-trait-obj]
|
||||
/// and [object safety][ref-obj-safety].
|
||||
///
|
||||
/// ## Trade-offs
|
||||
///
|
||||
/// The above indirection is the additional runtime cost of calling a function on a `dyn Trait`.
|
||||
@ -2264,9 +2267,9 @@ mod await_keyword {}
|
||||
/// However, `dyn Trait` is likely to produce smaller code than `impl Trait` / generic parameters as
|
||||
/// the method won't be duplicated for each concrete type.
|
||||
///
|
||||
/// Read more about `object safety` and [trait object]s.
|
||||
///
|
||||
/// [trait object]: ../book/ch17-02-trait-objects.html
|
||||
/// [ref-trait-obj]: ../reference/types/trait-object.html
|
||||
/// [ref-obj-safety]: ../reference/items/traits.html#object-safety
|
||||
/// [erased]: https://en.wikipedia.org/wiki/Type_erasure
|
||||
mod dyn_keyword {}
|
||||
|
||||
|
@ -488,7 +488,7 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
|
||||
.into(),
|
||||
("auto-hide-large-items", "Auto-hide item contents for large items.", true).into(),
|
||||
("auto-hide-method-docs", "Auto-hide item methods' documentation", false).into(),
|
||||
("auto-hide-trait-implementations", "Auto-hide trait implementation documentation", true)
|
||||
("auto-hide-trait-implementations", "Auto-hide trait implementation documentation", false)
|
||||
.into(),
|
||||
("auto-collapse-implementors", "Auto-hide implementors of a trait", true).into(),
|
||||
("go-to-only-result", "Directly go to item in search if there is only one result", false)
|
||||
@ -1543,15 +1543,10 @@ fn render_default_items(
|
||||
}
|
||||
}
|
||||
if render_mode == RenderMode::Normal {
|
||||
let is_implementing_trait = i.inner_impl().trait_.is_some();
|
||||
let toggled = !impl_items.is_empty() || !default_impl_items.is_empty();
|
||||
if toggled {
|
||||
close_tags.insert_str(0, "</details>");
|
||||
if is_implementing_trait {
|
||||
write!(w, "<details class=\"rustdoc-toggle implementors-toggle\">");
|
||||
} else {
|
||||
write!(w, "<details class=\"rustdoc-toggle implementors-toggle\" open>");
|
||||
}
|
||||
write!(w, "<details class=\"rustdoc-toggle implementors-toggle\" open>");
|
||||
}
|
||||
if toggled {
|
||||
write!(w, "<summary>")
|
||||
|
@ -864,7 +864,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
|
||||
if fields.peek().is_some() {
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"fields\" class=\"fields small-section-header\">
|
||||
"<h2 id=\"fields\" class=\"fields small-section-header\">\
|
||||
Fields<a href=\"#fields\" class=\"anchor\"></a></h2>"
|
||||
);
|
||||
for (field, ty) in fields {
|
||||
@ -953,8 +953,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
||||
if !e.variants.is_empty() {
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"variants\" class=\"variants small-section-header\">
|
||||
Variants{}<a href=\"#variants\" class=\"anchor\"></a></h2>\n",
|
||||
"<h2 id=\"variants\" class=\"variants small-section-header\">\
|
||||
Variants{}<a href=\"#variants\" class=\"anchor\"></a></h2>",
|
||||
document_non_exhaustive_header(it)
|
||||
);
|
||||
document_non_exhaustive(w, it);
|
||||
@ -1139,7 +1139,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
||||
if fields.peek().is_some() {
|
||||
write!(
|
||||
w,
|
||||
"<h2 id=\"fields\" class=\"fields small-section-header\">
|
||||
"<h2 id=\"fields\" class=\"fields small-section-header\">\
|
||||
Fields{}<a href=\"#fields\" class=\"anchor\"></a></h2>",
|
||||
document_non_exhaustive_header(it)
|
||||
);
|
||||
|
@ -779,25 +779,25 @@ function hideThemeButtonState() {
|
||||
|
||||
var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
|
||||
var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false";
|
||||
var hideImplementations = getSettingValue("auto-hide-trait-implementations") !== "false";
|
||||
var hideImplementations = getSettingValue("auto-hide-trait-implementations") === "true";
|
||||
var hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
|
||||
|
||||
function openImplementors(id) {
|
||||
function setImplementorsTogglesOpen(id, open) {
|
||||
var list = document.getElementById(id);
|
||||
if (list !== null) {
|
||||
onEachLazy(list.getElementsByClassName("implementors-toggle"), function(e) {
|
||||
e.open = true;
|
||||
e.open = open;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!hideImplementations) {
|
||||
openImplementors("trait-implementations-list");
|
||||
openImplementors("blanket-implementations-list");
|
||||
if (hideImplementations) {
|
||||
setImplementorsTogglesOpen("trait-implementations-list", false);
|
||||
setImplementorsTogglesOpen("blanket-implementations-list", false);
|
||||
}
|
||||
|
||||
if (!hideImplementors) {
|
||||
openImplementors("implementors-list");
|
||||
setImplementorsTogglesOpen("implementors-list", true);
|
||||
}
|
||||
|
||||
onEachLazy(document.getElementsByClassName("rustdoc-toggle"), function (e) {
|
||||
|
5
src/test/rustdoc-gui/toggled-open-implementations.goml
Normal file
5
src/test/rustdoc-gui/toggled-open-implementations.goml
Normal file
@ -0,0 +1,5 @@
|
||||
// This tests that the "implementations" section on struct/enum pages
|
||||
// has all the implementations toggled open by default, so users can
|
||||
// find method names in those implementations with Ctrl-F.
|
||||
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||
assert: (".rustdoc-toggle.implementors-toggle", "open", "")
|
15
src/test/ui/fmt/format-concat-span.rs
Normal file
15
src/test/ui/fmt/format-concat-span.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// If the format string is another macro invocation, rustc would previously
|
||||
// compute nonsensical spans, such as:
|
||||
//
|
||||
// error: invalid format string: unmatched `}` found
|
||||
// --> test.rs:2:17
|
||||
// |
|
||||
// 2 | format!(concat!("abc}"));
|
||||
// | ^ unmatched `}` in format string
|
||||
//
|
||||
// This test checks that this behavior has been fixed.
|
||||
|
||||
fn main() {
|
||||
format!(concat!("abc}"));
|
||||
//~^ ERROR: invalid format string: unmatched `}` found
|
||||
}
|
11
src/test/ui/fmt/format-concat-span.stderr
Normal file
11
src/test/ui/fmt/format-concat-span.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/format-concat-span.rs:13:13
|
||||
|
|
||||
LL | format!(concat!("abc}"));
|
||||
| ^^^^^^^^^^^^^^^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
6
src/test/ui/fmt/issue-86085.rs
Normal file
6
src/test/ui/fmt/issue-86085.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// Tests for an ICE with the fuzzed input below.
|
||||
|
||||
fn main ( ) {
|
||||
format ! ( concat ! ( r#"lJÆ<F0908FBF>.<>"# , "r} {}" ) ) ;
|
||||
//~^ ERROR: invalid format string: unmatched `}` found
|
||||
}
|
11
src/test/ui/fmt/issue-86085.stderr
Normal file
11
src/test/ui/fmt/issue-86085.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/issue-86085.rs:4:12
|
||||
|
|
||||
LL | format ! ( concat ! ( r#"lJÆ<F0908FBF>.<>"# , "r} {}" ) ) ;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user