From 13341f4c6b6fa470a97781703ac6fe356e307194 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 9 Mar 2017 13:45:52 +0100 Subject: [PATCH 01/19] Reword the non-dropping of `src` for `ptr::write{,_unaligned}` --- src/libcore/ptr.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 260fdab9d58fb..0b7aa4fa9117c 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -191,9 +191,8 @@ pub unsafe fn read_unaligned(src: *const T) -> T { /// allocations or resources, so care must be taken not to overwrite an object /// that should be dropped. /// -/// It does not immediately drop the contents of `src` either; it is rather -/// *moved* into the memory location `dst` and will be dropped whenever that -/// location goes out of scope. +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. @@ -233,6 +232,9 @@ pub unsafe fn write(dst: *mut T, src: T) { /// allocations or resources, so care must be taken not to overwrite an object /// that should be dropped. /// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. /// From 97a1b6a055d69cf21faa9773133725bdfddc5196 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 12 Mar 2017 14:13:35 -0400 Subject: [PATCH 02/19] Update usages of 'OSX' (and other old names) to 'macOS'. As of last year with version 'Sierra', the Mac operating system is now called 'macOS'. --- RELEASES.md | 2 +- src/bootstrap/bin/rustc.rs | 2 +- src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 2 +- src/bootstrap/lib.rs | 2 +- src/bootstrap/sanity.rs | 4 ++-- src/doc/book/src/testing.md | 2 +- src/liballoc_jemalloc/lib.rs | 2 +- src/librustc/middle/cstore.rs | 2 +- src/librustc/session/config.rs | 2 +- src/librustc_back/target/apple_base.rs | 8 ++++---- src/librustc_back/target/mod.rs | 4 ++-- src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/diagnostics.rs | 2 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_trans/back/link.rs | 6 +++--- src/librustc_trans/back/linker.rs | 2 +- src/librustc_trans/back/symbol_names.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 4 ++-- src/librustdoc/plugins.rs | 2 +- src/libstd/os/macos/mod.rs | 2 +- src/libstd/os/macos/raw.rs | 2 +- src/libstd/rand/mod.rs | 4 ++-- src/libstd/sys/redox/fast_thread_local.rs | 6 +++--- src/libstd/sys/redox/process.rs | 2 +- src/libstd/sys/unix/backtrace/mod.rs | 8 ++++---- src/libstd/sys/unix/ext/net.rs | 2 +- src/libstd/sys/unix/fast_thread_local.rs | 8 ++++---- src/libstd/sys/unix/fd.rs | 2 +- src/libstd/sys/unix/fs.rs | 4 ++-- src/libstd/sys/unix/process/process_common.rs | 4 ++-- src/libstd/sys/unix/process/process_unix.rs | 2 +- src/libstd/sys/unix/stack_overflow.rs | 2 +- src/libstd/thread/local.rs | 6 +++--- src/libterm/terminfo/searcher.rs | 4 ++-- src/test/compile-fail/allocator-dylib-is-system.rs | 2 +- src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs | 2 +- src/test/compile-fail/manual-link-framework.rs | 2 +- src/test/compile-fail/osx-frameworks.rs | 2 +- src/test/run-pass/simd-intrinsic-generic-cast.rs | 2 +- src/tools/compiletest/src/raise_fd_limit.rs | 2 +- 41 files changed, 63 insertions(+), 63 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 606936778c49a..16257c3e9c04c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -5056,7 +5056,7 @@ Version 0.1 (2012-01-20) * Compiler works with the following configurations: * Linux: x86 and x86_64 hosts and targets - * MacOS: x86 and x86_64 hosts and targets + * macOS: x86 and x86_64 hosts and targets * Windows: x86 hosts and targets * Cross compilation / multi-target configuration supported. diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index a996240f61650..ba85e81ff4fc4 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -182,7 +182,7 @@ fn main() { if env::var("RUSTC_RPATH") == Ok("true".to_string()) { let rpath = if target.contains("apple") { - // Note that we need to take one extra step on OSX to also pass + // Note that we need to take one extra step on macOS to also pass // `-Wl,-instal_name,@rpath/...` to get things to work right. To // do that we pass a weird flag to the compiler to get it to do // so. Note that this is definitely a hack, and we should likely diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 68b3623a53f25..0d962bd3b0c93 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -176,7 +176,7 @@ pub fn compiletest(build: &Build, cmd.arg("--docck-python").arg(build.python()); if build.config.build.ends_with("apple-darwin") { - // Force /usr/bin/python on OSX for LLDB tests because we're loading the + // Force /usr/bin/python on macOS for LLDB tests because we're loading the // LLDB plugin's compiled module which only works with the system python // (namely not Homebrew-installed python) cmd.arg("--lldb-python").arg("/usr/bin/python"); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 3459c1d2b8425..4201475c60c12 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -249,7 +249,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) { cargo.env("CFG_LLVM_ROOT", s); } // Building with a static libstdc++ is only supported on linux right now, - // not for MSVC or OSX + // not for MSVC or macOS if build.config.llvm_static_stdcpp && !target.contains("windows") && !target.contains("apple") { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 618e4d67705da..75a8b78024846 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -846,7 +846,7 @@ impl Build { .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .collect::>(); - // If we're compiling on OSX then we add a few unconditional flags + // If we're compiling on macOS then we add a few unconditional flags // indicating that we want libc++ (more filled out than libstdc++) and // we want to compile for 10.7. This way we can ensure that // LLVM/jemalloc/etc are all properly compiled. diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index bc439d6f7826d..235ce9360eff4 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -151,10 +151,10 @@ pub fn check(build: &mut Build) { } for target in build.config.target.iter() { - // Can't compile for iOS unless we're on OSX + // Can't compile for iOS unless we're on macOS if target.contains("apple-ios") && !build.config.build.contains("apple-darwin") { - panic!("the iOS target is only supported on OSX"); + panic!("the iOS target is only supported on macOS"); } // Make sure musl-root is valid if specified diff --git a/src/doc/book/src/testing.md b/src/doc/book/src/testing.md index 291c4481d5513..b4f580fcdfbef 100644 --- a/src/doc/book/src/testing.md +++ b/src/doc/book/src/testing.md @@ -147,7 +147,7 @@ And that's reflected in the summary line: test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured ``` -We also get a non-zero status code. We can use `$?` on OS X and Linux: +We also get a non-zero status code. We can use `$?` on macOS and Linux: ```bash $ echo $? diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index a496ab870c63b..a7a67ef76d4f7 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -30,7 +30,7 @@ pub use imp::*; mod imp { use libc::{c_int, c_void, size_t}; - // Note that the symbols here are prefixed by default on OSX and Windows (we + // Note that the symbols here are prefixed by default on macOS and Windows (we // don't explicitly request it), and on Android and DragonFly we explicitly // request it as unprefixing cause segfaults (mismatches in allocators). extern "C" { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index e9fb4632fa178..225d6fc9bb2b2 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -123,7 +123,7 @@ pub enum LinkagePreference { pub enum NativeLibraryKind { NativeStatic, // native static library (.a archive) NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs - NativeFramework, // OSX-specific + NativeFramework, // macOS-specific NativeUnknown, // default way to specify a dynamic library } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 5fff03dabcece..d7a765fb82215 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -971,7 +971,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], - "pass `-install_name @rpath/...` to the OSX linker"), + "pass `-install_name @rpath/...` to the macOS linker"), sanitizer: Option = (None, parse_sanitizer, [TRACKED], "Use a sanitizer"), } diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs index 21a2d4293df77..3a551a2b124b7 100644 --- a/src/librustc_back/target/apple_base.rs +++ b/src/librustc_back/target/apple_base.rs @@ -13,12 +13,12 @@ use std::env; use target::TargetOptions; pub fn opts() -> TargetOptions { - // ELF TLS is only available in OSX 10.7+. If you try to compile for 10.6 + // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 // either the linker will complain if it is used or the binary will end up - // segfaulting at runtime when run on 10.6. Rust by default supports OSX + // segfaulting at runtime when run on 10.6. Rust by default supports macOS // 10.7+, but there is a standard environment variable, // MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older - // versions of OSX. For example compiling on 10.10 with + // versions of macOS. For example compiling on 10.10 with // MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate // warnings about the usage of ELF TLS. // @@ -33,7 +33,7 @@ pub fn opts() -> TargetOptions { }).unwrap_or((10, 7)); TargetOptions { - // OSX has -dead_strip, which doesn't rely on function_sections + // macOS has -dead_strip, which doesn't rely on function_sections function_sections: false, dynamic_linking: true, executables: true, diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 0c179469448fe..559418d2c4f5f 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -318,8 +318,8 @@ pub struct TargetOptions { /// Whether the target toolchain is like OpenBSD's. /// Only useful for compiling against OpenBSD, for configuring abi when returning a struct. pub is_like_openbsd: bool, - /// Whether the target toolchain is like OSX's. Only useful for compiling against iOS/OS X, in - /// particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. + /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS, + /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. pub is_like_osx: bool, /// Whether the target toolchain is like Solaris's. /// Only useful for compiling against Illumos/Solaris, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 49dcffb4830a1..63c14a0035f1a 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -99,7 +99,7 @@ fn register_native_lib(sess: &Session, } let is_osx = sess.target.target.options.is_like_osx; if lib.kind == cstore::NativeFramework && !is_osx { - let msg = "native frameworks are only available on OSX targets"; + let msg = "native frameworks are only available on macOS targets"; match span { Some(span) => span_err!(sess, span, E0455, "{}", msg), None => sess.err(msg), diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs index d3a2b6f1683e2..fbdc4695cf826 100644 --- a/src/librustc_metadata/diagnostics.rs +++ b/src/librustc_metadata/diagnostics.rs @@ -27,7 +27,7 @@ name. Example: "##, E0455: r##" -Linking with `kind=framework` is only supported when targeting OS X, +Linking with `kind=framework` is only supported when targeting macOS, as frameworks are specific to that operating system. Erroneous code example: diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 8ddc1642d9e1c..0c31e30671dc2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1404,7 +1404,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // // And here we run into yet another obscure archive bug: in which metadata // loaded from archives may have trailing garbage bytes. Awhile back one of -// our tests was failing sporadically on the OSX 64-bit builders (both nopt +// our tests was failing sporadically on the macOS 64-bit builders (both nopt // and opt) by having ebml generate an out-of-bounds panic when looking at // metadata. // diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index a1703b1c155eb..cf1e10b317b1e 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -583,7 +583,7 @@ fn link_rlib<'a>(sess: &'a Session, } // After adding all files to the archive, we need to update the - // symbol table of the archive. This currently dies on OSX (see + // symbol table of the archive. This currently dies on macOS (see // #11162), and isn't necessary there anyway if !sess.target.target.options.is_like_osx { ab.update_symbols(); @@ -764,7 +764,7 @@ fn link_natively(sess: &Session, // pain to land PRs when they spuriously fail due to a segfault. // // The issue #38878 has some more debugging information on it as well, but - // this unfortunately looks like it's just a race condition in OSX's linker + // this unfortunately looks like it's just a race condition in macOS's linker // with some thread pool working in the background. It seems that no one // currently knows a fix for this so in the meantime we're left with this... info!("{:?}", &cmd); @@ -841,7 +841,7 @@ fn link_natively(sess: &Session, } - // On OSX, debuggers need this utility to get run to do some munging of + // On macOS, debuggers need this utility to get run to do some munging of // the symbols if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo { match Command::new("dsymutil").arg(out_filename).output() { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 830d1d0d3a558..80801e8161cd0 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -139,7 +139,7 @@ impl<'a> Linker for GnuLinker<'a> { .arg("-l").arg(lib) .arg("-Wl,--no-whole-archive"); } else { - // -force_load is the OSX equivalent of --whole-archive, but it + // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. let mut v = OsString::from("-Wl,-force_load,"); v.push(&archive::find_library(lib, search_path, &self.sess)); diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 20338e4f6afb0..fe58bc8f5f28b 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -351,7 +351,7 @@ fn mangle>(path: PI, hash: &str) -> String { // Follow C++ namespace-mangling style, see // http://en.wikipedia.org/wiki/Name_mangling for more info. // - // It turns out that on OSX you can actually have arbitrary symbols in + // It turns out that on macOS you can actually have arbitrary symbols in // function names (at least when given to LLVM), but this is not possible // when using unix's linker. Perhaps one day when we just use a linker from LLVM // we won't need to do this name mangling. The problem with name mangling is diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 6933f15825620..1d4aebf135b9e 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -164,9 +164,9 @@ pub fn finalize(cx: &CrateContext) { llvm::LLVMRustDIBuilderFinalize(DIB(cx)); llvm::LLVMRustDIBuilderDispose(DIB(cx)); // Debuginfo generation in LLVM by default uses a higher - // version of dwarf than OS X currently understands. We can + // version of dwarf than macOS currently understands. We can // instruct LLVM to emit an older version of dwarf, however, - // for OS X to understand. For more info see #11352 + // for macOS to understand. For more info see #11352 // This can be overridden using --llvm-opts -dwarf-version,N. // Android has the same issue (#22398) if cx.sess().target.target.options.is_like_osx || diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs index b8be84825c9cc..a38ef2b2518ed 100644 --- a/src/librustdoc/plugins.rs +++ b/src/librustdoc/plugins.rs @@ -42,7 +42,7 @@ impl PluginManager { /// Load a plugin with the given name. /// /// Turns `name` into the proper dynamic library filename for the given - /// platform. On windows, it turns into name.dll, on OS X, name.dylib, and + /// platform. On windows, it turns into name.dll, on macOS, name.dylib, and /// elsewhere, libname.so. pub fn load_plugin(&mut self, name: String) { let x = self.prefix.join(libname(name)); diff --git a/src/libstd/os/macos/mod.rs b/src/libstd/os/macos/mod.rs index 4e995358fd876..c9406f7310039 100644 --- a/src/libstd/os/macos/mod.rs +++ b/src/libstd/os/macos/mod.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! MacOS-specific definitions +//! macOS-specific definitions #![stable(feature = "raw_ext", since = "1.1.0")] diff --git a/src/libstd/os/macos/raw.rs b/src/libstd/os/macos/raw.rs index 8f9b29462c4f9..8ffddf638b10c 100644 --- a/src/libstd/os/macos/raw.rs +++ b/src/libstd/os/macos/raw.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! MacOS-specific raw type definitions +//! macOS-specific raw type definitions #![stable(feature = "raw_ext", since = "1.1.0")] #![rustc_deprecated(since = "1.8.0", diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index b853e83de5d6c..4f33d72639816 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -52,7 +52,7 @@ //! If an application does not have `getrandom` and likely to be run soon after first booting, //! or on a system with very few entropy sources, one should consider using `/dev/random` via //! `ReaderRng`. -//! - On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference +//! - On some systems (e.g. FreeBSD, OpenBSD and macOS) there is no difference //! between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random` //! and `/dev/urandom` may block once if the CSPRNG has not seeded yet.) @@ -195,7 +195,7 @@ impl Rng for ThreadRng { /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: /// -/// - Unix-like systems (Linux, Android, Mac OSX): read directly from +/// - Unix-like systems (Linux, Android, macOS): read directly from /// `/dev/urandom`, or from `getrandom(2)` system call if available. /// - Windows: calls `CryptGenRandom`, using the default cryptographic /// service provider with the `PROV_RSA_FULL` type. diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 6eeae2d90ea0e..f6414673dace1 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -96,17 +96,17 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { // `None`. (*ptr).dtor_running.set(true); - // The OSX implementation of TLS apparently had an odd aspect to it + // The macOS implementation of TLS apparently had an odd aspect to it // where the pointer we have may be overwritten while this destructor // is running. Specifically if a TLS destructor re-accesses TLS it may // trigger a re-initialization of all TLS variables, paving over at // least some destroyed ones with initial values. // - // This means that if we drop a TLS value in place on OSX that we could + // This means that if we drop a TLS value in place on macOS that we could // revert the value to its original state halfway through the // destructor, which would be bad! // - // Hence, we use `ptr::read` on OSX (to move to a "safe" location) + // Hence, we use `ptr::read` on macOS (to move to a "safe" location) // instead of drop_in_place. if cfg!(target_os = "macos") { ptr::read((*ptr).inner.get()); diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 60dc03fcf47e2..707b4cbc6acaf 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -249,7 +249,7 @@ impl Command { // mutex, and then after the fork they unlock it. // // Despite this information, libnative's spawn has been witnessed to - // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but + // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but // all collected backtraces point at malloc/free traffic in the // child spawned process. // diff --git a/src/libstd/sys/unix/backtrace/mod.rs b/src/libstd/sys/unix/backtrace/mod.rs index 29d4012dcdf98..bf52da2ed4ac5 100644 --- a/src/libstd/sys/unix/backtrace/mod.rs +++ b/src/libstd/sys/unix/backtrace/mod.rs @@ -13,7 +13,7 @@ /// Some methods of getting a backtrace: /// /// * The backtrace() functions on unix. It turns out this doesn't work very -/// well for green threads on OSX, and the address to symbol portion of it +/// well for green threads on macOS, and the address to symbol portion of it /// suffers problems that are described below. /// /// * Using libunwind. This is more difficult than it sounds because libunwind @@ -51,9 +51,9 @@ /// /// * Use dladdr(). The original backtrace()-based idea actually uses dladdr() /// behind the scenes to translate, and this is why backtrace() was not used. -/// Conveniently, this method works fantastically on OSX. It appears dladdr() +/// Conveniently, this method works fantastically on macOS. It appears dladdr() /// uses magic to consult the local symbol table, or we're putting everything -/// in the dynamic symbol table anyway. Regardless, for OSX, this is the +/// in the dynamic symbol table anyway. Regardless, for macOS, this is the /// method used for translation. It's provided by the system and easy to do.o /// /// Sadly, all other systems have a dladdr() implementation that does not @@ -75,7 +75,7 @@ /// * Use `libbacktrace`. It turns out that this is a small library bundled in /// the gcc repository which provides backtrace and symbol translation /// functionality. All we really need from it is the backtrace functionality, -/// and we only really need this on everything that's not OSX, so this is the +/// and we only really need this on everything that's not macOS, so this is the /// chosen route for now. /// /// In summary, the current situation uses libgcc_s to get a trace of stack diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 1ba4a104e515c..8a15f7ec68232 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -204,7 +204,7 @@ impl SocketAddr { let len = self.len as usize - sun_path_offset(); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - // OSX seems to return a len of 16 and a zeroed sun_path for unnamed addresses + // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses if len == 0 || (cfg!(not(target_os = "linux")) && self.addr.sun_path[0] == 0) { AddressKind::Unnamed } else if self.addr.sun_path[0] == 0 { diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index f4f73646e1b7e..07d76a93dd150 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -128,7 +128,7 @@ unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { register_dtor_fallback(t, dtor); } -// OSX's analog of the above linux function is this _tlv_atexit function. +// macOS's analog of the above linux function is this _tlv_atexit function. // The disassembly of thread_local globals in C++ (at least produced by // clang) will have this show up in the output. #[cfg(target_os = "macos")] @@ -154,17 +154,17 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { // `None`. (*ptr).dtor_running.set(true); - // The OSX implementation of TLS apparently had an odd aspect to it + // The macOS implementation of TLS apparently had an odd aspect to it // where the pointer we have may be overwritten while this destructor // is running. Specifically if a TLS destructor re-accesses TLS it may // trigger a re-initialization of all TLS variables, paving over at // least some destroyed ones with initial values. // - // This means that if we drop a TLS value in place on OSX that we could + // This means that if we drop a TLS value in place on macOS that we could // revert the value to its original state halfway through the // destructor, which would be bad! // - // Hence, we use `ptr::read` on OSX (to move to a "safe" location) + // Hence, we use `ptr::read` on macOS (to move to a "safe" location) // instead of drop_in_place. if cfg!(target_os = "macos") { ptr::read((*ptr).inner.get()); diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index c690fd467ee41..405fac2b9d743 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -29,7 +29,7 @@ fn max_len() -> usize { // with the man page quoting that if the count of bytes to read is // greater than `SSIZE_MAX` the result is "unspecified". // - // On OSX, however, apparently the 64-bit libc is either buggy or + // On macOS, however, apparently the 64-bit libc is either buggy or // intentionally showing odd behavior by rejecting any read with a size // larger than or equal to INT_MAX. To handle both of these the read // size is capped on both platforms. diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index d0fb96b1ff15d..e893a139094a1 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -439,7 +439,7 @@ impl File { // Linux kernel then the flag is just ignored by the OS, so we continue // to explicitly ask for a CLOEXEC fd here. // - // The CLOEXEC flag, however, is supported on versions of OSX/BSD/etc + // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc // that we support, so we only do this on Linux currently. if cfg!(target_os = "linux") { fd.set_cloexec()?; @@ -573,7 +573,7 @@ impl fmt::Debug for File { #[cfg(target_os = "macos")] fn get_path(fd: c_int) -> Option { // FIXME: The use of PATH_MAX is generally not encouraged, but it - // is inevitable in this case because OS X defines `fcntl` with + // is inevitable in this case because macOS defines `fcntl` with // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no // alternatives. If a better method is invented, it should be used // instead. diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index a4536520376e8..5f1a6c2f74651 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -434,8 +434,8 @@ mod tests { } // See #14232 for more information, but it appears that signal delivery to a - // newly spawned process may just be raced in the OSX, so to prevent this - // test from being flaky we ignore it on OSX. + // newly spawned process may just be raced in the macOS, so to prevent this + // test from being flaky we ignore it on macOS. #[test] #[cfg_attr(target_os = "macos", ignore)] #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl. diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index bbc987209e300..a213273aac8fd 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -129,7 +129,7 @@ impl Command { // mutex, and then after the fork they unlock it. // // Despite this information, libnative's spawn has been witnessed to - // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but + // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but // all collected backtraces point at malloc/free traffic in the // child spawned process. // diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 22d47ba0f620d..51adbc24ae047 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -187,7 +187,7 @@ mod imp { let stack = libc::stack_t { ss_sp: ptr::null_mut(), ss_flags: SS_DISABLE, - // Workaround for bug in MacOS implementation of sigaltstack + // Workaround for bug in macOS implementation of sigaltstack // UNIX2003 which returns ENOMEM when disabling a stack while // passing ss_size smaller than MINSIGSTKSZ. According to POSIX // both ss_sp and ss_size should be ignored in this case. diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 66f09a7069c13..e2b22b1d89f04 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -74,7 +74,7 @@ use mem; /// destroyed, but not all platforms have this guard. Those platforms that do /// not guard typically have a synthetic limit after which point no more /// destructors are run. -/// 3. On OSX, initializing TLS during destruction of other TLS slots can +/// 3. On macOS, initializing TLS during destruction of other TLS slots can /// sometimes cancel *all* destructors for the current thread, whether or not /// the slots have already had their destructors run or not. #[stable(feature = "rust1", since = "1.0.0")] @@ -524,9 +524,9 @@ mod tests { } // Note that this test will deadlock if TLS destructors aren't run (this - // requires the destructor to be run to pass the test). OSX has a known bug + // requires the destructor to be run to pass the test). macOS has a known bug // where dtors-in-dtors may cancel other destructors, so we just ignore this - // test on OSX. + // test on macOS. #[test] #[cfg_attr(target_os = "macos", ignore)] fn dtors_in_dtors_in_dtors() { diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index 011d06b1c0f21..c9bde8b7b33f2 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -67,7 +67,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { p.pop(); // on some installations the dir is named after the hex of the char - // (e.g. OS X) + // (e.g. macOS) p.push(&format!("{:x}", first_char as usize)); p.push(term); if fs::metadata(&p).is_ok() { @@ -82,7 +82,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { #[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")] fn test_get_dbpath_for_term() { // woefully inadequate test coverage - // note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's) + // note: current tests won't work with non-standard terminfo hierarchies (e.g. macOS's) use std::env; // FIXME (#9639): This needs to handle non-utf8 paths fn x(t: &str) -> String { diff --git a/src/test/compile-fail/allocator-dylib-is-system.rs b/src/test/compile-fail/allocator-dylib-is-system.rs index 4c576de22021c..31009554c690d 100644 --- a/src/test/compile-fail/allocator-dylib-is-system.rs +++ b/src/test/compile-fail/allocator-dylib-is-system.rs @@ -30,7 +30,7 @@ extern crate allocator_dylib; // that this just passes on those platforms we link in some other allocator to // ensure we get the same error. // -// So long as we CI linux/OSX we should be good. +// So long as we CI linux/macOS we should be good. #[cfg(any(target_os = "linux", target_os = "macos"))] extern crate alloc_jemalloc; #[cfg(not(any(target_os = "linux", target_os = "macos")))] diff --git a/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs b/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs index 5d566c0e0b4c7..68e01bad96bb2 100644 --- a/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs +++ b/src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs @@ -28,7 +28,7 @@ extern crate allocator_dylib2; // that this just passes on those platforms we link in some other allocator to // ensure we get the same error. // -// So long as we CI linux/OSX we should be good. +// So long as we CI linux/macOS we should be good. #[cfg(any(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")), target_os = "macos"))] extern crate alloc_system; diff --git a/src/test/compile-fail/manual-link-framework.rs b/src/test/compile-fail/manual-link-framework.rs index 97176a533d2bd..1ecf63813e9ab 100644 --- a/src/test/compile-fail/manual-link-framework.rs +++ b/src/test/compile-fail/manual-link-framework.rs @@ -11,7 +11,7 @@ // ignore-macos // ignore-ios // compile-flags:-l framework=foo -// error-pattern: native frameworks are only available on OSX targets +// error-pattern: native frameworks are only available on macOS targets fn main() { } diff --git a/src/test/compile-fail/osx-frameworks.rs b/src/test/compile-fail/osx-frameworks.rs index aba5fb3bc03ef..026ef3c95f663 100644 --- a/src/test/compile-fail/osx-frameworks.rs +++ b/src/test/compile-fail/osx-frameworks.rs @@ -12,7 +12,7 @@ #[link(name = "foo", kind = "framework")] extern {} -//~^^ ERROR: native frameworks are only available on OSX +//~^^ ERROR: native frameworks are only available on macOS fn main() { } diff --git a/src/test/run-pass/simd-intrinsic-generic-cast.rs b/src/test/run-pass/simd-intrinsic-generic-cast.rs index d32fa01c7b945..ede2325b51c2f 100644 --- a/src/test/run-pass/simd-intrinsic-generic-cast.rs +++ b/src/test/run-pass/simd-intrinsic-generic-cast.rs @@ -94,7 +94,7 @@ fn main() { // (E.g. negative float to unsigned integer goes through a // library routine on the default i686 platforms, and the // implementation of that routine differs on e.g. Linux - // vs. OSX, resulting in different answers.) + // vs. macOS, resulting in different answers.) if $from::is_float() { if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; } if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; } diff --git a/src/tools/compiletest/src/raise_fd_limit.rs b/src/tools/compiletest/src/raise_fd_limit.rs index e2629ffd8f54a..fcc5a727cf2d6 100644 --- a/src/tools/compiletest/src/raise_fd_limit.rs +++ b/src/tools/compiletest/src/raise_fd_limit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// darwin_fd_limit exists to work around an issue where launchctl on Mac OS X +/// darwin_fd_limit exists to work around an issue where launchctl on macOS /// defaults the rlimit maxfiles to 256/unlimited. The default soft limit of 256 /// ends up being far too low for our multithreaded scheduler testing, depending /// on the number of cores available. From 064477391c086d4ea26d880bc0f5e1a5c4cb1383 Mon Sep 17 00:00:00 2001 From: projektir Date: Mon, 13 Mar 2017 00:14:42 -0400 Subject: [PATCH 03/19] Remove doc about highlighting code in other languages #40301 --- src/doc/book/src/documentation.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/doc/book/src/documentation.md b/src/doc/book/src/documentation.md index 69d49e2f96aa8..551c393be775e 100644 --- a/src/doc/book/src/documentation.md +++ b/src/doc/book/src/documentation.md @@ -183,24 +183,6 @@ To write some Rust code in a comment, use the triple graves: # fn foo() {} ``` -If you want something that's not Rust code, you can add an annotation: - -```rust -/// ```c -/// printf("Hello, world\n"); -/// ``` -# fn foo() {} -``` - -This will highlight according to whatever language you're showing off. -If you're only showing plain text, choose `text`. - -It's important to choose the correct annotation here, because `rustdoc` uses it -in an interesting way: It can be used to actually test your examples in a -library crate, so that they don't get out of date. If you have some C code but -`rustdoc` thinks it's Rust because you left off the annotation, `rustdoc` will -complain when trying to generate the documentation. - ## Documentation as tests Let's discuss our sample example documentation: From 6b7b26228894a88bae0d1168777cc227cf7281da Mon Sep 17 00:00:00 2001 From: projektir Date: Mon, 13 Mar 2017 01:01:32 -0400 Subject: [PATCH 04/19] Updating README.md to point to the correct doc location --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 79f11144a073d..dc9362ca2f0b8 100644 --- a/README.md +++ b/README.md @@ -161,8 +161,9 @@ If you’d like to build the documentation, it’s almost the same: $ ./x.py doc ``` -The generated documentation will appear in a top-level `doc` directory, -created by the `make` rule. +The generated documentation will appear under `doc` in the `build` directory for +the ABI used. I.e., if the ABI was `x86_64-pc-windows-msvc`, the directory will be +`build\x86_64-pc-windows-msvc\doc`. ## Notes From 197e529c4425ba5d24cb3a3d59c1211093bbb82a Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Wed, 8 Mar 2017 16:28:47 -0500 Subject: [PATCH 05/19] Initial attempt at implementing optimization fuel and re-enabling struct field reordering. --- src/librustc/session/config.rs | 24 +++++++++ src/librustc/session/mod.rs | 52 ++++++++++++++++++++ src/librustc/ty/context.rs | 5 ++ src/librustc/ty/layout.rs | 9 +--- src/librustc/ty/mod.rs | 5 ++ src/librustc_driver/lib.rs | 8 +++ src/test/run-pass/type-sizes.rs | 13 +++++ src/test/ui/print_type_sizes/nullable.stdout | 35 ++++++------- src/test/ui/print_type_sizes/packed.stdout | 10 ++-- src/test/ui/print_type_sizes/padding.stdout | 16 +++--- 10 files changed, 138 insertions(+), 39 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 5fff03dabcece..53af7b9ac84c0 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -636,6 +636,8 @@ macro_rules! options { Some("either `panic` or `abort`"); pub const parse_sanitizer: Option<&'static str> = Some("one of: `address`, `leak`, `memory` or `thread`"); + pub const parse_optimization_fuel: Option<&'static str> = + Some("crate=integer"); } #[allow(dead_code)] @@ -772,6 +774,21 @@ macro_rules! options { } true } + + fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool { + match v { + None => false, + Some(s) => { + let parts = s.split('=').collect::>(); + if parts.len() != 2 { return false; } + let crate_name = parts[0].to_string(); + let fuel = parts[1].parse::(); + if fuel.is_err() { return false; } + *slot = Some((crate_name, fuel.unwrap())); + true + } + } + } } ) } @@ -974,6 +991,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "pass `-install_name @rpath/...` to the OSX linker"), sanitizer: Option = (None, parse_sanitizer, [TRACKED], "Use a sanitizer"), + fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], + "Set the optimization fuel quota for a crate."), + print_fuel: Option = (None, parse_opt_string, [TRACKED], + "Make Rustc print the total optimization fuel used by a crate."), } pub fn default_lib_output() -> CrateType { @@ -1766,11 +1787,13 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(bool); impl_dep_tracking_hash_via_hash!(usize); + impl_dep_tracking_hash_via_hash!(u64); impl_dep_tracking_hash_via_hash!(String); impl_dep_tracking_hash_via_hash!(lint::Level); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option<(String, u64)>); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); @@ -1792,6 +1815,7 @@ mod dep_tracking { impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); impl_dep_tracking_hash_for_sortable_vec_of!((String, Option, Option)); + impl_dep_tracking_hash_for_sortable_vec_of!((String, u64)); impl DepTrackingHash for SearchPaths { fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) { let mut elems: Vec<_> = self diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3ba82f34c3266..021cf2b3af941 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -123,6 +123,20 @@ pub struct Session { pub code_stats: RefCell, next_node_id: Cell, + + /// If -zfuel=crate=n is specified, Some(crate). + optimization_fuel_crate: Option, + /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0. + optimization_fuel_limit: Cell, + /// We're rejecting all further optimizations. + out_of_fuel: Cell, + + // The next two are public because the driver needs to read them. + + /// If -zprint-fuel=crate, Some(crate). + pub print_fuel_crate: Option, + /// Always set to zero and incremented so that we can print fuel expended by a crate. + pub print_fuel: Cell, } pub struct PerfStats { @@ -504,6 +518,33 @@ impl Session { println!("Total time spent decoding DefPath tables: {}", duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())); } + + /// We want to know if we're allowed to do an optimization for crate crate. + /// This expends fuel if applicable, and records fuel if applicable. + pub fn consider_optimizing String>(&self, crate_name: &str, msg: T) -> bool { + let mut ret = true; + match self.optimization_fuel_crate { + Some(ref c) if c == crate_name => { + let fuel = self.optimization_fuel_limit.get(); + ret = fuel != 0; + if fuel == 0 && !self.out_of_fuel.get(){ + println!("optimization-fuel-exhausted: {}", msg()); + self.out_of_fuel.set(true); + } + else { + self.optimization_fuel_limit.set(fuel-1); + } + } + _ => {} + } + match self.print_fuel_crate { + Some(ref c) if c == crate_name=> { + self.print_fuel.set(self.print_fuel.get()+1); + }, + _ => {} + } + ret + } } pub fn build_session(sopts: config::Options, @@ -599,6 +640,12 @@ pub fn build_session_(sopts: config::Options, } ); + let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone()); + let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref() + .map(|i| i.1).unwrap_or(0)); + let print_fuel_crate = sopts.debugging_opts.print_fuel.clone(); + let print_fuel = Cell::new(0); + let sess = Session { dep_graph: dep_graph.clone(), target: target_cfg, @@ -640,6 +687,11 @@ pub fn build_session_(sopts: config::Options, decode_def_path_tables_time: Cell::new(Duration::from_secs(0)), }, code_stats: RefCell::new(CodeStats::new()), + optimization_fuel_crate: optimization_fuel_crate, + optimization_fuel_limit: optimization_fuel_limit, + print_fuel_crate: print_fuel_crate, + print_fuel: print_fuel, + out_of_fuel: Cell::new(false), }; init_llvm(&sess); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a0aeb4107c156..47801c3921d2a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -728,6 +728,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ast_ty_to_ty_cache: RefCell::new(NodeMap()), }, f) } + + pub fn consider_optimizing String>(&self, msg: T) -> bool { + let cname = self.crate_name(LOCAL_CRATE).as_str(); + self.sess.consider_optimizing(&cname, msg) + } } impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 123db6e89476c..ade67e3efbe07 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -555,7 +555,6 @@ enum StructKind { } impl<'a, 'gcx, 'tcx> Struct { - // FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type. fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>, repr: &ReprOptions, kind: StructKind, scapegoat: Ty<'gcx>) -> Result> { @@ -573,12 +572,8 @@ impl<'a, 'gcx, 'tcx> Struct { // Neither do 1-member and 2-member structs. // In addition, code in trans assume that 2-element structs can become pairs. // It's easier to just short-circuit here. - let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind) - && ! (repr.c || repr.packed); - - // Disable field reordering until we can decide what to do. - // The odd pattern here avoids a warning about the value never being read. - if can_optimize { can_optimize = false; } + let can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind) + && ! (repr.c || repr.packed || repr.linear || repr.simd); let (optimize, sort_ascending) = match kind { StructKind::AlwaysSizedUnivariant => (can_optimize, false), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 3c37c7353d683..c2d977a793bba 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1376,6 +1376,8 @@ pub struct ReprOptions { pub packed: bool, pub simd: bool, pub int: Option, + // Internal only for now. If true, don't reorder fields. + pub linear: bool, } impl ReprOptions { @@ -1398,6 +1400,9 @@ impl ReprOptions { ret.simd = true; } + // This is here instead of layout because the choice must make it into metadata. + ret.linear = !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", + tcx.item_path_str(did))); ret } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 62d7512655728..d30183f01f54b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -514,6 +514,14 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.make_glob_map = resolve::MakeGlobMap::Yes; } + if sess.print_fuel_crate.is_some() { + control.compilation_done.callback = box |state| { + let sess = state.session; + println!("Fuel used by {}: {}", + sess.print_fuel_crate.as_ref().unwrap(), + sess.print_fuel.get()); + } + } control } } diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index bbb01eaaf46b9..9d1a3500a582a 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -31,6 +31,17 @@ enum e3 { a([u16; 0], u8), b } +struct ReorderedStruct { + a: u8, + b: u64, + c: u8 +} + +enum ReorderedEnum { + A(u8, u64, u8), + B(u8, u64, u8), +} + pub fn main() { assert_eq!(size_of::(), 1 as usize); assert_eq!(size_of::(), 4 as usize); @@ -54,4 +65,6 @@ pub fn main() { assert_eq!(size_of::(), 8 as usize); assert_eq!(size_of::(), 8 as usize); assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 16); + assert_eq!(size_of::(), 16); } diff --git a/src/test/ui/print_type_sizes/nullable.stdout b/src/test/ui/print_type_sizes/nullable.stdout index dd999c4a5e4c7..830678f174f88 100644 --- a/src/test/ui/print_type_sizes/nullable.stdout +++ b/src/test/ui/print_type_sizes/nullable.stdout @@ -1,25 +1,22 @@ -print-type-size type: `IndirectNonZero`: 20 bytes, alignment: 4 bytes -print-type-size field `.pre`: 1 bytes -print-type-size padding: 3 bytes -print-type-size field `.nested`: 12 bytes, alignment: 4 bytes +print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes +print-type-size field `.nested`: 8 bytes print-type-size field `.post`: 2 bytes -print-type-size end padding: 2 bytes -print-type-size type: `MyOption>`: 20 bytes, alignment: 4 bytes -print-type-size variant `Some`: 20 bytes -print-type-size field `.0`: 20 bytes -print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes -print-type-size variant `Record`: 10 bytes -print-type-size field `.pre`: 1 bytes -print-type-size padding: 3 bytes -print-type-size field `.val`: 4 bytes, alignment: 4 bytes -print-type-size field `.post`: 2 bytes -print-type-size end padding: 2 bytes -print-type-size type: `NestedNonZero`: 12 bytes, alignment: 4 bytes print-type-size field `.pre`: 1 bytes -print-type-size padding: 3 bytes -print-type-size field `.val`: 4 bytes, alignment: 4 bytes +print-type-size end padding: 1 bytes +print-type-size type: `MyOption>`: 12 bytes, alignment: 4 bytes +print-type-size variant `Some`: 12 bytes +print-type-size field `.0`: 12 bytes +print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes +print-type-size variant `Record`: 7 bytes +print-type-size field `.val`: 4 bytes +print-type-size field `.post`: 2 bytes +print-type-size field `.pre`: 1 bytes +print-type-size end padding: 1 bytes +print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes +print-type-size field `.val`: 4 bytes print-type-size field `.post`: 2 bytes -print-type-size end padding: 2 bytes +print-type-size field `.pre`: 1 bytes +print-type-size end padding: 1 bytes print-type-size type: `MyOption>`: 4 bytes, alignment: 4 bytes print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes diff --git a/src/test/ui/print_type_sizes/packed.stdout b/src/test/ui/print_type_sizes/packed.stdout index 1278a7d7c92c6..83fd333c9c7fc 100644 --- a/src/test/ui/print_type_sizes/packed.stdout +++ b/src/test/ui/print_type_sizes/packed.stdout @@ -1,13 +1,11 @@ -print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes +print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes +print-type-size field `.g`: 4 bytes +print-type-size field `.h`: 2 bytes print-type-size field `.a`: 1 bytes print-type-size field `.b`: 1 bytes -print-type-size padding: 2 bytes -print-type-size field `.g`: 4 bytes, alignment: 4 bytes print-type-size field `.c`: 1 bytes -print-type-size padding: 1 bytes -print-type-size field `.h`: 2 bytes, alignment: 2 bytes print-type-size field `.d`: 1 bytes -print-type-size end padding: 3 bytes +print-type-size end padding: 2 bytes print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes print-type-size field `.a`: 1 bytes print-type-size field `.b`: 1 bytes diff --git a/src/test/ui/print_type_sizes/padding.stdout b/src/test/ui/print_type_sizes/padding.stdout index bb95f790bd9e4..0eaff7118b35c 100644 --- a/src/test/ui/print_type_sizes/padding.stdout +++ b/src/test/ui/print_type_sizes/padding.stdout @@ -1,10 +1,12 @@ print-type-size type: `E1`: 12 bytes, alignment: 4 bytes -print-type-size discriminant: 4 bytes -print-type-size variant `A`: 5 bytes -print-type-size field `.0`: 4 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `A`: 7 bytes print-type-size field `.1`: 1 bytes -print-type-size variant `B`: 8 bytes -print-type-size field `.0`: 8 bytes +print-type-size padding: 2 bytes +print-type-size field `.0`: 4 bytes, alignment: 4 bytes +print-type-size variant `B`: 11 bytes +print-type-size padding: 3 bytes +print-type-size field `.0`: 8 bytes, alignment: 4 bytes print-type-size type: `E2`: 12 bytes, alignment: 4 bytes print-type-size discriminant: 1 bytes print-type-size variant `A`: 7 bytes @@ -15,7 +17,7 @@ print-type-size variant `B`: 11 bytes print-type-size padding: 3 bytes print-type-size field `.0`: 8 bytes, alignment: 4 bytes print-type-size type: `S`: 8 bytes, alignment: 4 bytes +print-type-size field `.g`: 4 bytes print-type-size field `.a`: 1 bytes print-type-size field `.b`: 1 bytes -print-type-size padding: 2 bytes -print-type-size field `.g`: 4 bytes, alignment: 4 bytes +print-type-size end padding: 2 bytes From 8f36057f6aec8c257cec5ceed69c71bc6f8ba56d Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Wed, 8 Mar 2017 22:20:07 -0500 Subject: [PATCH 06/19] Make a comment better. --- src/librustc/session/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 021cf2b3af941..1dd615273b9dc 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -519,7 +519,7 @@ impl Session { duration_to_secs_str(self.perf_stats.decode_def_path_tables_time.get())); } - /// We want to know if we're allowed to do an optimization for crate crate. + /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. /// This expends fuel if applicable, and records fuel if applicable. pub fn consider_optimizing String>(&self, crate_name: &str, msg: T) -> bool { let mut ret = true; From c2d14fc4c74d43d42cc753ccbb8374cdf86ff41e Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Fri, 10 Mar 2017 14:13:59 -0500 Subject: [PATCH 07/19] Tests for -Z fuel=foo=n --- src/librustc/session/mod.rs | 2 +- src/test/run-pass/optimization-fuel-0.rs | 24 ++++++++++++++++++++++ src/test/run-pass/optimization-fuel-1.rs | 26 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/optimization-fuel-0.rs create mode 100644 src/test/run-pass/optimization-fuel-1.rs diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 1dd615273b9dc..072301eeda5aa 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -531,7 +531,7 @@ impl Session { println!("optimization-fuel-exhausted: {}", msg()); self.out_of_fuel.set(true); } - else { + else if fuel > 0{ self.optimization_fuel_limit.set(fuel-1); } } diff --git a/src/test/run-pass/optimization-fuel-0.rs b/src/test/run-pass/optimization-fuel-0.rs new file mode 100644 index 0000000000000..3832c040108f8 --- /dev/null +++ b/src/test/run-pass/optimization-fuel-0.rs @@ -0,0 +1,24 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name="foo"] + +use std::mem::size_of; + +// compile-flags: -Z fuel=foo=0 + +struct S1(u8, u16, u8); +struct S2(u8, u16, u8); + +fn main() { + assert_eq!(size_of::(), 6); + assert_eq!(size_of::(), 6); +} + diff --git a/src/test/run-pass/optimization-fuel-1.rs b/src/test/run-pass/optimization-fuel-1.rs new file mode 100644 index 0000000000000..5f294e26aa53e --- /dev/null +++ b/src/test/run-pass/optimization-fuel-1.rs @@ -0,0 +1,26 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name="foo"] + +use std::mem::size_of; + +// compile-flags: -Z fuel=foo=1 + +struct S1(u8, u16, u8); +struct S2(u8, u16, u8); + +fn main() { + let optimized = (size_of::() == 4) as usize + +(size_of::() == 4) as usize; + assert_eq!(optimized, 1); +} + + From 3fb94b7ab064b23e62b018ef8b9dc47b2a59df2d Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Fri, 10 Mar 2017 14:24:50 -0500 Subject: [PATCH 08/19] UI test for -Z print-fuel=foo --- src/test/ui/print-fuel/print-fuel.rs | 21 +++++++++++++++++++++ src/test/ui/print-fuel/print-fuel.stdout | 1 + 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/print-fuel/print-fuel.rs create mode 100644 src/test/ui/print-fuel/print-fuel.stdout diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs new file mode 100644 index 0000000000000..0d9e243763f78 --- /dev/null +++ b/src/test/ui/print-fuel/print-fuel.rs @@ -0,0 +1,21 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_name="foo"] +#![allow(dead_code)] + +// compile-flags: -Z print-fuel=foo + +struct S1(u8, u16, u8); +struct S2(u8, u16, u8); +struct S3(u8, u16, u8); + +fn main() { +} diff --git a/src/test/ui/print-fuel/print-fuel.stdout b/src/test/ui/print-fuel/print-fuel.stdout new file mode 100644 index 0000000000000..cc88cc077bb21 --- /dev/null +++ b/src/test/ui/print-fuel/print-fuel.stdout @@ -0,0 +1 @@ +Fuel used by foo: 3 From eb203d597f6bed9bb6a7103649a36f19a087a2ab Mon Sep 17 00:00:00 2001 From: projektir Date: Mon, 13 Mar 2017 18:37:21 -0400 Subject: [PATCH 09/19] Adjust wording #40301 --- src/doc/book/src/documentation.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/book/src/documentation.md b/src/doc/book/src/documentation.md index 551c393be775e..176a7e508c0ac 100644 --- a/src/doc/book/src/documentation.md +++ b/src/doc/book/src/documentation.md @@ -170,8 +170,6 @@ more than one section: # fn foo() {} ``` -Let's discuss the details of these code blocks. - #### Code block annotations To write some Rust code in a comment, use the triple graves: @@ -183,6 +181,9 @@ To write some Rust code in a comment, use the triple graves: # fn foo() {} ``` +This will add code highlighting. If you are only showing plain text, put `text` +instead of `rust` after the triple graves (see below). + ## Documentation as tests Let's discuss our sample example documentation: From adba642a388cf14b6ffa9dd917443957c94e82fb Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Mon, 13 Mar 2017 23:56:27 +0100 Subject: [PATCH 10/19] fix format grammar --- src/libcollections/fmt.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index dfd292176d2f9..1ec1749c3aa64 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -306,7 +306,8 @@ //! `%`. The actual grammar for the formatting syntax is: //! //! ```text -//! format_string := [ format ] * +//! format_string := [ maybe-format ] * +//! maybe-format := '{' '{' | '}' '}' | //! format := '{' [ argument ] [ ':' format_spec ] '}' //! argument := integer | identifier //! From 5e49f79b068517ae238c7454f93cba6df31e47c0 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Fri, 10 Mar 2017 16:06:07 -0600 Subject: [PATCH 11/19] Add test for issue #29595 --- src/test/ui/span/issue-29595.rs | 19 +++++++++++++++++++ src/test/ui/span/issue-29595.stderr | 10 ++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/span/issue-29595.rs create mode 100644 src/test/ui/span/issue-29595.stderr diff --git a/src/test/ui/span/issue-29595.rs b/src/test/ui/span/issue-29595.rs new file mode 100644 index 0000000000000..79704619ccd37 --- /dev/null +++ b/src/test/ui/span/issue-29595.rs @@ -0,0 +1,19 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_consts)] + +trait Tr { + const C: Self; +} + +fn main() { + let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied +} diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr new file mode 100644 index 0000000000000..abbac245f89f6 --- /dev/null +++ b/src/test/ui/span/issue-29595.stderr @@ -0,0 +1,10 @@ +error[E0277]: the trait bound `u8: Tr` is not satisfied + --> $DIR/issue-29595.rs:18:17 + | +18 | let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied + | ^^^^^ the trait `Tr` is not implemented for `u8` + | + = note: required by `Tr::C` + +error: aborting due to previous error + From 11d3344562e8197cce5441d36bec636f917be5f2 Mon Sep 17 00:00:00 2001 From: projektir Date: Mon, 13 Mar 2017 19:13:26 -0400 Subject: [PATCH 12/19] Using X headings #39850 --- src/doc/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/index.md b/src/doc/index.md index 1f262b360e3ed..1294c1a8c59e7 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -11,18 +11,18 @@ Other unofficial documentation may exist elsewhere; for example, the [Rust Learning] project collects documentation from the community, and [Docs.rs] builds documentation for individual Rust packages. -## API Documentation +# API Documentation Rust provides a standard library with a number of features; [we host its documentation here][api]. -## Extended Error Documentation +# Extended Error Documentation Many of Rust's errors come with error codes, and you can request extended diagnostics from the compiler on those errors. We also [have the text of those extended errors on the web][err], if you prefer to read them that way. -## The Rust Bookshelf +# The Rust Bookshelf Rust provides a number of book-length sets of documentation, collectively nicknamed 'The Rust Bookshelf.' From 8b9b3b6d8b1b683dbc4bd2c2d5000cb87eb8b1a2 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 13 Mar 2017 20:36:41 -0400 Subject: [PATCH 13/19] Fix sidebar not extending to the bottom of the page Fixes #40459 --- src/librustdoc/html/static/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4047f6045bcc5..3df120eece9c5 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -167,7 +167,7 @@ nav.sub { position: absolute; left: 0; top: 0; - min-height: 100vh; + min-height: 100%; } .sidebar .current { From 1545f4e2a323eb869b13f36bd05cc91ff21d5161 Mon Sep 17 00:00:00 2001 From: Sean Gillespie Date: Mon, 13 Mar 2017 18:42:23 -0700 Subject: [PATCH 14/19] std: remove a workaround for privacy limitations that isn't necessary anymore --- src/libstd/rt.rs | 4 ++-- src/libstd/sys_common/thread_info.rs | 7 +------ src/libstd/thread/mod.rs | 7 +------ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 78d5aa597ba0d..6c791cd336ded 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -34,7 +34,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { use panic; use sys; use sys_common; - use sys_common::thread_info::{self, NewThread}; + use sys_common::thread_info; use thread::Thread; sys::init(); @@ -47,7 +47,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { // created. Note that this isn't necessary in general for new threads, // but we just do this to name the main thread and to give it correct // info about the stack bounds. - let thread: Thread = NewThread::new(Some("main".to_owned())); + let thread = Thread::new(Some("main".to_owned())); thread_info::set(main_guard, thread); // Store our args if necessary in a squirreled away location diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 95d8b6cc9516d..5ed48ee455871 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -31,7 +31,7 @@ impl ThreadInfo { if c.borrow().is_none() { *c.borrow_mut() = Some(ThreadInfo { stack_guard: None, - thread: NewThread::new(None), + thread: Thread::new(None), }) } Some(f(c.borrow_mut().as_mut().unwrap())) @@ -54,8 +54,3 @@ pub fn set(stack_guard: Option, thread: Thread) { thread: thread, })); } - -// a hack to get around privacy restrictions; implemented by `std::thread` -pub trait NewThread { - fn new(name: Option) -> Self; -} diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 2bc066d3fea55..fa4cc276ee5df 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -745,7 +745,7 @@ pub struct Thread { impl Thread { // Used only internally to construct a thread object without spawning - fn new(name: Option) -> Thread { + pub(crate) fn new(name: Option) -> Thread { let cname = name.map(|n| { CString::new(n).expect("thread name may not contain interior null bytes") }); @@ -858,11 +858,6 @@ impl fmt::Debug for Thread { } } -// a hack to get around privacy restrictions -impl thread_info::NewThread for Thread { - fn new(name: Option) -> Thread { Thread::new(name) } -} - //////////////////////////////////////////////////////////////////////////////// // JoinHandle //////////////////////////////////////////////////////////////////////////////// From e7b0f2badf7c3393f1b36339b121054d05353442 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sun, 12 Mar 2017 14:04:52 -0400 Subject: [PATCH 15/19] Remove function invokation parens from documentation links. This was never established as a convention we should follow in the 'More API Documentation Conventions' RFC: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md --- src/doc/book/src/ffi.md | 8 +- src/doc/book/src/guessing-game.md | 2 +- src/liballoc/rc.rs | 4 +- src/libcollections/binary_heap.rs | 4 +- src/libcollections/slice.rs | 22 +++--- src/libcollections/str.rs | 68 ++++++++--------- src/libcollections/string.rs | 94 +++++++++++------------ src/libcollections/vec.rs | 42 +++++------ src/libcore/char.rs | 20 ++--- src/libcore/clone.rs | 4 +- src/libcore/convert.rs | 8 +- src/libcore/hash/mod.rs | 4 +- src/libcore/iter/iterator.rs | 64 ++++++++-------- src/libcore/iter/mod.rs | 120 +++++++++++++++--------------- src/libcore/iter/sources.rs | 22 +++--- src/libcore/iter/traits.rs | 50 ++++++------- src/libcore/macros.rs | 4 +- src/libcore/marker.rs | 4 +- src/libcore/mem.rs | 2 +- src/libcore/num/mod.rs | 10 +-- src/libcore/ops.rs | 14 ++-- src/libcore/str/mod.rs | 70 ++++++++--------- src/libstd/fs.rs | 8 +- src/libstd/io/error.rs | 4 +- src/libstd/io/mod.rs | 92 +++++++++++------------ src/libstd/io/stdio.rs | 4 +- src/libstd/io/util.rs | 6 +- src/libstd/lib.rs | 4 +- src/libstd/net/tcp.rs | 18 ++--- src/libstd/net/udp.rs | 20 ++--- src/libstd/panicking.rs | 8 +- src/libstd/path.rs | 32 ++++---- src/libstd/prelude/mod.rs | 8 +- src/libstd/primitive_docs.rs | 6 +- src/libstd/sync/barrier.rs | 4 +- src/libstd/sync/condvar.rs | 18 ++--- src/libstd/sync/mpsc/mod.rs | 12 +-- src/libstd/sync/mutex.rs | 6 +- src/libstd/sync/rwlock.rs | 12 +-- src/libstd/sys/unix/ext/net.rs | 34 ++++----- src/libstd/thread/mod.rs | 32 ++++---- src/libstd_unicode/char.rs | 14 ++-- 42 files changed, 491 insertions(+), 491 deletions(-) diff --git a/src/doc/book/src/ffi.md b/src/doc/book/src/ffi.md index e9e2dab73eff3..3dd9aa3885bc0 100644 --- a/src/doc/book/src/ffi.md +++ b/src/doc/book/src/ffi.md @@ -687,7 +687,7 @@ attribute turns off Rust's name mangling, so that it is easier to link to. It’s important to be mindful of `panic!`s when working with FFI. A `panic!` across an FFI boundary is undefined behavior. If you’re writing code that may -panic, you should run it in a closure with [`catch_unwind()`]: +panic, you should run it in a closure with [`catch_unwind`]: ```rust use std::panic::catch_unwind; @@ -706,11 +706,11 @@ pub extern fn oh_no() -> i32 { fn main() {} ``` -Please note that [`catch_unwind()`] will only catch unwinding panics, not -those who abort the process. See the documentation of [`catch_unwind()`] +Please note that [`catch_unwind`] will only catch unwinding panics, not +those who abort the process. See the documentation of [`catch_unwind`] for more information. -[`catch_unwind()`]: ../std/panic/fn.catch_unwind.html +[`catch_unwind`]: ../std/panic/fn.catch_unwind.html # Representing opaque structs diff --git a/src/doc/book/src/guessing-game.md b/src/doc/book/src/guessing-game.md index 4d81438b11dea..bbb43b4a9ef4b 100644 --- a/src/doc/book/src/guessing-game.md +++ b/src/doc/book/src/guessing-game.md @@ -217,7 +217,7 @@ The next part will use this handle to get input from the user: .read_line(&mut guess) ``` -Here, we call the [`read_line()`][read_line] method on our handle. +Here, we call the [`read_line`][read_line] method on our handle. [Methods][method] are like associated functions, but are only available on a particular instance of a type, rather than the type itself. We’re also passing one argument to `read_line()`: `&mut guess`. diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 6108a06634bb8..eb449b2660679 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -13,7 +13,7 @@ //! Single-threaded reference-counting pointers. //! //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, -//! allocated in the heap. Invoking [`clone()`][clone] on [`Rc`] produces a new +//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new //! pointer to the same value in the heap. When the last [`Rc`] pointer to a //! given value is destroyed, the pointed-to value is also destroyed. //! @@ -30,7 +30,7 @@ //! threads. If you need multi-threaded, atomic reference counting, use //! [`sync::Arc`][arc]. //! -//! The [`downgrade()`][downgrade] method can be used to create a non-owning +//! The [`downgrade`][downgrade] method can be used to create a non-owning //! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d //! to an [`Rc`], but this will return [`None`] if the value has //! already been dropped. diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index a5a2f70492dc9..519117ff9e519 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -218,10 +218,10 @@ pub struct BinaryHeap { data: Vec, } -/// A container object that represents the result of the [`peek_mut()`] method +/// A container object that represents the result of the [`peek_mut`] method /// on `BinaryHeap`. See its documentation for details. /// -/// [`peek_mut()`]: struct.BinaryHeap.html#method.peek_mut +/// [`peek_mut`]: struct.BinaryHeap.html#method.peek_mut #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub struct PeekMut<'a, T: 'a + Ord> { heap: &'a mut BinaryHeap, diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 2ea953df87357..11fc1d553f28e 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -73,10 +73,10 @@ //! the element type of the slice is `i32`, the element type of the iterator is //! `&mut i32`. //! -//! * [`.iter()`] and [`.iter_mut()`] are the explicit methods to return the default +//! * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default //! iterators. -//! * Further methods that return iterators are [`.split()`], [`.splitn()`], -//! [`.chunks()`], [`.windows()`] and more. +//! * Further methods that return iterators are [`.split`], [`.splitn`], +//! [`.chunks`], [`.windows`] and more. //! //! *[See also the slice primitive type](../../std/primitive.slice.html).* //! @@ -85,12 +85,12 @@ //! [`Ord`]: ../../std/cmp/trait.Ord.html //! [`Iter`]: struct.Iter.html //! [`Hash`]: ../../std/hash/trait.Hash.html -//! [`.iter()`]: ../../std/primitive.slice.html#method.iter -//! [`.iter_mut()`]: ../../std/primitive.slice.html#method.iter_mut -//! [`.split()`]: ../../std/primitive.slice.html#method.split -//! [`.splitn()`]: ../../std/primitive.slice.html#method.splitn -//! [`.chunks()`]: ../../std/primitive.slice.html#method.chunks -//! [`.windows()`]: ../../std/primitive.slice.html#method.windows +//! [`.iter`]: ../../std/primitive.slice.html#method.iter +//! [`.iter_mut`]: ../../std/primitive.slice.html#method.iter_mut +//! [`.split`]: ../../std/primitive.slice.html#method.split +//! [`.splitn`]: ../../std/primitive.slice.html#method.splitn +//! [`.chunks`]: ../../std/primitive.slice.html#method.chunks +//! [`.windows`]: ../../std/primitive.slice.html#method.windows #![stable(feature = "rust1", since = "1.0.0")] // Many of the usings in this module are only used in the test configuration. @@ -368,9 +368,9 @@ impl [T] { } /// Returns a mutable reference to an element or subslice depending on the - /// type of index (see [`get()`]) or `None` if the index is out of bounds. + /// type of index (see [`get`]) or `None` if the index is out of bounds. /// - /// [`get()`]: #method.get + /// [`get`]: #method.get /// /// # Examples /// diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index e27c45773441a..90e54a383d623 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -298,9 +298,9 @@ impl str { /// excluding `end`. /// /// To get a mutable string slice instead, see the - /// [`slice_mut_unchecked()`] method. + /// [`slice_mut_unchecked`] method. /// - /// [`slice_mut_unchecked()`]: #method.slice_mut_unchecked + /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked /// /// # Safety /// @@ -341,9 +341,9 @@ impl str { /// excluding `end`. /// /// To get an immutable string slice instead, see the - /// [`slice_unchecked()`] method. + /// [`slice_unchecked`] method. /// - /// [`slice_unchecked()`]: #method.slice_unchecked + /// [`slice_unchecked`]: #method.slice_unchecked /// /// # Safety /// @@ -367,10 +367,10 @@ impl str { /// The two slices returned go from the start of the string slice to `mid`, /// and from `mid` to the end of the string slice. /// - /// To get mutable string slices instead, see the [`split_at_mut()`] + /// To get mutable string slices instead, see the [`split_at_mut`] /// method. /// - /// [`split_at_mut()`]: #method.split_at_mut + /// [`split_at_mut`]: #method.split_at_mut /// /// # Panics /// @@ -403,9 +403,9 @@ impl str { /// The two slices returned go from the start of the string slice to `mid`, /// and from `mid` to the end of the string slice. /// - /// To get immutable string slices instead, see the [`split_at()`] method. + /// To get immutable string slices instead, see the [`split_at`] method. /// - /// [`split_at()`]: #method.split_at + /// [`split_at`]: #method.split_at /// /// # Panics /// @@ -824,10 +824,10 @@ impl str { /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html /// /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit()`] method can be used. + /// from a forward search, the [`rsplit`] method can be used. /// /// [`char`]: primitive.char.html - /// [`rsplit()`]: #method.rsplit + /// [`rsplit`]: #method.rsplit /// /// # Examples /// @@ -912,9 +912,9 @@ impl str { /// assert_eq!(d, &["a", "b", "c"]); /// ``` /// - /// Use [`split_whitespace()`] for this behavior. + /// Use [`split_whitespace`] for this behavior. /// - /// [`split_whitespace()`]: #method.split_whitespace + /// [`split_whitespace`]: #method.split_whitespace #[stable(feature = "rust1", since = "1.0.0")] pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> { core_str::StrExt::split(self, pat) @@ -936,9 +936,9 @@ impl str { /// /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html /// - /// For iterating from the front, the [`split()`] method can be used. + /// For iterating from the front, the [`split`] method can be used. /// - /// [`split()`]: #method.split + /// [`split`]: #method.split /// /// # Examples /// @@ -977,10 +977,10 @@ impl str { /// The pattern can be a `&str`, [`char`], or a closure that determines the /// split. /// - /// Equivalent to [`split()`], except that the trailing substring + /// Equivalent to [`split`], except that the trailing substring /// is skipped if empty. /// - /// [`split()`]: #method.split + /// [`split`]: #method.split /// /// This method can be used for string data that is _terminated_, /// rather than _separated_ by a pattern. @@ -995,9 +995,9 @@ impl str { /// [`char`]: primitive.char.html /// /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rsplit_terminator()`] method can be used. + /// from a forward search, the [`rsplit_terminator`] method can be used. /// - /// [`rsplit_terminator()`]: #method.rsplit_terminator + /// [`rsplit_terminator`]: #method.rsplit_terminator /// /// # Examples /// @@ -1025,10 +1025,10 @@ impl str { /// /// [`char`]: primitive.char.html /// - /// Equivalent to [`split()`], except that the trailing substring is + /// Equivalent to [`split`], except that the trailing substring is /// skipped if empty. /// - /// [`split()`]: #method.split + /// [`split`]: #method.split /// /// This method can be used for string data that is _terminated_, /// rather than _separated_ by a pattern. @@ -1039,10 +1039,10 @@ impl str { /// reverse search, and it will be double ended if a forward/reverse /// search yields the same elements. /// - /// For iterating from the front, the [`split_terminator()`] method can be + /// For iterating from the front, the [`split_terminator`] method can be /// used. /// - /// [`split_terminator()`]: #method.split_terminator + /// [`split_terminator`]: #method.split_terminator /// /// # Examples /// @@ -1076,10 +1076,10 @@ impl str { /// The returned iterator will not be double ended, because it is /// not efficient to support. /// - /// If the pattern allows a reverse search, the [`rsplitn()`] method can be + /// If the pattern allows a reverse search, the [`rsplitn`] method can be /// used. /// - /// [`rsplitn()`]: #method.rsplitn + /// [`rsplitn`]: #method.rsplitn /// /// # Examples /// @@ -1127,9 +1127,9 @@ impl str { /// The returned iterator will not be double ended, because it is not /// efficient to support. /// - /// For splitting from the front, the [`splitn()`] method can be used. + /// For splitting from the front, the [`splitn`] method can be used. /// - /// [`splitn()`]: #method.splitn + /// [`splitn`]: #method.splitn /// /// # Examples /// @@ -1177,9 +1177,9 @@ impl str { /// [`char`]: primitive.char.html /// /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatches()`] method can be used. + /// from a forward search, the [`rmatches`] method can be used. /// - /// [`rmatches()`]: #method.rmatches + /// [`rmatches`]: #method.rmatches /// /// # Examples /// @@ -1213,9 +1213,9 @@ impl str { /// /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html /// - /// For iterating from the front, the [`matches()`] method can be used. + /// For iterating from the front, the [`matches`] method can be used. /// - /// [`matches()`]: #method.matches + /// [`matches`]: #method.matches /// /// # Examples /// @@ -1255,9 +1255,9 @@ impl str { /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html /// /// If the pattern allows a reverse search but its results might differ - /// from a forward search, the [`rmatch_indices()`] method can be used. + /// from a forward search, the [`rmatch_indices`] method can be used. /// - /// [`rmatch_indices()`]: #method.rmatch_indices + /// [`rmatch_indices`]: #method.rmatch_indices /// /// # Examples /// @@ -1297,9 +1297,9 @@ impl str { /// /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html /// - /// For iterating from the front, the [`match_indices()`] method can be used. + /// For iterating from the front, the [`match_indices`] method can be used. /// - /// [`match_indices()`]: #method.match_indices + /// [`match_indices`]: #method.match_indices /// /// # Examples /// diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 43323676ab459..e8e3a25a8f45c 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -89,8 +89,8 @@ use boxed::Box; /// let hello = String::from("Hello, world!"); /// ``` /// -/// You can append a [`char`] to a `String` with the [`push()`] method, and -/// append a [`&str`] with the [`push_str()`] method: +/// You can append a [`char`] to a `String` with the [`push`] method, and +/// append a [`&str`] with the [`push_str`] method: /// /// ``` /// let mut hello = String::from("Hello, "); @@ -100,11 +100,11 @@ use boxed::Box; /// ``` /// /// [`char`]: ../../std/primitive.char.html -/// [`push()`]: #method.push -/// [`push_str()`]: #method.push_str +/// [`push`]: #method.push +/// [`push_str`]: #method.push_str /// /// If you have a vector of UTF-8 bytes, you can create a `String` from it with -/// the [`from_utf8()`] method: +/// the [`from_utf8`] method: /// /// ``` /// // some bytes, in a vector @@ -116,7 +116,7 @@ use boxed::Box; /// assert_eq!("💖", sparkle_heart); /// ``` /// -/// [`from_utf8()`]: #method.from_utf8 +/// [`from_utf8`]: #method.from_utf8 /// /// # UTF-8 /// @@ -136,11 +136,11 @@ use boxed::Box; /// Indexing is intended to be a constant-time operation, but UTF-8 encoding /// does not allow us to do this. Furthermore, it's not clear what sort of /// thing the index should return: a byte, a codepoint, or a grapheme cluster. -/// The [`bytes()`] and [`chars()`] methods return iterators over the first +/// The [`bytes`] and [`chars`] methods return iterators over the first /// two, respectively. /// -/// [`bytes()`]: #method.bytes -/// [`chars()`]: #method.chars +/// [`bytes`]: #method.bytes +/// [`chars`]: #method.chars /// /// # Deref /// @@ -174,7 +174,7 @@ use boxed::Box; /// /// This buffer is always stored on the heap. /// -/// You can look at these with the [`as_ptr()`], [`len()`], and [`capacity()`] +/// You can look at these with the [`as_ptr`], [`len`], and [`capacity`] /// methods: /// /// ``` @@ -200,9 +200,9 @@ use boxed::Box; /// assert_eq!(String::from("Once upon a time..."), s); /// ``` /// -/// [`as_ptr()`]: #method.as_ptr -/// [`len()`]: #method.len -/// [`capacity()`]: #method.capacity +/// [`as_ptr`]: #method.as_ptr +/// [`len`]: #method.len +/// [`capacity`]: #method.capacity /// /// If a `String` has enough capacity, adding elements to it will not /// re-allocate. For example, consider this program: @@ -231,7 +231,7 @@ use boxed::Box; /// /// At first, we have no memory allocated at all, but as we append to the /// string, it increases its capacity appropriately. If we instead use the -/// [`with_capacity()`] method to allocate the correct capacity initially: +/// [`with_capacity`] method to allocate the correct capacity initially: /// /// ``` /// let mut s = String::with_capacity(25); @@ -244,7 +244,7 @@ use boxed::Box; /// } /// ``` /// -/// [`with_capacity()`]: #method.with_capacity +/// [`with_capacity`]: #method.with_capacity /// /// We end up with a different output: /// @@ -266,25 +266,25 @@ pub struct String { /// A possible error value when converting a `String` from a UTF-8 byte vector. /// -/// This type is the error type for the [`from_utf8()`] method on [`String`]. It +/// This type is the error type for the [`from_utf8`] method on [`String`]. It /// is designed in such a way to carefully avoid reallocations: the -/// [`into_bytes()`] method will give back the byte vector that was used in the +/// [`into_bytes`] method will give back the byte vector that was used in the /// conversion attempt. /// -/// [`from_utf8()`]: struct.String.html#method.from_utf8 +/// [`from_utf8`]: struct.String.html#method.from_utf8 /// [`String`]: struct.String.html -/// [`into_bytes()`]: struct.FromUtf8Error.html#method.into_bytes +/// [`into_bytes`]: struct.FromUtf8Error.html#method.into_bytes /// /// The [`Utf8Error`] type provided by [`std::str`] represents an error that may /// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's /// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error` -/// through the [`utf8_error()`] method. +/// through the [`utf8_error`] method. /// /// [`Utf8Error`]: ../../std/str/struct.Utf8Error.html /// [`std::str`]: ../../std/str/index.html /// [`u8`]: ../../std/primitive.u8.html /// [`&str`]: ../../std/primitive.str.html -/// [`utf8_error()`]: #method.utf8_error +/// [`utf8_error`]: #method.utf8_error /// /// # Examples /// @@ -308,9 +308,9 @@ pub struct FromUtf8Error { /// A possible error value when converting a `String` from a UTF-16 byte slice. /// -/// This type is the error type for the [`from_utf16()`] method on [`String`]. +/// This type is the error type for the [`from_utf16`] method on [`String`]. /// -/// [`from_utf16()`]: struct.String.html#method.from_utf16 +/// [`from_utf16`]: struct.String.html#method.from_utf16 /// [`String`]: struct.String.html /// /// # Examples @@ -335,10 +335,10 @@ impl String { /// buffer. While that means that this initial operation is very /// inexpensive, but may cause excessive allocation later, when you add /// data. If you have an idea of how much data the `String` will hold, - /// consider the [`with_capacity()`] method to prevent excessive + /// consider the [`with_capacity`] method to prevent excessive /// re-allocation. /// - /// [`with_capacity()`]: #method.with_capacity + /// [`with_capacity`]: #method.with_capacity /// /// # Examples /// @@ -356,18 +356,18 @@ impl String { /// Creates a new empty `String` with a particular capacity. /// /// `String`s have an internal buffer to hold their data. The capacity is - /// the length of that buffer, and can be queried with the [`capacity()`] + /// the length of that buffer, and can be queried with the [`capacity`] /// method. This method creates an empty `String`, but one with an initial /// buffer that can hold `capacity` bytes. This is useful when you may be /// appending a bunch of data to the `String`, reducing the number of /// reallocations it needs to do. /// - /// [`capacity()`]: #method.capacity + /// [`capacity`]: #method.capacity /// /// If the given capacity is `0`, no allocation will occur, and this method - /// is identical to the [`new()`] method. + /// is identical to the [`new`] method. /// - /// [`new()`]: #method.new + /// [`new`]: #method.new /// /// # Examples /// @@ -420,18 +420,18 @@ impl String { /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the validity check, there is an unsafe version - /// of this function, [`from_utf8_unchecked()`], which has the same behavior + /// of this function, [`from_utf8_unchecked`], which has the same behavior /// but skips the check. /// - /// [`from_utf8_unchecked()`]: struct.String.html#method.from_utf8_unchecked + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked /// /// This method will take care to not copy the vector, for efficiency's /// sake. /// /// If you need a `&str` instead of a `String`, consider - /// [`str::from_utf8()`]. + /// [`str::from_utf8`]. /// - /// [`str::from_utf8()`]: ../../std/str/fn.from_utf8.html + /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html /// /// The inverse of this method is [`as_bytes`]. /// @@ -497,10 +497,10 @@ impl String { /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the conversion, there is an unsafe version - /// of this function, [`from_utf8_unchecked()`], which has the same behavior + /// of this function, [`from_utf8_unchecked`], which has the same behavior /// but skips the checks. /// - /// [`from_utf8_unchecked()`]: struct.String.html#method.from_utf8_unchecked + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked /// /// This function returns a [`Cow<'a, str>`]. If our byte slice is invalid /// UTF-8, then we need to insert the replacement characters, which will @@ -738,9 +738,9 @@ impl String { /// Converts a vector of bytes to a `String` without checking that the /// string contains valid UTF-8. /// - /// See the safe version, [`from_utf8()`], for more details. + /// See the safe version, [`from_utf8`], for more details. /// - /// [`from_utf8()`]: struct.String.html#method.from_utf8 + /// [`from_utf8`]: struct.String.html#method.from_utf8 /// /// # Safety /// @@ -845,10 +845,10 @@ impl String { /// The capacity may be increased by more than `additional` bytes if it /// chooses, to prevent frequent reallocations. /// - /// If you do not want this "at least" behavior, see the [`reserve_exact()`] + /// If you do not want this "at least" behavior, see the [`reserve_exact`] /// method. /// - /// [`reserve_exact()`]: #method.reserve_exact + /// [`reserve_exact`]: #method.reserve_exact /// /// # Panics /// @@ -892,10 +892,10 @@ impl String { /// Ensures that this `String`'s capacity is `additional` bytes /// larger than its length. /// - /// Consider using the [`reserve()`] method unless you absolutely know + /// Consider using the [`reserve`] method unless you absolutely know /// better than the allocator. /// - /// [`reserve()`]: #method.reserve + /// [`reserve`]: #method.reserve /// /// # Panics /// @@ -1699,9 +1699,9 @@ impl<'a> Add<&'a str> for String { /// Implements the `+=` operator for appending to a `String`. /// -/// This has the same behavior as the [`push_str()`] method. +/// This has the same behavior as the [`push_str`] method. /// -/// [`push_str()`]: struct.String.html#method.push_str +/// [`push_str`]: struct.String.html#method.push_str #[stable(feature = "stringaddassign", since = "1.12.0")] impl<'a> AddAssign<&'a str> for String { #[inline] @@ -1830,14 +1830,14 @@ impl ops::DerefMut for String { /// /// This `enum` is slightly awkward: it will never actually exist. This error is /// part of the type signature of the implementation of [`FromStr`] on -/// [`String`]. The return type of [`from_str()`], requires that an error be +/// [`String`]. The return type of [`from_str`], requires that an error be /// defined, but, given that a [`String`] can always be made into a new /// [`String`] without error, this type will never actually be returned. As /// such, it is only here to satisfy said signature, and is useless otherwise. /// /// [`FromStr`]: ../../std/str/trait.FromStr.html /// [`String`]: struct.String.html -/// [`from_str()`]: ../../std/str/trait.FromStr.html#tymethod.from_str +/// [`from_str`]: ../../std/str/trait.FromStr.html#tymethod.from_str #[stable(feature = "str_parse_error", since = "1.5.0")] #[derive(Copy)] pub enum ParseError {} @@ -2042,10 +2042,10 @@ impl fmt::Write for String { /// A draining iterator for `String`. /// -/// This struct is created by the [`drain()`] method on [`String`]. See its +/// This struct is created by the [`drain`] method on [`String`]. See its /// documentation for more. /// -/// [`drain()`]: struct.String.html#method.drain +/// [`drain`]: struct.String.html#method.drain /// [`String`]: struct.String.html #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a> { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index d38c9f6e1cf80..76bc3fc3575d9 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -16,7 +16,7 @@ //! //! # Examples //! -//! You can explicitly create a [`Vec`] with [`new()`]: +//! You can explicitly create a [`Vec`] with [`new`]: //! //! ``` //! let v: Vec = Vec::new(); @@ -58,7 +58,7 @@ //! ``` //! //! [`Vec`]: ../../std/vec/struct.Vec.html -//! [`new()`]: ../../std/vec/struct.Vec.html#method.new +//! [`new`]: ../../std/vec/struct.Vec.html#method.new //! [`push`]: ../../std/vec/struct.Vec.html#method.push //! [`Index`]: ../../std/ops/trait.Index.html //! [`IndexMut`]: ../../std/ops/trait.IndexMut.html @@ -216,19 +216,19 @@ use Bound::{Excluded, Included, Unbounded}; /// The pointer will never be null, so this type is null-pointer-optimized. /// /// However, the pointer may not actually point to allocated memory. In particular, -/// if you construct a `Vec` with capacity 0 via [`Vec::new()`], [`vec![]`][`vec!`], -/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit()`] +/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], +/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized /// types inside a `Vec`, it will not allocate space for them. *Note that in this case -/// the `Vec` may not report a [`capacity()`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::()`]` * capacity() > 0`. In general, `Vec`'s allocation +/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// if [`mem::size_of::`]` * capacity() > 0`. In general, `Vec`'s allocation /// details are subtle enough that it is strongly recommended that you only /// free memory allocated by a `Vec` by creating a new `Vec` and dropping it. /// /// If a `Vec` *has* allocated memory, then the memory it points to is on the heap /// (as defined by the allocator Rust is configured to use by default), and its -/// pointer points to [`len()`] initialized elements in order (what you would see -/// if you coerced it to a slice), followed by [`capacity()`]` - `[`len()`] +/// pointer points to [`len`] initialized elements in order (what you would see +/// if you coerced it to a slice), followed by [`capacity`]` - `[`len`] /// logically uninitialized elements. /// /// `Vec` will never perform a "small optimization" where elements are actually @@ -244,13 +244,13 @@ use Bound::{Excluded, Included, Unbounded}; /// /// `Vec` will never automatically shrink itself, even if completely empty. This /// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` -/// and then filling it back up to the same [`len()`] should incur no calls to +/// and then filling it back up to the same [`len`] should incur no calls to /// the allocator. If you wish to free up unused memory, use -/// [`shrink_to_fit`][`shrink_to_fit()`]. +/// [`shrink_to_fit`][`shrink_to_fit`]. /// /// [`push`] and [`insert`] will never (re)allocate if the reported capacity is /// sufficient. [`push`] and [`insert`] *will* (re)allocate if -/// [`len()`]` == `[`capacity()`]. That is, the reported capacity is completely +/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely /// accurate, and can be relied on. It can even be used to manually free the memory /// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even /// when not necessary. @@ -262,7 +262,7 @@ use Bound::{Excluded, Included, Unbounded}; /// /// `vec![x; n]`, `vec![a, b, c, d]`, and /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` -/// with exactly the requested capacity. If [`len()`]` == `[`capacity()`], +/// with exactly the requested capacity. If [`len`]` == `[`capacity`], /// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to /// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. /// @@ -283,11 +283,11 @@ use Bound::{Excluded, Included, Unbounded}; /// [`String`]: ../../std/string/struct.String.html /// [`&str`]: ../../std/primitive.str.html /// [`Vec::with_capacity`]: ../../std/vec/struct.Vec.html#method.with_capacity -/// [`Vec::new()`]: ../../std/vec/struct.Vec.html#method.new -/// [`shrink_to_fit()`]: ../../std/vec/struct.Vec.html#method.shrink_to_fit -/// [`capacity()`]: ../../std/vec/struct.Vec.html#method.capacity -/// [`mem::size_of::()`]: ../../std/mem/fn.size_of.html -/// [`len()`]: ../../std/vec/struct.Vec.html#method.len +/// [`Vec::new`]: ../../std/vec/struct.Vec.html#method.new +/// [`shrink_to_fit`]: ../../std/vec/struct.Vec.html#method.shrink_to_fit +/// [`capacity`]: ../../std/vec/struct.Vec.html#method.capacity +/// [`mem::size_of::`]: ../../std/mem/fn.size_of.html +/// [`len`]: ../../std/vec/struct.Vec.html#method.len /// [`push`]: ../../std/vec/struct.Vec.html#method.push /// [`insert`]: ../../std/vec/struct.Vec.html#method.insert /// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve @@ -504,12 +504,12 @@ impl Vec { /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Note that this will drop any excess capacity. Calling this and - /// converting back to a vector with [`into_vec()`] is equivalent to calling - /// [`shrink_to_fit()`]. + /// converting back to a vector with [`into_vec`] is equivalent to calling + /// [`shrink_to_fit`]. /// /// [owned slice]: ../../std/boxed/struct.Box.html - /// [`into_vec()`]: ../../std/primitive.slice.html#method.into_vec - /// [`shrink_to_fit()`]: #method.shrink_to_fit + /// [`into_vec`]: ../../std/primitive.slice.html#method.into_vec + /// [`shrink_to_fit`]: #method.shrink_to_fit /// /// # Examples /// diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 78764091cf032..a9282b5b02fea 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -97,9 +97,9 @@ pub const MAX: char = '\u{10ffff}'; /// [`as`]: ../../book/casting-between-types.html#as /// /// For an unsafe version of this function which ignores these checks, see -/// [`from_u32_unchecked()`]. +/// [`from_u32_unchecked`]. /// -/// [`from_u32_unchecked()`]: fn.from_u32_unchecked.html +/// [`from_u32_unchecked`]: fn.from_u32_unchecked.html /// /// # Examples /// @@ -152,9 +152,9 @@ pub fn from_u32(i: u32) -> Option { /// /// This function is unsafe, as it may construct invalid `char` values. /// -/// For a safe version of this function, see the [`from_u32()`] function. +/// For a safe version of this function, see the [`from_u32`] function. /// -/// [`from_u32()`]: fn.from_u32.html +/// [`from_u32`]: fn.from_u32.html /// /// # Examples /// @@ -479,10 +479,10 @@ impl CharExt for char { /// Returns an iterator that yields the hexadecimal Unicode escape of a /// character, as `char`s. /// -/// This `struct` is created by the [`escape_unicode()`] method on [`char`]. See +/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See /// its documentation for more. /// -/// [`escape_unicode()`]: ../../std/primitive.char.html#method.escape_unicode +/// [`escape_unicode`]: ../../std/primitive.char.html#method.escape_unicode /// [`char`]: ../../std/primitive.char.html #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] @@ -600,10 +600,10 @@ impl fmt::Display for EscapeUnicode { /// An iterator that yields the literal escape code of a `char`. /// -/// This `struct` is created by the [`escape_default()`] method on [`char`]. See +/// This `struct` is created by the [`escape_default`] method on [`char`]. See /// its documentation for more. /// -/// [`escape_default()`]: ../../std/primitive.char.html#method.escape_default +/// [`escape_default`]: ../../std/primitive.char.html#method.escape_default /// [`char`]: ../../std/primitive.char.html #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] @@ -713,10 +713,10 @@ impl fmt::Display for EscapeDefault { /// An iterator that yields the literal escape code of a `char`. /// -/// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its +/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its /// documentation for more. /// -/// [`escape_debug()`]: ../../std/primitive.char.html#method.escape_debug +/// [`escape_debug`]: ../../std/primitive.char.html#method.escape_debug /// [`char`]: ../../std/primitive.char.html #[unstable(feature = "char_escape_debug", issue = "35068")] #[derive(Clone, Debug)] diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 8dbbc5928f45a..97b9525da6715 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -61,7 +61,7 @@ /// ## Derivable /// /// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d -/// implementation of [`clone()`] calls [`clone()`] on each field. +/// implementation of [`clone`] calls [`clone`] on each field. /// /// ## How can I implement `Clone`? /// @@ -75,7 +75,7 @@ /// `Clone` cannot be `derive`d, but can be implemented as: /// /// [`Copy`]: ../../std/marker/trait.Copy.html -/// [`clone()`]: trait.Clone.html#tymethod.clone +/// [`clone`]: trait.Clone.html#tymethod.clone /// /// ``` /// #[derive(Copy)] diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 4e170794c1d6e..70e285f202e52 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -154,14 +154,14 @@ pub trait AsMut { /// # Generic Impls /// /// - [`From`][From]` for U` implies `Into for T` -/// - [`into()`] is reflexive, which means that `Into for T` is implemented +/// - [`into`] is reflexive, which means that `Into for T` is implemented /// /// [`TryInto`]: trait.TryInto.html /// [`Option`]: ../../std/option/enum.Option.html /// [`Result`]: ../../std/result/enum.Result.html /// [`String`]: ../../std/string/struct.String.html /// [From]: trait.From.html -/// [`into()`]: trait.Into.html#tymethod.into +/// [`into`]: trait.Into.html#tymethod.into #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. @@ -187,14 +187,14 @@ pub trait Into: Sized { /// # Generic impls /// /// - `From for U` implies [`Into`]` for T` -/// - [`from()`] is reflexive, which means that `From for T` is implemented +/// - [`from`] is reflexive, which means that `From for T` is implemented /// /// [`TryFrom`]: trait.TryFrom.html /// [`Option`]: ../../std/option/enum.Option.html /// [`Result`]: ../../std/result/enum.Result.html /// [`String`]: ../../std/string/struct.String.html /// [`Into`]: trait.Into.html -/// [`from()`]: trait.From.html#tymethod.from +/// [`from`]: trait.From.html#tymethod.from #[stable(feature = "rust1", since = "1.0.0")] pub trait From: Sized { /// Performs the conversion. diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index f0d8d1a321917..aadeaac83d5c8 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -106,7 +106,7 @@ mod sip; /// /// This trait can be used with `#[derive]` if all fields implement `Hash`. /// When `derive`d, the resulting hash will be the combination of the values -/// from calling [`.hash()`] on each field. +/// from calling [`.hash`] on each field. /// /// ## How can I implement `Hash`? /// @@ -133,7 +133,7 @@ mod sip; /// [`Eq`]: ../../std/cmp/trait.Eq.html /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html -/// [`.hash()`]: #tymethod.hash +/// [`.hash`]: #tymethod.hash #[stable(feature = "rust1", since = "1.0.0")] pub trait Hash { /// Feeds this value into the state given, updating the hasher as necessary. diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 0f47378aebb7c..1301c311c14ca 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -140,11 +140,11 @@ pub trait Iterator { /// Consumes the iterator, counting the number of iterations and returning it. /// - /// This method will evaluate the iterator until its [`next()`] returns + /// This method will evaluate the iterator until its [`next`] returns /// [`None`]. Once [`None`] is encountered, `count()` returns the number of - /// times it called [`next()`]. + /// times it called [`next`]. /// - /// [`next()`]: #tymethod.next + /// [`next`]: #tymethod.next /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Overflow Behavior @@ -323,7 +323,7 @@ pub trait Iterator { /// /// In other words, it zips two iterators together, into a single one. /// - /// When either iterator returns [`None`], all further calls to [`next()`] + /// When either iterator returns [`None`], all further calls to [`next`] /// will return [`None`]. /// /// # Examples @@ -364,7 +364,7 @@ pub trait Iterator { /// /// `zip()` is often used to zip an infinite iterator to a finite one. /// This works because the finite iterator will eventually return [`None`], - /// ending the zipper. Zipping with `(0..)` can look a lot like [`enumerate()`]: + /// ending the zipper. Zipping with `(0..)` can look a lot like [`enumerate`]: /// /// ``` /// let enumerate: Vec<_> = "foo".chars().enumerate().collect(); @@ -381,8 +381,8 @@ pub trait Iterator { /// assert_eq!((2, 'o'), zipper[2]); /// ``` /// - /// [`enumerate()`]: trait.Iterator.html#method.enumerate - /// [`next()`]: ../../std/iter/trait.Iterator.html#tymethod.next + /// [`enumerate`]: trait.Iterator.html#method.enumerate + /// [`next`]: ../../std/iter/trait.Iterator.html#tymethod.next /// [`None`]: ../../std/option/enum.Option.html#variant.None #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -524,11 +524,11 @@ pub trait Iterator { /// closure returns [`None`], it will try again, and call the closure on the /// next element, seeing if it will return [`Some`]. /// - /// Why `filter_map()` and not just [`filter()`].[`map()`]? The key is in this + /// Why `filter_map()` and not just [`filter()`].[`map`]? The key is in this /// part: /// - /// [`filter()`]: #method.filter - /// [`map()`]: #method.map + /// [`filter`]: #method.filter + /// [`map`]: #method.map /// /// > If the closure returns [`Some(element)`][`Some`], then that element is returned. /// @@ -550,7 +550,7 @@ pub trait Iterator { /// assert_eq!(iter.next(), None); /// ``` /// - /// Here's the same example, but with [`filter()`] and [`map()`]: + /// Here's the same example, but with [`filter`] and [`map`]: /// /// ``` /// let a = ["1", "2", "lol"]; @@ -585,7 +585,7 @@ pub trait Iterator { /// iterator. /// /// `enumerate()` keeps its count as a [`usize`]. If you want to count by a - /// different sized integer, the [`zip()`] function provides similar + /// different sized integer, the [`zip`] function provides similar /// functionality. /// /// # Overflow Behavior @@ -601,7 +601,7 @@ pub trait Iterator { /// /// [`usize::MAX`]: ../../std/usize/constant.MAX.html /// [`usize`]: ../../std/primitive.usize.html - /// [`zip()`]: #method.zip + /// [`zip`]: #method.zip /// /// # Examples /// @@ -624,16 +624,16 @@ pub trait Iterator { /// Creates an iterator which can use `peek` to look at the next element of /// the iterator without consuming it. /// - /// Adds a [`peek()`] method to an iterator. See its documentation for + /// Adds a [`peek`] method to an iterator. See its documentation for /// more information. /// - /// Note that the underlying iterator is still advanced when [`peek()`] is + /// Note that the underlying iterator is still advanced when [`peek`] is /// called for the first time: In order to retrieve the next element, - /// [`next()`] is called on the underlying iterator, hence any side effects of - /// the [`next()`] method will occur. + /// [`next`] is called on the underlying iterator, hence any side effects of + /// the [`next`] method will occur. /// - /// [`peek()`]: struct.Peekable.html#method.peek - /// [`next()`]: ../../std/iter/trait.Iterator.html#tymethod.next + /// [`peek`]: struct.Peekable.html#method.peek + /// [`next`]: ../../std/iter/trait.Iterator.html#tymethod.next /// /// # Examples /// @@ -666,9 +666,9 @@ pub trait Iterator { Peekable{iter: self, peeked: None} } - /// Creates an iterator that [`skip()`]s elements based on a predicate. + /// Creates an iterator that [`skip`]s elements based on a predicate. /// - /// [`skip()`]: #method.skip + /// [`skip`]: #method.skip /// /// `skip_while()` takes a closure as an argument. It will call this /// closure on each element of the iterator, and ignore elements @@ -863,10 +863,10 @@ pub trait Iterator { Take{iter: self, n: n} } - /// An iterator adaptor similar to [`fold()`] that holds internal state and + /// An iterator adaptor similar to [`fold`] that holds internal state and /// produces a new iterator. /// - /// [`fold()`]: #method.fold + /// [`fold`]: #method.fold /// /// `scan()` takes two arguments: an initial value which seeds the internal /// state, and a closure with two arguments, the first being a mutable @@ -910,16 +910,16 @@ pub trait Iterator { /// Creates an iterator that works like map, but flattens nested structure. /// - /// The [`map()`] adapter is very useful, but only when the closure + /// The [`map`] adapter is very useful, but only when the closure /// argument produces values. If it produces an iterator instead, there's /// an extra layer of indirection. `flat_map()` will remove this extra layer /// on its own. /// - /// Another way of thinking about `flat_map()`: [`map()`]'s closure returns + /// Another way of thinking about `flat_map()`: [`map`]'s closure returns /// one item for each element, and `flat_map()`'s closure returns an /// iterator for each element. /// - /// [`map()`]: #method.map + /// [`map`]: #method.map /// /// # Examples /// @@ -1106,7 +1106,7 @@ pub trait Iterator { /// library, used in a variety of contexts. /// /// The most basic pattern in which `collect()` is used is to turn one - /// collection into another. You take a collection, call [`iter()`] on it, + /// collection into another. You take a collection, call [`iter`] on it, /// do a bunch of transformations, and then `collect()` at the end. /// /// One of the keys to `collect()`'s power is that many things you might @@ -1211,7 +1211,7 @@ pub trait Iterator { /// assert_eq!(Ok(vec![1, 3]), result); /// ``` /// - /// [`iter()`]: ../../std/iter/trait.Iterator.html#tymethod.next + /// [`iter`]: ../../std/iter/trait.Iterator.html#tymethod.next /// [`String`]: ../../std/string/struct.String.html /// [`char`]: ../../std/primitive.char.html /// [`Result`]: ../../std/result/enum.Result.html @@ -1816,9 +1816,9 @@ pub trait Iterator { /// collections: one from the left elements of the pairs, and one /// from the right elements. /// - /// This function is, in some sense, the opposite of [`zip()`]. + /// This function is, in some sense, the opposite of [`zip`]. /// - /// [`zip()`]: #method.zip + /// [`zip`]: #method.zip /// /// # Examples /// @@ -1849,12 +1849,12 @@ pub trait Iterator { (ts, us) } - /// Creates an iterator which [`clone()`]s all of its elements. + /// Creates an iterator which [`clone`]s all of its elements. /// /// This is useful when you have an iterator over `&T`, but you need an /// iterator over `T`. /// - /// [`clone()`]: ../../std/clone/trait.Clone.html#tymethod.clone + /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone /// /// # Examples /// diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d9b8c5ea589fd..dcb3da4f839a5 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -48,15 +48,15 @@ //! } //! ``` //! -//! An iterator has a method, [`next()`], which when called, returns an -//! [`Option`]``. [`next()`] will return `Some(Item)` as long as there +//! An iterator has a method, [`next`], which when called, returns an +//! [`Option`]``. [`next`] will return `Some(Item)` as long as there //! are elements, and once they've all been exhausted, will return `None` to //! indicate that iteration is finished. Individual iterators may choose to -//! resume iteration, and so calling [`next()`] again may or may not eventually +//! resume iteration, and so calling [`next`] again may or may not eventually //! start returning `Some(Item)` again at some point. //! //! [`Iterator`]'s full definition includes a number of other methods as well, -//! but they are default methods, built on top of [`next()`], and so you get +//! but they are default methods, built on top of [`next`], and so you get //! them for free. //! //! Iterators are also composable, and it's common to chain them together to do @@ -64,7 +64,7 @@ //! below for more details. //! //! [`Iterator`]: trait.Iterator.html -//! [`next()`]: trait.Iterator.html#tymethod.next +//! [`next`]: trait.Iterator.html#tymethod.next //! [`Option`]: ../../std/option/enum.Option.html //! //! # The three forms of iteration @@ -168,13 +168,13 @@ //! produce an iterator. What gives? //! //! There's a trait in the standard library for converting something into an -//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter()`], +//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter`], //! which converts the thing implementing [`IntoIterator`] into an iterator. //! Let's take a look at that `for` loop again, and what the compiler converts //! it into: //! //! [`IntoIterator`]: trait.IntoIterator.html -//! [`into_iter()`]: trait.IntoIterator.html#tymethod.into_iter +//! [`into_iter`]: trait.IntoIterator.html#tymethod.into_iter //! //! ``` //! let values = vec![1, 2, 3, 4, 5]; @@ -202,7 +202,7 @@ //! ``` //! //! First, we call `into_iter()` on the value. Then, we match on the iterator -//! that returns, calling [`next()`] over and over until we see a `None`. At +//! that returns, calling [`next`] over and over until we see a `None`. At //! that point, we `break` out of the loop, and we're done iterating. //! //! There's one more subtle bit here: the standard library contains an @@ -225,19 +225,19 @@ //! often called 'iterator adapters', as they're a form of the 'adapter //! pattern'. //! -//! Common iterator adapters include [`map()`], [`take()`], and [`filter()`]. +//! Common iterator adapters include [`map`], [`take`], and [`filter`]. //! For more, see their documentation. //! -//! [`map()`]: trait.Iterator.html#method.map -//! [`take()`]: trait.Iterator.html#method.take -//! [`filter()`]: trait.Iterator.html#method.filter +//! [`map`]: trait.Iterator.html#method.map +//! [`take`]: trait.Iterator.html#method.take +//! [`filter`]: trait.Iterator.html#method.filter //! //! # Laziness //! //! Iterators (and iterator [adapters](#adapters)) are *lazy*. This means that //! just creating an iterator doesn't _do_ a whole lot. Nothing really happens -//! until you call [`next()`]. This is sometimes a source of confusion when -//! creating an iterator solely for its side effects. For example, the [`map()`] +//! until you call [`next`]. This is sometimes a source of confusion when +//! creating an iterator solely for its side effects. For example, the [`map`] //! method calls a closure on each element it iterates over: //! //! ``` @@ -254,7 +254,7 @@ //! do nothing unless consumed //! ``` //! -//! The idiomatic way to write a [`map()`] for its side effects is to use a +//! The idiomatic way to write a [`map`] for its side effects is to use a //! `for` loop instead: //! //! ``` @@ -265,12 +265,12 @@ //! } //! ``` //! -//! [`map()`]: trait.Iterator.html#method.map +//! [`map`]: trait.Iterator.html#method.map //! //! The two most common ways to evaluate an iterator are to use a `for` loop -//! like this, or using the [`collect()`] method to produce a new collection. +//! like this, or using the [`collect`] method to produce a new collection. //! -//! [`collect()`]: trait.Iterator.html#method.collect +//! [`collect`]: trait.Iterator.html#method.collect //! //! # Infinity //! @@ -281,7 +281,7 @@ //! let numbers = 0..; //! ``` //! -//! It is common to use the [`take()`] iterator adapter to turn an infinite +//! It is common to use the [`take`] iterator adapter to turn an infinite //! iterator into a finite one: //! //! ``` @@ -295,7 +295,7 @@ //! //! This will print the numbers `0` through `4`, each on their own line. //! -//! [`take()`]: trait.Iterator.html#method.take +//! [`take`]: trait.Iterator.html#method.take #![stable(feature = "rust1", since = "1.0.0")] @@ -338,10 +338,10 @@ mod traits; /// An double-ended iterator with the direction inverted. /// -/// This `struct` is created by the [`rev()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`rev()`]: trait.Iterator.html#method.rev +/// [`rev`]: trait.Iterator.html#method.rev /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -389,10 +389,10 @@ unsafe impl TrustedLen for Rev /// An iterator that clones the elements of an underlying iterator. /// -/// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`cloned()`]: trait.Iterator.html#method.cloned +/// [`cloned`]: trait.Iterator.html#method.cloned /// [`Iterator`]: trait.Iterator.html #[stable(feature = "iter_cloned", since = "1.1.0")] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -469,10 +469,10 @@ unsafe impl<'a, I, T: 'a> TrustedLen for Cloned /// An iterator that repeats endlessly. /// -/// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`cycle()`]: trait.Iterator.html#method.cycle +/// [`cycle`]: trait.Iterator.html#method.cycle /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -510,10 +510,10 @@ impl FusedIterator for Cycle where I: Clone + Iterator {} /// An iterator that strings two iterators together. /// -/// This `struct` is created by the [`chain()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`chain()`]: trait.Iterator.html#method.chain +/// [`chain`]: trait.Iterator.html#method.chain /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -703,10 +703,10 @@ unsafe impl TrustedLen for Chain /// An iterator that iterates two other iterators simultaneously. /// -/// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`zip`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`zip()`]: trait.Iterator.html#method.zip +/// [`zip`]: trait.Iterator.html#method.zip /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -925,16 +925,16 @@ unsafe impl TrustedLen for Zip /// An iterator that maps the values of `iter` with `f`. /// -/// This `struct` is created by the [`map()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`map`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`map()`]: trait.Iterator.html#method.map +/// [`map`]: trait.Iterator.html#method.map /// [`Iterator`]: trait.Iterator.html /// /// # Notes about side effects /// -/// The [`map()`] iterator implements [`DoubleEndedIterator`], meaning that -/// you can also [`map()`] backwards: +/// The [`map`] iterator implements [`DoubleEndedIterator`], meaning that +/// you can also [`map`] backwards: /// /// ```rust /// let v: Vec = vec![1, 2, 3].into_iter().map(|x| x + 1).rev().collect(); @@ -1058,10 +1058,10 @@ unsafe impl TrustedRandomAccess for Map /// An iterator that filters the elements of `iter` with `predicate`. /// -/// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`filter()`]: trait.Iterator.html#method.filter +/// [`filter`]: trait.Iterator.html#method.filter /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1142,10 +1142,10 @@ impl FusedIterator for Filter /// An iterator that uses `f` to both filter and map elements from `iter`. /// -/// This `struct` is created by the [`filter_map()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`filter_map()`]: trait.Iterator.html#method.filter_map +/// [`filter_map`]: trait.Iterator.html#method.filter_map /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1208,10 +1208,10 @@ impl FusedIterator for FilterMap /// An iterator that yields the current count and the element during iteration. /// -/// This `struct` is created by the [`enumerate()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`enumerate()`]: trait.Iterator.html#method.enumerate +/// [`enumerate`]: trait.Iterator.html#method.enumerate /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1317,10 +1317,10 @@ unsafe impl TrustedLen for Enumerate /// An iterator with a `peek()` that returns an optional reference to the next /// element. /// -/// This `struct` is created by the [`peekable()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`peekable()`]: trait.Iterator.html#method.peekable +/// [`peekable`]: trait.Iterator.html#method.peekable /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1401,10 +1401,10 @@ impl FusedIterator for Peekable {} impl Peekable { /// Returns a reference to the next() value without advancing the iterator. /// - /// Like [`next()`], if there is a value, it is wrapped in a `Some(T)`. + /// Like [`next`], if there is a value, it is wrapped in a `Some(T)`. /// But if the iteration is over, `None` is returned. /// - /// [`next()`]: trait.Iterator.html#tymethod.next + /// [`next`]: trait.Iterator.html#tymethod.next /// /// Because `peek()` returns a reference, and many iterators iterate over /// references, there can be a possibly confusing situation where the @@ -1452,10 +1452,10 @@ impl Peekable { /// An iterator that rejects elements while `predicate` is true. /// -/// This `struct` is created by the [`skip_while()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`skip_while()`]: trait.Iterator.html#method.skip_while +/// [`skip_while`]: trait.Iterator.html#method.skip_while /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1506,10 +1506,10 @@ impl FusedIterator for SkipWhile /// An iterator that only accepts elements while `predicate` is true. /// -/// This `struct` is created by the [`take_while()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`take_while()`]: trait.Iterator.html#method.take_while +/// [`take_while`]: trait.Iterator.html#method.take_while /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1565,10 +1565,10 @@ impl FusedIterator for TakeWhile /// An iterator that skips over `n` elements of `iter`. /// -/// This `struct` is created by the [`skip()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`skip()`]: trait.Iterator.html#method.skip +/// [`skip`]: trait.Iterator.html#method.skip /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1659,10 +1659,10 @@ impl FusedIterator for Skip where I: FusedIterator {} /// An iterator that only iterates over the first `n` iterations of `iter`. /// -/// This `struct` is created by the [`take()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`take`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`take()`]: trait.Iterator.html#method.take +/// [`take`]: trait.Iterator.html#method.take /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -1723,10 +1723,10 @@ impl FusedIterator for Take where I: FusedIterator {} /// An iterator to maintain state while iterating another iterator. /// -/// This `struct` is created by the [`scan()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`scan()`]: trait.Iterator.html#method.scan +/// [`scan`]: trait.Iterator.html#method.scan /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1773,10 +1773,10 @@ impl FusedIterator for Scan /// An iterator that maps each element to an iterator, and yields the elements /// of the produced iterators. /// -/// This `struct` is created by the [`flat_map()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`flat_map()`]: trait.Iterator.html#method.flat_map +/// [`flat_map`]: trait.Iterator.html#method.flat_map /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1863,10 +1863,10 @@ impl FusedIterator for FlatMap /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// -/// This `struct` is created by the [`fuse()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`fuse()`]: trait.Iterator.html#method.fuse +/// [`fuse`]: trait.Iterator.html#method.fuse /// [`Iterator`]: trait.Iterator.html #[derive(Clone, Debug)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -2012,10 +2012,10 @@ impl ExactSizeIterator for Fuse where I: ExactSizeIterator { /// An iterator that calls a function with a reference to each element before /// yielding it. /// -/// This `struct` is created by the [`inspect()`] method on [`Iterator`]. See its +/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its /// documentation for more. /// -/// [`inspect()`]: trait.Iterator.html#method.inspect +/// [`inspect`]: trait.Iterator.html#method.inspect /// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index b988ce73bdefc..b405f35d5e4db 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -16,9 +16,9 @@ use super::{FusedIterator, TrustedLen}; /// An iterator that repeats an element endlessly. /// -/// This `struct` is created by the [`repeat()`] function. See its documentation for more. +/// This `struct` is created by the [`repeat`] function. See its documentation for more. /// -/// [`repeat()`]: fn.repeat.html +/// [`repeat`]: fn.repeat.html #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Repeat { @@ -50,9 +50,9 @@ impl FusedIterator for Repeat {} /// over and over and 🔁. /// /// Infinite iterators like `repeat()` are often used with adapters like -/// [`take()`], in order to make them finite. +/// [`take`], in order to make them finite. /// -/// [`take()`]: trait.Iterator.html#method.take +/// [`take`]: trait.Iterator.html#method.take /// /// # Examples /// @@ -74,7 +74,7 @@ impl FusedIterator for Repeat {} /// assert_eq!(Some(4), fours.next()); /// ``` /// -/// Going finite with [`take()`]: +/// Going finite with [`take`]: /// /// ``` /// use std::iter; @@ -98,9 +98,9 @@ pub fn repeat(elt: T) -> Repeat { /// An iterator that yields nothing. /// -/// This `struct` is created by the [`empty()`] function. See its documentation for more. +/// This `struct` is created by the [`empty`] function. See its documentation for more. /// -/// [`empty()`]: fn.empty.html +/// [`empty`]: fn.empty.html #[stable(feature = "iter_empty", since = "1.2.0")] pub struct Empty(marker::PhantomData); @@ -183,9 +183,9 @@ pub fn empty() -> Empty { /// An iterator that yields an element exactly once. /// -/// This `struct` is created by the [`once()`] function. See its documentation for more. +/// This `struct` is created by the [`once`] function. See its documentation for more. /// -/// [`once()`]: fn.once.html +/// [`once`]: fn.once.html #[derive(Clone, Debug)] #[stable(feature = "iter_once", since = "1.2.0")] pub struct Once { @@ -227,12 +227,12 @@ impl FusedIterator for Once {} /// Creates an iterator that yields an element exactly once. /// -/// This is commonly used to adapt a single value into a [`chain()`] of other +/// This is commonly used to adapt a single value into a [`chain`] of other /// kinds of iteration. Maybe you have an iterator that covers almost /// everything, but you need an extra special case. Maybe you have a function /// which works on iterators, but you only need to process one value. /// -/// [`chain()`]: trait.Iterator.html#method.chain +/// [`chain`]: trait.Iterator.html#method.chain /// /// # Examples /// diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index cb180110d3cc0..3415b0eea9bd0 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -16,13 +16,13 @@ use num::Wrapping; /// created from an iterator. This is common for types which describe a /// collection of some kind. /// -/// `FromIterator`'s [`from_iter()`] is rarely called explicitly, and is instead -/// used through [`Iterator`]'s [`collect()`] method. See [`collect()`]'s +/// `FromIterator`'s [`from_iter`] is rarely called explicitly, and is instead +/// used through [`Iterator`]'s [`collect`] method. See [`collect`]'s /// documentation for more examples. /// -/// [`from_iter()`]: #tymethod.from_iter +/// [`from_iter`]: #tymethod.from_iter /// [`Iterator`]: trait.Iterator.html -/// [`collect()`]: trait.Iterator.html#method.collect +/// [`collect`]: trait.Iterator.html#method.collect /// /// See also: [`IntoIterator`]. /// @@ -42,7 +42,7 @@ use num::Wrapping; /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// ``` /// -/// Using [`collect()`] to implicitly use `FromIterator`: +/// Using [`collect`] to implicitly use `FromIterator`: /// /// ``` /// let five_fives = std::iter::repeat(5).take(5); @@ -487,17 +487,17 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { /// backwards, a good start is to know where the end is. /// /// When implementing an `ExactSizeIterator`, You must also implement -/// [`Iterator`]. When doing so, the implementation of [`size_hint()`] *must* +/// [`Iterator`]. When doing so, the implementation of [`size_hint`] *must* /// return the exact size of the iterator. /// /// [`Iterator`]: trait.Iterator.html -/// [`size_hint()`]: trait.Iterator.html#method.size_hint +/// [`size_hint`]: trait.Iterator.html#method.size_hint /// -/// The [`len()`] method has a default implementation, so you usually shouldn't +/// The [`len`] method has a default implementation, so you usually shouldn't /// implement it. However, you may be able to provide a more performant /// implementation than the default, so overriding it in this case makes sense. /// -/// [`len()`]: #method.len +/// [`len`]: #method.len /// /// # Examples /// @@ -557,11 +557,11 @@ pub trait ExactSizeIterator: Iterator { /// implementation, you can do so. See the [trait-level] docs for an /// example. /// - /// This function has the same safety guarantees as the [`size_hint()`] + /// This function has the same safety guarantees as the [`size_hint`] /// function. /// /// [trait-level]: trait.ExactSizeIterator.html - /// [`size_hint()`]: trait.Iterator.html#method.size_hint + /// [`size_hint`]: trait.Iterator.html#method.size_hint /// /// # Examples /// @@ -624,14 +624,14 @@ impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I { /// Trait to represent types that can be created by summing up an iterator. /// -/// This trait is used to implement the [`sum()`] method on iterators. Types which -/// implement the trait can be generated by the [`sum()`] method. Like +/// This trait is used to implement the [`sum`] method on iterators. Types which +/// implement the trait can be generated by the [`sum`] method. Like /// [`FromIterator`] this trait should rarely be called directly and instead -/// interacted with through [`Iterator::sum()`]. +/// interacted with through [`Iterator::sum`]. /// -/// [`sum()`]: ../../std/iter/trait.Sum.html#tymethod.sum +/// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html -/// [`Iterator::sum()`]: ../../std/iter/trait.Iterator.html#method.sum +/// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum #[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by @@ -643,14 +643,14 @@ pub trait Sum: Sized { /// Trait to represent types that can be created by multiplying elements of an /// iterator. /// -/// This trait is used to implement the [`product()`] method on iterators. Types -/// which implement the trait can be generated by the [`product()`] method. Like +/// This trait is used to implement the [`product`] method on iterators. Types +/// which implement the trait can be generated by the [`product`] method. Like /// [`FromIterator`] this trait should rarely be called directly and instead -/// interacted with through [`Iterator::product()`]. +/// interacted with through [`Iterator::product`]. /// -/// [`product()`]: ../../std/iter/trait.Product.html#tymethod.product +/// [`product`]: ../../std/iter/trait.Product.html#tymethod.product /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html -/// [`Iterator::product()`]: ../../std/iter/trait.Iterator.html#method.product +/// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product #[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by @@ -823,12 +823,12 @@ impl Product> for Result /// that behave this way because it allows for some significant optimizations. /// /// Note: In general, you should not use `FusedIterator` in generic bounds if -/// you need a fused iterator. Instead, you should just call [`Iterator::fuse()`] +/// you need a fused iterator. Instead, you should just call [`Iterator::fuse`] /// on the iterator. If the iterator is already fused, the additional [`Fuse`] /// wrapper will be a no-op with no performance penalty. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None -/// [`Iterator::fuse()`]: ../../std/iter/trait.Iterator.html#method.fuse +/// [`Iterator::fuse`]: ../../std/iter/trait.Iterator.html#method.fuse /// [`Fuse`]: ../../std/iter/struct.Fuse.html #[unstable(feature = "fused", issue = "35602")] pub trait FusedIterator: Iterator {} @@ -848,11 +848,11 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} /// # Safety /// /// This trait must only be implemented when the contract is upheld. -/// Consumers of this trait must inspect [`.size_hint()`]’s upper bound. +/// Consumers of this trait must inspect [`.size_hint`]’s upper bound. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None /// [`usize::MAX`]: ../../std/usize/constant.MAX.html -/// [`.size_hint()`]: ../../std/iter/trait.Iterator.html#method.size_hint +/// [`.size_hint`]: ../../std/iter/trait.Iterator.html#method.size_hint #[unstable(feature = "trusted_len", issue = "37572")] pub unsafe trait TrustedLen : Iterator {} diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index b22f7fa17077b..021079f85f6be 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -90,10 +90,10 @@ macro_rules! assert { /// On panic, this macro will print the values of the expressions with their /// debug representations. /// -/// Like [`assert!()`], this macro has a second version, where a custom +/// Like [`assert!`], this macro has a second version, where a custom /// panic message can be provided. /// -/// [`assert!()`]: macro.assert.html +/// [`assert!`]: macro.assert.html /// /// # Examples /// diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 1e9eaaf5f3223..393c01b0105c5 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -245,7 +245,7 @@ pub trait Unsize { /// [`String`]'s buffer, leading to a double free. /// /// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's -/// managing some resource besides its own [`size_of::()`] bytes. +/// managing some resource besides its own [`size_of::`] bytes. /// /// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get /// the error [E0204]. @@ -262,7 +262,7 @@ pub trait Unsize { /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`String`]: ../../std/string/struct.String.html /// [`Drop`]: ../../std/ops/trait.Drop.html -/// [`size_of::()`]: ../../std/mem/fn.size_of.html +/// [`size_of::`]: ../../std/mem/fn.size_of.html /// [`Clone`]: ../clone/trait.Clone.html /// [`String`]: ../../std/string/struct.String.html /// [`i32`]: ../../std/primitive.i32.html diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index f4ce4697d7cf4..ba65e4494a8bb 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -617,7 +617,7 @@ pub fn drop(_x: T) { } /// the contained value. /// /// This function will unsafely assume the pointer `src` is valid for -/// [`size_of::()`][size_of] bytes by transmuting `&T` to `&U` and then reading +/// [`size_of::`][size_of] bytes by transmuting `&T` to `&U` and then reading /// the `&U`. It will also unsafely create a copy of the contained value instead of /// moving out of `src`. /// diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 97ea6bb347b54..81c80ba51152d 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2390,11 +2390,11 @@ impl usize { /// A classification of floating point numbers. /// -/// This `enum` is used as the return type for [`f32::classify()`] and [`f64::classify()`]. See +/// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See /// their documentation for more. /// -/// [`f32::classify()`]: ../../std/primitive.f32.html#method.classify -/// [`f64::classify()`]: ../../std/primitive.f64.html#method.classify +/// [`f32::classify`]: ../../std/primitive.f32.html#method.classify +/// [`f64::classify`]: ../../std/primitive.f64.html#method.classify /// /// # Examples /// @@ -2756,9 +2756,9 @@ fn from_str_radix(src: &str, radix: u32) -> Result> Range { /// A range which is only bounded below: { x | start <= x }. /// Use `start..` for its shorthand. /// -/// See the [`contains()`](#method.contains) method for its characterization. +/// See the [`contains`](#method.contains) method for its characterization. /// /// Note: Currently, no overflow checking is done for the iterator /// implementation; if you use an integer range and the integer overflows, it @@ -2141,7 +2141,7 @@ impl> RangeFrom { /// A range which is only bounded above: { x | x < end }. /// Use `..end` (two dots) for its shorthand. /// -/// See the [`contains()`](#method.contains) method for its characterization. +/// See the [`contains`](#method.contains) method for its characterization. /// /// It cannot serve as an iterator because it doesn't have a starting point. /// @@ -2207,7 +2207,7 @@ impl> RangeTo { /// An inclusive range which is bounded at both ends: { x | start <= x <= end }. /// Use `start...end` (three dots) for its shorthand. /// -/// See the [`contains()`](#method.contains) method for its characterization. +/// See the [`contains`](#method.contains) method for its characterization. /// /// # Examples /// @@ -2293,7 +2293,7 @@ impl> RangeInclusive { /// An inclusive range which is only bounded above: { x | x <= end }. /// Use `...end` (three dots) for its shorthand. /// -/// See the [`contains()`](#method.contains) method for its characterization. +/// See the [`contains`](#method.contains) method for its characterization. /// /// It cannot serve as an iterator because it doesn't have a starting point. /// diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 52e3301631052..395a84460a91d 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -28,12 +28,12 @@ pub mod pattern; /// A trait to abstract the idea of creating a new instance of a type from a /// string. /// -/// `FromStr`'s [`from_str()`] method is often used implicitly, through -/// [`str`]'s [`parse()`] method. See [`parse()`]'s documentation for examples. +/// `FromStr`'s [`from_str`] method is often used implicitly, through +/// [`str`]'s [`parse`] method. See [`parse`]'s documentation for examples. /// -/// [`from_str()`]: #tymethod.from_str +/// [`from_str`]: #tymethod.from_str /// [`str`]: ../../std/primitive.str.html -/// [`parse()`]: ../../std/primitive.str.html#method.parse +/// [`parse`]: ../../std/primitive.str.html#method.parse #[stable(feature = "rust1", since = "1.0.0")] pub trait FromStr: Sized { /// The associated error which can be returned from parsing. @@ -164,13 +164,13 @@ impl Utf8Error { /// /// If you are sure that the byte slice is valid UTF-8, and you don't want to /// incur the overhead of the validity check, there is an unsafe version of -/// this function, [`from_utf8_unchecked()`][fromutf8u], which has the same +/// this function, [`from_utf8_unchecked`][fromutf8u], which has the same /// behavior but skips the check. /// /// [fromutf8u]: fn.from_utf8_unchecked.html /// /// If you need a `String` instead of a `&str`, consider -/// [`String::from_utf8()`][string]. +/// [`String::from_utf8`][string]. /// /// [string]: ../../std/string/struct.String.html#method.from_utf8 /// @@ -265,7 +265,7 @@ unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str { /// Converts a slice of bytes to a string slice without checking /// that the string contains valid UTF-8. /// -/// See the safe version, [`from_utf8()`][fromutf8], for more information. +/// See the safe version, [`from_utf8`][fromutf8], for more information. /// /// [fromutf8]: fn.from_utf8.html /// @@ -310,9 +310,9 @@ Section: Iterators /// Iterator for the char (representing *Unicode Scalar Values*) of a string /// -/// Created with the method [`chars()`]. +/// Created with the method [`chars`]. /// -/// [`chars()`]: ../../std/primitive.str.html#method.chars +/// [`chars`]: ../../std/primitive.str.html#method.chars #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Chars<'a> { @@ -567,9 +567,9 @@ impl<'a> CharIndices<'a> { /// External iterator for a string's bytes. /// Use with the `std::iter` module. /// -/// Created with the method [`bytes()`]. +/// Created with the method [`bytes`]. /// -/// [`bytes()`]: ../../std/primitive.str.html#method.bytes +/// [`bytes`]: ../../std/primitive.str.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone, Debug)] pub struct Bytes<'a>(Cloned>); @@ -902,14 +902,14 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { generate_pattern_iterators! { forward: - /// Created with the method [`split()`]. + /// Created with the method [`split`]. /// - /// [`split()`]: ../../std/primitive.str.html#method.split + /// [`split`]: ../../std/primitive.str.html#method.split struct Split; reverse: - /// Created with the method [`rsplit()`]. + /// Created with the method [`rsplit`]. /// - /// [`rsplit()`]: ../../std/primitive.str.html#method.rsplit + /// [`rsplit`]: ../../std/primitive.str.html#method.rsplit struct RSplit; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -920,14 +920,14 @@ generate_pattern_iterators! { generate_pattern_iterators! { forward: - /// Created with the method [`split_terminator()`]. + /// Created with the method [`split_terminator`]. /// - /// [`split_terminator()`]: ../../std/primitive.str.html#method.split_terminator + /// [`split_terminator`]: ../../std/primitive.str.html#method.split_terminator struct SplitTerminator; reverse: - /// Created with the method [`rsplit_terminator()`]. + /// Created with the method [`rsplit_terminator`]. /// - /// [`rsplit_terminator()`]: ../../std/primitive.str.html#method.rsplit_terminator + /// [`rsplit_terminator`]: ../../std/primitive.str.html#method.rsplit_terminator struct RSplitTerminator; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -980,14 +980,14 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> { generate_pattern_iterators! { forward: - /// Created with the method [`splitn()`]. + /// Created with the method [`splitn`]. /// - /// [`splitn()`]: ../../std/primitive.str.html#method.splitn + /// [`splitn`]: ../../std/primitive.str.html#method.splitn struct SplitN; reverse: - /// Created with the method [`rsplitn()`]. + /// Created with the method [`rsplitn`]. /// - /// [`rsplitn()`]: ../../std/primitive.str.html#method.rsplitn + /// [`rsplitn`]: ../../std/primitive.str.html#method.rsplitn struct RSplitN; stability: #[stable(feature = "rust1", since = "1.0.0")] @@ -1031,14 +1031,14 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { generate_pattern_iterators! { forward: - /// Created with the method [`match_indices()`]. + /// Created with the method [`match_indices`]. /// - /// [`match_indices()`]: ../../std/primitive.str.html#method.match_indices + /// [`match_indices`]: ../../std/primitive.str.html#method.match_indices struct MatchIndices; reverse: - /// Created with the method [`rmatch_indices()`]. + /// Created with the method [`rmatch_indices`]. /// - /// [`rmatch_indices()`]: ../../std/primitive.str.html#method.rmatch_indices + /// [`rmatch_indices`]: ../../std/primitive.str.html#method.rmatch_indices struct RMatchIndices; stability: #[stable(feature = "str_match_indices", since = "1.5.0")] @@ -1084,14 +1084,14 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> { generate_pattern_iterators! { forward: - /// Created with the method [`matches()`]. + /// Created with the method [`matches`]. /// - /// [`matches()`]: ../../std/primitive.str.html#method.matches + /// [`matches`]: ../../std/primitive.str.html#method.matches struct Matches; reverse: - /// Created with the method [`rmatches()`]. + /// Created with the method [`rmatches`]. /// - /// [`rmatches()`]: ../../std/primitive.str.html#method.rmatches + /// [`rmatches`]: ../../std/primitive.str.html#method.rmatches struct RMatches; stability: #[stable(feature = "str_matches", since = "1.2.0")] @@ -1100,9 +1100,9 @@ generate_pattern_iterators! { delegate double ended; } -/// Created with the method [`lines()`]. +/// Created with the method [`lines`]. /// -/// [`lines()`]: ../../std/primitive.str.html#method.lines +/// [`lines`]: ../../std/primitive.str.html#method.lines #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone, Debug)] pub struct Lines<'a>(Map, LinesAnyMap>); @@ -1133,9 +1133,9 @@ impl<'a> DoubleEndedIterator for Lines<'a> { #[unstable(feature = "fused", issue = "35602")] impl<'a> FusedIterator for Lines<'a> {} -/// Created with the method [`lines_any()`]. +/// Created with the method [`lines_any`]. /// -/// [`lines_any()`]: ../../std/primitive.str.html#method.lines_any +/// [`lines_any`]: ../../std/primitive.str.html#method.lines_any #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.4.0", reason = "use lines()/Lines instead now")] #[derive(Clone, Debug)] diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index e5562d05f10ae..b074e8b86b9a3 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -142,14 +142,14 @@ pub struct DirEntry(fs_imp::DirEntry); /// [`File::open`]: struct.File.html#method.open /// [`File::create`]: struct.File.html#method.create /// -/// Generally speaking, when using `OpenOptions`, you'll first call [`new()`], -/// then chain calls to methods to set each option, then call [`open()`], +/// Generally speaking, when using `OpenOptions`, you'll first call [`new`], +/// then chain calls to methods to set each option, then call [`open`], /// passing the path of the file you're trying to open. This will give you a /// [`io::Result`][result] with a [`File`][file] inside that you can further /// operate on. /// -/// [`new()`]: struct.OpenOptions.html#method.new -/// [`open()`]: struct.OpenOptions.html#method.open +/// [`new`]: struct.OpenOptions.html#method.new +/// [`open`]: struct.OpenOptions.html#method.open /// [result]: ../io/type.Result.html /// [file]: struct.File.html /// diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 6d4da2e6a88cf..fb67eaf3c63a9 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -140,13 +140,13 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] TimedOut, /// An error returned when an operation could not be completed because a - /// call to [`write()`] returned [`Ok(0)`]. + /// call to [`write`] returned [`Ok(0)`]. /// /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. /// - /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// [`Ok(0)`]: ../../std/io/type.Result.html #[stable(feature = "rust1", since = "1.0.0")] WriteZero, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 58788cdcd4c7c..850885a8c0f3a 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -21,7 +21,7 @@ //! of other types, and you can implement them for your types too. As such, //! you'll see a few different types of I/O throughout the documentation in //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec`]s. For -//! example, [`Read`] adds a [`read()`] method, which we can use on `File`s: +//! example, [`Read`] adds a [`read`] method, which we can use on `File`s: //! //! ``` //! use std::io; @@ -106,7 +106,7 @@ //! ``` //! //! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call -//! to [`write()`]: +//! to [`write`]: //! //! ``` //! use std::io; @@ -157,7 +157,7 @@ //! # } //! ``` //! -//! Of course, using [`io::stdout()`] directly is less common than something like +//! Of course, using [`io::stdout`] directly is less common than something like //! [`println!`]. //! //! ## Iterator types @@ -245,13 +245,13 @@ //! [`Vec`]: ../vec/struct.Vec.html //! [`BufReader`]: struct.BufReader.html //! [`BufWriter`]: struct.BufWriter.html -//! [`write()`]: trait.Write.html#tymethod.write -//! [`io::stdout()`]: fn.stdout.html +//! [`write`]: trait.Write.html#tymethod.write +//! [`io::stdout`]: fn.stdout.html //! [`println!`]: ../macro.println.html //! [`Lines`]: struct.Lines.html //! [`io::Result`]: type.Result.html //! [`?` operator]: ../../book/syntax-index.html -//! [`read()`]: trait.Read.html#tymethod.read +//! [`read`]: trait.Read.html#tymethod.read #![stable(feature = "rust1", since = "1.0.0")] @@ -530,7 +530,7 @@ pub trait Read { /// If the data in this stream is *not* valid UTF-8 then an error is /// returned and `buf` is unchanged. /// - /// See [`read_to_end()`][readtoend] for other error semantics. + /// See [`read_to_end`][readtoend] for other error semantics. /// /// [readtoend]: #method.read_to_end /// @@ -815,12 +815,12 @@ pub trait Read { /// /// Implementors of the `Write` trait are sometimes called 'writers'. /// -/// Writers are defined by two required methods, [`write()`] and [`flush()`]: +/// Writers are defined by two required methods, [`write`] and [`flush`]: /// -/// * The [`write()`] method will attempt to write some data into the object, +/// * The [`write`] method will attempt to write some data into the object, /// returning how many bytes were successfully written. /// -/// * The [`flush()`] method is useful for adaptors and explicit buffers +/// * The [`flush`] method is useful for adaptors and explicit buffers /// themselves for ensuring that all buffered data has been pushed out to the /// 'true sink'. /// @@ -828,8 +828,8 @@ pub trait Read { /// throughout [`std::io`] take and provide types which implement the `Write` /// trait. /// -/// [`write()`]: #tymethod.write -/// [`flush()`]: #tymethod.flush +/// [`write`]: #tymethod.write +/// [`flush`]: #tymethod.flush /// [`std::io`]: index.html /// /// # Examples @@ -1159,7 +1159,7 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// For example, reading line-by-line is inefficient without using a buffer, so /// if you want to read by line, you'll need `BufRead`, which includes a -/// [`read_line()`] method as well as a [`lines()`] iterator. +/// [`read_line`] method as well as a [`lines`] iterator. /// /// # Examples /// @@ -1183,8 +1183,8 @@ fn read_until(r: &mut R, delim: u8, buf: &mut Vec) /// /// [`BufReader`]: struct.BufReader.html /// [`File`]: ../fs/struct.File.html -/// [`read_line()`]: #method.read_line -/// [`lines()`]: #method.lines +/// [`read_line`]: #method.read_line +/// [`lines`]: #method.lines /// [`Read`]: trait.Read.html /// /// ``` @@ -1209,13 +1209,13 @@ pub trait BufRead: Read { /// Fills the internal buffer of this object, returning the buffer contents. /// /// This function is a lower-level call. It needs to be paired with the - /// [`consume()`] method to function properly. When calling this + /// [`consume`] method to function properly. When calling this /// method, none of the contents will be "read" in the sense that later - /// calling `read` may return the same contents. As such, [`consume()`] must + /// calling `read` may return the same contents. As such, [`consume`] must /// be called with the number of bytes that are consumed from this buffer to /// ensure that the bytes are never returned twice. /// - /// [`consume()`]: #tymethod.consume + /// [`consume`]: #tymethod.consume /// /// An empty buffer returned indicates that the stream has reached EOF. /// @@ -1256,21 +1256,21 @@ pub trait BufRead: Read { /// so they should no longer be returned in calls to `read`. /// /// This function is a lower-level call. It needs to be paired with the - /// [`fill_buf()`] method to function properly. This function does + /// [`fill_buf`] method to function properly. This function does /// not perform any I/O, it simply informs this object that some amount of - /// its buffer, returned from [`fill_buf()`], has been consumed and should + /// its buffer, returned from [`fill_buf`], has been consumed and should /// no longer be returned. As such, this function may do odd things if - /// [`fill_buf()`] isn't called before calling it. + /// [`fill_buf`] isn't called before calling it. /// /// The `amt` must be `<=` the number of bytes in the buffer returned by - /// [`fill_buf()`]. + /// [`fill_buf`]. /// /// # Examples /// - /// Since `consume()` is meant to be used with [`fill_buf()`], + /// Since `consume()` is meant to be used with [`fill_buf`], /// that method's example includes an example of `consume()`. /// - /// [`fill_buf()`]: #tymethod.fill_buf + /// [`fill_buf`]: #tymethod.fill_buf #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); @@ -1285,7 +1285,7 @@ pub trait BufRead: Read { /// # Errors /// /// This function will ignore all instances of [`ErrorKind::Interrupted`] and - /// will otherwise return any errors returned by [`fill_buf()`]. + /// will otherwise return any errors returned by [`fill_buf`]. /// /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. @@ -1295,7 +1295,7 @@ pub trait BufRead: Read { /// A locked standard input implements `BufRead`. In this example, we'll /// read from standard input until we see an `a` byte. /// - /// [`fill_buf()`]: #tymethod.fill_buf + /// [`fill_buf`]: #tymethod.fill_buf /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted /// /// ``` @@ -1330,7 +1330,7 @@ pub trait BufRead: Read { /// /// # Errors /// - /// This function has the same error semantics as [`read_until()`] and will + /// This function has the same error semantics as [`read_until`] and will /// also return an error if the read bytes are not valid UTF-8. If an I/O /// error is encountered then `buf` may contain some bytes already read in /// the event that all data read so far was valid UTF-8. @@ -1339,11 +1339,11 @@ pub trait BufRead: Read { /// /// A locked standard input implements `BufRead`. In this example, we'll /// read all of the lines from standard input. If we were to do this in - /// an actual project, the [`lines()`] method would be easier, of + /// an actual project, the [`lines`] method would be easier, of /// course. /// - /// [`lines()`]: #method.lines - /// [`read_until()`]: #method.read_until + /// [`lines`]: #method.lines + /// [`read_until`]: #method.read_until /// /// ``` /// use std::io; @@ -1375,7 +1375,7 @@ pub trait BufRead: Read { /// [`io::Result`]`<`[`Vec`]`>`. Each vector returned will *not* have /// the delimiter byte at the end. /// - /// This function will yield errors whenever [`read_until()`] would have + /// This function will yield errors whenever [`read_until`] would have /// also yielded an error. /// /// # Examples @@ -1385,7 +1385,7 @@ pub trait BufRead: Read { /// /// [`io::Result`]: type.Result.html /// [`Vec`]: ../vec/struct.Vec.html - /// [`read_until()`]: #method.read_until + /// [`read_until`]: #method.read_until /// /// ``` /// use std::io; @@ -1428,9 +1428,9 @@ pub trait BufRead: Read { /// /// # Errors /// - /// Each line of the iterator has the same error semantics as [`BufRead::read_line()`]. + /// Each line of the iterator has the same error semantics as [`BufRead::read_line`]. /// - /// [`BufRead::read_line()`]: trait.BufRead.html#method.read_line + /// [`BufRead::read_line`]: trait.BufRead.html#method.read_line #[stable(feature = "rust1", since = "1.0.0")] fn lines(self) -> Lines where Self: Sized { Lines { buf: self } @@ -1439,10 +1439,10 @@ pub trait BufRead: Read { /// Adaptor to chain together two readers. /// -/// This struct is generally created by calling [`chain()`] on a reader. -/// Please see the documentation of [`chain()`] for more details. +/// This struct is generally created by calling [`chain`] on a reader. +/// Please see the documentation of [`chain`] for more details. /// -/// [`chain()`]: trait.Read.html#method.chain +/// [`chain`]: trait.Read.html#method.chain #[stable(feature = "rust1", since = "1.0.0")] pub struct Chain { first: T, @@ -1496,10 +1496,10 @@ impl BufRead for Chain { /// Reader adaptor which limits the bytes read from an underlying reader. /// -/// This struct is generally created by calling [`take()`] on a reader. -/// Please see the documentation of [`take()`] for more details. +/// This struct is generally created by calling [`take`] on a reader. +/// Please see the documentation of [`take`] for more details. /// -/// [`take()`]: trait.Read.html#method.take +/// [`take`]: trait.Read.html#method.take #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Take { @@ -1614,10 +1614,10 @@ fn read_one_byte(reader: &mut Read) -> Option> { /// An iterator over `u8` values of a reader. /// -/// This struct is generally created by calling [`bytes()`] on a reader. -/// Please see the documentation of [`bytes()`] for more details. +/// This struct is generally created by calling [`bytes`] on a reader. +/// Please see the documentation of [`bytes`] for more details. /// -/// [`bytes()`]: trait.Read.html#method.bytes +/// [`bytes`]: trait.Read.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct Bytes { @@ -1635,7 +1635,7 @@ impl Iterator for Bytes { /// An iterator over the `char`s of a reader. /// -/// This struct is generally created by calling [`chars()`][chars] on a reader. +/// This struct is generally created by calling [`chars`][chars] on a reader. /// Please see the documentation of `chars()` for more details. /// /// [chars]: trait.Read.html#method.chars @@ -1726,7 +1726,7 @@ impl fmt::Display for CharsError { /// An iterator over the contents of an instance of `BufRead` split on a /// particular byte. /// -/// This struct is generally created by calling [`split()`][split] on a +/// This struct is generally created by calling [`split`][split] on a /// `BufRead`. Please see the documentation of `split()` for more details. /// /// [split]: trait.BufRead.html#method.split @@ -1758,7 +1758,7 @@ impl Iterator for Split { /// An iterator over the lines of an instance of `BufRead`. /// -/// This struct is generally created by calling [`lines()`][lines] on a +/// This struct is generally created by calling [`lines`][lines] on a /// `BufRead`. Please see the documentation of `lines()` for more details. /// /// [lines]: trait.BufRead.html#method.lines diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index e16e8019b5f73..38ad23e14b3eb 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -332,11 +332,11 @@ impl<'a> fmt::Debug for StdinLock<'a> { /// /// Each handle shares a global buffer of data to be written to the standard /// output stream. Access is also synchronized via a lock and explicit control -/// over locking is available via the [`lock()`] method. +/// over locking is available via the [`lock`] method. /// /// Created by the [`io::stdout`] method. /// -/// [`lock()`]: #method.lock +/// [`lock`]: #method.lock /// [`io::stdout`]: fn.stdout.html #[stable(feature = "rust1", since = "1.0.0")] pub struct Stdout { diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 4163187488e65..078f1ad3f6cfe 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -63,7 +63,7 @@ pub fn copy(reader: &mut R, writer: &mut W) -> io::Result< /// A reader which is always at EOF. /// -/// This struct is generally created by calling [`empty()`][empty]. Please see +/// This struct is generally created by calling [`empty`][empty]. Please see /// the documentation of `empty()` for more details. /// /// [empty]: fn.empty.html @@ -107,7 +107,7 @@ impl fmt::Debug for Empty { /// A reader which yields one byte over and over and over and over and over and... /// -/// This struct is generally created by calling [`repeat()`][repeat]. Please +/// This struct is generally created by calling [`repeat`][repeat]. Please /// see the documentation of `repeat()` for more details. /// /// [repeat]: fn.repeat.html @@ -150,7 +150,7 @@ impl fmt::Debug for Repeat { /// A writer which will move data into the void. /// -/// This struct is generally created by calling [`sink()`][sink]. Please +/// This struct is generally created by calling [`sink`][sink]. Please /// see the documentation of `sink()` for more details. /// /// [sink]: fn.sink.html diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 070690773b6c4..a6ea890c3ee8d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -21,7 +21,7 @@ //! contained an `extern crate std;` import at the [crate root]. Therefore the //! standard library can be accessed in [`use`] statements through the path //! `std`, as in [`use std::env`], or in expressions through the absolute path -//! `::std`, as in [`::std::env::args()`]. +//! `::std`, as in [`::std::env::args`]. //! //! # How to read this documentation //! @@ -156,7 +156,7 @@ //! [TCP]: net/struct.TcpStream.html //! [The Rust Prelude]: prelude/index.html //! [UDP]: net/struct.UdpSocket.html -//! [`::std::env::args()`]: env/fn.args.html +//! [`::std::env::args`]: env/fn.args.html //! [`Arc`]: sync/struct.Arc.html //! [owned slice]: boxed/index.html //! [`Cell`]: cell/struct.Cell.html diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 9bead22ef7f5e..a07972468e68a 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -183,7 +183,7 @@ impl TcpStream { /// Sets the read timeout to the timeout specified. /// - /// If the value specified is [`None`], then [`read()`] calls will block + /// If the value specified is [`None`], then [`read`] calls will block /// indefinitely. It is an error to pass the zero `Duration` to this /// method. /// @@ -194,7 +194,7 @@ impl TcpStream { /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`read`]: ../../std/io/trait.Read.html#tymethod.read /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut /// @@ -214,7 +214,7 @@ impl TcpStream { /// Sets the write timeout to the timeout specified. /// - /// If the value specified is [`None`], then [`write()`] calls will block + /// If the value specified is [`None`], then [`write`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// @@ -225,7 +225,7 @@ impl TcpStream { /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../std/time/struct.Duration.html /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut @@ -246,14 +246,14 @@ impl TcpStream { /// Returns the read timeout of this socket. /// - /// If the timeout is [`None`], then [`read()`] calls will block indefinitely. + /// If the timeout is [`None`], then [`read`] calls will block indefinitely. /// /// # Note /// /// Some platforms do not provide access to the current timeout. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`read`]: ../../std/io/trait.Read.html#tymethod.read /// /// # Examples /// @@ -272,14 +272,14 @@ impl TcpStream { /// Returns the write timeout of this socket. /// - /// If the timeout is [`None`], then [`write()`] calls will block indefinitely. + /// If the timeout is [`None`], then [`write`] calls will block indefinitely. /// /// # Note /// /// Some platforms do not provide access to the current timeout. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// /// # Examples /// @@ -618,7 +618,7 @@ impl TcpListener { /// Gets the value of the `IP_TTL` option for this socket. /// - /// For more information about this option, see [`set_ttl()`][link]. + /// For more information about this option, see [`set_ttl`][link]. /// /// [link]: #method.set_ttl /// diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index f452c75d38966..1ebce93934840 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -175,7 +175,7 @@ impl UdpSocket { /// Sets the read timeout to the timeout specified. /// - /// If the value specified is [`None`], then [`read()`] calls will block + /// If the value specified is [`None`], then [`read`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// @@ -186,7 +186,7 @@ impl UdpSocket { /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`read`]: ../../std/io/trait.Read.html#tymethod.read /// [`Duration`]: ../../std/time/struct.Duration.html /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut @@ -206,7 +206,7 @@ impl UdpSocket { /// Sets the write timeout to the timeout specified. /// - /// If the value specified is [`None`], then [`write()`] calls will block + /// If the value specified is [`None`], then [`write`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// @@ -217,7 +217,7 @@ impl UdpSocket { /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../std/time/struct.Duration.html /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut @@ -237,10 +237,10 @@ impl UdpSocket { /// Returns the read timeout of this socket. /// - /// If the timeout is [`None`], then [`read()`] calls will block indefinitely. + /// If the timeout is [`None`], then [`read`] calls will block indefinitely. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`read`]: ../../std/io/trait.Read.html#tymethod.read /// /// # Examples /// @@ -258,10 +258,10 @@ impl UdpSocket { /// Returns the write timeout of this socket. /// - /// If the timeout is [`None`], then [`write()`] calls will block indefinitely. + /// If the timeout is [`None`], then [`write`] calls will block indefinitely. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`write`]: ../../std/io/trait.Write.html#tymethod.write /// /// # Examples /// @@ -560,10 +560,10 @@ impl UdpSocket { /// Sends data on the socket to the remote address to which it is connected. /// - /// The [`connect()`] method will connect this socket to a remote address. This + /// The [`connect`] method will connect this socket to a remote address. This /// method will fail if the socket is not connected. /// - /// [`connect()`]: #method.connect + /// [`connect`]: #method.connect /// /// # Examples /// diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 3b5a1cffc7a22..6f46a73698f35 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -160,10 +160,10 @@ pub fn take_hook() -> Box { /// A struct providing information about a panic. /// -/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook()`] +/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`] /// function. /// -/// [`set_hook()`]: ../../std/panic/fn.set_hook.html +/// [`set_hook`]: ../../std/panic/fn.set_hook.html /// /// # Examples /// @@ -237,9 +237,9 @@ impl<'a> PanicInfo<'a> { /// A struct containing information about the location of a panic. /// -/// This structure is created by the [`location()`] method of [`PanicInfo`]. +/// This structure is created by the [`location`] method of [`PanicInfo`]. /// -/// [`location()`]: ../../std/panic/struct.PanicInfo.html#method.location +/// [`location`]: ../../std/panic/struct.PanicInfo.html#method.location /// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html /// /// # Examples diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 245a6d945b5a3..b5d2fe82dea80 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1065,13 +1065,13 @@ impl PathBuf { self.inner.push(path); } - /// Truncate `self` to [`self.parent()`]. + /// Truncate `self` to [`self.parent`]. /// - /// Returns false and does nothing if [`self.file_name()`] is `None`. + /// Returns false and does nothing if [`self.file_name`] is `None`. /// Otherwise, returns `true`. /// - /// [`self.parent()`]: struct.PathBuf.html#method.parent - /// [`self.file_name()`]: struct.PathBuf.html#method.file_name + /// [`self.parent`]: struct.PathBuf.html#method.parent + /// [`self.file_name`]: struct.PathBuf.html#method.file_name /// /// # Examples /// @@ -1096,12 +1096,12 @@ impl PathBuf { } } - /// Updates [`self.file_name()`] to `file_name`. + /// Updates [`self.file_name`] to `file_name`. /// - /// If [`self.file_name()`] was [`None`], this is equivalent to pushing + /// If [`self.file_name`] was [`None`], this is equivalent to pushing /// `file_name`. /// - /// [`self.file_name()`]: struct.PathBuf.html#method.file_name + /// [`self.file_name`]: struct.PathBuf.html#method.file_name /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples @@ -1130,15 +1130,15 @@ impl PathBuf { self.push(file_name); } - /// Updates [`self.extension()`] to `extension`. + /// Updates [`self.extension`] to `extension`. /// - /// If [`self.file_name()`] is `None`, does nothing and returns `false`. + /// If [`self.file_name`] is `None`, does nothing and returns `false`. /// - /// Otherwise, returns `true`; if [`self.extension()`] is [`None`], the + /// Otherwise, returns `true`; if [`self.extension`] is [`None`], the /// extension is added; otherwise it is replaced. /// - /// [`self.file_name()`]: struct.PathBuf.html#method.file_name - /// [`self.extension()`]: struct.PathBuf.html#method.extension + /// [`self.file_name`]: struct.PathBuf.html#method.file_name + /// [`self.extension`]: struct.PathBuf.html#method.extension /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples @@ -1733,9 +1733,9 @@ impl Path { iter_after(self.components().rev(), child.components().rev()).is_some() } - /// Extracts the stem (non-extension) portion of [`self.file_name()`]. + /// Extracts the stem (non-extension) portion of [`self.file_name`]. /// - /// [`self.file_name()`]: struct.Path.html#method.file_name + /// [`self.file_name`]: struct.Path.html#method.file_name /// /// The stem is: /// @@ -1760,7 +1760,7 @@ impl Path { self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after)) } - /// Extracts the extension of [`self.file_name()`], if possible. + /// Extracts the extension of [`self.file_name`], if possible. /// /// The extension is: /// @@ -1769,7 +1769,7 @@ impl Path { /// * [`None`], if the file name begins with `.` and has no other `.`s within; /// * Otherwise, the portion of the file name after the final `.` /// - /// [`self.file_name()`]: struct.Path.html#method.file_name + /// [`self.file_name`]: struct.Path.html#method.file_name /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index f4cd319f06454..c71e0b2a7035a 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -60,9 +60,9 @@ //! value. //! * [`std::boxed`]::[`Box`], a way to allocate values on the heap. //! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines -//! [`to_owned()`], the generic method for creating an owned type from a +//! [`to_owned`], the generic method for creating an owned type from a //! borrowed type. -//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone()`], +//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines [`clone`], //! the method for producing a copy of a value. //! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The //! comparison traits, which implement the comparison operators and are often @@ -117,7 +117,7 @@ //! [`ToOwned`]: ../borrow/trait.ToOwned.html //! [`ToString`]: ../string/trait.ToString.html //! [`Vec`]: ../vec/struct.Vec.html -//! [`clone()`]: ../clone/trait.Clone.html#tymethod.clone +//! [`clone`]: ../clone/trait.Clone.html#tymethod.clone //! [`drop`]: ../mem/fn.drop.html //! [`std::borrow`]: ../borrow/index.html //! [`std::boxed`]: ../boxed/index.html @@ -135,7 +135,7 @@ //! [`std::slice`]: ../slice/index.html //! [`std::string`]: ../string/index.html //! [`std::vec`]: ../vec/index.html -//! [`to_owned()`]: ../borrow/trait.ToOwned.html#tymethod.to_owned +//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned //! [book-closures]: ../../book/closures.html //! [book-dtor]: ../../book/drop.html //! [book-enums]: ../../book/enums.html diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 11197db98a396..7d6d16f474845 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -420,7 +420,7 @@ mod prim_slice { } /// # Representation /// /// A `&str` is made up of two components: a pointer to some bytes, and a -/// length. You can look at these with the [`.as_ptr()`] and [`len()`] methods: +/// length. You can look at these with the [`.as_ptr`] and [`len`] methods: /// /// ``` /// use std::slice; @@ -447,8 +447,8 @@ mod prim_slice { } /// assert_eq!(s, Ok(story)); /// ``` /// -/// [`.as_ptr()`]: #method.as_ptr -/// [`len()`]: #method.len +/// [`.as_ptr`]: #method.as_ptr +/// [`len`]: #method.len /// /// Note: This example shows the internals of `&str`. `unsafe` should not be /// used to get a string slice under normal circumstances. Use `.as_slice()` diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index f15e7ff891684..295a49d6a8e89 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -52,10 +52,10 @@ struct BarrierState { /// A result returned from wait. /// -/// Currently this opaque structure only has one method, [`.is_leader()`]. Only +/// Currently this opaque structure only has one method, [`.is_leader`]. Only /// one thread will receive a result that will return `true` from this function. /// -/// [`.is_leader()`]: #method.is_leader +/// [`.is_leader`]: #method.is_leader /// /// # Examples /// diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 68c7e88f67fc5..7ad9d9ee37ce6 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -150,7 +150,7 @@ impl Condvar { /// /// This function will atomically unlock the mutex specified (represented by /// `guard`) and block the current thread. This means that any calls - /// to [`notify_one()`] or [`notify_all()`] which happen logically after the + /// to [`notify_one`] or [`notify_all`] which happen logically after the /// mutex is unlocked are candidates to wake this thread up. When this /// function call returns, the lock specified will have been re-acquired. /// @@ -167,16 +167,16 @@ impl Condvar { /// /// # Panics /// - /// This function will [`panic!()`] if it is used with more than one mutex + /// This function will [`panic!`] if it is used with more than one mutex /// over time. Each condition variable is dynamically bound to exactly one /// mutex to ensure defined behavior across platforms. If this functionality /// is not desired, then unsafe primitives in `sys` are provided. /// - /// [`notify_one()`]: #method.notify_one - /// [`notify_all()`]: #method.notify_all + /// [`notify_one`]: #method.notify_one + /// [`notify_all`]: #method.notify_all /// [poisoning]: ../sync/struct.Mutex.html#poisoning /// [`Mutex`]: ../sync/struct.Mutex.html - /// [`panic!()`]: ../../std/macro.panic.html + /// [`panic!`]: ../../std/macro.panic.html /// /// # Examples /// @@ -359,11 +359,11 @@ impl Condvar { /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to /// `notify_one` are not buffered in any way. /// - /// To wake up all threads, see [`notify_all()`]. + /// To wake up all threads, see [`notify_all`]. /// /// [`wait`]: #method.wait /// [`wait_timeout`]: #method.wait_timeout - /// [`notify_all()`]: #method.notify_all + /// [`notify_all`]: #method.notify_all /// /// # Examples /// @@ -401,9 +401,9 @@ impl Condvar { /// variable are awoken. Calls to `notify_all()` are not buffered in any /// way. /// - /// To wake up only one thread, see [`notify_one()`]. + /// To wake up only one thread, see [`notify_one`]. /// - /// [`notify_one()`]: #method.notify_one + /// [`notify_one`]: #method.notify_one /// /// # Examples /// diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index aeeab170deafe..71dd94161c03d 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -460,10 +460,10 @@ impl UnsafeFlavor for Receiver { /// All data sent on the sender will become available on the receiver, and no /// send will block the calling thread (this channel has an "infinite buffer"). /// -/// If the [`Receiver`] is disconnected while trying to [`send()`] with the -/// [`Sender`], the [`send()`] method will return an error. +/// If the [`Receiver`] is disconnected while trying to [`send`] with the +/// [`Sender`], the [`send`] method will return an error. /// -/// [`send()`]: ../../../std/sync/mpsc/struct.Sender.html#method.send +/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send /// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html /// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html /// @@ -504,13 +504,13 @@ pub fn channel() -> (Sender, Receiver) { /// `bound` specifies the buffer size. When the internal buffer becomes full, /// future sends will *block* waiting for the buffer to open up. Note that a /// buffer size of 0 is valid, in which case this becomes "rendezvous channel" -/// where each [`send()`] will not return until a recv is paired with it. +/// where each [`send`] will not return until a recv is paired with it. /// /// Like asynchronous channels, if the [`Receiver`] is disconnected while -/// trying to [`send()`] with the [`SyncSender`], the [`send()`] method will +/// trying to [`send`] with the [`SyncSender`], the [`send`] method will /// return an error. /// -/// [`send()`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send +/// [`send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send /// [`SyncSender`]: ../../../std/sync/mpsc/struct.SyncSender.html /// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html /// diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 97b84d59218ac..48d8d34dbe090 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -135,13 +135,13 @@ unsafe impl Sync for Mutex { } /// The data protected by the mutex can be access through this guard via its /// [`Deref`] and [`DerefMut`] implementations. /// -/// This structure is created by the [`lock()`] and [`try_lock()`] methods on +/// This structure is created by the [`lock`] and [`try_lock`] methods on /// [`Mutex`]. /// /// [`Deref`]: ../../std/ops/trait.Deref.html /// [`DerefMut`]: ../../std/ops/trait.DerefMut.html -/// [`lock()`]: struct.Mutex.html#method.lock -/// [`try_lock()`]: struct.Mutex.html#method.try_lock +/// [`lock`]: struct.Mutex.html#method.lock +/// [`try_lock`]: struct.Mutex.html#method.try_lock /// [`Mutex`]: struct.Mutex.html #[must_use] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index a3db0adeda00d..d26f2f7bb7e3c 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -78,11 +78,11 @@ unsafe impl Sync for RwLock {} /// RAII structure used to release the shared read access of a lock when /// dropped. /// -/// This structure is created by the [`read()`] and [`try_read()`] methods on +/// This structure is created by the [`read`] and [`try_read`] methods on /// [`RwLock`]. /// -/// [`read()`]: struct.RwLock.html#method.read -/// [`try_read()`]: struct.RwLock.html#method.try_read +/// [`read`]: struct.RwLock.html#method.read +/// [`try_read`]: struct.RwLock.html#method.try_read /// [`RwLock`]: struct.RwLock.html #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -96,11 +96,11 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {} /// RAII structure used to release the exclusive write access of a lock when /// dropped. /// -/// This structure is created by the [`write()`] and [`try_write()`] methods +/// This structure is created by the [`write`] and [`try_write`] methods /// on [`RwLock`]. /// -/// [`write()`]: struct.RwLock.html#method.write -/// [`try_write()`]: struct.RwLock.html#method.try_write +/// [`write`]: struct.RwLock.html#method.write +/// [`try_write`]: struct.RwLock.html#method.try_write /// [`RwLock`]: struct.RwLock.html #[must_use] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 1ba4a104e515c..d5933d316c4bd 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -375,12 +375,12 @@ impl UnixStream { /// Sets the read timeout for the socket. /// - /// If the provided value is [`None`], then [`read()`] calls will block + /// If the provided value is [`None`], then [`read`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples @@ -399,12 +399,12 @@ impl UnixStream { /// Sets the write timeout for the socket. /// - /// If the provided value is [`None`], then [`write()`] calls will block + /// If the provided value is [`None`], then [`write`] calls will block /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`read`]: ../../../../std/io/trait.Write.html#tymethod.write /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples @@ -974,12 +974,12 @@ impl UnixDatagram { /// Connects the socket to the specified address. /// - /// The [`send()`] method may be used to send data to the specified address. - /// [`recv()`] and [`recv_from()`] will only receive data from that address. + /// The [`send`] method may be used to send data to the specified address. + /// [`recv`] and [`recv_from`] will only receive data from that address. /// - /// [`send()`]: #method.send - /// [`recv()`]: #method.recv - /// [`recv_from()`]: #method.recv_from + /// [`send`]: #method.send + /// [`recv`]: #method.recv + /// [`recv_from`]: #method.recv_from /// /// # Examples /// @@ -1047,9 +1047,9 @@ impl UnixDatagram { /// Returns the address of this socket's peer. /// - /// The [`connect()`] method will connect the socket to a peer. + /// The [`connect`] method will connect the socket to a peer. /// - /// [`connect()`]: #method.connect + /// [`connect`]: #method.connect /// /// # Examples /// @@ -1178,13 +1178,13 @@ impl UnixDatagram { /// Sets the read timeout for the socket. /// - /// If the provided value is [`None`], then [`recv()`] and [`recv_from()`] calls will + /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`recv()`]: #method.recv - /// [`recv_from()`]: #method.recv_from + /// [`recv`]: #method.recv + /// [`recv_from`]: #method.recv_from /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples @@ -1203,13 +1203,13 @@ impl UnixDatagram { /// Sets the write timeout for the socket. /// - /// If the provided value is [`None`], then [`send()`] and [`send_to()`] calls will + /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// /// [`None`]: ../../../../std/option/enum.Option.html#variant.None - /// [`send()`]: #method.send - /// [`send_to()`]: #method.send_to + /// [`send`]: #method.send + /// [`send_to`]: #method.send_to /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 2bc066d3fea55..64c2be25222a0 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -90,29 +90,29 @@ //! two ways: //! //! * By spawning a new thread, e.g. using the [`thread::spawn`][`spawn`] -//! function, and calling [`thread()`] on the [`JoinHandle`]. -//! * By requesting the current thread, using the [`thread::current()`] function. +//! function, and calling [`thread`] on the [`JoinHandle`]. +//! * By requesting the current thread, using the [`thread::current`] function. //! -//! The [`thread::current()`] function is available even for threads not spawned +//! The [`thread::current`] function is available even for threads not spawned //! by the APIs of this module. //! //! ## Blocking support: park and unpark //! //! Every thread is equipped with some basic low-level blocking support, via the -//! [`thread::park()`][`park()`] function and [`thread::Thread::unpark()`][`unpark()`] -//! method. [`park()`] blocks the current thread, which can then be resumed from -//! another thread by calling the [`unpark()`] method on the blocked thread's handle. +//! [`thread::park`][`park`] function and [`thread::Thread::unpark()`][`unpark`] +//! method. [`park`] blocks the current thread, which can then be resumed from +//! another thread by calling the [`unpark`] method on the blocked thread's handle. //! //! Conceptually, each [`Thread`] handle has an associated token, which is //! initially not present: //! -//! * The [`thread::park()`][`park()`] function blocks the current thread unless or until +//! * The [`thread::park`][`park`] function blocks the current thread unless or until //! the token is available for its thread handle, at which point it atomically //! consumes the token. It may also return *spuriously*, without consuming the -//! token. [`thread::park_timeout()`] does the same, but allows specifying a +//! token. [`thread::park_timeout`] does the same, but allows specifying a //! maximum time to block the thread for. //! -//! * The [`unpark()`] method on a [`Thread`] atomically makes the token available +//! * The [`unpark`] method on a [`Thread`] atomically makes the token available //! if it wasn't already. //! //! In other words, each [`Thread`] acts a bit like a semaphore with initial count @@ -122,7 +122,7 @@ //! The API is typically used by acquiring a handle to the current thread, //! placing that handle in a shared data structure so that other threads can //! find it, and then `park`ing. When some desired condition is met, another -//! thread calls [`unpark()`] on the handle. +//! thread calls [`unpark`] on the handle. //! //! The motivation for this design is twofold: //! @@ -151,18 +151,18 @@ //! [`Arc`]: ../../std/sync/struct.Arc.html //! [`spawn`]: ../../std/thread/fn.spawn.html //! [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html -//! [`thread()`]: ../../std/thread/struct.JoinHandle.html#method.thread +//! [`thread`]: ../../std/thread/struct.JoinHandle.html#method.thread //! [`join`]: ../../std/thread/struct.JoinHandle.html#method.join //! [`Result`]: ../../std/result/enum.Result.html //! [`Ok`]: ../../std/result/enum.Result.html#variant.Ok //! [`Err`]: ../../std/result/enum.Result.html#variant.Err //! [`panic!`]: ../../std/macro.panic.html //! [`Builder`]: ../../std/thread/struct.Builder.html -//! [`thread::current()`]: ../../std/thread/fn.spawn.html +//! [`thread::current`]: ../../std/thread/fn.spawn.html //! [`Thread`]: ../../std/thread/struct.Thread.html -//! [`park()`]: ../../std/thread/fn.park.html -//! [`unpark()`]: ../../std/thread/struct.Thread.html#method.unpark -//! [`thread::park_timeout()`]: ../../std/thread/fn.park_timeout.html +//! [`park`]: ../../std/thread/fn.park.html +//! [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark +//! [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html //! [`Cell`]: ../cell/struct.Cell.html //! [`RefCell`]: ../cell/struct.RefCell.html //! [`thread_local!`]: ../macro.thread_local.html @@ -547,7 +547,7 @@ pub fn sleep(dur: Duration) { /// Blocks unless or until the current thread's token is made available. /// /// Every thread is equipped with some basic low-level blocking support, via -/// the `park()` function and the [`unpark()`][unpark] method. These can be +/// the `park()` function and the [`unpark`][unpark] method. These can be /// used as a more CPU-efficient implementation of a spinlock. /// /// [unpark]: struct.Thread.html#method.unpark diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 4269ce8534bd0..682eec490bc65 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -49,10 +49,10 @@ pub use tables::UNICODE_VERSION; /// Returns an iterator that yields the lowercase equivalent of a `char`. /// -/// This `struct` is created by the [`to_lowercase()`] method on [`char`]. See +/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See /// its documentation for more. /// -/// [`to_lowercase()`]: ../../std/primitive.char.html#method.to_lowercase +/// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase /// [`char`]: ../../std/primitive.char.html #[stable(feature = "rust1", since = "1.0.0")] pub struct ToLowercase(CaseMappingIter); @@ -70,10 +70,10 @@ impl FusedIterator for ToLowercase {} /// Returns an iterator that yields the uppercase equivalent of a `char`. /// -/// This `struct` is created by the [`to_uppercase()`] method on [`char`]. See +/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See /// its documentation for more. /// -/// [`to_uppercase()`]: ../../std/primitive.char.html#method.to_uppercase +/// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase /// [`char`]: ../../std/primitive.char.html #[stable(feature = "rust1", since = "1.0.0")] pub struct ToUppercase(CaseMappingIter); @@ -183,7 +183,7 @@ impl char { /// * `a-z` /// * `A-Z` /// - /// For a more comprehensive understanding of 'digit', see [`is_numeric()`][is_numeric]. + /// For a more comprehensive understanding of 'digit', see [`is_numeric`][is_numeric]. /// /// [is_numeric]: #method.is_numeric /// @@ -465,10 +465,10 @@ impl char { /// Returns the number of 16-bit code units this `char` would need if /// encoded in UTF-16. /// - /// See the documentation for [`len_utf8()`] for more explanation of this + /// See the documentation for [`len_utf8`] for more explanation of this /// concept. This function is a mirror, but for UTF-16 instead of UTF-8. /// - /// [`len_utf8()`]: #method.len_utf8 + /// [`len_utf8`]: #method.len_utf8 /// /// # Examples /// From 460bf55f8a649a7f19680df2ac67dbeb936f8700 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 6 Mar 2017 06:45:28 +0000 Subject: [PATCH 16/19] Cleanup. --- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/parse/parser.rs | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index b9cb3d82d4f7c..6385d206a0cb9 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -488,7 +488,7 @@ pub fn parse(sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], directory: Op fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { match name { "tt" => { - return token::NtTT(panictry!(p.parse_token_tree())); + return token::NtTT(p.parse_token_tree()); } _ => {} } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6446d38e5ef70..9872afd27b7bc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -891,7 +891,7 @@ impl<'a> Parser<'a> { self.parse_seq_to_before_tokens(kets, SeqSep::none(), - |p| p.parse_token_tree(), + |p| Ok(p.parse_token_tree()), |mut e| handler.cancel(&mut e)); } @@ -1267,7 +1267,7 @@ impl<'a> Parser<'a> { break; } token::OpenDelim(token::Brace) => { - self.parse_token_tree()?; + self.parse_token_tree(); break; } _ => self.bump(), @@ -2101,10 +2101,10 @@ impl<'a> Parser<'a> { fn expect_delimited_token_tree(&mut self) -> PResult<'a, (token::DelimToken, ThinTokenStream)> { match self.token { - token::OpenDelim(delim) => self.parse_token_tree().map(|tree| match tree { - TokenTree::Delimited(_, delimited) => (delim, delimited.stream().into()), + token::OpenDelim(delim) => match self.parse_token_tree() { + TokenTree::Delimited(_, delimited) => Ok((delim, delimited.stream().into())), _ => unreachable!(), - }), + }, _ => Err(self.fatal("expected open delimiter")), } } @@ -2643,24 +2643,23 @@ impl<'a> Parser<'a> { } /// parse a single token tree from the input. - pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> { + pub fn parse_token_tree(&mut self) -> TokenTree { match self.token { token::OpenDelim(..) => { let frame = mem::replace(&mut self.token_cursor.frame, self.token_cursor.stack.pop().unwrap()); self.span = frame.span; self.bump(); - return Ok(TokenTree::Delimited(frame.span, Delimited { + TokenTree::Delimited(frame.span, Delimited { delim: frame.delim, tts: frame.tree_cursor.original_stream().into(), - })); + }) }, token::CloseDelim(_) | token::Eof => unreachable!(), _ => { let token = mem::replace(&mut self.token, token::Underscore); - let res = Ok(TokenTree::Token(self.span, token)); self.bump(); - res + TokenTree::Token(self.prev_span, token) } } } @@ -2670,7 +2669,7 @@ impl<'a> Parser<'a> { pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec> { let mut tts = Vec::new(); while self.token != token::Eof { - tts.push(self.parse_token_tree()?); + tts.push(self.parse_token_tree()); } Ok(tts) } From 68c1cc68b44bb987ec57251bc457a55292515d1d Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 3 Mar 2017 09:23:59 +0000 Subject: [PATCH 17/19] Refactor `Attribute` to use `Path` and `TokenStream` instead of `MetaItem`. --- src/librustc/hir/check_attr.rs | 11 +- src/librustc/hir/lowering.rs | 2 +- src/librustc/lint/context.rs | 4 +- src/librustc/middle/stability.rs | 4 +- src/librustc/traits/error_reporting.rs | 2 +- .../calculate_svh/svh_visitor.rs | 55 +--- .../persist/dirty_clean.rs | 8 +- src/librustc_lint/builtin.rs | 8 +- src/librustc_lint/lib.rs | 1 + src/librustc_lint/unused.rs | 5 +- src/librustc_metadata/creader.rs | 8 +- src/librustc_metadata/cstore.rs | 9 +- src/librustc_passes/ast_validation.rs | 4 +- src/librustc_resolve/lib.rs | 5 +- src/librustc_resolve/macros.rs | 43 ++- src/librustc_save_analysis/external_data.rs | 4 +- src/librustc_save_analysis/lib.rs | 5 +- src/librustc_trans/assert_module_sources.rs | 2 +- src/librustdoc/clean/mod.rs | 21 +- src/librustdoc/html/render.rs | 4 +- src/librustdoc/test.rs | 14 +- src/librustdoc/visit_ast.rs | 2 +- src/libsyntax/ast.rs | 9 +- src/libsyntax/attr.rs | 306 +++++++++++++++--- src/libsyntax/config.rs | 8 +- src/libsyntax/ext/derive.rs | 4 +- src/libsyntax/ext/expand.rs | 42 +-- src/libsyntax/ext/quote.rs | 14 +- src/libsyntax/feature_gate.rs | 28 +- src/libsyntax/fold.rs | 7 +- src/libsyntax/lib.rs | 10 + src/libsyntax/parse/attr.rs | 16 +- src/libsyntax/parse/mod.rs | 131 +++++--- src/libsyntax/parse/parser.rs | 44 +-- src/libsyntax/parse/token.rs | 4 +- src/libsyntax/print/pprust.rs | 100 +++--- src/libsyntax/std_inject.rs | 8 +- src/libsyntax/tokenstream.rs | 2 +- src/libsyntax_ext/deriving/custom.rs | 8 +- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- src/libsyntax_ext/proc_macro_registrar.rs | 12 +- 41 files changed, 614 insertions(+), 362 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 6f5f548aa7802..54ae947214091 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -120,11 +120,12 @@ impl<'a> CheckAttrVisitor<'a> { } fn check_attribute(&self, attr: &ast::Attribute, target: Target) { - let name: &str = &attr.name().as_str(); - match name { - "inline" => self.check_inline(attr, target), - "repr" => self.check_repr(attr, target), - _ => (), + if let Some(name) = attr.name() { + match &*name.as_str() { + "inline" => self.check_inline(attr, target), + "repr" => self.check_repr(attr, target), + _ => (), + } } } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index aa6614b0af4f7..a5c8213067550 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1277,7 +1277,7 @@ impl<'a> LoweringContext<'a> { let attrs = self.lower_attrs(&i.attrs); let mut vis = self.lower_visibility(&i.vis); if let ItemKind::MacroDef(ref tts) = i.node { - if i.attrs.iter().any(|attr| attr.name() == "macro_export") { + if i.attrs.iter().any(|attr| attr.path == "macro_export") { self.exported_macros.push(hir::MacroDef { name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(), }); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 9279f24a57ab3..65e2fec0b8b09 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -402,14 +402,14 @@ pub fn gather_attrs(attrs: &[ast::Attribute]) -> Vec Vec> { let mut out = vec![]; - let level = match Level::from_str(&attr.name().as_str()) { + let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) { None => return out, Some(lvl) => lvl, }; + let meta = unwrap_or!(attr.meta(), return out); attr::mark_used(attr); - let meta = &attr.value; let metas = if let Some(metas) = meta.meta_item_list() { metas } else { diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index baa22d7061435..1fb5371402574 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -197,7 +197,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } else { // Emit errors for non-staged-api crates. for attr in attrs { - let tag = attr.name(); + let tag = unwrap_or!(attr.name(), continue); if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" { attr::mark_used(attr); self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \ @@ -402,7 +402,7 @@ impl<'a, 'tcx> Index<'tcx> { let mut is_staged_api = false; for attr in &krate.attrs { - if attr.name() == "stable" || attr.name() == "unstable" { + if attr.path == "stable" || attr.path == "unstable" { is_staged_api = true; break } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0e5c786cd8dcf..27525d550ff20 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -274,7 +274,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .filter(|a| a.check_name("rustc_on_unimplemented")) .next() { - let err_sp = item.meta().span.substitute_dummy(span); + let err_sp = item.span.substitute_dummy(span); let trait_str = self.tcx.item_path_str(trait_ref.def_id); if let Some(istring) = item.value_str() { let istring = &*istring.as_str(); diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index d0eedcac0c06a..fac49b29598aa 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -18,16 +18,15 @@ use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::parse::token; -use syntax::symbol::{Symbol, InternedString}; +use syntax::symbol::InternedString; use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos}; use syntax::tokenstream; use rustc::hir; use rustc::hir::*; use rustc::hir::def::Def; use rustc::hir::def_id::DefId; -use rustc::hir::intravisit as visit; +use rustc::hir::intravisit::{self as visit, Visitor}; use rustc::ty::TyCtxt; -use rustc_data_structures::fnv; use std::hash::{Hash, Hasher}; use super::def_path_hash::DefPathHashes; @@ -559,7 +558,7 @@ macro_rules! hash_span { }); } -impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> { +impl<'a, 'hash, 'tcx> Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> visit::NestedVisitorMap<'this, 'tcx> { if self.hash_bodies { visit::NestedVisitorMap::OnlyBodies(&self.tcx.hir) @@ -960,50 +959,24 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { } } - fn hash_meta_item(&mut self, meta_item: &ast::MetaItem) { - debug!("hash_meta_item: st={:?}", self.st); - - // ignoring span information, it doesn't matter here - self.hash_discriminant(&meta_item.node); - meta_item.name.as_str().len().hash(self.st); - meta_item.name.as_str().hash(self.st); - - match meta_item.node { - ast::MetaItemKind::Word => {} - ast::MetaItemKind::NameValue(ref lit) => saw_lit(lit).hash(self.st), - ast::MetaItemKind::List(ref items) => { - // Sort subitems so the hash does not depend on their order - let indices = self.indices_sorted_by(&items, |p| { - (p.name().map(Symbol::as_str), fnv::hash(&p.literal().map(saw_lit))) - }); - items.len().hash(self.st); - for (index, &item_index) in indices.iter().enumerate() { - index.hash(self.st); - let nested_meta_item: &ast::NestedMetaItemKind = &items[item_index].node; - self.hash_discriminant(nested_meta_item); - match *nested_meta_item { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => { - self.hash_meta_item(meta_item); - } - ast::NestedMetaItemKind::Literal(ref lit) => { - saw_lit(lit).hash(self.st); - } - } - } - } - } - } - pub fn hash_attributes(&mut self, attributes: &[ast::Attribute]) { debug!("hash_attributes: st={:?}", self.st); let indices = self.indices_sorted_by(attributes, |attr| attr.name()); for i in indices { let attr = &attributes[i]; - if !attr.is_sugared_doc && - !IGNORED_ATTRIBUTES.contains(&&*attr.value.name().as_str()) { + match attr.name() { + Some(name) if IGNORED_ATTRIBUTES.contains(&&*name.as_str()) => continue, + _ => {} + }; + if !attr.is_sugared_doc { SawAttribute(attr.style).hash(self.st); - self.hash_meta_item(&attr.value); + for segment in &attr.path.segments { + SawIdent(segment.identifier.name.as_str()).hash(self.st); + } + for tt in attr.tokens.trees() { + self.hash_token_tree(&tt); + } } } } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 156f8b9e7c489..929249df0b173 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -104,9 +104,9 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> { impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { - for item in attr.meta_item_list().unwrap_or(&[]) { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(LABEL) { - let value = expect_associated_value(self.tcx, item); + let value = expect_associated_value(self.tcx, &item); match DepNode::from_label_string(&value.as_str(), def_id) { Ok(def_id) => return def_id, Err(()) => { @@ -331,9 +331,9 @@ fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool { debug!("check_config(attr={:?})", attr); let config = &tcx.sess.parse_sess.config; debug!("check_config: config={:?}", config); - for item in attr.meta_item_list().unwrap_or(&[]) { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(CFG) { - let value = expect_associated_value(tcx, item); + let value = expect_associated_value(tcx, &item); debug!("check_config: searching for cfg {:?}", value); return config.contains(&(value, None)); } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 58336f939d122..f0276f90f274d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -312,7 +312,7 @@ impl MissingDoc { } } - let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc"); + let has_doc = attrs.iter().any(|a| a.is_value_str() && a.check_name("doc")); if !has_doc { cx.span_lint(MISSING_DOCS, sp, @@ -635,7 +635,7 @@ impl LintPass for DeprecatedAttr { impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) { - let name = attr.name(); + let name = unwrap_or!(attr.name(), return); for &&(n, _, ref g) in &self.depr_attrs { if name == n { if let &AttributeGate::Gated(Stability::Deprecated(link), @@ -1121,8 +1121,8 @@ impl LintPass for UnstableFeatures { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) { - if attr.meta().check_name("feature") { - if let Some(items) = attr.meta().meta_item_list() { + if attr.check_name("feature") { + if let Some(items) = attr.meta_item_list() { for item in items { ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature"); } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 443a219928f1c..05dbbc0987025 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -38,6 +38,7 @@ #![feature(slice_patterns)] #![feature(staged_api)] +#[macro_use] extern crate syntax; #[macro_use] extern crate rustc; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index f9b7c68587678..abba8afd9da86 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -269,6 +269,7 @@ impl LintPass for UnusedAttributes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) { debug!("checking attribute: {:?}", attr); + let name = unwrap_or!(attr.name(), return); // Note that check_name() marks the attribute as used if it matches. for &(ref name, ty, _) in BUILTIN_ATTRIBUTES { @@ -294,13 +295,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); // Is it a builtin attribute that must be used at the crate level? let known_crate = BUILTIN_ATTRIBUTES.iter() - .find(|&&(name, ty, _)| attr.name() == name && ty == AttributeType::CrateLevel) + .find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel) .is_some(); // Has a plugin registered this attribute as one which must be used at // the crate level? let plugin_crate = plugin_attributes.iter() - .find(|&&(ref x, t)| attr.name() == &**x && AttributeType::CrateLevel == t) + .find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t) .is_some(); if known_crate || plugin_crate { let msg = match attr.style { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 49dcffb4830a1..9f5ce00f40812 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -973,9 +973,11 @@ impl<'a> CrateLoader<'a> { impl<'a> CrateLoader<'a> { pub fn preprocess(&mut self, krate: &ast::Crate) { - for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") { - if let Some(linkarg) = attr.value_str() { - self.cstore.add_used_link_args(&linkarg.as_str()); + for attr in &krate.attrs { + if attr.path == "link_args" { + if let Some(linkarg) = attr.value_str() { + self.cstore.add_used_link_args(&linkarg.as_str()); + } } } } diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index bb30245df5f56..17a6a706e0aaa 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -269,9 +269,12 @@ impl CrateMetadata { } pub fn is_staged_api(&self) -> bool { - self.get_item_attrs(CRATE_DEF_INDEX) - .iter() - .any(|attr| attr.name() == "stable" || attr.name() == "unstable") + for attr in self.get_item_attrs(CRATE_DEF_INDEX) { + if attr.path == "stable" || attr.path == "unstable" { + return true; + } + } + false } pub fn is_allocator(&self) -> bool { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 0933fdfd357cd..8c45a66694533 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -241,12 +241,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). attr::first_attr_value_str_by_name(&item.attrs, "path"); - if let Some(attr) = - item.attrs.iter().find(|attr| attr.name() == "warn_directory_ownership") { + if item.attrs.iter().any(|attr| attr.check_name("warn_directory_ownership")) { let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let msg = "cannot declare a new module at this location"; self.session.add_lint(lint, item.id, item.span, msg.to_string()); - attr::mark_used(attr); } } ItemKind::Union(ref vdata, _) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0958748ed092f..c3e471650a3e1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3360,8 +3360,9 @@ impl<'a> Resolver<'a> { if self.proc_macro_enabled { return; } for attr in attrs { - let maybe_binding = self.builtin_macros.get(&attr.name()).cloned().or_else(|| { - let ident = Ident::with_empty_ctxt(attr.name()); + let name = unwrap_or!(attr.name(), continue); + let maybe_binding = self.builtin_macros.get(&name).cloned().or_else(|| { + let ident = Ident::with_empty_ctxt(name); self.resolve_lexical_macro_path_segment(ident, MacroNS, None).ok() }); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 7ad122d1c31d8..9e1dcd1bc35c4 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -30,6 +30,7 @@ use syntax::feature_gate::{self, emit_feature_err, GateIssue}; use syntax::fold::{self, Folder}; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; +use syntax::tokenstream::TokenStream; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; @@ -176,12 +177,14 @@ impl<'a> base::Resolver for Resolver<'a> { fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec) -> Option { for i in 0..attrs.len() { + let name = unwrap_or!(attrs[i].name(), continue); + if self.session.plugin_attributes.borrow().iter() - .any(|&(ref attr_nm, _)| attrs[i].name() == &**attr_nm) { + .any(|&(ref attr_nm, _)| name == &**attr_nm) { attr::mark_known(&attrs[i]); } - match self.builtin_macros.get(&attrs[i].name()).cloned() { + match self.builtin_macros.get(&name).cloned() { Some(binding) => match *binding.get_macro(self) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) @@ -194,9 +197,11 @@ impl<'a> base::Resolver for Resolver<'a> { // Check for legacy derives for i in 0..attrs.len() { - if attrs[i].name() == "derive" { + let name = unwrap_or!(attrs[i].name(), continue); + + if name == "derive" { let mut traits = match attrs[i].meta_item_list() { - Some(traits) if !traits.is_empty() => traits.to_owned(), + Some(traits) => traits, _ => continue, }; @@ -213,18 +218,11 @@ impl<'a> base::Resolver for Resolver<'a> { if traits.is_empty() { attrs.remove(i); } else { - attrs[i].value = ast::MetaItem { - name: attrs[i].name(), - span: attrs[i].span, - node: ast::MetaItemKind::List(traits), - }; + attrs[i].tokens = ast::MetaItemKind::List(traits).tokens(attrs[i].span); } return Some(ast::Attribute { - value: ast::MetaItem { - name: legacy_name, - span: span, - node: ast::MetaItemKind::Word, - }, + path: ast::Path::from_ident(span, Ident::with_empty_ctxt(legacy_name)), + tokens: TokenStream::empty(), id: attr::mk_attr_id(), style: ast::AttrStyle::Outer, is_sugared_doc: false, @@ -270,19 +268,20 @@ impl<'a> Resolver<'a> { } }; - let (attr_name, path) = { - let attr = attr.as_ref().unwrap(); - (attr.name(), ast::Path::from_ident(attr.span, Ident::with_empty_ctxt(attr.name()))) - }; - let mut determined = true; + let path = attr.as_ref().unwrap().path.clone(); + let mut determinacy = Determinacy::Determined; match self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force) { Ok(def) => return Ok(def), - Err(Determinacy::Undetermined) => determined = false, + Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, Err(Determinacy::Determined) if force => return Err(Determinacy::Determined), Err(Determinacy::Determined) => {} } + let attr_name = match path.segments.len() { + 1 => path.segments[0].identifier.name, + _ => return Err(determinacy), + }; for &(name, span) in traits { let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); match self.resolve_macro(scope, &path, MacroKind::Derive, force) { @@ -304,12 +303,12 @@ impl<'a> Resolver<'a> { } return Err(Determinacy::Undetermined); }, - Err(Determinacy::Undetermined) => determined = false, + Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, Err(Determinacy::Determined) => {} } } - Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined }) + Err(determinacy) } fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) diff --git a/src/librustc_save_analysis/external_data.rs b/src/librustc_save_analysis/external_data.rs index 41658dc5b1b48..f038c2dc298ad 100644 --- a/src/librustc_save_analysis/external_data.rs +++ b/src/librustc_save_analysis/external_data.rs @@ -14,7 +14,6 @@ use rustc::ty::TyCtxt; use syntax::ast::{self, NodeId}; use syntax::codemap::CodeMap; use syntax::print::pprust; -use syntax::symbol::Symbol; use syntax_pos::Span; use data::{self, Visibility, SigElement}; @@ -77,10 +76,9 @@ impl Lower for Vec { type Target = Vec; fn lower(self, tcx: TyCtxt) -> Vec { - let doc = Symbol::intern("doc"); self.into_iter() // Only retain real attributes. Doc comments are lowered separately. - .filter(|attr| attr.name() != doc) + .filter(|attr| attr.path != "doc") .map(|mut attr| { // Remove the surrounding '#[..]' or '#![..]' of the pretty printed // attribute. First normalize all inner attribute (#![..]) to outer diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 111c8370be2b1..90ee19198c939 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -54,7 +54,7 @@ use std::path::{Path, PathBuf}; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::parse::token; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ty_to_string, arg_to_string}; use syntax::codemap::MacroAttribute; @@ -829,11 +829,10 @@ impl<'a> Visitor<'a> for PathCollector { } fn docs_for_attrs(attrs: &[Attribute]) -> String { - let doc = Symbol::intern("doc"); let mut result = String::new(); for attr in attrs { - if attr.name() == doc { + if attr.check_name("doc") { if let Some(val) = attr.value_str() { if attr.is_sugared_doc { result.push_str(&strip_doc_comment_decoration(&val.as_str())); diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_trans/assert_module_sources.rs index 7a41f8341099b..8528482c7856c 100644 --- a/src/librustc_trans/assert_module_sources.rs +++ b/src/librustc_trans/assert_module_sources.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { } fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name { - for item in attr.meta_item_list().unwrap_or(&[]) { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(name) { if let Some(value) = item.value_str() { return value; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1294296840ebd..660fa647882aa 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -39,12 +39,11 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc::hir; +use std::{mem, slice, vec}; use std::path::PathBuf; use std::rc::Rc; -use std::slice; use std::sync::Arc; use std::u32; -use std::mem; use core::DocContext; use doctree; @@ -472,12 +471,12 @@ impl Clean for doctree::Module { pub struct ListAttributesIter<'a> { attrs: slice::Iter<'a, ast::Attribute>, - current_list: slice::Iter<'a, ast::NestedMetaItem>, + current_list: vec::IntoIter, name: &'a str } impl<'a> Iterator for ListAttributesIter<'a> { - type Item = &'a ast::NestedMetaItem; + type Item = ast::NestedMetaItem; fn next(&mut self) -> Option { if let Some(nested) = self.current_list.next() { @@ -485,9 +484,9 @@ impl<'a> Iterator for ListAttributesIter<'a> { } for attr in &mut self.attrs { - if let Some(ref list) = attr.meta_item_list() { + if let Some(list) = attr.meta_item_list() { if attr.check_name(self.name) { - self.current_list = list.iter(); + self.current_list = list.into_iter(); if let Some(nested) = self.current_list.next() { return Some(nested); } @@ -508,7 +507,7 @@ impl AttributesExt for [ast::Attribute] { fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> { ListAttributesIter { attrs: self.iter(), - current_list: [].iter(), + current_list: Vec::new().into_iter(), name: name } } @@ -519,7 +518,7 @@ pub trait NestedAttributesExt { fn has_word(self, &str) -> bool; } -impl<'a, I: IntoIterator> NestedAttributesExt for I { +impl> NestedAttributesExt for I { fn has_word(self, word: &str) -> bool { self.into_iter().any(|attr| attr.is_word() && attr.check_name(word)) } @@ -2596,9 +2595,9 @@ impl Clean> for doctree::Import { // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. let denied = self.vis != hir::Public || self.attrs.iter().any(|a| { - a.name() == "doc" && match a.meta_item_list() { - Some(l) => attr::list_contains_name(l, "no_inline") || - attr::list_contains_name(l, "hidden"), + a.name().unwrap() == "doc" && match a.meta_item_list() { + Some(l) => attr::list_contains_name(&l, "no_inline") || + attr::list_contains_name(&l, "hidden"), None => false, } }); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 44f71d8952985..130a4526bf705 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2620,11 +2620,11 @@ fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { let mut attrs = String::new(); for attr in &it.attrs.other_attrs { - let name = attr.name(); + let name = attr.name().unwrap(); if !ATTRIBUTE_WHITELIST.contains(&&name.as_str()[..]) { continue; } - if let Some(s) = render_attribute(attr.meta()) { + if let Some(s) = render_attribute(&attr.meta().unwrap()) { attrs.push_str(&format!("#[{}]\n", s)); } } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index c1ecc241b7b63..f6b7a07bdae01 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -137,13 +137,13 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions { attrs: Vec::new(), }; - let attrs = krate.attrs.iter() - .filter(|a| a.check_name("doc")) - .filter_map(|a| a.meta_item_list()) - .flat_map(|l| l) - .filter(|a| a.check_name("test")) - .filter_map(|a| a.meta_item_list()) - .flat_map(|l| l); + let test_attrs: Vec<_> = krate.attrs.iter() + .filter(|a| a.check_name("doc")) + .flat_map(|a| a.meta_item_list().unwrap_or_else(Vec::new)) + .filter(|a| a.check_name("test")) + .collect(); + let attrs = test_attrs.iter().flat_map(|a| a.meta_item_list().unwrap_or(&[])); + for attr in attrs { if attr.check_name("no_crate_inject") { opts.no_crate_inject = true; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b80de3cc50546..4a909f8e2a972 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -376,7 +376,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if item.vis == hir::Public && self.inside_public_path { let please_inline = item.attrs.iter().any(|item| { match item.meta_item_list() { - Some(list) if item.check_name("doc") => { + Some(ref list) if item.check_name("doc") => { list.iter().any(|i| i.check_name("inline")) } _ => false, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 981667337d59a..5deb91ef53aeb 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -116,6 +116,12 @@ pub struct Path { pub segments: Vec, } +impl<'a> PartialEq<&'a str> for Path { + fn eq(&self, string: &&'a str) -> bool { + self.segments.len() == 1 && self.segments[0].identifier.name == *string + } +} + impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "path({})", pprust::path_to_string(self)) @@ -1679,7 +1685,8 @@ pub struct AttrId(pub usize); pub struct Attribute { pub id: AttrId, pub style: AttrStyle, - pub value: MetaItem, + pub path: Path, + pub tokens: TokenStream, pub is_sugared_doc: bool, pub span: Span, } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 096657a6e7ac8..68f1f690a62f0 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -15,20 +15,24 @@ pub use self::ReprAttr::*; pub use self::IntType::*; use ast; -use ast::{AttrId, Attribute, Name}; +use ast::{AttrId, Attribute, Name, Ident}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; -use ast::{Lit, Expr, Item, Local, Stmt, StmtKind}; +use ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind}; use codemap::{Spanned, spanned, dummy_spanned, mk_sp}; use syntax_pos::{Span, BytePos, DUMMY_SP}; use errors::Handler; use feature_gate::{Features, GatedCfg}; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use parse::ParseSess; +use parse::parser::Parser; +use parse::{self, ParseSess, PResult}; +use parse::token::{self, Token}; use ptr::P; use symbol::Symbol; +use tokenstream::{TokenStream, TokenTree, Delimited}; use util::ThinVec; use std::cell::{RefCell, Cell}; +use std::iter; thread_local! { static USED_ATTRS: RefCell> = RefCell::new(Vec::new()); @@ -185,26 +189,38 @@ impl NestedMetaItem { impl Attribute { pub fn check_name(&self, name: &str) -> bool { - let matches = self.name() == name; + let matches = self.path == name; if matches { mark_used(self); } matches } - pub fn name(&self) -> Name { self.meta().name() } + pub fn name(&self) -> Option { + match self.path.segments.len() { + 1 => Some(self.path.segments[0].identifier.name), + _ => None, + } + } pub fn value_str(&self) -> Option { - self.meta().value_str() + self.meta().and_then(|meta| meta.value_str()) } - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { - self.meta().meta_item_list() + pub fn meta_item_list(&self) -> Option> { + match self.meta() { + Some(MetaItem { node: MetaItemKind::List(list), .. }) => Some(list), + _ => None + } } - pub fn is_word(&self) -> bool { self.meta().is_word() } + pub fn is_word(&self) -> bool { + self.path.segments.len() == 1 && self.tokens.is_empty() + } - pub fn span(&self) -> Span { self.meta().span } + pub fn span(&self) -> Span { + self.span + } pub fn is_meta_item_list(&self) -> bool { self.meta_item_list().is_some() @@ -225,7 +241,7 @@ impl MetaItem { match self.node { MetaItemKind::NameValue(ref v) => { match v.node { - ast::LitKind::Str(ref s, _) => Some((*s).clone()), + LitKind::Str(ref s, _) => Some((*s).clone()), _ => None, } }, @@ -264,8 +280,35 @@ impl MetaItem { impl Attribute { /// Extract the MetaItem from inside this Attribute. - pub fn meta(&self) -> &MetaItem { - &self.value + pub fn meta(&self) -> Option { + let mut tokens = self.tokens.trees().peekable(); + Some(MetaItem { + name: match self.path.segments.len() { + 1 => self.path.segments[0].identifier.name, + _ => return None, + }, + node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) { + if tokens.peek().is_some() { + return None; + } + node + } else { + return None; + }, + span: self.span, + }) + } + + pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { + if self.path.segments.len() > 1 { + sess.span_diagnostic.span_err(self.path.span, "expected ident, found path"); + } + + Ok(MetaItem { + name: self.path.segments.last().unwrap().identifier.name, + node: Parser::new(sess, self.tokens.clone(), None, false).parse_meta_item_kind()?, + span: self.span, + }) } /// Convert self to a normal #[doc="foo"] comment, if it is a @@ -293,7 +336,7 @@ impl Attribute { /* Constructors */ pub fn mk_name_value_item_str(name: Name, value: Symbol) -> MetaItem { - let value_lit = dummy_spanned(ast::LitKind::Str(value, ast::StrStyle::Cooked)); + let value_lit = dummy_spanned(LitKind::Str(value, ast::StrStyle::Cooked)); mk_spanned_name_value_item(DUMMY_SP, name, value_lit) } @@ -348,7 +391,8 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id: id, style: ast::AttrStyle::Inner, - value: item, + path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)), + tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, } @@ -365,7 +409,8 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id: id, style: ast::AttrStyle::Outer, - value: item, + path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)), + tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, } @@ -374,32 +419,25 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, lo: BytePos, hi: BytePos) -> Attribute { let style = doc_comment_style(&text.as_str()); - let lit = spanned(lo, hi, ast::LitKind::Str(text, ast::StrStyle::Cooked)); + let lit = spanned(lo, hi, LitKind::Str(text, ast::StrStyle::Cooked)); Attribute { id: id, style: style, - value: MetaItem { - span: mk_sp(lo, hi), - name: Symbol::intern("doc"), - node: MetaItemKind::NameValue(lit), - }, + path: ast::Path::from_ident(mk_sp(lo, hi), ast::Ident::from_str("doc")), + tokens: MetaItemKind::NameValue(lit).tokens(mk_sp(lo, hi)), is_sugared_doc: true, span: mk_sp(lo, hi), } } pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool { - debug!("attr::list_contains_name (name={})", name); items.iter().any(|item| { - debug!(" testing: {:?}", item.name()); item.check_name(name) }) } pub fn contains_name(attrs: &[Attribute], name: &str) -> bool { - debug!("attr::contains_name (name={})", name); attrs.iter().any(|item| { - debug!(" testing: {}", item.name()); item.check_name(name) }) } @@ -452,8 +490,14 @@ pub enum InlineAttr { /// Determine what `#[inline]` attribute is present in `attrs`, if any. pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr { attrs.iter().fold(InlineAttr::None, |ia, attr| { - match attr.value.node { - _ if attr.value.name != "inline" => ia, + if attr.path != "inline" { + return ia; + } + let meta = match attr.meta() { + Some(meta) => meta.node, + None => return ia, + }; + match meta { MetaItemKind::Word => { mark_used(attr); InlineAttr::Hint @@ -574,14 +618,15 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut rustc_depr: Option = None; 'outer: for attr in attrs_iter { - let tag = attr.name(); - if tag != "rustc_deprecated" && tag != "unstable" && tag != "stable" { + if attr.path != "rustc_deprecated" && attr.path != "unstable" && attr.path != "stable" { continue // not a stability level } mark_used(attr); - if let Some(metas) = attr.meta_item_list() { + let meta = attr.meta(); + if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta { + let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); @@ -596,7 +641,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } }; - match &*tag.as_str() { + match &*meta.name.as_str() { "rustc_deprecated" => { if rustc_depr.is_some() { span_err!(diagnostic, item_sp, E0540, @@ -772,7 +817,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, let mut depr: Option = None; 'outer: for attr in attrs_iter { - if attr.name() != "deprecated" { + if attr.path != "deprecated" { continue } @@ -847,8 +892,8 @@ pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute], /// structure layout, and `packed` to remove padding. pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec { let mut acc = Vec::new(); - match attr.value.node { - ast::MetaItemKind::List(ref items) if attr.value.name == "repr" => { + if attr.path == "repr" { + if let Some(items) = attr.meta_item_list() { mark_used(attr); for item in items { if !item.is_meta_item() { @@ -883,8 +928,6 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec } } } - // Not a "repr" hint: ignore. - _ => { } } acc } @@ -931,6 +974,195 @@ impl IntType { } } +impl MetaItem { + fn tokens(&self) -> TokenStream { + let ident = TokenTree::Token(self.span, Token::Ident(Ident::with_empty_ctxt(self.name))); + TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)]) + } + + fn from_tokens(tokens: &mut iter::Peekable) -> Option + where I: Iterator, + { + let (mut span, name) = match tokens.next() { + Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name), + _ => return None, + }; + let node = match MetaItemKind::from_tokens(tokens) { + Some(node) => node, + _ => return None, + }; + if let Some(last_span) = node.last_span() { + span.hi = last_span.hi; + } + Some(MetaItem { name: name, span: span, node: node }) + } +} + +impl MetaItemKind { + fn last_span(&self) -> Option { + match *self { + MetaItemKind::Word => None, + MetaItemKind::List(ref list) => list.last().map(NestedMetaItem::span), + MetaItemKind::NameValue(ref lit) => Some(lit.span), + } + } + + pub fn tokens(&self, span: Span) -> TokenStream { + match *self { + MetaItemKind::Word => TokenStream::empty(), + MetaItemKind::NameValue(ref lit) => { + TokenStream::concat(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()]) + } + MetaItemKind::List(ref list) => { + let mut tokens = Vec::new(); + for (i, item) in list.iter().enumerate() { + if i > 0 { + tokens.push(TokenTree::Token(span, Token::Comma).into()); + } + tokens.push(item.node.tokens()); + } + TokenTree::Delimited(span, Delimited { + delim: token::Paren, + tts: TokenStream::concat(tokens).into(), + }).into() + } + } + } + + fn from_tokens(tokens: &mut iter::Peekable) -> Option + where I: Iterator, + { + let delimited = match tokens.peek().cloned() { + Some(TokenTree::Token(_, token::Eq)) => { + tokens.next(); + return if let Some(TokenTree::Token(span, token)) = tokens.next() { + LitKind::from_token(token) + .map(|lit| MetaItemKind::NameValue(Spanned { node: lit, span: span })) + } else { + None + }; + } + Some(TokenTree::Delimited(_, ref delimited)) if delimited.delim == token::Paren => { + tokens.next(); + delimited.stream() + } + _ => return Some(MetaItemKind::Word), + }; + + let mut tokens = delimited.into_trees().peekable(); + let mut result = Vec::new(); + while let Some(..) = tokens.peek() { + match NestedMetaItemKind::from_tokens(&mut tokens) { + Some(item) => result.push(Spanned { span: item.span(), node: item }), + None => return None, + } + match tokens.next() { + None | Some(TokenTree::Token(_, Token::Comma)) => {} + _ => return None, + } + } + Some(MetaItemKind::List(result)) + } +} + +impl NestedMetaItemKind { + fn span(&self) -> Span { + match *self { + NestedMetaItemKind::MetaItem(ref item) => item.span, + NestedMetaItemKind::Literal(ref lit) => lit.span, + } + } + + fn tokens(&self) -> TokenStream { + match *self { + NestedMetaItemKind::MetaItem(ref item) => item.tokens(), + NestedMetaItemKind::Literal(ref lit) => lit.tokens(), + } + } + + fn from_tokens(tokens: &mut iter::Peekable) -> Option + where I: Iterator, + { + if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { + if let Some(node) = LitKind::from_token(token) { + tokens.next(); + return Some(NestedMetaItemKind::Literal(Spanned { node: node, span: span })); + } + } + + MetaItem::from_tokens(tokens).map(NestedMetaItemKind::MetaItem) + } +} + +impl Lit { + fn tokens(&self) -> TokenStream { + TokenTree::Token(self.span, self.node.token()).into() + } +} + +impl LitKind { + fn token(&self) -> Token { + use std::ascii; + + match *self { + LitKind::Str(string, ast::StrStyle::Cooked) => { + let mut escaped = String::new(); + for ch in string.as_str().chars() { + escaped.extend(ch.escape_unicode()); + } + Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None) + } + LitKind::Str(string, ast::StrStyle::Raw(n)) => { + Token::Literal(token::Lit::StrRaw(string, n), None) + } + LitKind::ByteStr(ref bytes) => { + let string = bytes.iter().cloned().flat_map(ascii::escape_default) + .map(Into::::into).collect::(); + Token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None) + } + LitKind::Byte(byte) => { + let string: String = ascii::escape_default(byte).map(Into::::into).collect(); + Token::Literal(token::Lit::Byte(Symbol::intern(&string)), None) + } + LitKind::Char(ch) => { + let string: String = ch.escape_default().map(Into::::into).collect(); + Token::Literal(token::Lit::Char(Symbol::intern(&string)), None) + } + LitKind::Int(n, ty) => { + let suffix = match ty { + ast::LitIntType::Unsigned(ty) => Some(Symbol::intern(ty.ty_to_string())), + ast::LitIntType::Signed(ty) => Some(Symbol::intern(ty.ty_to_string())), + ast::LitIntType::Unsuffixed => None, + }; + Token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), suffix) + } + LitKind::Float(symbol, ty) => { + Token::Literal(token::Lit::Float(symbol), Some(Symbol::intern(ty.ty_to_string()))) + } + LitKind::FloatUnsuffixed(symbol) => Token::Literal(token::Lit::Float(symbol), None), + LitKind::Bool(value) => Token::Ident(Ident::with_empty_ctxt(Symbol::intern(match value { + true => "true", + false => "false", + }))), + } + } + + fn from_token(token: Token) -> Option { + match token { + Token::Ident(ident) if ident.name == "true" => Some(LitKind::Bool(true)), + Token::Ident(ident) if ident.name == "false" => Some(LitKind::Bool(false)), + Token::Literal(lit, suf) => { + let (suffix_illegal, result) = parse::lit_token(lit, suf, None); + if suffix_illegal && suf.is_some() { + return None; + } + result + } + _ => None, + } + } +} + pub trait HasAttrs: Sized { fn attrs(&self) -> &[ast::Attribute]; fn map_attrs) -> Vec>(self, f: F) -> Self; diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index ea12a31770fc0..2591a5766693f 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -109,7 +109,8 @@ impl<'a> StripUnconfigured<'a> { self.process_cfg_attr(ast::Attribute { id: attr::mk_attr_id(), style: attr.style, - value: mi.clone(), + path: ast::Path::from_ident(mi.span, ast::Ident::with_empty_ctxt(mi.name)), + tokens: mi.node.tokens(mi.span), is_sugared_doc: false, span: mi.span, }) @@ -132,8 +133,9 @@ impl<'a> StripUnconfigured<'a> { return false; } - let mis = match attr.value.node { - ast::MetaItemKind::List(ref mis) if is_cfg(&attr) => mis, + let mis = attr.meta_item_list(); + let mis = match mis { + Some(ref mis) if is_cfg(&attr) => mis, _ => return true }; diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 77cc7bab0315a..5b253635f257e 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -18,7 +18,7 @@ use syntax_pos::Span; pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec<(Symbol, Span)> { let mut result = Vec::new(); attrs.retain(|attr| { - if attr.name() != "derive" { + if attr.path != "derive" { return true; } @@ -27,7 +27,7 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec return false; } - let traits = attr.meta_item_list().unwrap_or(&[]).to_owned(); + let traits = attr.meta_item_list().unwrap_or_else(Vec::new); if traits.is_empty() { cx.span_warn(attr.span, "empty trait list in `derive`"); return false; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 10168f010a077..c1095d3445682 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -272,7 +272,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.collect_invocations(expansion, &[]) } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind { let item = item - .map_attrs(|mut attrs| { attrs.retain(|a| a.name() != "derive"); attrs }); + .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs }); let item_with_markers = add_derived_markers(&mut self.cx, &traits, item.clone()); let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new); @@ -380,7 +380,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; attr::mark_used(&attr); - let name = attr.name(); + let name = attr.path.segments[0].identifier.name; self.cx.bt_push(ExpnInfo { call_site: attr.span, callee: NameAndSpan { @@ -392,25 +392,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match *ext { MultiModifier(ref mac) => { - let item = mac.expand(self.cx, attr.span, &attr.value, item); + let meta = panictry!(attr.parse_meta(&self.cx.parse_sess)); + let item = mac.expand(self.cx, attr.span, &meta, item); kind.expect_from_annotatables(item) } MultiDecorator(ref mac) => { let mut items = Vec::new(); - mac.expand(self.cx, attr.span, &attr.value, &item, - &mut |item| items.push(item)); + let meta = panictry!(attr.parse_meta(&self.cx.parse_sess)); + mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item)); items.push(item); kind.expect_from_annotatables(items) } SyntaxExtension::AttrProcMacro(ref mac) => { - let attr_toks = stream_for_attr_args(&attr, &self.cx.parse_sess); let item_toks = stream_for_item(&item, &self.cx.parse_sess); let span = Span { expn_id: self.cx.codemap().record_expansion(ExpnInfo { call_site: attr.span, callee: NameAndSpan { - format: MacroAttribute(name), + format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))), span: None, allow_internal_unstable: false, }, @@ -418,7 +418,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ..attr.span }; - let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks); + let tok_result = mac.expand(self.cx, attr.span, attr.tokens.clone(), item_toks); self.parse_expansion(tok_result, kind, name, span) } SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { @@ -784,32 +784,6 @@ fn stream_for_item(item: &Annotatable, parse_sess: &ParseSess) -> TokenStream { string_to_stream(text, parse_sess) } -fn stream_for_attr_args(attr: &ast::Attribute, parse_sess: &ParseSess) -> TokenStream { - use ast::MetaItemKind::*; - use print::pp::Breaks; - use print::pprust::PrintState; - - let token_string = match attr.value.node { - // For `#[foo]`, an empty token - Word => return TokenStream::empty(), - // For `#[foo(bar, baz)]`, returns `(bar, baz)` - List(ref items) => pprust::to_string(|s| { - s.popen()?; - s.commasep(Breaks::Consistent, - &items[..], - |s, i| s.print_meta_list_item(&i))?; - s.pclose() - }), - // For `#[foo = "bar"]`, returns `= "bar"` - NameValue(ref lit) => pprust::to_string(|s| { - s.word_space("=")?; - s.print_literal(lit) - }), - }; - - string_to_stream(token_string, parse_sess) -} - fn string_to_stream(text: String, parse_sess: &ParseSess) -> TokenStream { let filename = String::from(""); filemap_to_stream(parse_sess, parse_sess.codemap().new_filemap(filename, None, text)) diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 69ff726e719a9..10b7249743b8c 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -220,16 +220,24 @@ pub mod rt { } impl ToTokens for ast::Attribute { - fn to_tokens(&self, cx: &ExtCtxt) -> Vec { + fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let mut r = vec![]; // FIXME: The spans could be better r.push(TokenTree::Token(self.span, token::Pound)); if self.style == ast::AttrStyle::Inner { r.push(TokenTree::Token(self.span, token::Not)); } + let mut inner = Vec::new(); + for (i, segment) in self.path.segments.iter().enumerate() { + if i > 0 { + inner.push(TokenTree::Token(self.span, token::Colon).into()); + } + inner.push(TokenTree::Token(self.span, token::Ident(segment.identifier)).into()); + } + inner.push(self.tokens.clone()); + r.push(TokenTree::Delimited(self.span, tokenstream::Delimited { - delim: token::Bracket, - tts: self.value.to_tokens(cx).into_iter().collect::().into(), + delim: token::Bracket, tts: TokenStream::concat(inner).into() })); r } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e7bf16eae9ee6..2c3ad98a6be63 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -859,35 +859,34 @@ macro_rules! gate_feature { impl<'a> Context<'a> { fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) { debug!("check_attribute(attr = {:?})", attr); - let name = &*attr.name().as_str(); + let name = unwrap_or!(attr.name(), return); + for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES { - if n == name { + if name == n { if let &Gated(_, ref name, ref desc, ref has_feature) = gateage { gate_feature_fn!(self, has_feature, attr.span, name, desc); } - debug!("check_attribute: {:?} is builtin, {:?}, {:?}", name, ty, gateage); + debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); return; } } for &(ref n, ref ty) in self.plugin_attributes { - if n == name { + if attr.path == &**n { // Plugins can't gate attributes, so we don't check for it // unlike the code above; we only use this loop to // short-circuit to avoid the checks below - debug!("check_attribute: {:?} is registered by a plugin, {:?}", name, ty); + debug!("check_attribute: {:?} is registered by a plugin, {:?}", attr.path, ty); return; } } - if name.starts_with("rustc_") { + if name.as_str().starts_with("rustc_") { gate_feature!(self, rustc_attrs, attr.span, "unless otherwise specified, attributes \ with the prefix `rustc_` \ are reserved for internal compiler diagnostics"); - } else if name.starts_with("derive_") { + } else if name.as_str().starts_with("derive_") { gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE); - } else if attr::is_known(attr) { - debug!("check_attribute: {:?} is known", name); - } else { + } else if !attr::is_known(attr) { // Only run the custom attribute lint during regular // feature gate checking. Macro gating runs // before the plugin attributes are registered @@ -898,7 +897,7 @@ impl<'a> Context<'a> { unknown to the compiler and \ may have meaning \ added to it in the future", - name)); + attr.path)); } } } @@ -1097,7 +1096,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.context.check_attribute(attr, false); } - if contains_novel_literal(&attr.value) { + let meta = panictry!(attr.parse_meta(&self.context.parse_sess)); + if contains_novel_literal(&meta) { gate_feature_post!(&self, attr_literals, attr.span, "non-string literals in attributes, or string \ literals in top-level positions, are experimental"); @@ -1160,8 +1160,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { `#[repr(simd)]` instead"); } for attr in &i.attrs { - if attr.name() == "repr" { - for item in attr.meta_item_list().unwrap_or(&[]) { + if attr.path == "repr" { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name("simd") { gate_feature_post!(&self, repr_simd, i.span, "SIMD types are experimental \ diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index fb4eb19be2b15..903dac1f379ca 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -488,7 +488,8 @@ pub fn noop_fold_attribute(attr: Attribute, fld: &mut T) -> Option(nt: token::Nonterminal, fld: &mut T) token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), token::NtIdent(id) => token::NtIdent(Spanned::{node: fld.fold_ident(id.node), ..id}), - token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)), + token::NtMeta(meta) => token::NtMeta(fld.fold_meta_item(meta)), token::NtPath(path) => token::NtPath(fld.fold_path(path)), token::NtTT(tt) => token::NtTT(fld.fold_tt(tt)), token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)), @@ -1369,7 +1370,7 @@ mod tests { matches_codepattern, "matches_codepattern", pprust::to_string(|s| fake_print_crate(s, &folded_crate)), - "#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()); + "#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string()); } // even inside macro defs.... diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 39a9aff48bf27..4c9a5d512af02 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -65,6 +65,16 @@ macro_rules! panictry { }) } +#[macro_export] +macro_rules! unwrap_or { + ($opt:expr, $default:expr) => { + match $opt { + Some(x) => x, + None => $default, + } + } +} + #[macro_use] pub mod diagnostics { #[macro_use] diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index ded676da3c676..272cff7ad34b2 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -143,7 +143,8 @@ impl<'a> Parser<'a> { Ok(ast::Attribute { id: attr::mk_attr_id(), style: style, - value: value, + path: ast::Path::from_ident(value.span, ast::Ident::with_empty_ctxt(value.name)), + tokens: value.node.tokens(value.span), is_sugared_doc: false, span: span, }) @@ -221,15 +222,20 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let ident = self.parse_ident()?; - let node = if self.eat(&token::Eq) { + let node = self.parse_meta_item_kind()?; + let hi = self.prev_span.hi; + Ok(ast::MetaItem { name: ident.name, node: node, span: mk_sp(lo, hi) }) + } + + pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> { + Ok(if self.eat(&token::Eq) { ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?) } else if self.token == token::OpenDelim(token::Paren) { ast::MetaItemKind::List(self.parse_meta_seq()?) } else { + self.eat(&token::OpenDelim(token::Paren)); ast::MetaItemKind::Word - }; - let hi = self.prev_span.hi; - Ok(ast::MetaItem { name: ident.name, node: node, span: mk_sp(lo, hi) }) + }) } /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index c00d2952b3b42..2bdd3938d6bd5 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -374,38 +374,80 @@ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s[1..].chars().all(|c| '0' <= c && c <= '9') } -fn filtered_float_lit(data: Symbol, suffix: Option, sd: &Handler, sp: Span) - -> ast::LitKind { +macro_rules! err { + ($opt_diag:expr, |$span:ident, $diag:ident| $($body:tt)*) => { + match $opt_diag { + Some(($span, $diag)) => { $($body)* } + None => return None, + } + } +} + +pub fn lit_token(lit: token::Lit, suf: Option, diag: Option<(Span, &Handler)>) + -> (bool /* suffix illegal? */, Option) { + use ast::LitKind; + + match lit { + token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))), + token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str()).0))), + + // There are some valid suffixes for integer and float literals, + // so all the handling is done internally. + token::Integer(s) => (false, integer_lit(&s.as_str(), suf, diag)), + token::Float(s) => (false, float_lit(&s.as_str(), suf, diag)), + + token::Str_(s) => { + let s = Symbol::intern(&str_lit(&s.as_str())); + (true, Some(LitKind::Str(s, ast::StrStyle::Cooked))) + } + token::StrRaw(s, n) => { + let s = Symbol::intern(&raw_str_lit(&s.as_str())); + (true, Some(LitKind::Str(s, ast::StrStyle::Raw(n)))) + } + token::ByteStr(i) => { + (true, Some(LitKind::ByteStr(byte_str_lit(&i.as_str())))) + } + token::ByteStrRaw(i, _) => { + (true, Some(LitKind::ByteStr(Rc::new(i.to_string().into_bytes())))) + } + } +} + +fn filtered_float_lit(data: Symbol, suffix: Option, diag: Option<(Span, &Handler)>) + -> Option { debug!("filtered_float_lit: {}, {:?}", data, suffix); let suffix = match suffix { Some(suffix) => suffix, - None => return ast::LitKind::FloatUnsuffixed(data), + None => return Some(ast::LitKind::FloatUnsuffixed(data)), }; - match &*suffix.as_str() { + Some(match &*suffix.as_str() { "f32" => ast::LitKind::Float(data, ast::FloatTy::F32), "f64" => ast::LitKind::Float(data, ast::FloatTy::F64), suf => { - if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { - // if it looks like a width, lets try to be helpful. - sd.struct_span_err(sp, &format!("invalid width `{}` for float literal", &suf[1..])) - .help("valid widths are 32 and 64") - .emit(); - } else { - sd.struct_span_err(sp, &format!("invalid suffix `{}` for float literal", suf)) - .help("valid suffixes are `f32` and `f64`") - .emit(); - } + err!(diag, |span, diag| { + if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { + // if it looks like a width, lets try to be helpful. + let msg = format!("invalid width `{}` for float literal", &suf[1..]); + diag.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit() + } else { + let msg = format!("invalid suffix `{}` for float literal", suf); + diag.struct_span_err(span, &msg) + .help("valid suffixes are `f32` and `f64`") + .emit(); + } + }); ast::LitKind::FloatUnsuffixed(data) } - } + }) } -pub fn float_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> ast::LitKind { +pub fn float_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) + -> Option { debug!("float_lit: {:?}, {:?}", s, suffix); // FIXME #2252: bounds checking float literals is deferred until trans let s = s.chars().filter(|&c| c != '_').collect::(); - filtered_float_lit(Symbol::intern(&s), suffix, sd, sp) + filtered_float_lit(Symbol::intern(&s), suffix, diag) } /// Parse a string representing a byte literal into its final form. Similar to `char_lit` @@ -500,7 +542,8 @@ pub fn byte_str_lit(lit: &str) -> Rc> { Rc::new(res) } -pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> ast::LitKind { +pub fn integer_lit(s: &str, suffix: Option, diag: Option<(Span, &Handler)>) + -> Option { // s can only be ascii, byte indexing is fine let s2 = s.chars().filter(|&c| c != '_').collect::(); @@ -524,13 +567,16 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a // 1f64 and 2f32 etc. are valid float literals. if let Some(suf) = suffix { if looks_like_width_suffix(&['f'], &suf.as_str()) { - match base { - 16 => sd.span_err(sp, "hexadecimal float literal is not supported"), - 8 => sd.span_err(sp, "octal float literal is not supported"), - 2 => sd.span_err(sp, "binary float literal is not supported"), - _ => () + let err = match base { + 16 => Some("hexadecimal float literal is not supported"), + 8 => Some("octal float literal is not supported"), + 2 => Some("binary float literal is not supported"), + _ => None, + }; + if let Some(err) = err { + err!(diag, |span, diag| diag.span_err(span, err)); } - return filtered_float_lit(Symbol::intern(&s), Some(suf), sd, sp) + return filtered_float_lit(Symbol::intern(&s), Some(suf), diag) } } @@ -539,7 +585,9 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a } if let Some(suf) = suffix { - if suf.as_str().is_empty() { sd.span_bug(sp, "found empty literal suffix in Some")} + if suf.as_str().is_empty() { + err!(diag, |span, diag| diag.span_bug(span, "found empty literal suffix in Some")); + } ty = match &*suf.as_str() { "isize" => ast::LitIntType::Signed(ast::IntTy::Is), "i8" => ast::LitIntType::Signed(ast::IntTy::I8), @@ -556,17 +604,20 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a suf => { // i and u look like widths, so lets // give an error message along those lines - if looks_like_width_suffix(&['i', 'u'], suf) { - sd.struct_span_err(sp, &format!("invalid width `{}` for integer literal", - &suf[1..])) - .help("valid widths are 8, 16, 32, 64 and 128") - .emit(); - } else { - sd.struct_span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf)) - .help("the suffix must be one of the integral types \ - (`u32`, `isize`, etc)") - .emit(); - } + err!(diag, |span, diag| { + if looks_like_width_suffix(&['i', 'u'], suf) { + let msg = format!("invalid width `{}` for integer literal", &suf[1..]); + diag.struct_span_err(span, &msg) + .help("valid widths are 8, 16, 32, 64 and 128") + .emit(); + } else { + let msg = format!("invalid suffix `{}` for numeric literal", suf); + diag.struct_span_err(span, &msg) + .help("the suffix must be one of the integral types \ + (`u32`, `isize`, etc)") + .emit(); + } + }); ty } @@ -576,7 +627,7 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); - match u128::from_str_radix(s, base) { + Some(match u128::from_str_radix(s, base) { Ok(r) => ast::LitKind::Int(r, ty), Err(_) => { // small bases are lexed as if they were base 10, e.g, the string @@ -588,11 +639,11 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); if !already_errored { - sd.span_err(sp, "int literal is too large"); + err!(diag, |span, diag| diag.span_err(span, "int literal is too large")); } ast::LitKind::Int(0, ty) } - } + }) } #[cfg(test)] @@ -957,7 +1008,7 @@ mod tests { let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name.clone(), source, &sess) .unwrap().unwrap(); - let docs = item.attrs.iter().filter(|a| a.name() == "doc") + let docs = item.attrs.iter().filter(|a| a.path == "doc") .map(|a| a.value_str().unwrap().to_string()).collect::>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; assert_eq!(&docs[..], b); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 9872afd27b7bc..ed512b899877d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -60,7 +60,6 @@ use util::ThinVec; use std::collections::HashSet; use std::{cmp, mem, slice}; use std::path::{Path, PathBuf}; -use std::rc::Rc; bitflags! { flags Restrictions: u8 { @@ -1643,44 +1642,15 @@ impl<'a> Parser<'a> { _ => { return self.unexpected_last(&self.token); } }, token::Literal(lit, suf) => { - let (suffix_illegal, out) = match lit { - token::Byte(i) => (true, LitKind::Byte(parse::byte_lit(&i.as_str()).0)), - token::Char(i) => (true, LitKind::Char(parse::char_lit(&i.as_str()).0)), - - // there are some valid suffixes for integer and - // float literals, so all the handling is done - // internally. - token::Integer(s) => { - let diag = &self.sess.span_diagnostic; - (false, parse::integer_lit(&s.as_str(), suf, diag, self.span)) - } - token::Float(s) => { - let diag = &self.sess.span_diagnostic; - (false, parse::float_lit(&s.as_str(), suf, diag, self.span)) - } - - token::Str_(s) => { - let s = Symbol::intern(&parse::str_lit(&s.as_str())); - (true, LitKind::Str(s, ast::StrStyle::Cooked)) - } - token::StrRaw(s, n) => { - let s = Symbol::intern(&parse::raw_str_lit(&s.as_str())); - (true, LitKind::Str(s, ast::StrStyle::Raw(n))) - } - token::ByteStr(i) => { - (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str()))) - } - token::ByteStrRaw(i, _) => { - (true, LitKind::ByteStr(Rc::new(i.to_string().into_bytes()))) - } - }; + let diag = Some((self.span, &self.sess.span_diagnostic)); + let (suffix_illegal, result) = parse::lit_token(lit, suf, diag); if suffix_illegal { let sp = self.span; self.expect_no_suffix(sp, &format!("{} literal", lit.short_name()), suf) } - out + result.unwrap() } _ => { return self.unexpected_last(&self.token); } }; @@ -5135,11 +5105,9 @@ impl<'a> Parser<'a> { let attr = ast::Attribute { id: attr::mk_attr_id(), style: ast::AttrStyle::Outer, - value: ast::MetaItem { - name: Symbol::intern("warn_directory_ownership"), - node: ast::MetaItemKind::Word, - span: syntax_pos::DUMMY_SP, - }, + path: ast::Path::from_ident(syntax_pos::DUMMY_SP, + Ident::from_str("warn_directory_ownership")), + tokens: TokenStream::empty(), is_sugared_doc: false, span: syntax_pos::DUMMY_SP, }; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 5b65aac92b81c..3837700457290 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -17,7 +17,7 @@ pub use self::Token::*; use ast::{self}; use ptr::P; use symbol::keywords; -use tokenstream; +use tokenstream::TokenTree; use std::fmt; use std::rc::Rc; @@ -348,7 +348,7 @@ pub enum Nonterminal { /// Stuff inside brackets for attributes NtMeta(ast::MetaItem), NtPath(ast::Path), - NtTT(tokenstream::TokenTree), + NtTT(TokenTree), // These are not exposed to macros, but are used by quasiquote. NtArm(ast::Arm), NtImplItem(ast::ImplItem), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3efadbd00d1e0..d8af95d8d3062 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -28,7 +28,7 @@ use ptr::P; use std_inject; use symbol::{Symbol, keywords}; use syntax_pos::DUMMY_SP; -use tokenstream::{self, TokenTree}; +use tokenstream::{self, TokenStream, TokenTree}; use std::ascii; use std::io::{self, Write, Read}; @@ -329,6 +329,10 @@ pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String { to_string(|s| s.print_tts(tts.iter().cloned().collect())) } +pub fn tokens_to_string(tokens: TokenStream) -> String { + to_string(|s| s.print_tts(tokens)) +} + pub fn stmt_to_string(stmt: &ast::Stmt) -> String { to_string(|s| s.print_stmt(stmt)) } @@ -750,7 +754,21 @@ pub trait PrintState<'a> { ast::AttrStyle::Inner => word(self.writer(), "#![")?, ast::AttrStyle::Outer => word(self.writer(), "#[")?, } - self.print_meta_item(&attr.meta())?; + if let Some(mi) = attr.meta() { + self.print_meta_item(&mi)? + } else { + for (i, segment) in attr.path.segments.iter().enumerate() { + if i > 0 { + word(self.writer(), "::")? + } + if segment.identifier.name != keywords::CrateRoot.name() && + segment.identifier.name != "$crate" { + word(self.writer(), &segment.identifier.name.as_str())?; + } + } + space(self.writer())?; + self.print_tts(attr.tokens.clone())?; + } word(self.writer(), "]") } } @@ -789,6 +807,45 @@ pub trait PrintState<'a> { self.end() } + /// This doesn't deserve to be called "pretty" printing, but it should be + /// meaning-preserving. A quick hack that might help would be to look at the + /// spans embedded in the TTs to decide where to put spaces and newlines. + /// But it'd be better to parse these according to the grammar of the + /// appropriate macro, transcribe back into the grammar we just parsed from, + /// and then pretty-print the resulting AST nodes (so, e.g., we print + /// expression arguments as expressions). It can be done! I think. + fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> { + match tt { + TokenTree::Token(_, ref tk) => { + word(self.writer(), &token_to_string(tk))?; + match *tk { + parse::token::DocComment(..) => { + hardbreak(self.writer()) + } + _ => Ok(()) + } + } + TokenTree::Delimited(_, ref delimed) => { + word(self.writer(), &token_to_string(&delimed.open_token()))?; + space(self.writer())?; + self.print_tts(delimed.stream())?; + space(self.writer())?; + word(self.writer(), &token_to_string(&delimed.close_token())) + }, + } + } + + fn print_tts(&mut self, tts: tokenstream::TokenStream) -> io::Result<()> { + self.ibox(0)?; + for (i, tt) in tts.into_trees().enumerate() { + if i != 0 { + space(self.writer())?; + } + self.print_tt(tt)?; + } + self.end() + } + fn space_if_not_bol(&mut self) -> io::Result<()> { if !self.is_bol() { space(self.writer())?; } Ok(()) @@ -1458,45 +1515,6 @@ impl<'a> State<'a> { } } - /// This doesn't deserve to be called "pretty" printing, but it should be - /// meaning-preserving. A quick hack that might help would be to look at the - /// spans embedded in the TTs to decide where to put spaces and newlines. - /// But it'd be better to parse these according to the grammar of the - /// appropriate macro, transcribe back into the grammar we just parsed from, - /// and then pretty-print the resulting AST nodes (so, e.g., we print - /// expression arguments as expressions). It can be done! I think. - pub fn print_tt(&mut self, tt: tokenstream::TokenTree) -> io::Result<()> { - match tt { - TokenTree::Token(_, ref tk) => { - word(&mut self.s, &token_to_string(tk))?; - match *tk { - parse::token::DocComment(..) => { - hardbreak(&mut self.s) - } - _ => Ok(()) - } - } - TokenTree::Delimited(_, ref delimed) => { - word(&mut self.s, &token_to_string(&delimed.open_token()))?; - space(&mut self.s)?; - self.print_tts(delimed.stream())?; - space(&mut self.s)?; - word(&mut self.s, &token_to_string(&delimed.close_token())) - }, - } - } - - pub fn print_tts(&mut self, tts: tokenstream::TokenStream) -> io::Result<()> { - self.ibox(0)?; - for (i, tt) in tts.into_trees().enumerate() { - if i != 0 { - space(&mut self.s)?; - } - self.print_tt(tt)?; - } - self.end() - } - pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> { self.head("")?; let generics = ast::Generics::default(); diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 4a2dfaf61247c..94954e2c42980 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -15,6 +15,7 @@ use syntax_pos::{DUMMY_SP, Span}; use codemap::{self, ExpnInfo, NameAndSpan, MacroAttribute}; use parse::ParseSess; use ptr::P; +use tokenstream::TokenStream; /// Craft a span that will be ignored by the stability lint's /// call to codemap's is_internal check. @@ -70,11 +71,8 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess, krate.module.items.insert(0, P(ast::Item { attrs: vec![ast::Attribute { style: ast::AttrStyle::Outer, - value: ast::MetaItem { - name: Symbol::intern("prelude_import"), - node: ast::MetaItemKind::Word, - span: span, - }, + path: ast::Path::from_ident(span, ast::Ident::from_str("prelude_import")), + tokens: TokenStream::empty(), id: attr::mk_attr_id(), is_sugared_doc: false, span: span, diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 2da442a1a53da..35e4d9eb68aea 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -360,7 +360,7 @@ impl PartialEq for ThinTokenStream { impl fmt::Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&pprust::tts_to_string(&self.trees().collect::>())) + f.write_str(&pprust::tokens_to_string(self.clone())) } } diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index a7e2d82bb978f..b01ef65e5fe5e 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -23,9 +23,11 @@ struct MarkAttrs<'a>(&'a [ast::Name]); impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - if self.0.contains(&attr.name()) { - mark_used(attr); - mark_known(attr); + if let Some(name) = attr.name() { + if self.0.contains(&name) { + mark_used(attr); + mark_known(attr); + } } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index fe492bd7fc849..48e7ff0d24370 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -439,7 +439,7 @@ impl<'a> TraitDef<'a> { attrs.extend(item.attrs .iter() .filter(|a| { - match &*a.name().as_str() { + a.name().is_some() && match &*a.name().unwrap().as_str() { "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true, _ => false, } diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index 5adaf470f2374..2d815b3f1bb7d 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -248,7 +248,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { fn visit_item(&mut self, item: &'a ast::Item) { if let ast::ItemKind::MacroDef(..) = item.node { if self.is_proc_macro_crate && - item.attrs.iter().any(|attr| attr.name() == "macro_export") { + item.attrs.iter().any(|attr| attr.path == "macro_export") { let msg = "cannot export macro_rules! macros from a `proc-macro` crate type currently"; self.handler.span_err(item.span, msg); @@ -270,12 +270,12 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { for attr in &item.attrs { if is_proc_macro_attr(&attr) { if let Some(prev_attr) = found_attr { - let msg = if attr.name() == prev_attr.name() { + let msg = if attr.path == prev_attr.path { format!("Only one `#[{}]` attribute is allowed on any given function", - attr.name()) + attr.path) } else { format!("`#[{}]` and `#[{}]` attributes cannot both be applied \ - to the same function", attr.name(), prev_attr.name()) + to the same function", attr.path, prev_attr.path) }; self.handler.struct_span_err(attr.span(), &msg) @@ -299,7 +299,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { if !is_fn { let msg = format!("the `#[{}]` attribute may only be used on bare functions", - attr.name()); + attr.path); self.handler.span_err(attr.span(), &msg); return; @@ -311,7 +311,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { if !self.is_proc_macro_crate { let msg = format!("the `#[{}]` attribute is only usable with crates of the \ - `proc-macro` crate type", attr.name()); + `proc-macro` crate type", attr.path); self.handler.span_err(attr.span(), &msg); return; From 839c2860ccb7cd3d381abf2838dfba566f52618e Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 8 Mar 2017 23:13:35 +0000 Subject: [PATCH 18/19] Liberalize attributes. --- src/librustc_resolve/lib.rs | 2 + src/librustc_resolve/macros.rs | 54 +++++++---- src/libsyntax/attr.rs | 46 ++++++++- src/libsyntax/config.rs | 72 +++++++------- src/libsyntax/ext/derive.rs | 45 ++++----- src/libsyntax/ext/expand.rs | 94 ++++++++++--------- src/libsyntax/ext/tt/macro_rules.rs | 3 +- src/libsyntax/feature_gate.rs | 4 + src/libsyntax/parse/attr.rs | 32 +++++-- src/libsyntax/parse/parser.rs | 11 +++ .../macro-attribute.rs | 2 - .../compile-fail/malformed-derive-entry.rs | 4 +- .../compile-fail/suffixed-literal-meta.rs | 25 +++++ src/test/parse-fail/attr-bad-meta.rs | 6 +- src/test/parse-fail/suffixed-literal-meta.rs | 25 ----- src/test/ui/span/E0536.stderr | 2 +- src/test/ui/span/E0537.stderr | 2 +- 17 files changed, 257 insertions(+), 172 deletions(-) rename src/test/{parse-fail => compile-fail}/macro-attribute.rs (94%) create mode 100644 src/test/compile-fail/suffixed-literal-meta.rs delete mode 100644 src/test/parse-fail/suffixed-literal-meta.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c3e471650a3e1..bf7115abd4edd 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1165,6 +1165,7 @@ pub struct Resolver<'a> { privacy_errors: Vec>, ambiguity_errors: Vec>, + gated_errors: FxHashSet, disallowed_shadowing: Vec<&'a LegacyBinding<'a>>, arenas: &'a ResolverArenas<'a>, @@ -1355,6 +1356,7 @@ impl<'a> Resolver<'a> { privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), + gated_errors: FxHashSet(), disallowed_shadowing: Vec::new(), arenas: arenas, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 9e1dcd1bc35c4..67ce24efb3b1f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -28,9 +28,11 @@ use syntax::ext::placeholders::placeholder; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{self, emit_feature_err, GateIssue}; use syntax::fold::{self, Folder}; +use syntax::parse::parser::PathStyle; +use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; -use syntax::tokenstream::TokenStream; +use syntax::tokenstream::{TokenStream, TokenTree, Delimited}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; @@ -200,16 +202,22 @@ impl<'a> base::Resolver for Resolver<'a> { let name = unwrap_or!(attrs[i].name(), continue); if name == "derive" { - let mut traits = match attrs[i].meta_item_list() { - Some(traits) => traits, - _ => continue, + let result = attrs[i].parse_list(&self.session.parse_sess, + |parser| parser.parse_path(PathStyle::Mod)); + let mut traits = match result { + Ok(traits) => traits, + Err(mut e) => { + e.cancel(); + continue + } }; for j in 0..traits.len() { - let legacy_name = Symbol::intern(&match traits[j].word() { - Some(..) => format!("derive_{}", traits[j].name().unwrap()), - None => continue, - }); + if traits[j].segments.len() > 1 { + continue + } + let trait_name = traits[j].segments[0].identifier.name; + let legacy_name = Symbol::intern(&format!("derive_{}", trait_name)); if !self.builtin_macros.contains_key(&legacy_name) { continue } @@ -218,7 +226,23 @@ impl<'a> base::Resolver for Resolver<'a> { if traits.is_empty() { attrs.remove(i); } else { - attrs[i].tokens = ast::MetaItemKind::List(traits).tokens(attrs[i].span); + let mut tokens = Vec::new(); + for (i, path) in traits.iter().enumerate() { + if i > 0 { + tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into()); + } + for (j, segment) in path.segments.iter().enumerate() { + if j > 0 { + tokens.push(TokenTree::Token(path.span, Token::ModSep).into()); + } + let tok = Token::Ident(segment.identifier); + tokens.push(TokenTree::Token(path.span, tok).into()); + } + } + attrs[i].tokens = TokenTree::Delimited(attrs[i].span, Delimited { + delim: token::Paren, + tts: TokenStream::concat(tokens).into(), + }).into(); } return Some(ast::Attribute { path: ast::Path::from_ident(span, Ident::with_empty_ctxt(legacy_name)), @@ -262,9 +286,8 @@ impl<'a> Resolver<'a> { InvocationKind::Bang { ref mac, .. } => { return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force); } - InvocationKind::Derive { name, span, .. } => { - let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); - return self.resolve_macro_to_def(scope, &path, MacroKind::Derive, force); + InvocationKind::Derive { ref path, .. } => { + return self.resolve_macro_to_def(scope, path, MacroKind::Derive, force); } }; @@ -282,9 +305,8 @@ impl<'a> Resolver<'a> { 1 => path.segments[0].identifier.name, _ => return Err(determinacy), }; - for &(name, span) in traits { - let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); - match self.resolve_macro(scope, &path, MacroKind::Derive, force) { + for path in traits { + match self.resolve_macro(scope, path, MacroKind::Derive, force) { Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext { if inert_attrs.contains(&attr_name) { // FIXME(jseyfried) Avoid `mem::replace` here. @@ -327,7 +349,7 @@ impl<'a> Resolver<'a> { self.current_module = invocation.module.get(); if path.len() > 1 { - if !self.use_extern_macros { + if !self.use_extern_macros && self.gated_errors.insert(span) { let msg = "non-ident macro paths are experimental"; let feature = "use_extern_macros"; emit_feature_err(&self.session.parse_sess, feature, span, GateIssue::Language, msg); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 68f1f690a62f0..2f1efd6ad00ee 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -17,7 +17,7 @@ pub use self::IntType::*; use ast; use ast::{AttrId, Attribute, Name, Ident}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; -use ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind}; +use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind}; use codemap::{Spanned, spanned, dummy_spanned, mk_sp}; use syntax_pos::{Span, BytePos, DUMMY_SP}; use errors::Handler; @@ -299,6 +299,37 @@ impl Attribute { }) } + pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + { + let mut parser = Parser::new(sess, self.tokens.clone(), None, false); + let result = f(&mut parser)?; + if parser.token != token::Eof { + parser.unexpected()?; + } + Ok(result) + } + + pub fn parse_list<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, Vec> + where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, + { + if self.tokens.is_empty() { + return Ok(Vec::new()); + } + self.parse(sess, |parser| { + parser.expect(&token::OpenDelim(token::Paren))?; + let mut list = Vec::new(); + while !parser.eat(&token::CloseDelim(token::Paren)) { + list.push(f(parser)?); + if !parser.eat(&token::Comma) { + parser.expect(&token::CloseDelim(token::Paren))?; + break + } + } + Ok(list) + }) + } + pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { if self.path.segments.len() > 1 { sess.span_diagnostic.span_err(self.path.span, "expected ident, found path"); @@ -306,7 +337,7 @@ impl Attribute { Ok(MetaItem { name: self.path.segments.last().unwrap().identifier.name, - node: Parser::new(sess, self.tokens.clone(), None, false).parse_meta_item_kind()?, + node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, span: self.span, }) } @@ -985,6 +1016,10 @@ impl MetaItem { { let (mut span, name) = match tokens.next() { Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name), + Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => return match **nt { + token::Nonterminal::NtMeta(ref meta) => Some(meta.clone()), + _ => None, + }, _ => return None, }; let node = match MetaItemKind::from_tokens(tokens) { @@ -1151,6 +1186,13 @@ impl LitKind { match token { Token::Ident(ident) if ident.name == "true" => Some(LitKind::Bool(true)), Token::Ident(ident) if ident.name == "false" => Some(LitKind::Bool(false)), + Token::Interpolated(ref nt) => match **nt { + token::NtExpr(ref v) => match v.node { + ExprKind::Lit(ref lit) => Some(lit.node.clone()), + _ => None, + }, + _ => None, + }, Token::Literal(lit, suf) => { let (suffix_illegal, result) = parse::lit_token(lit, suf, None); if suffix_illegal && suf.is_some() { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 2591a5766693f..ede8a33df6546 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -13,9 +13,10 @@ use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features use {fold, attr}; use ast; use codemap::Spanned; -use parse::ParseSess; -use ptr::P; +use parse::{token, ParseSess}; +use syntax_pos::Span; +use ptr::P; use util::small_vector::SmallVector; /// A folder that strips out items that do not belong in the current configuration. @@ -84,44 +85,33 @@ impl<'a> StripUnconfigured<'a> { return Some(attr); } - let attr_list = match attr.meta_item_list() { - Some(attr_list) => attr_list, - None => { - let msg = "expected `#[cfg_attr(, )]`"; - self.sess.span_diagnostic.span_err(attr.span, msg); - return None; - } - }; - - let (cfg, mi) = match (attr_list.len(), attr_list.get(0), attr_list.get(1)) { - (2, Some(cfg), Some(mi)) => (cfg, mi), - _ => { - let msg = "expected `#[cfg_attr(, )]`"; - self.sess.span_diagnostic.span_err(attr.span, msg); + let (cfg, path, tokens, span) = match attr.parse(self.sess, |parser| { + parser.expect(&token::OpenDelim(token::Paren))?; + let cfg = parser.parse_meta_item()?; + parser.expect(&token::Comma)?; + let lo = parser.span.lo; + let (path, tokens) = parser.parse_path_and_tokens()?; + parser.expect(&token::CloseDelim(token::Paren))?; + Ok((cfg, path, tokens, Span { lo: lo, ..parser.prev_span })) + }) { + Ok(result) => result, + Err(mut e) => { + e.emit(); return None; } }; - use attr::cfg_matches; - match (cfg.meta_item(), mi.meta_item()) { - (Some(cfg), Some(mi)) => - if cfg_matches(&cfg, self.sess, self.features) { - self.process_cfg_attr(ast::Attribute { - id: attr::mk_attr_id(), - style: attr.style, - path: ast::Path::from_ident(mi.span, ast::Ident::with_empty_ctxt(mi.name)), - tokens: mi.node.tokens(mi.span), - is_sugared_doc: false, - span: mi.span, - }) - } else { - None - }, - _ => { - let msg = "unexpected literal(s) in `#[cfg_attr(, )]`"; - self.sess.span_diagnostic.span_err(attr.span, msg); - None - } + if attr::cfg_matches(&cfg, self.sess, self.features) { + self.process_cfg_attr(ast::Attribute { + id: attr::mk_attr_id(), + style: attr.style, + path: path, + tokens: tokens, + is_sugared_doc: false, + span: span, + }) + } else { + None } } @@ -133,10 +123,12 @@ impl<'a> StripUnconfigured<'a> { return false; } - let mis = attr.meta_item_list(); - let mis = match mis { - Some(ref mis) if is_cfg(&attr) => mis, - _ => return true + let mis = if !is_cfg(&attr) { + return true; + } else if let Some(mis) = attr.meta_item_list() { + mis + } else { + return true; }; if mis.len() != 1 { diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 5b253635f257e..1569d9f540b8e 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -12,36 +12,31 @@ use attr::HasAttrs; use {ast, codemap}; use ext::base::ExtCtxt; use ext::build::AstBuilder; +use parse::parser::PathStyle; use symbol::Symbol; use syntax_pos::Span; -pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec<(Symbol, Span)> { +pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec { let mut result = Vec::new(); attrs.retain(|attr| { if attr.path != "derive" { return true; } - if attr.value_str().is_some() { - cx.span_err(attr.span, "unexpected value in `derive`"); - return false; - } - - let traits = attr.meta_item_list().unwrap_or_else(Vec::new); - if traits.is_empty() { - cx.span_warn(attr.span, "empty trait list in `derive`"); - return false; - } - - for titem in traits { - if titem.word().is_none() { - cx.span_err(titem.span, "malformed `derive` entry"); - return false; + match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) { + Ok(ref traits) if traits.is_empty() => { + cx.span_warn(attr.span, "empty trait list in `derive`"); + false + } + Ok(traits) => { + result.extend(traits); + true + } + Err(mut e) => { + e.emit(); + false } - result.push((titem.name().unwrap(), titem.span)); } - - true }); result } @@ -60,21 +55,21 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { } } -pub fn add_derived_markers(cx: &mut ExtCtxt, traits: &[(Symbol, Span)], item: T) -> T { +pub fn add_derived_markers(cx: &mut ExtCtxt, traits: &[ast::Path], item: T) -> T { let span = match traits.get(0) { - Some(&(_, span)) => span, + Some(path) => path.span, None => return item, }; item.map_attrs(|mut attrs| { - if traits.iter().any(|&(name, _)| name == "PartialEq") && - traits.iter().any(|&(name, _)| name == "Eq") { + if traits.iter().any(|path| *path == "PartialEq") && + traits.iter().any(|path| *path == "Eq") { let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); let meta = cx.meta_word(span, Symbol::intern("structural_match")); attrs.push(cx.attribute(span, meta)); } - if traits.iter().any(|&(name, _)| name == "Copy") && - traits.iter().any(|&(name, _)| name == "Clone") { + if traits.iter().any(|path| *path == "Copy") && + traits.iter().any(|path| *path == "Clone") { let span = allow_unstable(cx, span, "derive(Copy, Clone)"); let meta = cx.meta_word(span, Symbol::intern("rustc_copy_clone_marker")); attrs.push(cx.attribute(span, meta)); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c1095d3445682..c1816582bc6ca 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{self, Block, Ident, PatKind}; -use ast::{Name, MacStmtStyle, StmtKind, ItemKind}; +use ast::{self, Block, Ident, PatKind, Path}; +use ast::{MacStmtStyle, StmtKind, ItemKind}; use attr::{self, HasAttrs}; use codemap::{ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use config::{is_test_or_bench, StripUnconfigured}; @@ -27,7 +27,7 @@ use ptr::P; use std_inject; use symbol::Symbol; use symbol::keywords; -use syntax_pos::{self, Span, ExpnId}; +use syntax_pos::{Span, ExpnId, DUMMY_SP}; use tokenstream::TokenStream; use util::small_vector::SmallVector; use visit::Visitor; @@ -165,12 +165,11 @@ pub enum InvocationKind { }, Attr { attr: Option, - traits: Vec<(Symbol, Span)>, + traits: Vec, item: Annotatable, }, Derive { - name: Symbol, - span: Span, + path: Path, item: Annotatable, }, } @@ -180,8 +179,8 @@ impl Invocation { match self.kind { InvocationKind::Bang { span, .. } => span, InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span, - InvocationKind::Attr { attr: None, .. } => syntax_pos::DUMMY_SP, - InvocationKind::Derive { span, .. } => span, + InvocationKind::Attr { attr: None, .. } => DUMMY_SP, + InvocationKind::Derive { ref path, .. } => path.span, } } } @@ -277,12 +276,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { add_derived_markers(&mut self.cx, &traits, item.clone()); let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new); - for &(name, span) in &traits { + for path in &traits { let mark = Mark::fresh(); derives.push(mark); - let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); let item = match self.cx.resolver.resolve_macro( - Mark::root(), &path, MacroKind::Derive, false) { + Mark::root(), path, MacroKind::Derive, false) { Ok(ext) => match *ext { SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(), _ => item.clone(), @@ -290,7 +288,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => item.clone(), }; invocations.push(Invocation { - kind: InvocationKind::Derive { name: name, span: span, item: item }, + kind: InvocationKind::Derive { path: path.clone(), item: item }, expansion_kind: invoc.expansion_kind, expansion_data: ExpansionData { mark: mark, @@ -380,11 +378,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; attr::mark_used(&attr); - let name = attr.path.segments[0].identifier.name; self.cx.bt_push(ExpnInfo { call_site: attr.span, callee: NameAndSpan { - format: MacroAttribute(name), + format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))), span: Some(attr.span), allow_internal_unstable: false, } @@ -419,14 +416,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let tok_result = mac.expand(self.cx, attr.span, attr.tokens.clone(), item_toks); - self.parse_expansion(tok_result, kind, name, span) + self.parse_expansion(tok_result, kind, &attr.path, span) } SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { - self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name)); + self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path)); kind.dummy(attr.span) } _ => { - let msg = &format!("macro `{}` may not be used in attributes", name); + let msg = &format!("macro `{}` may not be used in attributes", attr.path); self.cx.span_err(attr.span, &msg); kind.dummy(attr.span) } @@ -442,7 +439,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let path = &mac.node.path; - let extname = path.segments.last().unwrap().identifier.name; let ident = ident.unwrap_or(keywords::Invalid.ident()); let marked_tts = noop_fold_tts(mac.node.stream(), &mut Marker { mark: mark, expn_id: None }); @@ -450,7 +446,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { NormalTT(ref expandfun, exp_span, allow_internal_unstable) => { if ident.name != keywords::Invalid.name() { let msg = - format!("macro {}! expects no ident argument, given '{}'", extname, ident); + format!("macro {}! expects no ident argument, given '{}'", path, ident); self.cx.span_err(path.span, &msg); return kind.dummy(span); } @@ -458,7 +454,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.bt_push(ExpnInfo { call_site: span, callee: NameAndSpan { - format: MacroBang(extname), + format: MacroBang(Symbol::intern(&format!("{}", path))), span: exp_span, allow_internal_unstable: allow_internal_unstable, }, @@ -470,14 +466,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { IdentTT(ref expander, tt_span, allow_internal_unstable) => { if ident.name == keywords::Invalid.name() { self.cx.span_err(path.span, - &format!("macro {}! expects an ident argument", extname)); + &format!("macro {}! expects an ident argument", path)); return kind.dummy(span); }; self.cx.bt_push(ExpnInfo { call_site: span, callee: NameAndSpan { - format: MacroBang(extname), + format: MacroBang(Symbol::intern(&format!("{}", path))), span: tt_span, allow_internal_unstable: allow_internal_unstable, } @@ -489,19 +485,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> { MultiDecorator(..) | MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => { self.cx.span_err(path.span, - &format!("`{}` can only be used in attributes", extname)); + &format!("`{}` can only be used in attributes", path)); return kind.dummy(span); } SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => { - self.cx.span_err(path.span, &format!("`{}` is a derive mode", extname)); + self.cx.span_err(path.span, &format!("`{}` is a derive mode", path)); return kind.dummy(span); } SyntaxExtension::ProcMacro(ref expandfun) => { if ident.name != keywords::Invalid.name() { let msg = - format!("macro {}! expects no ident argument, given '{}'", extname, ident); + format!("macro {}! expects no ident argument, given '{}'", path, ident); self.cx.span_err(path.span, &msg); return kind.dummy(span); } @@ -509,7 +505,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.bt_push(ExpnInfo { call_site: span, callee: NameAndSpan { - format: MacroBang(extname), + format: MacroBang(Symbol::intern(&format!("{}", path))), // FIXME procedural macros do not have proper span info // yet, when they do, we should use it here. span: None, @@ -519,7 +515,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); let tok_result = expandfun.expand(self.cx, span, marked_tts); - Some(self.parse_expansion(tok_result, kind, extname, span)) + Some(self.parse_expansion(tok_result, kind, path, span)) } }; @@ -541,19 +537,24 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// Expand a derive invocation. Returns the result of expansion. fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc) -> Expansion { let Invocation { expansion_kind: kind, .. } = invoc; - let (name, span, item) = match invoc.kind { - InvocationKind::Derive { name, span, item } => (name, span, item), + let (path, item) = match invoc.kind { + InvocationKind::Derive { path, item } => (path, item), _ => unreachable!(), }; - let mitem = ast::MetaItem { name: name, span: span, node: ast::MetaItemKind::Word }; - let pretty_name = Symbol::intern(&format!("derive({})", name)); + let pretty_name = Symbol::intern(&format!("derive({})", path)); + let span = path.span; + let attr = ast::Attribute { + path: path, tokens: TokenStream::empty(), span: span, + // irrelevant: + id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false, + }; self.cx.bt_push(ExpnInfo { call_site: span, callee: NameAndSpan { format: MacroAttribute(pretty_name), - span: Some(span), + span: None, allow_internal_unstable: false, } }); @@ -571,7 +572,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }), ..span }; - return kind.expect_from_annotatables(ext.expand(self.cx, span, &mitem, item)); + let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this + name: keywords::Invalid.name(), + span: DUMMY_SP, + node: ast::MetaItemKind::Word, + }; + return kind.expect_from_annotatables(ext.expand(self.cx, span, &dummy, item)); } SyntaxExtension::BuiltinDerive(func) => { let span = Span { @@ -586,20 +592,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ..span }; let mut items = Vec::new(); - func(self.cx, span, &mitem, &item, &mut |a| { - items.push(a) - }); + func(self.cx, span, &attr.meta().unwrap(), &item, &mut |a| items.push(a)); return kind.expect_from_annotatables(items); } _ => { - let msg = &format!("macro `{}` may not be used for derive attributes", name); + let msg = &format!("macro `{}` may not be used for derive attributes", attr.path); self.cx.span_err(span, &msg); kind.dummy(span) } } } - fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span) + fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, path: &Path, span: Span) -> Expansion { let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); let expansion = match parser.parse_expansion(kind, false) { @@ -609,7 +613,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { return kind.dummy(span); } }; - parser.ensure_complete_parse(name, kind.name(), span); + parser.ensure_complete_parse(path, kind.name(), span); // FIXME better span info expansion.fold_with(&mut ChangeSpan { span: span }) } @@ -658,14 +662,14 @@ impl<'a> Parser<'a> { }) } - pub fn ensure_complete_parse(&mut self, macro_name: ast::Name, kind_name: &str, span: Span) { + pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) { if self.token != token::Eof { let msg = format!("macro expansion ignores token `{}` and any following", self.this_token_to_string()); let mut err = self.diagnostic().struct_span_err(self.span, &msg); let msg = format!("caused by the macro expansion here; the usage \ of `{}!` is likely invalid in {} context", - macro_name, kind_name); + macro_path, kind_name); err.span_note(span, &msg).emit(); } } @@ -708,20 +712,20 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_attr(&mut self, attr: Option, - traits: Vec<(Symbol, Span)>, + traits: Vec, item: Annotatable, kind: ExpansionKind) -> Expansion { if !traits.is_empty() && (kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems) { - self.cx.span_err(traits[0].1, "`derive` can be only be applied to items"); + self.cx.span_err(traits[0].span, "`derive` can be only be applied to items"); return kind.expect_from_annotatables(::std::iter::once(item)); } self.collect(kind, InvocationKind::Attr { attr: attr, traits: traits, item: item }) } // If `item` is an attr invocation, remove and return the macro attribute. - fn classify_item(&mut self, mut item: T) -> (Option, Vec<(Symbol, Span)>, T) + fn classify_item(&mut self, mut item: T) -> (Option, Vec, T) where T: HasAttrs, { let (mut attr, mut traits) = (None, Vec::new()); @@ -900,7 +904,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`). // In the non-inline case, `inner` is never the dummy span (c.f. `parse_item_mod`). // Thus, if `inner` is the dummy span, we know the module is inline. - let inline_module = item.span.contains(inner) || inner == syntax_pos::DUMMY_SP; + let inline_module = item.span.contains(inner) || inner == DUMMY_SP; if inline_module { if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 7aa1230f9aeea..021c5398a4200 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -51,7 +51,8 @@ impl<'a> ParserAnyMacro<'a> { } // Make sure we don't have any tokens left to parse so we don't silently drop anything. - parser.ensure_complete_parse(macro_ident.name, kind.name(), site_span); + let path = ast::Path::from_ident(site_span, macro_ident); + parser.ensure_complete_parse(&path, kind.name(), site_span); expansion } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2c3ad98a6be63..05e7b0f9aa4da 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1096,6 +1096,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.context.check_attribute(attr, false); } + if self.context.features.proc_macro && attr::is_known(attr) { + return + } + let meta = panictry!(attr.parse_meta(&self.context.parse_sess)); if contains_novel_literal(&meta) { gate_feature_post!(&self, attr_literals, attr.span, diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 272cff7ad34b2..53106214fa310 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -14,8 +14,9 @@ use syntax_pos::{mk_sp, Span}; use codemap::spanned; use parse::common::SeqSep; use parse::PResult; -use parse::token; -use parse::parser::{Parser, TokenType}; +use parse::token::{self, Nonterminal}; +use parse::parser::{Parser, TokenType, PathStyle}; +use tokenstream::TokenStream; #[derive(PartialEq, Eq, Debug)] enum InnerAttributeParsePolicy<'a> { @@ -91,7 +92,7 @@ impl<'a> Parser<'a> { debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}", inner_parse_policy, self.token); - let (span, value, mut style) = match self.token { + let (span, path, tokens, mut style) = match self.token { token::Pound => { let lo = self.span.lo; self.bump(); @@ -119,11 +120,11 @@ impl<'a> Parser<'a> { }; self.expect(&token::OpenDelim(token::Bracket))?; - let meta_item = self.parse_meta_item()?; + let (path, tokens) = self.parse_path_and_tokens()?; self.expect(&token::CloseDelim(token::Bracket))?; let hi = self.prev_span.hi; - (mk_sp(lo, hi), meta_item, style) + (mk_sp(lo, hi), path, tokens, style) } _ => { let token_str = self.this_token_to_string(); @@ -143,13 +144,30 @@ impl<'a> Parser<'a> { Ok(ast::Attribute { id: attr::mk_attr_id(), style: style, - path: ast::Path::from_ident(value.span, ast::Ident::with_empty_ctxt(value.name)), - tokens: value.node.tokens(value.span), + path: path, + tokens: tokens, is_sugared_doc: false, span: span, }) } + pub fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)> { + let meta = match self.token { + token::Interpolated(ref nt) => match **nt { + Nonterminal::NtMeta(ref meta) => Some(meta.clone()), + _ => None, + }, + _ => None, + }; + Ok(if let Some(meta) = meta { + self.bump(); + (ast::Path::from_ident(meta.span, ast::Ident::with_empty_ctxt(meta.name)), + meta.node.tokens(meta.span)) + } else { + (self.parse_path(PathStyle::Mod)?, self.parse_tokens()) + }) + } + /// Parse attributes that appear after the opening of an item. These should /// be preceded by an exclamation mark, but we accept and warn about one /// terminated by a semicolon. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ed512b899877d..308876fed56dc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2644,6 +2644,17 @@ impl<'a> Parser<'a> { Ok(tts) } + pub fn parse_tokens(&mut self) -> TokenStream { + let mut result = Vec::new(); + loop { + match self.token { + token::Eof | token::CloseDelim(..) => break, + _ => result.push(self.parse_token_tree().into()), + } + } + TokenStream::concat(result) + } + /// Parse a prefix-unary-operator expr pub fn parse_prefix_expr(&mut self, already_parsed_attrs: Option>) diff --git a/src/test/parse-fail/macro-attribute.rs b/src/test/compile-fail/macro-attribute.rs similarity index 94% rename from src/test/parse-fail/macro-attribute.rs rename to src/test/compile-fail/macro-attribute.rs index 18add7d011cba..52f867fe913b8 100644 --- a/src/test/parse-fail/macro-attribute.rs +++ b/src/test/compile-fail/macro-attribute.rs @@ -8,7 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only - #[doc = $not_there] //~ error: unexpected token: `$` fn main() { } diff --git a/src/test/compile-fail/malformed-derive-entry.rs b/src/test/compile-fail/malformed-derive-entry.rs index 62dbc21495a54..ac000628f2b04 100644 --- a/src/test/compile-fail/malformed-derive-entry.rs +++ b/src/test/compile-fail/malformed-derive-entry.rs @@ -9,11 +9,11 @@ // except according to those terms. #[derive(Copy(Bad))] -//~^ ERROR malformed `derive` entry +//~^ ERROR expected one of `)`, `,`, or `::`, found `(` struct Test1; #[derive(Copy="bad")] -//~^ ERROR malformed `derive` entry +//~^ ERROR expected one of `)`, `,`, or `::`, found `=` struct Test2; #[derive()] diff --git a/src/test/compile-fail/suffixed-literal-meta.rs b/src/test/compile-fail/suffixed-literal-meta.rs new file mode 100644 index 0000000000000..bf55b7bdcb1de --- /dev/null +++ b/src/test/compile-fail/suffixed-literal-meta.rs @@ -0,0 +1,25 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(attr_literals)] + +#[path = 1usize] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1u8] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1u16] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1u32] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1u64] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1isize] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1i8] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1i16] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1i32] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1i64] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes +#[path = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes +fn main() { } diff --git a/src/test/parse-fail/attr-bad-meta.rs b/src/test/parse-fail/attr-bad-meta.rs index 092adbf29e340..d57a813311b5a 100644 --- a/src/test/parse-fail/attr-bad-meta.rs +++ b/src/test/parse-fail/attr-bad-meta.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only - -// error-pattern:expected one of `=` or `]` - // asterisk is bogus -#[attr*] +#[path*] //~ ERROR expected one of `(` or `=` mod m {} diff --git a/src/test/parse-fail/suffixed-literal-meta.rs b/src/test/parse-fail/suffixed-literal-meta.rs deleted file mode 100644 index 0e2840c69d364..0000000000000 --- a/src/test/parse-fail/suffixed-literal-meta.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z parse-only - -#[foo = 1usize] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1u8] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1u16] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1u32] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1u64] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1isize] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1i8] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1i16] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1i32] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1i64] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes -#[foo = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes -fn main() { } diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr index c33b89953e274..b2da0c6a296d8 100644 --- a/src/test/ui/span/E0536.stderr +++ b/src/test/ui/span/E0536.stderr @@ -2,7 +2,7 @@ error[E0536]: expected 1 cfg-pattern --> $DIR/E0536.rs:11:7 | 11 | #[cfg(not())] //~ ERROR E0536 - | ^^^^^ + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr index 9d66ddbaae317..29873943f444d 100644 --- a/src/test/ui/span/E0537.stderr +++ b/src/test/ui/span/E0537.stderr @@ -2,7 +2,7 @@ error[E0537]: invalid predicate `unknown` --> $DIR/E0537.rs:11:7 | 11 | #[cfg(unknown())] //~ ERROR E0537 - | ^^^^^^^^^ + | ^^^^^^^ error: aborting due to previous error From 85e02bdbfcfd0e38def7656a8295a5260640fd4a Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 8 Mar 2017 23:13:43 +0000 Subject: [PATCH 19/19] Add tests. --- .../proc-macro/proc-macro-attributes.rs | 1 + src/test/compile-fail/macro-with-seps-err-msg.rs | 1 + src/test/run-pass-fulldeps/proc-macro/attr-args.rs | 6 +++--- .../run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs | 5 +++++ .../run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs | 2 +- src/test/run-pass-fulldeps/proc-macro/derive-b.rs | 7 ++++--- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs index 4ad1cf79d61c6..df881bedec1bb 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs @@ -20,6 +20,7 @@ extern crate derive_b; #[C] //~ ERROR: The attribute `C` is currently unknown to the compiler #[B(D)] #[B(E = "foo")] +#[B arbitrary tokens] //~ expected one of `(` or `=`, found `arbitrary` struct B; fn main() {} diff --git a/src/test/compile-fail/macro-with-seps-err-msg.rs b/src/test/compile-fail/macro-with-seps-err-msg.rs index 6cc682bde997f..c28e22d58f9db 100644 --- a/src/test/compile-fail/macro-with-seps-err-msg.rs +++ b/src/test/compile-fail/macro-with-seps-err-msg.rs @@ -14,4 +14,5 @@ fn main() { globnar::brotz!(); //~ ERROR non-ident macro paths are experimental ::foo!(); //~ ERROR non-ident macro paths are experimental foo::!(); //~ ERROR type parameters are not allowed on macros + #[derive(foo::Bar)] struct T; //~ ERROR non-ident macro paths are experimental } diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-args.rs b/src/test/run-pass-fulldeps/proc-macro/attr-args.rs index d28d75d81a2fb..8a9fdd7536770 100644 --- a/src/test/run-pass-fulldeps/proc-macro/attr-args.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-args.rs @@ -19,6 +19,6 @@ use attr_args::attr_with_args; #[attr_with_args(text = "Hello, world!")] fn foo() {} -fn main() { - assert_eq!(foo(), "Hello, world!"); -} +#[::attr_args::identity + fn main() { assert_eq!(foo(), "Hello, world!"); }] +struct Dummy; diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs index 6e1eb395a0a19..989c77f1089cf 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs @@ -30,3 +30,8 @@ pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream { fn foo() -> &'static str { "Hello, world!" } "#.parse().unwrap() } + +#[proc_macro_attribute] +pub fn identity(attr_args: TokenStream, _: TokenStream) -> TokenStream { + attr_args +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs index bf793534d50c9..7b521f2b9138a 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs @@ -19,7 +19,7 @@ use proc_macro::TokenStream; #[proc_macro_derive(B, attributes(B, C))] pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); - assert!(input.contains("#[B]")); + assert!(input.contains("#[B arbitrary tokens]")); assert!(input.contains("struct B {")); assert!(input.contains("#[C]")); "".parse().unwrap() diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs index f1e1626ddf8ca..995dc65729a50 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs @@ -11,11 +11,12 @@ // aux-build:derive-b.rs // ignore-stage1 -#[macro_use] +#![feature(proc_macro)] + extern crate derive_b; -#[derive(Debug, PartialEq, B, Eq, Copy, Clone)] -#[B] +#[derive(Debug, PartialEq, derive_b::B, Eq, Copy, Clone)] +#[cfg_attr(all(), B arbitrary tokens)] struct B { #[C] a: u64