Auto merge of #101295 - matthiaskrgr:rollup-046o38p, r=matthiaskrgr

Rollup of 14 pull requests

Successful merges:

 - #94467 (Add `special_module_name` lint)
 - #100852 (Use `getuid` to check instead of `USER` env var in rustbuild)
 - #101072 (bootstrap: Add llvm-has-rust-patches target option)
 - #101190 (Make docs formulation more consistent for NonZero{int})
 - #101245 (Remove unneeded where whitespace)
 - #101251 (Fix  bad target name in Walkthrough)
 - #101254 (rustdoc: remove unused `.docblock .impl-items` CSS)
 - #101256 (Fixes/adjustments to Fuchsia doc walkthrough)
 - #101270 (Update outdated comment about output capturing in print_to.)
 - #101271 (Fix filename of armv4t-none-eabi.md)
 - #101274 (Fix typo in comment)
 - #101279 (Fix doc_auto_cfg for impl blocks in different modules with different `cfg`)
 - #101285 (Do not suggest adding `move` to closure when `move` is already used)
 - #101292 (rustdoc: remove unneeded CSS `.content table td:first-child > a`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-09-01 22:12:32 +00:00
commit 10706d62da
50 changed files with 412 additions and 136 deletions

1
.gitignore vendored
View File

@ -46,6 +46,7 @@ no_llvm_build
/dist/ /dist/
/unicode-downloads /unicode-downloads
/target /target
/src/bootstrap/target
/src/tools/x/target /src/tools/x/target
# Created by default with `src/ci/docker/run.sh` # Created by default with `src/ci/docker/run.sh`
/obj/ /obj/

View File

@ -902,7 +902,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
hir::ExprKind::MethodCall(.., args, _) => { hir::ExprKind::MethodCall(.., args, _) => {
// only the first closre parameter of the method. args[0] is MethodCall PathSegment // only the first closre parameter of the method. args[0] is MethodCall PathSegment
for i in 1..args.len() { for i in 1..args.len() {
if let hir::ExprKind::Closure(..) = args[i].kind { if let hir::ExprKind::Closure(hir::Closure {
capture_clause: hir::CaptureBy::Ref,
..
}) = args[i].kind
{
closure_span = Some(args[i].span.shrink_to_lo()); closure_span = Some(args[i].span.shrink_to_lo());
break; break;
} }
@ -911,7 +915,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
hir::ExprKind::Block(blk, _) => { hir::ExprKind::Block(blk, _) => {
if let Some(ref expr) = blk.expr { if let Some(ref expr) = blk.expr {
// only when the block is a closure // only when the block is a closure
if let hir::ExprKind::Closure(..) = expr.kind { if let hir::ExprKind::Closure(hir::Closure {
capture_clause: hir::CaptureBy::Ref,
..
}) = expr.kind
{
closure_span = Some(expr.span.shrink_to_lo()); closure_span = Some(expr.span.shrink_to_lo());
} }
} }
@ -921,7 +929,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(closure_span) = closure_span { if let Some(closure_span) = closure_span {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
closure_span, closure_span,
format!("consider adding 'move' keyword before the nested closure"), "consider adding 'move' keyword before the nested closure",
"move ", "move ",
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );

View File

@ -3172,3 +3172,81 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
} }
} }
} }
declare_lint! {
/// The `special_module_name` lint detects module
/// declarations for files that have a special meaning.
///
/// ### Example
///
/// ```rust,compile_fail
/// mod lib;
///
/// fn main() {
/// lib::run();
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Cargo recognizes `lib.rs` and `main.rs` as the root of a
/// library or binary crate, so declaring them as modules
/// will lead to miscompilation of the crate unless configured
/// explicitly.
///
/// To access a library from a binary target within the same crate,
/// use `your_crate_name::` as the path path instead of `lib::`:
///
/// ```rust,compile_fail
/// // bar/src/lib.rs
/// fn run() {
/// // ...
/// }
///
/// // bar/src/main.rs
/// fn main() {
/// bar::run();
/// }
/// ```
///
/// Binary targets cannot be used as libraries and so declaring
/// one as a module is not allowed.
pub SPECIAL_MODULE_NAME,
Warn,
"module declarations for files with a special meaning",
}
declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]);
impl EarlyLintPass for SpecialModuleName {
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
for item in &krate.items {
if let ast::ItemKind::Mod(
_,
ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
) = item.kind
{
if item.attrs.iter().any(|a| a.has_name(sym::path)) {
continue;
}
match item.ident.name.as_str() {
"lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
lint.build("found module declaration for lib.rs")
.note("lib.rs is the root of this crate's library target")
.help("to refer to it from other targets, use the library's name as the path")
.emit()
}),
"main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
lint.build("found module declaration for main.rs")
.note("a binary crate cannot be used as library")
.emit()
}),
_ => continue
}
}
}
}
}

View File

@ -133,6 +133,7 @@ macro_rules! early_lint_passes {
UnusedBraces: UnusedBraces, UnusedBraces: UnusedBraces,
UnusedImportBraces: UnusedImportBraces, UnusedImportBraces: UnusedImportBraces,
UnsafeCode: UnsafeCode, UnsafeCode: UnsafeCode,
SpecialModuleName: SpecialModuleName,
AnonymousParameters: AnonymousParameters, AnonymousParameters: AnonymousParameters,
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(), EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
NonCamelCaseTypes: NonCamelCaseTypes, NonCamelCaseTypes: NonCamelCaseTypes,

View File

@ -666,6 +666,10 @@ changelog-seen = 2
# target. # target.
#llvm-config = <none> (path) #llvm-config = <none> (path)
# Override detection of whether this is a Rust-patched LLVM. This would be used
# in conjunction with either an llvm-config or build.submodules = false.
#llvm-has-rust-patches = if llvm-config { false } else { true }
# Normally the build system can find LLVM's FileCheck utility, but if # Normally the build system can find LLVM's FileCheck utility, but if
# not, you can specify an explicit file name for it. # not, you can specify an explicit file name for it.
#llvm-filecheck = "/path/to/llvm-version/bin/FileCheck" #llvm-filecheck = "/path/to/llvm-version/bin/FileCheck"

View File

@ -309,8 +309,8 @@ macro_rules! nonzero_unsigned_operations {
( $( $Ty: ident($Int: ident); )+ ) => { ( $( $Ty: ident($Int: ident); )+ ) => {
$( $(
impl $Ty { impl $Ty {
/// Add an unsigned integer to a non-zero value. /// Adds an unsigned integer to a non-zero value.
/// Check for overflow and return [`None`] on overflow /// Checks for overflow and returns [`None`] on overflow.
/// As a consequence, the result cannot wrap to zero. /// As a consequence, the result cannot wrap to zero.
/// ///
/// ///
@ -346,7 +346,7 @@ macro_rules! nonzero_unsigned_operations {
} }
} }
/// Add an unsigned integer to a non-zero value. /// Adds an unsigned integer to a non-zero value.
#[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")]
/// ///
/// # Examples /// # Examples
@ -377,7 +377,7 @@ macro_rules! nonzero_unsigned_operations {
unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) }
} }
/// Add an unsigned integer to a non-zero value, /// Adds an unsigned integer to a non-zero value,
/// assuming overflow cannot occur. /// assuming overflow cannot occur.
/// Overflow is unchecked, and it is undefined behaviour to overflow /// Overflow is unchecked, and it is undefined behaviour to overflow
/// *even if the result would wrap to a non-zero value*. /// *even if the result would wrap to a non-zero value*.
@ -409,7 +409,7 @@ macro_rules! nonzero_unsigned_operations {
} }
/// Returns the smallest power of two greater than or equal to n. /// Returns the smallest power of two greater than or equal to n.
/// Check for overflow and return [`None`] /// Checks for overflow and returns [`None`]
/// if the next power of two is greater than the types maximum value. /// if the next power of two is greater than the types maximum value.
/// As a consequence, the result cannot wrap to zero. /// As a consequence, the result cannot wrap to zero.
/// ///
@ -545,7 +545,7 @@ macro_rules! nonzero_signed_operations {
} }
/// Checked absolute value. /// Checked absolute value.
/// Check for overflow and returns [`None`] if /// Checks for overflow and returns [`None`] if
#[doc = concat!("`self == ", stringify!($Int), "::MIN`.")] #[doc = concat!("`self == ", stringify!($Int), "::MIN`.")]
/// The result cannot be zero. /// The result cannot be zero.
/// ///
@ -740,8 +740,8 @@ macro_rules! nonzero_unsigned_signed_operations {
( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => { ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => {
$( $(
impl $Ty { impl $Ty {
/// Multiply two non-zero integers together. /// Multiplies two non-zero integers together.
/// Check for overflow and return [`None`] on overflow. /// Checks for overflow and returns [`None`] on overflow.
/// As a consequence, the result cannot wrap to zero. /// As a consequence, the result cannot wrap to zero.
/// ///
/// # Examples /// # Examples
@ -777,7 +777,7 @@ macro_rules! nonzero_unsigned_signed_operations {
} }
} }
/// Multiply two non-zero integers together. /// Multiplies two non-zero integers together.
#[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")]
/// ///
/// # Examples /// # Examples
@ -809,7 +809,7 @@ macro_rules! nonzero_unsigned_signed_operations {
unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) }
} }
/// Multiply two non-zero integers together, /// Multiplies two non-zero integers together,
/// assuming overflow cannot occur. /// assuming overflow cannot occur.
/// Overflow is unchecked, and it is undefined behaviour to overflow /// Overflow is unchecked, and it is undefined behaviour to overflow
/// *even if the result would wrap to a non-zero value*. /// *even if the result would wrap to a non-zero value*.
@ -849,8 +849,8 @@ macro_rules! nonzero_unsigned_signed_operations {
unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) }
} }
/// Raise non-zero value to an integer power. /// Raises non-zero value to an integer power.
/// Check for overflow and return [`None`] on overflow. /// Checks for overflow and returns [`None`] on overflow.
/// As a consequence, the result cannot wrap to zero. /// As a consequence, the result cannot wrap to zero.
/// ///
/// # Examples /// # Examples

View File

@ -986,10 +986,10 @@ pub fn set_output_capture(sink: Option<LocalStream>) -> Option<LocalStream> {
/// otherwise. `label` identifies the stream in a panic message. /// otherwise. `label` identifies the stream in a panic message.
/// ///
/// This function is used to print error messages, so it takes extra /// This function is used to print error messages, so it takes extra
/// care to avoid causing a panic when `local_s` is unusable. /// care to avoid causing a panic when `OUTPUT_CAPTURE` is unusable.
/// For instance, if the TLS key for the local stream is /// For instance, if the TLS key for output capturing is already destroyed, or
/// already destroyed, or if the local stream is locked by another /// if the local stream is in use by another thread, it will just fall back to
/// thread, it will just fall back to the global stream. /// the global stream.
/// ///
/// However, if the actual I/O causes an error, this function does panic. /// However, if the actual I/O causes an error, this function does panic.
fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str) fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)

View File

@ -793,6 +793,8 @@ class RustBuild(object):
def check_vendored_status(self): def check_vendored_status(self):
"""Check that vendoring is configured properly""" """Check that vendoring is configured properly"""
# keep this consistent with the equivalent check in rustbuild:
# https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/lib.rs#L399-L405
if 'SUDO_USER' in os.environ and not self.use_vendored_sources: if 'SUDO_USER' in os.environ and not self.use_vendored_sources:
if os.getuid() == 0: if os.getuid() == 0:
self.use_vendored_sources = True self.use_vendored_sources = True

View File

@ -388,6 +388,7 @@ impl PartialEq<&str> for TargetSelection {
pub struct Target { pub struct Target {
/// Some(path to llvm-config) if using an external LLVM. /// Some(path to llvm-config) if using an external LLVM.
pub llvm_config: Option<PathBuf>, pub llvm_config: Option<PathBuf>,
pub llvm_has_rust_patches: Option<bool>,
/// Some(path to FileCheck) if one was specified. /// Some(path to FileCheck) if one was specified.
pub llvm_filecheck: Option<PathBuf>, pub llvm_filecheck: Option<PathBuf>,
pub llvm_libunwind: Option<LlvmLibunwind>, pub llvm_libunwind: Option<LlvmLibunwind>,
@ -733,6 +734,7 @@ define_config! {
default_linker: Option<PathBuf> = "default-linker", default_linker: Option<PathBuf> = "default-linker",
linker: Option<String> = "linker", linker: Option<String> = "linker",
llvm_config: Option<String> = "llvm-config", llvm_config: Option<String> = "llvm-config",
llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
llvm_filecheck: Option<String> = "llvm-filecheck", llvm_filecheck: Option<String> = "llvm-filecheck",
llvm_libunwind: Option<String> = "llvm-libunwind", llvm_libunwind: Option<String> = "llvm-libunwind",
android_ndk: Option<String> = "android-ndk", android_ndk: Option<String> = "android-ndk",
@ -1109,6 +1111,7 @@ impl Config {
if let Some(ref s) = cfg.llvm_config { if let Some(ref s) = cfg.llvm_config {
target.llvm_config = Some(config.src.join(s)); target.llvm_config = Some(config.src.join(s));
} }
target.llvm_has_rust_patches = cfg.llvm_has_rust_patches;
if let Some(ref s) = cfg.llvm_filecheck { if let Some(ref s) = cfg.llvm_filecheck {
target.llvm_filecheck = Some(config.src.join(s)); target.llvm_filecheck = Some(config.src.join(s));
} }

View File

@ -112,6 +112,7 @@ use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use std::str; use std::str;
use config::Target;
use filetime::FileTime; use filetime::FileTime;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@ -395,13 +396,18 @@ impl Build {
let src = config.src.clone(); let src = config.src.clone();
let out = config.out.clone(); let out = config.out.clone();
#[cfg(unix)]
// keep this consistent with the equivalent check in x.py:
// https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/bootstrap.py#L796-L797
let is_sudo = match env::var_os("SUDO_USER") { let is_sudo = match env::var_os("SUDO_USER") {
Some(sudo_user) => match env::var_os("USER") { Some(_sudo_user) => {
Some(user) => user != sudo_user, let uid = unsafe { libc::getuid() };
None => false, uid == 0
}, }
None => false, None => false,
}; };
#[cfg(not(unix))]
let is_sudo = false;
let ignore_git = config.ignore_git; let ignore_git = config.ignore_git;
let rust_info = channel::GitInfo::new(ignore_git, &src); let rust_info = channel::GitInfo::new(ignore_git, &src);
@ -834,12 +840,13 @@ impl Build {
/// ///
/// If no custom `llvm-config` was specified then Rust's llvm will be used. /// If no custom `llvm-config` was specified then Rust's llvm will be used.
fn is_rust_llvm(&self, target: TargetSelection) -> bool { fn is_rust_llvm(&self, target: TargetSelection) -> bool {
if self.config.llvm_from_ci && target == self.config.build {
return true;
}
match self.config.target_config.get(&target) { match self.config.target_config.get(&target) {
Some(ref c) => c.llvm_config.is_none(), Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched,
Some(Target { llvm_config, .. }) => {
// If the user set llvm-config we assume Rust is not patched,
// but first check to see if it was configured by llvm-from-ci.
(self.config.llvm_from_ci && target == self.config.build) || llvm_config.is_none()
}
None => true, None => true,
} }
} }

View File

@ -79,7 +79,7 @@ the following commands:
```sh ```sh
rustup target add x86_64-fuchsia rustup target add x86_64-fuchsia
rustup target add aarch_64-fuchsia rustup target add aarch64-fuchsia
``` ```
After installing our Fuchsia targets, we can now compile a Rust binary that targets After installing our Fuchsia targets, we can now compile a Rust binary that targets
@ -125,13 +125,20 @@ during compilation:
[target.x86_64-fuchsia] [target.x86_64-fuchsia]
rustflags = [ rustflags = [
"-Lnative", "<SDK_PATH>/arch/x64/sysroot/lib", "-Lnative=<SDK_PATH>/arch/x64/lib",
"-Lnative", "<SDK_PATH>/arch/x64/lib" "-Lnative=<SDK_PATH>/arch/x64/sysroot/lib"
] ]
``` ```
*Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].* *Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].*
These options configure the following:
* `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from
the SDK
* `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel
libraries from the SDK
In total, our new project will look like: In total, our new project will look like:
**Current directory structure** **Current directory structure**
@ -368,6 +375,7 @@ language called CML. The Fuchsia devsite contains an [overview of CML] and a
} }
``` ```
**Current directory structure**
```txt ```txt
hello_fuchsia/ hello_fuchsia/
┗━ pkg/ ┗━ pkg/
@ -386,6 +394,9 @@ ${SDK_PATH}/tools/${ARCH}/cmc compile \
-o pkg/meta/hello_fuchsia.cm -o pkg/meta/hello_fuchsia.cm
``` ```
*Note: `--includepath` tells the compiler where to look for `include`s from our CML.
In our case, we're only using `syslog/client.shard.cml`.*
**Current directory structure** **Current directory structure**
```txt ```txt
hello_fuchsia/ hello_fuchsia/
@ -397,19 +408,16 @@ hello_fuchsia/
┗━ hello_fuchsia.cml ┗━ hello_fuchsia.cml
``` ```
*Note: `--includepath` tells the compiler where to look for `include`s from our CML.
In our case, we're only using `syslog/client.shard.cml`.*
### Building a Fuchsia package ### Building a Fuchsia package
Next, we'll build a package manifest as defined by our manifest: Next, we'll build a package manifest as defined by our manifest:
```sh ```sh
${SDK_PATH}/tools/${ARCH}/pm \ ${SDK_PATH}/tools/${ARCH}/pm \
-o hello_fuchsia_manifest \ -o pkg/hello_fuchsia_manifest \
-m pkg/hello_fuchsia.manifest \ -m pkg/hello_fuchsia.manifest \
build \ build \
-output-package-manifest hello_fuchsia_package_manifest -output-package-manifest pkg/hello_fuchsia_package_manifest
``` ```
This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can
@ -469,15 +477,15 @@ We can publish our new package to that repository with:
```sh ```sh
${SDK_PATH}/tools/${ARCH}/pm publish \ ${SDK_PATH}/tools/${ARCH}/pm publish \
-repo repo \ -repo pkg/repo \
-lp -f <(echo "hello_fuchsia_package_manifest") -lp -f <(echo "pkg/hello_fuchsia_package_manifest")
``` ```
Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using: Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
```sh ```sh
${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \ ${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
repo \ pkg/repo \
-r hello-fuchsia -r hello-fuchsia
``` ```

View File

@ -349,8 +349,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
let where_preds = comma_sep(where_predicates, false); let where_preds = comma_sep(where_predicates, false);
let clause = if f.alternate() { let clause = if f.alternate() {
if ending == Ending::Newline { if ending == Ending::Newline {
// add a space so stripping <br> tags and breaking spaces still renders properly format!(" where{where_preds},")
format!(" where{where_preds}, ")
} else { } else {
format!(" where{where_preds}") format!(" where{where_preds}")
} }
@ -364,20 +363,16 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
if ending == Ending::Newline { if ending == Ending::Newline {
let mut clause = "&nbsp;".repeat(indent.saturating_sub(1)); let mut clause = "&nbsp;".repeat(indent.saturating_sub(1));
// add a space so stripping <br> tags and breaking spaces still renders properly write!(clause, "<span class=\"where fmt-newline\">where{where_preds},</span>")?;
write!(
clause,
" <span class=\"where fmt-newline\">where{where_preds},&nbsp;</span>"
)?;
clause clause
} else { } else {
// insert a <br> tag after a single space but before multiple spaces at the start // insert a <br> tag after a single space but before multiple spaces at the start
if indent == 0 { if indent == 0 {
format!(" <br><span class=\"where\">where{where_preds}</span>") format!("<br><span class=\"where\">where{where_preds}</span>")
} else { } else {
let mut clause = br_with_padding; let mut clause = br_with_padding;
clause.truncate(clause.len() - 5 * "&nbsp;".len()); clause.truncate(clause.len() - 5 * "&nbsp;".len());
write!(clause, " <span class=\"where\">where{where_preds}</span>")?; write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
clause clause
} }
} }

View File

@ -1737,8 +1737,8 @@ pub(crate) fn render_impl_summary(
// in documentation pages for trait with automatic implementations like "Send" and "Sync". // in documentation pages for trait with automatic implementations like "Send" and "Sync".
aliases: &[String], aliases: &[String],
) { ) {
let id = let inner_impl = i.inner_impl();
cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx)); let id = cx.derive_id(get_id_for_impl(&inner_impl.for_, inner_impl.trait_.as_ref(), cx));
let aliases = if aliases.is_empty() { let aliases = if aliases.is_empty() {
String::new() String::new()
} else { } else {
@ -1750,9 +1750,9 @@ pub(crate) fn render_impl_summary(
write!(w, "<h3 class=\"code-header in-band\">"); write!(w, "<h3 class=\"code-header in-band\">");
if let Some(use_absolute) = use_absolute { if let Some(use_absolute) = use_absolute {
write!(w, "{}", i.inner_impl().print(use_absolute, cx)); write!(w, "{}", inner_impl.print(use_absolute, cx));
if show_def_docs { if show_def_docs {
for it in &i.inner_impl().items { for it in &inner_impl.items {
if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
w.write_str("<span class=\"where fmt-newline\"> "); w.write_str("<span class=\"where fmt-newline\"> ");
assoc_type( assoc_type(
@ -1770,11 +1770,11 @@ pub(crate) fn render_impl_summary(
} }
} }
} else { } else {
write!(w, "{}", i.inner_impl().print(false, cx)); write!(w, "{}", inner_impl.print(false, cx));
} }
write!(w, "</h3>"); write!(w, "</h3>");
let is_trait = i.inner_impl().trait_.is_some(); let is_trait = inner_impl.trait_.is_some();
if is_trait { if is_trait {
if let Some(portability) = portability(&i.impl_item, Some(parent)) { if let Some(portability) = portability(&i.impl_item, Some(parent)) {
write!(w, "<span class=\"item-info\">{}</span>", portability); write!(w, "<span class=\"item-info\">{}</span>", portability);

View File

@ -207,7 +207,6 @@ h1, h2, h3, h4, h5, h6,
a.source, a.source,
.search-input, .search-input,
.search-results .result-name, .search-results .result-name,
.content table td:first-child > a,
.item-left > a, .item-left > a,
.out-of-band, .out-of-band,
span.since, span.since,
@ -759,14 +758,6 @@ pre, .rustdoc.source .example-wrap {
margin-bottom: 15px; margin-bottom: 15px;
} }
.content .docblock > .impl-items {
margin-left: 20px;
margin-top: -34px;
}
.content .docblock >.impl-items table td {
padding: 0;
}
.item-info { .item-info {
display: block; display: block;
} }

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use crate::clean::cfg::Cfg; use crate::clean::cfg::Cfg;
use crate::clean::inline::{load_attrs, merge_attrs}; use crate::clean::inline::{load_attrs, merge_attrs};
use crate::clean::{Crate, Item}; use crate::clean::{Crate, Item, ItemKind};
use crate::core::DocContext; use crate::core::DocContext;
use crate::fold::DocFolder; use crate::fold::DocFolder;
use crate::passes::Pass; use crate::passes::Pass;
@ -26,30 +26,50 @@ struct CfgPropagator<'a, 'tcx> {
cx: &'a mut DocContext<'tcx>, cx: &'a mut DocContext<'tcx>,
} }
impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
// Some items need to merge their attributes with their parents' otherwise a few of them
// (mostly `cfg` ones) will be missing.
fn merge_with_parent_attributes(&mut self, item: &mut Item) {
let check_parent = match &*item.kind {
// impl blocks can be in different modules with different cfg and we need to get them
// as well.
ItemKind::ImplItem(_) => false,
kind if kind.is_non_assoc() => true,
_ => return,
};
let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local())
else { return };
let hir = self.cx.tcx.hir();
let hir_id = hir.local_def_id_to_hir_id(def_id);
if check_parent {
let expected_parent = hir.get_parent_item(hir_id);
// If parents are different, it means that `item` is a reexport and we need
// to compute the actual `cfg` by iterating through its "real" parents.
if self.parent == Some(expected_parent) {
return;
}
}
let mut attrs = Vec::new();
for (parent_hir_id, _) in hir.parent_iter(hir_id) {
if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
}
}
let (_, cfg) = merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
item.cfg = cfg;
}
}
impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> { impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> {
fn fold_item(&mut self, mut item: Item) -> Option<Item> { fn fold_item(&mut self, mut item: Item) -> Option<Item> {
let old_parent_cfg = self.parent_cfg.clone(); let old_parent_cfg = self.parent_cfg.clone();
if item.kind.is_non_assoc() && self.merge_with_parent_attributes(&mut item);
let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) {
let hir = self.cx.tcx.hir();
let hir_id = hir.local_def_id_to_hir_id(def_id);
let expected_parent = hir.get_parent_item(hir_id);
// If parents are different, it means that `item` is a reexport and we need to compute
// the actual `cfg` by iterating through its "real" parents.
if self.parent != Some(expected_parent) {
let mut attrs = Vec::new();
for (parent_hir_id, _) in hir.parent_iter(hir_id) {
if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
}
}
let (_, cfg) =
merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
item.cfg = cfg;
}
}
let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) { let new_cfg = match (self.parent_cfg.take(), item.cfg.take()) {
(None, None) => None, (None, None) => None,
(Some(rc), None) | (None, Some(rc)) => Some(rc), (Some(rc), None) | (None, Some(rc)) => Some(rc),

View File

@ -91,7 +91,7 @@ impl<'a> DocFolder for Stripper<'a> {
clean::ExternCrateItem { .. } => {} clean::ExternCrateItem { .. } => {}
clean::ImportItem(ref imp) => { clean::ImportItem(ref imp) => {
// Because json doesn't inline imports from private modules, we need to mark // Because json doesn't inline imports from private modules, we need to mark
// the imported item as retained so it's impls won't be stripped.i // the imported item as retained so it's impls won't be stripped.
// //
// FIXME: Is it necessary to check for json output here: See // FIXME: Is it necessary to check for json output here: See
// https://github.com/rust-lang/rust/pull/100325#discussion_r941495215 // https://github.com/rust-lang/rust/pull/100325#discussion_r941495215

View File

@ -143,3 +143,30 @@ pub struct LongItemInfo2;
/// Some docs. /// Some docs.
#[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))] #[doc(cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
impl SimpleTrait for LongItemInfo2 {} impl SimpleTrait for LongItemInfo2 {}
pub struct WhereWhitespace<T>;
impl<T> WhereWhitespace<T> {
pub fn new<F>(f: F) -> Self
where
F: FnMut() -> i32,
{}
}
impl<K, T> Whitespace<&K> for WhereWhitespace<T>
where
K: std::fmt::Debug,
{
type Output = WhereWhitespace<T>;
fn index(&self, _key: &K) -> &Self::Output {
self
}
}
pub trait Whitespace<Idx>
where
Idx: ?Sized,
{
type Output;
fn index(&self, index: Idx) -> &Self::Output;
}

View File

@ -0,0 +1,27 @@
// This test ensures that the where conditions are correctly displayed.
goto: file://|DOC_PATH|/lib2/trait.Whitespace.html
show-text: true
// First, we check in the trait definition if the where clause is "on its own" (not on the same
// line than "pub trait Whitespace<Idx>").
compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y"))
// And that the code following it isn't on the same line either.
compare-elements-position-false: (".item-decl .fnname", ".where.fmt-newline", ("y"))
goto: file://|DOC_PATH|/lib2/struct.WhereWhitespace.html
// We make the screen a bit wider to ensure that the trait impl is on one line.
size: (915, 915)
compare-elements-position-false: ("#method\.new .fnname", "#method\.new .where.fmt-newline", ("y"))
// We ensure that both the trait name and the struct name are on the same line in
// "impl<K, T> Whitespace<&K> for WhereWhitespace<T>".
compare-elements-position: (
"#trait-implementations-list .impl h3 .trait",
"#trait-implementations-list .impl h3 .struct",
("y"),
)
// And we now check that the where condition isn't on the same line.
compare-elements-position-false: (
"#trait-implementations-list .impl h3 .trait",
"#trait-implementations-list .impl h3 .where.fmt-newline",
("y"),
)

View File

@ -31,12 +31,12 @@ impl Trait<{1 + 2}> for u8 {}
impl<const N: usize> Trait<N> for [u8; N] {} impl<const N: usize> Trait<N> for [u8; N] {}
// @has foo/struct.Foo.html '//pre[@class="rust struct"]' \ // @has foo/struct.Foo.html '//pre[@class="rust struct"]' \
// 'pub struct Foo<const N: usize> where u8: Trait<N>' // 'pub struct Foo<const N: usize>where u8: Trait<N>'
pub struct Foo<const N: usize> where u8: Trait<N>; pub struct Foo<const N: usize> where u8: Trait<N>;
// @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)' // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)'
pub struct Bar<T, const N: usize>([T; N]); pub struct Bar<T, const N: usize>([T; N]);
// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>' // @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
impl<const M: usize> Foo<M> where u8: Trait<M> { impl<const M: usize> Foo<M> where u8: Trait<M> {
// @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize' // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
pub const FOO_ASSOC: usize = M + 13; pub const FOO_ASSOC: usize = M + 13;
@ -50,14 +50,14 @@ impl<const M: usize> Foo<M> where u8: Trait<M> {
// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>' // @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>'
impl<const M: usize> Bar<u8, M> { impl<const M: usize> Bar<u8, M> {
// @has - '//*[@id="method.hey"]' \ // @has - '//*[@id="method.hey"]' \
// 'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>' // 'pub fn hey<const N: usize>(&self) -> Foo<N>where u8: Trait<N>'
pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N> { pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N> {
Foo Foo
} }
} }
// @has foo/fn.test.html '//pre[@class="rust fn"]' \ // @has foo/fn.test.html '//pre[@class="rust fn"]' \
// 'pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N>' // 'pub fn test<const N: usize>() -> impl Trait<N>where u8: Trait<N>'
pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> { pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
2u8 2u8
} }

View File

@ -0,0 +1,24 @@
// Regression test for <https://github.com/rust-lang/rust/issues/101129>.
#![feature(doc_auto_cfg)]
#![crate_type = "lib"]
#![crate_name = "foo"]
pub struct S;
pub trait MyTrait1 {}
pub trait MyTrait2 {}
// @has foo/struct.S.html
// @has - '//*[@id="impl-MyTrait1-for-S"]//*[@class="stab portability"]' \
// 'Available on non-crate feature coolstuff only.'
#[cfg(not(feature = "coolstuff"))]
impl MyTrait1 for S {}
#[cfg(not(feature = "coolstuff"))]
mod submod {
use crate::{S, MyTrait2};
// This impl should also have the `not(feature = "coolstuff")`.
// @has - '//*[@id="impl-MyTrait2-for-S"]//*[@class="stab portability"]' \
// 'Available on non-crate feature coolstuff only.'
impl MyTrait2 for S {}
}

View File

@ -3,7 +3,7 @@
// @has foo/trait.LendingIterator.html // @has foo/trait.LendingIterator.html
pub trait LendingIterator { pub trait LendingIterator {
// @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a" // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a"
type Item<'a> where Self: 'a; type Item<'a> where Self: 'a;
// @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \ // @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \
@ -24,7 +24,7 @@ impl LendingIterator for () {
pub struct Infinite<T>(T); pub struct Infinite<T>(T);
// @has foo/trait.LendingIterator.html // @has foo/trait.LendingIterator.html
// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T" // @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a = &'a T"
impl<T> LendingIterator for Infinite<T> { impl<T> LendingIterator for Infinite<T> {
type Item<'a> where Self: 'a = &'a T; type Item<'a> where Self: 'a = &'a T;

View File

@ -4,7 +4,7 @@
pub trait Trait<'x> {} pub trait Trait<'x> {}
// @has foo/fn.test1.html // @has foo/fn.test1.html
// @has - '//pre' "pub fn test1<T>() where for<'a> &'a T: Iterator," // @has - '//pre' "pub fn test1<T>()where for<'a> &'a T: Iterator,"
pub fn test1<T>() pub fn test1<T>()
where where
for<'a> &'a T: Iterator, for<'a> &'a T: Iterator,
@ -12,7 +12,7 @@ where
} }
// @has foo/fn.test2.html // @has foo/fn.test2.html
// @has - '//pre' "pub fn test2<T>() where for<'a, 'b> &'a T: Trait<'b>," // @has - '//pre' "pub fn test2<T>()where for<'a, 'b> &'a T: Trait<'b>,"
pub fn test2<T>() pub fn test2<T>()
where where
for<'a, 'b> &'a T: Trait<'b>, for<'a, 'b> &'a T: Trait<'b>,
@ -20,7 +20,7 @@ where
} }
// @has foo/fn.test3.html // @has foo/fn.test3.html
// @has - '//pre' "pub fn test3<F>() where F: for<'a, 'b> Fn(&'a u8, &'b u8)," // @has - '//pre' "pub fn test3<F>()where F: for<'a, 'b> Fn(&'a u8, &'b u8),"
pub fn test3<F>() pub fn test3<F>()
where where
F: for<'a, 'b> Fn(&'a u8, &'b u8), F: for<'a, 'b> Fn(&'a u8, &'b u8),
@ -38,7 +38,7 @@ pub struct Foo<'a> {
// @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>" // @has - '//span[@id="structfield.some_trait"]' "some_trait: &'a dyn for<'b> Trait<'b>"
impl<'a> Foo<'a> { impl<'a> Foo<'a> {
// @has - '//h4[@class="code-header"]' "pub fn bar<T>() where T: Trait<'a>," // @has - '//h4[@class="code-header"]' "pub fn bar<T>()where T: Trait<'a>,"
pub fn bar<T>() pub fn bar<T>()
where where
T: Trait<'a>, T: Trait<'a>,

View File

@ -6,7 +6,7 @@ pub auto trait AnAutoTrait {}
pub struct Foo<T> { field: T } pub struct Foo<T> { field: T }
// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync," // "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync,"
// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \ // @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
// "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync," // "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync,"
impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {} impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {}

View File

@ -25,7 +25,7 @@ pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
pub mod reexport { pub mod reexport {
// @has issue_20727_4/reexport/trait.Index.html // @has issue_20727_4/reexport/trait.Index.html
// @has - '//*[@class="rust trait"]' 'trait Index<Idx> where Idx: ?Sized, {' // @has - '//*[@class="rust trait"]' 'trait Index<Idx>where Idx: ?Sized,{'
// @has - '//*[@class="rust trait"]' 'type Output: ?Sized' // @has - '//*[@class="rust trait"]' 'type Output: ?Sized'
// @has - '//*[@class="rust trait"]' \ // @has - '//*[@class="rust trait"]' \
// 'fn index(&self, index: Idx) -> &Self::Output' // 'fn index(&self, index: Idx) -> &Self::Output'
@ -33,7 +33,7 @@ pub mod reexport {
// @has issue_20727_4/reexport/trait.IndexMut.html // @has issue_20727_4/reexport/trait.IndexMut.html
// @has - '//*[@class="rust trait"]' \ // @has - '//*[@class="rust trait"]' \
// 'trait IndexMut<Idx>: Index<Idx> where Idx: ?Sized, {' // 'trait IndexMut<Idx>: Index<Idx>where Idx: ?Sized,{'
// @has - '//*[@class="rust trait"]' \ // @has - '//*[@class="rust trait"]' \
// 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;' // 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
pub use issue_20727::IndexMut; pub use issue_20727::IndexMut;

View File

@ -5,5 +5,5 @@ extern crate issue_21801;
// @has issue_21801/struct.Foo.html // @has issue_21801/struct.Foo.html
// @has - '//*[@id="method.new"]' \ // @has - '//*[@id="method.new"]' \
// 'fn new<F>(f: F) -> Foo where F: FnMut() -> i32' // 'fn new<F>(f: F) -> Foowhere F: FnMut() -> i32'
pub use issue_21801::Foo; pub use issue_21801::Foo;

View File

@ -5,7 +5,7 @@ pub trait MyTrait {
fn my_string(&self) -> String; fn my_string(&self) -> String;
} }
// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for T where T: Debug" // @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for Twhere T: Debug"
impl<T> MyTrait for T impl<T> MyTrait for T
where where
T: fmt::Debug, T: fmt::Debug,

View File

@ -2,5 +2,5 @@
pub trait Bar {} pub trait Bar {}
// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T) where T: Bar;' // @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T)where T: Bar;'
pub struct Foo<T>(pub T) where T: Bar; pub struct Foo<T>(pub T) where T: Bar;

View File

@ -11,8 +11,8 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
} }
// @has issue_50159/struct.Switch.html // @has issue_50159/struct.Switch.html
// @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send' // @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
// @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync' // @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
pub struct Switch<B: Signal> { pub struct Switch<B: Signal> {

View File

@ -8,7 +8,7 @@ pub mod traits {
// @has issue_51236/struct.Owned.html // @has issue_51236/struct.Owned.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<T> Send for Owned<T> where <T as Owned<'static>>::Reader: Send" // "impl<T> Send for Owned<T>where <T as Owned<'static>>::Reader: Send"
pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> { pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>, marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
} }

View File

@ -1,13 +1,11 @@
pub trait ScopeHandle<'scope> {} pub trait ScopeHandle<'scope> {}
// @has issue_54705/struct.ScopeFutureContents.html // @has issue_54705/struct.ScopeFutureContents.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync" // "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync"
// //
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync" // "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync"
pub struct ScopeFutureContents<'scope, S> pub struct ScopeFutureContents<'scope, S>
where S: ScopeHandle<'scope>, where S: ScopeHandle<'scope>,
{ {

View File

@ -8,7 +8,7 @@
extern crate issue_98697_reexport_with_anonymous_lifetime; extern crate issue_98697_reexport_with_anonymous_lifetime;
// @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro<F>() where F: Fn(&str)' // @has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'fn repro<F>()where F: Fn(&str)'
// @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<' // @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/code' 'for<'
pub use issue_98697_reexport_with_anonymous_lifetime::repro; pub use issue_98697_reexport_with_anonymous_lifetime::repro;

View File

@ -7,8 +7,8 @@
// @has - '//span[@class="in-band"]' 'Primitive Type slice' // @has - '//span[@class="in-band"]' 'Primitive Type slice'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T] where T: Send' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T] where T: Sync' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Sync for [T]where T: Sync'
#[doc(primitive = "slice")] #[doc(primitive = "slice")]
/// this is a test! /// this is a test!
mod slice_prim {} mod slice_prim {}

View File

@ -1,6 +1,6 @@
// @has basic/struct.Foo.html // @has basic/struct.Foo.html
// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T> where T: Send' // @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T>where T: Send'
// @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T> where T: Sync' // @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T>where T: Sync'
// @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0 // @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0
// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5 // @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
pub struct Foo<T> { pub struct Foo<T> {

View File

@ -21,7 +21,7 @@ mod foo {
// @has complex/struct.NotOuter.html // @has complex/struct.NotOuter.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \ // "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \
// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static" // -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter}; pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};

View File

@ -10,10 +10,10 @@ where
// @has lifetimes/struct.Foo.html // @has lifetimes/struct.Foo.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static" // "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
// //
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'c, K> Sync for Foo<'c, K> where K: Sync" // "impl<'c, K> Sync for Foo<'c, K>where K: Sync"
pub struct Foo<'c, K: 'c> { pub struct Foo<'c, K: 'c> {
inner_field: Inner<'c, K>, inner_field: Inner<'c, K>,
} }

View File

@ -1,6 +1,6 @@
// @has manual/struct.Foo.html // @has manual/struct.Foo.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// 'impl<T> Sync for Foo<T> where T: Sync' // 'impl<T> Sync for Foo<T>where T: Sync'
// //
// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// 'impl<T> Send for Foo<T>' // 'impl<T> Send for Foo<T>'

View File

@ -10,10 +10,10 @@ where
// @has nested/struct.Foo.html // @has nested/struct.Foo.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// 'impl<T> Send for Foo<T> where T: Copy' // 'impl<T> Send for Foo<T>where T: Copy'
// //
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// 'impl<T> Sync for Foo<T> where T: Sync' // 'impl<T> Sync for Foo<T>where T: Sync'
pub struct Foo<T> { pub struct Foo<T> {
inner_field: Inner<T>, inner_field: Inner<T>,
} }

View File

@ -10,7 +10,7 @@ where
// @has no_redundancy/struct.Outer.html // @has no_redundancy/struct.Outer.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<T> Send for Outer<T> where T: Send + Copy" // "impl<T> Send for Outer<T>where T: Send + Copy"
pub struct Outer<T> { pub struct Outer<T> {
inner_field: Inner<T>, inner_field: Inner<T>,
} }

View File

@ -24,10 +24,10 @@ where
// @has project/struct.Foo.html // @has project/struct.Foo.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'c, K> Send for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static" // "impl<'c, K> Send for Foo<'c, K>where K: MyTrait<MyItem = bool>, 'c: 'static"
// //
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \ // "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
// 'c: 'static," // 'c: 'static,"
pub struct Foo<'c, K: 'c> { pub struct Foo<'c, K: 'c> {
inner_field: Inner<'c, K>, inner_field: Inner<'c, K>,

View File

@ -24,6 +24,6 @@ impl<T> Pattern for Wrapper<T> {
// @has self_referential/struct.WriteAndThen.html // @has self_referential/struct.WriteAndThen.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<P1> Send for WriteAndThen<P1> where <P1 as Pattern>::Value: Send" // "impl<P1> Send for WriteAndThen<P1>where <P1 as Pattern>::Value: Send"
pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value) pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
where P1: Pattern; where P1: Pattern;

View File

@ -4,7 +4,7 @@ pub trait OwnedTrait<'a> {
// @has static_region/struct.Owned.html // @has static_region/struct.Owned.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<T> Send for Owned<T> where <T as OwnedTrait<'static>>::Reader: Send" // "impl<T> Send for Owned<T>where <T as OwnedTrait<'static>>::Reader: Send"
pub struct Owned<T> where T: OwnedTrait<'static> { pub struct Owned<T> where T: OwnedTrait<'static> {
marker: <T as OwnedTrait<'static>>::Reader, marker: <T as OwnedTrait<'static>>::Reader,
} }

View File

@ -7,7 +7,7 @@ where
} }
// @has 'foo/trait.SomeTrait.html' // @has 'foo/trait.SomeTrait.html'
// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, " // @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E) impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)
where where
A: PartialOrd<A> + PartialEq<A>, A: PartialOrd<A> + PartialEq<A>,

View File

@ -3,17 +3,17 @@
pub trait MyTrait { fn dummy(&self) { } } pub trait MyTrait { fn dummy(&self) { } }
// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait" // @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_)where A: MyTrait"
pub struct Alpha<A>(A) where A: MyTrait; pub struct Alpha<A>(A) where A: MyTrait;
// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait" // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait"
pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); } pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
// @has foo/fn.charlie.html '//pre' "pub fn charlie<C>() where C: MyTrait" // @has foo/fn.charlie.html '//pre' "pub fn charlie<C>()where C: MyTrait"
pub fn charlie<C>() where C: MyTrait {} pub fn charlie<C>() where C: MyTrait {}
pub struct Delta<D>(D); pub struct Delta<D>(D);
// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<D> Delta<D> where D: MyTrait" // "impl<D> Delta<D>where D: MyTrait"
impl<D> Delta<D> where D: MyTrait { impl<D> Delta<D> where D: MyTrait {
pub fn delta() {} pub fn delta() {}
} }
@ -33,19 +33,19 @@ pub trait TraitWhere {
} }
// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<E> MyTrait for Echo<E> where E: MyTrait" // "impl<E> MyTrait for Echo<E>where E: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
// "impl<E> MyTrait for Echo<E> where E: MyTrait" // "impl<E> MyTrait for Echo<E>where E: MyTrait"
impl<E> MyTrait for Echo<E> where E: MyTrait {} impl<E> MyTrait for Echo<E>where E: MyTrait {}
pub enum Foxtrot<F> { Foxtrot1(F) } pub enum Foxtrot<F> { Foxtrot1(F) }
// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \ // @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
// "impl<F> MyTrait for Foxtrot<F> where F: MyTrait" // "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \ // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header in-band"]' \
// "impl<F> MyTrait for Foxtrot<F> where F: MyTrait" // "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
impl<F> MyTrait for Foxtrot<F> where F: MyTrait {} impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
// @has foo/type.Golf.html '//pre[@class="rust typedef"]' \ // @has foo/type.Golf.html '//pre[@class="rust typedef"]' \
// "type Golf<T> where T: Clone, = (T, T)" // "type Golf<T>where T: Clone, = (T, T)"
pub type Golf<T> where T: Clone = (T, T); pub type Golf<T> where T: Clone = (T, T);

View File

@ -0,0 +1,8 @@
fn main() {
let mut vec: Vec<i32> = Vec::new();
let closure = move || {
vec.clear();
let mut iter = vec.iter();
move || { iter.next() } //~ ERROR captured variable cannot escape `FnMut` closure bod
};
}

View File

@ -0,0 +1,18 @@
error: captured variable cannot escape `FnMut` closure body
--> $DIR/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs:6:9
|
LL | let mut vec: Vec<i32> = Vec::new();
| ------- variable defined here
LL | let closure = move || {
| - inferred to be a `FnMut` closure
LL | vec.clear();
| --- variable captured here
LL | let mut iter = vec.iter();
LL | move || { iter.next() }
| ^^^^^^^^^^^^^^^^^^^^^^^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
error: aborting due to previous error

View File

@ -0,0 +1,2 @@
#[allow(dead_code)]
pub struct Dummy;

View File

@ -0,0 +1,8 @@
mod lib;
//~^ WARN found module declaration for lib.rs
//~| ERROR file not found for module `lib`
mod main;
//~^ WARN found module declaration for main.rs
//~| ERROR file not found for module `main`
fn main() {}

View File

@ -0,0 +1,37 @@
error[E0583]: file not found for module `lib`
--> $DIR/special_module_name.rs:1:1
|
LL | mod lib;
| ^^^^^^^^
|
= help: to create the module `lib`, create file "$DIR/lib.rs" or "$DIR/lib/mod.rs"
error[E0583]: file not found for module `main`
--> $DIR/special_module_name.rs:4:1
|
LL | mod main;
| ^^^^^^^^^
|
= help: to create the module `main`, create file "$DIR/main.rs" or "$DIR/main/mod.rs"
warning: found module declaration for lib.rs
--> $DIR/special_module_name.rs:1:1
|
LL | mod lib;
| ^^^^^^^^
|
= note: `#[warn(special_module_name)]` on by default
= note: lib.rs is the root of this crate's library target
= help: to refer to it from other targets, use the library's name as the path
warning: found module declaration for main.rs
--> $DIR/special_module_name.rs:4:1
|
LL | mod main;
| ^^^^^^^^^
|
= note: a binary crate cannot be used as library
error: aborting due to 2 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0583`.

View File

@ -0,0 +1,9 @@
// run-pass
#[path = "auxiliary/dummy_lib.rs"]
mod lib;
#[path = "auxiliary/dummy_lib.rs"]
mod main;
fn main() {}