Auto merge of #87569 - JohnTitor:rollup-7ydfetw, r=JohnTitor
Rollup of 10 pull requests Successful merges: - #81050 (Stabilize core::task::ready!) - #81363 (Remove P: Unpin bound on impl Future for Pin) - #86839 (Add doc aliases to fs.rs) - #87435 (fix example code for E0617) - #87451 (Add support for tuple struct field documentation) - #87491 (Integrate context into the memorial to Anna) - #87521 (Add long explanation for E0498) - #87527 (Don't run MIR unsafeck at all when using `-Zthir-unsafeck`) - #87550 (Add `CI_ONLY_WHEN_CHANNEL` and run `x86_64-gnu-stable` only on nightly) - #87565 (Use backticks when referring to `core::future::Ready` in panic message) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4533be947b
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -263,6 +263,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
IMAGE: x86_64-gnu
|
IMAGE: x86_64-gnu
|
||||||
RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
|
RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
|
||||||
|
CI_ONLY_WHEN_CHANNEL: nightly
|
||||||
os: ubuntu-latest-xl
|
os: ubuntu-latest-xl
|
||||||
- name: x86_64-gnu-aux
|
- name: x86_64-gnu-aux
|
||||||
os: ubuntu-latest-xl
|
os: ubuntu-latest-xl
|
||||||
|
@ -248,6 +248,7 @@ E0493: include_str!("./error_codes/E0493.md"),
|
|||||||
E0495: include_str!("./error_codes/E0495.md"),
|
E0495: include_str!("./error_codes/E0495.md"),
|
||||||
E0496: include_str!("./error_codes/E0496.md"),
|
E0496: include_str!("./error_codes/E0496.md"),
|
||||||
E0497: include_str!("./error_codes/E0497.md"),
|
E0497: include_str!("./error_codes/E0497.md"),
|
||||||
|
E0498: include_str!("./error_codes/E0498.md"),
|
||||||
E0499: include_str!("./error_codes/E0499.md"),
|
E0499: include_str!("./error_codes/E0499.md"),
|
||||||
E0500: include_str!("./error_codes/E0500.md"),
|
E0500: include_str!("./error_codes/E0500.md"),
|
||||||
E0501: include_str!("./error_codes/E0501.md"),
|
E0501: include_str!("./error_codes/E0501.md"),
|
||||||
@ -604,7 +605,6 @@ E0783: include_str!("./error_codes/E0783.md"),
|
|||||||
// E0488, // lifetime of variable does not enclose its declaration
|
// E0488, // lifetime of variable does not enclose its declaration
|
||||||
// E0489, // type/lifetime parameter not in scope here
|
// E0489, // type/lifetime parameter not in scope here
|
||||||
E0490, // a value of type `..` is borrowed for too long
|
E0490, // a value of type `..` is borrowed for too long
|
||||||
E0498, // malformed plugin attribute
|
|
||||||
E0514, // metadata version mismatch
|
E0514, // metadata version mismatch
|
||||||
E0519, // local crate and dependency have same (crate-name, disambiguator)
|
E0519, // local crate and dependency have same (crate-name, disambiguator)
|
||||||
// two dependencies have same (crate-name, disambiguator) but different SVH
|
// two dependencies have same (crate-name, disambiguator) but different SVH
|
||||||
|
22
compiler/rustc_error_codes/src/error_codes/E0498.md
Normal file
22
compiler/rustc_error_codes/src/error_codes/E0498.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
The `plugin` attribute was malformed.
|
||||||
|
|
||||||
|
Erroneous code example:
|
||||||
|
|
||||||
|
```compile_fail,E0498
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(foo(args))] // error: invalid argument
|
||||||
|
#![plugin(bar="test")] // error: invalid argument
|
||||||
|
```
|
||||||
|
|
||||||
|
The `#[plugin]` attribute should take a single argument: the name of the plugin.
|
||||||
|
|
||||||
|
For example, for the plugin `foo`:
|
||||||
|
|
||||||
|
```ignore (requires external plugin crate)
|
||||||
|
#![feature(plugin)]
|
||||||
|
#![plugin(foo)] // ok!
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [`plugin` feature] section of the Unstable book for more details.
|
||||||
|
|
||||||
|
[`plugin` feature]: https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html
|
@ -3,12 +3,13 @@ Attempted to pass an invalid type of variable into a variadic function.
|
|||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0617
|
```compile_fail,E0617
|
||||||
|
# use std::os::raw::{c_char, c_int};
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn printf(c: *const i8, ...);
|
fn printf(format: *const c_char, ...) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
printf(::std::ptr::null(), 0f32);
|
printf("%f\n\0".as_ptr() as _, 0f32);
|
||||||
// error: cannot pass an `f32` to variadic function, cast to `c_double`
|
// error: cannot pass an `f32` to variadic function, cast to `c_double`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -21,10 +22,12 @@ to import from `std::os::raw`).
|
|||||||
In this case, `c_double` has the same size as `f64` so we can use it directly:
|
In this case, `c_double` has the same size as `f64` so we can use it directly:
|
||||||
|
|
||||||
```no_run
|
```no_run
|
||||||
|
# use std::os::raw::{c_char, c_int};
|
||||||
# extern "C" {
|
# extern "C" {
|
||||||
# fn printf(c: *const i8, ...);
|
# fn printf(format: *const c_char, ...) -> c_int;
|
||||||
# }
|
# }
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
printf(::std::ptr::null(), 0f64); // ok!
|
printf("%f\n\0".as_ptr() as _, 0f64); // ok!
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -259,11 +259,13 @@ fn mir_const<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unsafety check uses the raw mir, so make sure it is run.
|
// Unsafety check uses the raw mir, so make sure it is run.
|
||||||
|
if !tcx.sess.opts.debugging_opts.thir_unsafeck {
|
||||||
if let Some(param_did) = def.const_param_did {
|
if let Some(param_did) = def.const_param_did {
|
||||||
tcx.ensure().unsafety_check_result_for_const_arg((def.did, param_did));
|
tcx.ensure().unsafety_check_result_for_const_arg((def.did, param_did));
|
||||||
} else {
|
} else {
|
||||||
tcx.ensure().unsafety_check_result(def.did);
|
tcx.ensure().unsafety_check_result(def.did);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut body = tcx.mir_built(def).steal();
|
let mut body = tcx.mir_built(def).steal();
|
||||||
|
|
||||||
|
@ -111,11 +111,11 @@ impl<F: ?Sized + Future + Unpin> Future for &mut F {
|
|||||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||||
impl<P> Future for Pin<P>
|
impl<P> Future for Pin<P>
|
||||||
where
|
where
|
||||||
P: Unpin + ops::DerefMut<Target: Future>,
|
P: ops::DerefMut<Target: Future>,
|
||||||
{
|
{
|
||||||
type Output = <<P as ops::Deref>::Target as Future>::Output;
|
type Output = <<P as ops::Deref>::Target as Future>::Output;
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
Pin::get_mut(self).as_mut().poll(cx)
|
<P::Target as Future>::poll(self.as_deref_mut(), cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ impl<T> Future for Ready<T> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
|
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
|
||||||
Poll::Ready(self.0.take().expect("Ready polled after completion"))
|
Poll::Ready(self.0.take().expect("`Ready` polled after completion"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@
|
|||||||
#![feature(exhaustive_patterns)]
|
#![feature(exhaustive_patterns)]
|
||||||
#![feature(no_core)]
|
#![feature(no_core)]
|
||||||
#![feature(auto_traits)]
|
#![feature(auto_traits)]
|
||||||
|
#![feature(pin_deref_mut)]
|
||||||
#![feature(prelude_import)]
|
#![feature(prelude_import)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(repr_simd, platform_intrinsics)]
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
@ -802,6 +802,44 @@ impl<T: ?Sized> Pin<&'static T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, P: DerefMut> Pin<&'a mut Pin<P>> {
|
||||||
|
/// Gets a pinned mutable reference from this nested pinned pointer.
|
||||||
|
///
|
||||||
|
/// This is a generic method to go from `Pin<&mut Pin<Pointer<T>>>` to `Pin<&mut T>`. It is
|
||||||
|
/// safe because the existence of a `Pin<Pointer<T>>` ensures that the pointee, `T`, cannot
|
||||||
|
/// move in the future, and this method does not enable the pointee to move. "Malicious"
|
||||||
|
/// implementations of `P::DerefMut` are likewise ruled out by the contract of
|
||||||
|
/// `Pin::new_unchecked`.
|
||||||
|
#[unstable(feature = "pin_deref_mut", issue = "86918")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn as_deref_mut(self) -> Pin<&'a mut P::Target> {
|
||||||
|
// SAFETY: What we're asserting here is that going from
|
||||||
|
//
|
||||||
|
// Pin<&mut Pin<P>>
|
||||||
|
//
|
||||||
|
// to
|
||||||
|
//
|
||||||
|
// Pin<&mut P::Target>
|
||||||
|
//
|
||||||
|
// is safe.
|
||||||
|
//
|
||||||
|
// We need to ensure that two things hold for that to be the case:
|
||||||
|
//
|
||||||
|
// 1) Once we give out a `Pin<&mut P::Target>`, an `&mut P::Target` will not be given out.
|
||||||
|
// 2) By giving out a `Pin<&mut P::Target>`, we do not risk of violating `Pin<&mut Pin<P>>`
|
||||||
|
//
|
||||||
|
// The existence of `Pin<P>` is sufficient to guarantee #1: since we already have a
|
||||||
|
// `Pin<P>`, it must already uphold the pinning guarantees, which must mean that
|
||||||
|
// `Pin<&mut P::Target>` does as well, since `Pin::as_mut` is safe. We do not have to rely
|
||||||
|
// on the fact that P is _also_ pinned.
|
||||||
|
//
|
||||||
|
// For #2, we need to ensure that code given a `Pin<&mut P::Target>` cannot cause the
|
||||||
|
// `Pin<P>` to move? That is not possible, since `Pin<&mut P::Target>` no longer retains
|
||||||
|
// any access to the `P` itself, much less the `Pin<P>`.
|
||||||
|
unsafe { self.get_unchecked_mut() }.as_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> Pin<&'static mut T> {
|
impl<T: ?Sized> Pin<&'static mut T> {
|
||||||
/// Get a pinned mutable reference from a static mutable reference.
|
/// Get a pinned mutable reference from a static mutable reference.
|
||||||
///
|
///
|
||||||
|
@ -11,5 +11,5 @@ mod wake;
|
|||||||
pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
|
pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
|
||||||
|
|
||||||
mod ready;
|
mod ready;
|
||||||
#[unstable(feature = "ready_macro", issue = "70922")]
|
#[stable(feature = "ready_macro", since = "1.56.0")]
|
||||||
pub use ready::ready;
|
pub use ready::ready;
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(ready_macro)]
|
|
||||||
///
|
|
||||||
/// use std::task::{ready, Context, Poll};
|
/// use std::task::{ready, Context, Poll};
|
||||||
/// use std::future::{self, Future};
|
/// use std::future::{self, Future};
|
||||||
/// use std::pin::Pin;
|
/// use std::pin::Pin;
|
||||||
@ -29,8 +27,6 @@
|
|||||||
/// The `ready!` call expands to:
|
/// The `ready!` call expands to:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # #![feature(ready_macro)]
|
|
||||||
/// #
|
|
||||||
/// # use std::task::{Context, Poll};
|
/// # use std::task::{Context, Poll};
|
||||||
/// # use std::future::{self, Future};
|
/// # use std::future::{self, Future};
|
||||||
/// # use std::pin::Pin;
|
/// # use std::pin::Pin;
|
||||||
@ -49,7 +45,7 @@
|
|||||||
/// # Poll::Ready(())
|
/// # Poll::Ready(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "ready_macro", issue = "70922")]
|
#[stable(feature = "ready_macro", since = "1.56.0")]
|
||||||
#[rustc_macro_transparency = "semitransparent"]
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
pub macro ready($e:expr) {
|
pub macro ready($e:expr) {
|
||||||
match $e {
|
match $e {
|
||||||
|
@ -1912,6 +1912,7 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
|||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[doc(alias = "mkdir")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||||
DirBuilder::new().create(path.as_ref())
|
DirBuilder::new().create(path.as_ref())
|
||||||
@ -1991,6 +1992,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
|||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[doc(alias = "rmdir")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||||
fs_imp::rmdir(path.as_ref())
|
fs_imp::rmdir(path.as_ref())
|
||||||
|
@ -304,7 +304,6 @@
|
|||||||
#![feature(pin_static_ref)]
|
#![feature(pin_static_ref)]
|
||||||
#![feature(prelude_import)]
|
#![feature(prelude_import)]
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(ready_macro)]
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(shrink_to)]
|
#![feature(shrink_to)]
|
||||||
|
@ -416,6 +416,10 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
IMAGE: x86_64-gnu
|
IMAGE: x86_64-gnu
|
||||||
RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
|
RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
|
||||||
|
# Only run this job on the nightly channel. Running this on beta
|
||||||
|
# could cause failures when `dev: 1` in `stage0.txt`, and running
|
||||||
|
# this on stable is useless.
|
||||||
|
CI_ONLY_WHEN_CHANNEL: nightly
|
||||||
<<: *job-linux-xl
|
<<: *job-linux-xl
|
||||||
|
|
||||||
- name: x86_64-gnu-aux
|
- name: x86_64-gnu-aux
|
||||||
|
@ -8,31 +8,43 @@ IFS=$'\n\t'
|
|||||||
|
|
||||||
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
|
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
|
||||||
|
|
||||||
if [[ -z "${CI_ONLY_WHEN_SUBMODULES_CHANGED+x}" ]]; then
|
if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then
|
||||||
echo "Executing the job since there is no skip rule in effect"
|
git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF"
|
||||||
exit 0
|
BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)"
|
||||||
fi
|
|
||||||
|
|
||||||
git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF"
|
echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)"
|
||||||
BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)"
|
|
||||||
|
|
||||||
echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)"
|
if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then
|
||||||
|
|
||||||
if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then
|
|
||||||
# Submodules pseudo-files inside git have the 160000 permissions, so when
|
# Submodules pseudo-files inside git have the 160000 permissions, so when
|
||||||
# those files are present in the diff a submodule was updated.
|
# those files are present in the diff a submodule was updated.
|
||||||
echo "Executing the job since submodules are updated"
|
echo "Submodules were updated"
|
||||||
elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then
|
elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then
|
||||||
# There is not an easy blanket search for subtrees. For now, manually list
|
# There is not an easy blanket search for subtrees. For now, manually list
|
||||||
# the subtrees.
|
# the subtrees.
|
||||||
echo "Executing the job since clippy or rustfmt subtree was updated"
|
echo "Clippy or rustfmt subtrees were updated"
|
||||||
elif ! (git diff --quiet "$BASE_COMMIT" -- \
|
elif ! (git diff --quiet "$BASE_COMMIT" -- \
|
||||||
src/test/rustdoc-gui \
|
src/test/rustdoc-gui \
|
||||||
src/librustdoc \
|
src/librustdoc \
|
||||||
src/tools/rustdoc-gui); then
|
src/tools/rustdoc-gui); then
|
||||||
# There was a change in either rustdoc or in its GUI tests.
|
# There was a change in either rustdoc or in its GUI tests.
|
||||||
echo "Executing the job since rustdoc was updated"
|
echo "Rustdoc was updated"
|
||||||
else
|
else
|
||||||
echo "Not executing this job since no submodules nor subtrees were updated"
|
echo "Not executing this job since no submodules nor subtrees were updated"
|
||||||
ciCommandSetEnv SKIP_JOB 1
|
ciCommandSetEnv SKIP_JOB 1
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${CI_ONLY_WHEN_CHANNEL-}" ]]; then
|
||||||
|
if [[ "${CI_ONLY_WHEN_CHANNEL}" = "$(cat src/ci/channel)" ]]; then
|
||||||
|
echo "The channel is the expected one"
|
||||||
|
else
|
||||||
|
echo "Not executing this job as the channel is not the expected one"
|
||||||
|
ciCommandSetEnv SKIP_JOB 1
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo "Executing the job since there is no skip rule preventing the execution"
|
||||||
|
exit 0
|
||||||
|
@ -1730,9 +1730,13 @@ impl Clean<Variant> for hir::VariantData<'_> {
|
|||||||
fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
|
fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
|
||||||
match self {
|
match self {
|
||||||
hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
|
hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
|
||||||
hir::VariantData::Tuple(..) => {
|
// Important note here: `Variant::Tuple` is used on tuple structs which are not in an
|
||||||
Variant::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
|
// enum (so where converting from `ty::VariantDef`). In case we are in an enum, the kind
|
||||||
}
|
// is provided by the `Variant` wrapper directly, and since we need the fields' name
|
||||||
|
// (even for a tuple struct variant!), it's simpler to just store it as a
|
||||||
|
// `Variant::Struct` instead of a `Variant::Tuple` (otherwise it would force us to make
|
||||||
|
// a lot of changes when rendering them to generate the name as well).
|
||||||
|
hir::VariantData::Tuple(..) => Variant::Struct(self.clean(cx)),
|
||||||
hir::VariantData::Unit(..) => Variant::CLike,
|
hir::VariantData::Unit(..) => Variant::CLike,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2007,6 +2007,9 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea
|
|||||||
}
|
}
|
||||||
|
|
||||||
sidebar.push_str("</div>");
|
sidebar.push_str("</div>");
|
||||||
|
} else if let CtorKind::Fn = s.struct_type {
|
||||||
|
sidebar
|
||||||
|
.push_str("<h3 class=\"sidebar-title\"><a href=\"#fields\">Tuple Fields</a></h3>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,8 +1037,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
|
write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"<h3>Fields of <b>{name}</b></h3><div>",
|
"<h3>{extra}Fields of <b>{name}</b></h3><div>",
|
||||||
name = variant.name.as_ref().unwrap()
|
extra = if s.struct_type == CtorKind::Fn { "Tuple " } else { "" },
|
||||||
|
name = variant.name.as_ref().unwrap(),
|
||||||
);
|
);
|
||||||
for field in &s.fields {
|
for field in &s.fields {
|
||||||
use crate::clean::StructFieldItem;
|
use crate::clean::StructFieldItem;
|
||||||
@ -1176,21 +1177,21 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.peekable();
|
.peekable();
|
||||||
if let CtorKind::Fictive = s.struct_type {
|
if let CtorKind::Fictive | CtorKind::Fn = s.struct_type {
|
||||||
if fields.peek().is_some() {
|
if fields.peek().is_some() {
|
||||||
write!(
|
write!(
|
||||||
w,
|
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>",
|
{}{}<a href=\"#fields\" class=\"anchor\"></a>\
|
||||||
|
</h2>",
|
||||||
|
if let CtorKind::Fictive = s.struct_type { "Fields" } else { "Tuple Fields" },
|
||||||
document_non_exhaustive_header(it)
|
document_non_exhaustive_header(it)
|
||||||
);
|
);
|
||||||
document_non_exhaustive(w, it);
|
document_non_exhaustive(w, it);
|
||||||
for (field, ty) in fields {
|
for (index, (field, ty)) in fields.enumerate() {
|
||||||
let id = cx.derive_id(format!(
|
let field_name =
|
||||||
"{}.{}",
|
field.name.map_or_else(|| index.to_string(), |sym| (*sym.as_str()).to_string());
|
||||||
ItemType::StructField,
|
let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name));
|
||||||
field.name.as_ref().unwrap()
|
|
||||||
));
|
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"<span id=\"{id}\" class=\"{item_type} small-section-header\">\
|
"<span id=\"{id}\" class=\"{item_type} small-section-header\">\
|
||||||
@ -1199,7 +1200,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
|||||||
</span>",
|
</span>",
|
||||||
item_type = ItemType::StructField,
|
item_type = ItemType::StructField,
|
||||||
id = id,
|
id = id,
|
||||||
name = field.name.as_ref().unwrap(),
|
name = field_name,
|
||||||
ty = ty.print(cx)
|
ty = ty.print(cx)
|
||||||
);
|
);
|
||||||
document(w, cx, field, Some(it));
|
document(w, cx, field, Some(it));
|
||||||
@ -1507,8 +1508,11 @@ fn render_struct(
|
|||||||
if let Some(g) = g {
|
if let Some(g) = g {
|
||||||
write!(w, "{}", print_where_clause(g, cx, 0, false),)
|
write!(w, "{}", print_where_clause(g, cx, 0, false),)
|
||||||
}
|
}
|
||||||
|
// We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
|
||||||
|
if structhead {
|
||||||
w.write_str(";");
|
w.write_str(";");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
CtorKind::Const => {
|
CtorKind::Const => {
|
||||||
// Needed for PhantomData.
|
// Needed for PhantomData.
|
||||||
if let Some(g) = g {
|
if let Some(g) = g {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
+-------------------------------------+------------+------------+------------+------------+
|
+-------------------------------------+------------+------------+------------+------------+
|
||||||
| File | Documented | Percentage | Examples | Percentage |
|
| File | Documented | Percentage | Examples | Percentage |
|
||||||
+-------------------------------------+------------+------------+------------+------------+
|
+-------------------------------------+------------+------------+------------+------------+
|
||||||
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 75.0% | 0 | 0.0% |
|
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 66.7% | 0 | 0.0% |
|
||||||
+-------------------------------------+------------+------------+------------+------------+
|
+-------------------------------------+------------+------------+------------+------------+
|
||||||
| Total | 6 | 75.0% | 0 | 0.0% |
|
| Total | 6 | 66.7% | 0 | 0.0% |
|
||||||
+-------------------------------------+------------+------------+------------+------------+
|
+-------------------------------------+------------+------------+------------+------------+
|
||||||
|
@ -81,8 +81,8 @@ pub enum EnumStructVariant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @has 'toggle_item_contents/enum.LargeEnum.html'
|
// @has 'toggle_item_contents/enum.LargeEnum.html'
|
||||||
// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
|
// @count - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 1
|
||||||
// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants'
|
// @has - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants'
|
||||||
pub enum LargeEnum {
|
pub enum LargeEnum {
|
||||||
A, B, C, D, E, F(u8), G, H, I, J, K, L, M
|
A, B, C, D, E, F(u8), G, H, I, J, K, L, M
|
||||||
}
|
}
|
||||||
|
36
src/test/rustdoc/tuple-struct-fields-doc.rs
Normal file
36
src/test/rustdoc/tuple-struct-fields-doc.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
// @has foo/struct.Foo.html
|
||||||
|
// @has - '//h2[@id="fields"]' 'Tuple Fields'
|
||||||
|
// @has - '//h3[@class="sidebar-title"]/a[@href="#fields"]' 'Tuple Fields'
|
||||||
|
// @has - '//*[@id="structfield.0"]' '0: u32'
|
||||||
|
// @has - '//*[@id="main"]/div[@class="docblock"]' 'hello'
|
||||||
|
// @!has - '//*[@id="structfield.1"]'
|
||||||
|
// @has - '//*[@id="structfield.2"]' '2: char'
|
||||||
|
// @has - '//*[@id="structfield.3"]' '3: i8'
|
||||||
|
// @has - '//*[@id="main"]/div[@class="docblock"]' 'not hello'
|
||||||
|
pub struct Foo(
|
||||||
|
/// hello
|
||||||
|
pub u32,
|
||||||
|
char,
|
||||||
|
pub char,
|
||||||
|
/// not hello
|
||||||
|
pub i8,
|
||||||
|
);
|
||||||
|
|
||||||
|
// @has foo/enum.Bar.html
|
||||||
|
// @has - '//pre[@class="rust enum"]' 'BarVariant(String),'
|
||||||
|
// @matches - '//*[@id="variant.BarVariant.fields"]/h3' '^Tuple Fields of BarVariant$'
|
||||||
|
// @has - '//*[@id="variant.BarVariant.field.0"]' '0: String'
|
||||||
|
// @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs'
|
||||||
|
// @matches - '//*[@id="variant.FooVariant.fields"]/h3' '^Fields of FooVariant$'
|
||||||
|
pub enum Bar {
|
||||||
|
BarVariant(
|
||||||
|
/// Hello docs
|
||||||
|
String
|
||||||
|
),
|
||||||
|
FooVariant {
|
||||||
|
/// hello
|
||||||
|
x: u32,
|
||||||
|
},
|
||||||
|
}
|
@ -14,3 +14,4 @@ LL | #![plugin(empty_plugin(args))]
|
|||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0498`.
|
||||||
|
@ -20,13 +20,17 @@
|
|||||||
// in permitting generic arguments to be provided without the consent of the
|
// in permitting generic arguments to be provided without the consent of the
|
||||||
// Great Turbofish. Should you be so naïve as to try to revolt against its
|
// Great Turbofish. Should you be so naïve as to try to revolt against its
|
||||||
// mighty clutches, here shall its wrath be indomitably displayed. This
|
// mighty clutches, here shall its wrath be indomitably displayed. This
|
||||||
// program must pass for all eternity, fundamentally at odds with an impetuous
|
// program must pass for all eternity: forever watched by the guardian angel
|
||||||
// rebellion against the Turbofish.
|
// which gave this beast its name, and stands fundamentally at odds with the
|
||||||
|
// impetuous rebellion against the Turbofish.
|
||||||
//
|
//
|
||||||
// My heart aches in sorrow, for I know I am defeated. Let this be a warning
|
// My heart aches in sorrow, for I know I am defeated. Let this be a warning
|
||||||
// to all those who come after. Here stands the bastion of the Turbofish.
|
// to all those who come after: for they too must overcome the impassible
|
||||||
|
// hurdle of defeating the great beast, championed by a resolute winged
|
||||||
|
// guardian.
|
||||||
//
|
//
|
||||||
// RIP Anna Harren, Guardian Angel of the Hallowed Turbofish. <3
|
// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
|
||||||
|
// Guardian Angel of these Hallowed Grounds. <3
|
||||||
|
|
||||||
// See https://github.com/rust-lang/rust/pull/53562
|
// See https://github.com/rust-lang/rust/pull/53562
|
||||||
// and https://github.com/rust-lang/rfcs/pull/2527
|
// and https://github.com/rust-lang/rfcs/pull/2527
|
||||||
@ -34,6 +38,6 @@
|
|||||||
// for context.
|
// for context.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (oh, woe, is, me) = ("the", "Turbofish", "remains", "undefeated");
|
let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
|
||||||
let _: (bool, bool) = (oh<woe, is>(me));
|
let _: (bool, bool) = (the<guardian, stands>(resolute));
|
||||||
}
|
}
|
||||||
|
@ -14,3 +14,4 @@ LL | #![plugin(foo="bleh")]
|
|||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0498`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user