diff --git a/.gitignore b/.gitignore index a0b491f42789a..81a472451d777 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ __pycache__/ /inst/ /llvm/ /mingw-build/ +# Created by default with `src/ci/docker/run.sh`: /obj/ /rustllvm/ /src/libcore/unicode/DerivedCoreProperties.txt @@ -38,6 +39,8 @@ __pycache__/ /src/libcore/unicode/UnicodeData.txt /src/libcore/unicode/downloaded /target/ +# Generated by compiletest for incremental: +/tmp/ tags tags.* TAGS diff --git a/Cargo.lock b/Cargo.lock index 52cfa2cb1f80e..ab6731e4d433d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3252,7 +3252,6 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 15a329a5b9152..df7eb7c455d02 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -9,7 +9,7 @@ use build_helper::t; use crate::Mode; use crate::Compiler; use crate::builder::{Step, RunConfig, ShouldRun, Builder}; -use crate::util::{exe, add_lib_path}; +use crate::util::{exe, add_lib_path, CiEnv}; use crate::compile; use crate::channel::GitInfo; use crate::channel; @@ -279,11 +279,26 @@ pub fn prepare_tool_cargo( cargo } +fn rustbook_features() -> Vec { + let mut features = Vec::new(); + + // Due to CI budged and risk of spurious failures we want to limit jobs running this check. + // At same time local builds should run it regardless of the platform. + // `CiEnv::None` means it's local build and `CHECK_LINKS` is defined in x86_64-gnu-tools to + // explicitly enable it on single job + if CiEnv::current() == CiEnv::None || env::var("CHECK_LINKS").is_ok() { + features.push("linkcheck".to_string()); + } + + features +} + macro_rules! bootstrap_tool { ($( $name:ident, $path:expr, $tool_name:expr $(,llvm_tools = $llvm:expr)* $(,is_external_tool = $external:expr)* + $(,features = $features:expr)* ; )+) => { #[derive(Copy, PartialEq, Eq, Clone)] @@ -350,7 +365,12 @@ macro_rules! bootstrap_tool { } else { SourceType::InTree }, - extra_features: Vec::new(), + extra_features: { + // FIXME(#60643): avoid this lint by using `_` + let mut _tmp = Vec::new(); + $(_tmp.extend($features);)* + _tmp + }, }).expect("expected to build -- essential tool") } } @@ -359,7 +379,7 @@ macro_rules! bootstrap_tool { } bootstrap_tool!( - Rustbook, "src/tools/rustbook", "rustbook"; + Rustbook, "src/tools/rustbook", "rustbook", features = rustbook_features(); UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen"; Tidy, "src/tools/tidy", "tidy"; Linkchecker, "src/tools/linkchecker", "linkchecker"; diff --git a/src/ci/docker/x86_64-gnu-tools/Dockerfile b/src/ci/docker/x86_64-gnu-tools/Dockerfile index f11ae7a34cb91..8035195c6ed0a 100644 --- a/src/ci/docker/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/x86_64-gnu-tools/Dockerfile @@ -21,6 +21,9 @@ COPY x86_64-gnu-tools/checkregression.py /tmp/ COPY x86_64-gnu-tools/checktools.sh /tmp/ COPY x86_64-gnu-tools/repo.sh /tmp/ +# Run rustbook with `linkcheck` feature enabled +ENV CHECK_LINKS 1 + ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --save-toolstates=/tmp/toolstates.json diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index d5e15b3719c2e..a9c5bce4c25fc 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -329,8 +329,8 @@ impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Cow<'_, B> - where B: fmt::Debug + ToOwned, - ::Owned: fmt::Debug +where + B: fmt::Debug + ToOwned, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -342,8 +342,8 @@ impl fmt::Debug for Cow<'_, B> #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Cow<'_, B> - where B: fmt::Display + ToOwned, - ::Owned: fmt::Display +where + B: fmt::Display + ToOwned, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -355,8 +355,8 @@ impl fmt::Display for Cow<'_, B> #[stable(feature = "default", since = "1.11.0")] impl Default for Cow<'_, B> - where B: ToOwned, - ::Owned: Default +where + B: ToOwned, { /// Creates an owned Cow<'a, B> with the default value for the contained owned value. fn default() -> Self { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index deea74daa52d5..a1936b36ac6bf 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -122,6 +122,7 @@ #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(mem_take)] +#![feature(associated_type_bounds)] // Allow testing this library diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 844afe870766b..266a0d055d5bc 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -689,7 +689,10 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_large_random_sorted() { + #[cfg(not(miri))] // Miri is too slow let mut data = rand_data(1529); + #[cfg(miri)] + let mut data = rand_data(529); // special case with maximum height. data.sort(); diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 989beb3b1bfd9..62ccb53fcea18 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -10,7 +10,7 @@ fn test_clone_eq() { m.insert(1); m.insert(2); - assert!(m.clone() == m); + assert_eq!(m.clone(), m); } #[test] @@ -28,7 +28,7 @@ fn test_hash() { y.insert(2); y.insert(1); - assert!(hash(&x) == hash(&y)); + assert_eq!(hash(&x), hash(&y)); } fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) @@ -69,6 +69,11 @@ fn test_intersection() { check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]); + + if cfg!(miri) { // Miri is too slow + return; + } + let large = (0..1000).collect::>(); check_intersection(&[], &large, &[]); check_intersection(&large, &[], &[]); @@ -98,6 +103,11 @@ fn test_difference() { check_difference(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 14, 23, 34, 38, 39, 50], &[11, 22, 33, 40, 42]); + + if cfg!(miri) { // Miri is too slow + return; + } + let large = (0..1000).collect::>(); check_difference(&[], &large, &[]); check_difference(&[-1], &large, &[-1]); @@ -166,6 +176,17 @@ fn test_is_subset() { assert_eq!(is_subset(&[1, 2], &[1]), false); assert_eq!(is_subset(&[1, 2], &[1, 2]), true); assert_eq!(is_subset(&[1, 2], &[2, 3]), false); + assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 11, 34, 22, 38, 33, 42, 39, 40]), + true); + assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], + &[-12, -5, 14, 23, 34, 38, 22, 11]), + false); + + if cfg!(miri) { // Miri is too slow + return; + } + let large = (0..1000).collect::>(); assert_eq!(is_subset(&[], &large), true); assert_eq!(is_subset(&large, &[]), false); @@ -371,7 +392,10 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_large_random_sorted() { + #[cfg(not(miri))] // Miri is too slow let mut data = rand_data(1529); + #[cfg(miri)] + let mut data = rand_data(529); // special case with maximum height. data.sort(); diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 6d774f3fecd92..5723a30c0f34f 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -8,6 +8,7 @@ #![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] +#![feature(associated_type_bounds)] use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index c5198ca39fedf..4332b2e90fdaf 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1638,10 +1638,12 @@ mod pattern { } } - fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str, - right: Vec) - where P::Searcher: ReverseSearcher<'a> - { + fn cmp_search_to_vec<'a>( + rev: bool, + pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>, + haystack: &'a str, + right: Vec + ) { let mut searcher = pat.into_searcher(haystack); let mut v = vec![]; loop { diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 9e32acb97d360..0c99356390bda 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -133,6 +133,14 @@ pub trait Clone : Sized { } } +/// Derive macro generating an impl of the trait `Clone`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy)] +pub macro Clone($item:item) { /* compiler built-in */ } + // FIXME(aburka): these structs are used solely by #[derive] to // assert that every component of a type implements Clone or Copy. // diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index f9613556a1ebc..38a52d97da212 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -200,6 +200,14 @@ pub trait PartialEq { fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } } +/// Derive macro generating an impl of the trait `PartialEq`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro PartialEq($item:item) { /* compiler built-in */ } + /// Trait for equality comparisons which are [equivalence relations]( /// https://en.wikipedia.org/wiki/Equivalence_relation). /// @@ -256,6 +264,14 @@ pub trait Eq: PartialEq { fn assert_receiver_is_total_eq(&self) {} } +/// Derive macro generating an impl of the trait `Eq`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_eq)] +pub macro Eq($item:item) { /* compiler built-in */ } + // FIXME: this struct is used solely by #[derive] to // assert that every component of a type implements Eq. // @@ -600,6 +616,14 @@ pub trait Ord: Eq + PartialOrd { } } +/// Derive macro generating an impl of the trait `Ord`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro Ord($item:item) { /* compiler built-in */ } + #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Ordering {} @@ -842,6 +866,14 @@ pub trait PartialOrd: PartialEq { } } +/// Derive macro generating an impl of the trait `PartialOrd`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro PartialOrd($item:item) { /* compiler built-in */ } + /// Compares and returns the minimum of two values. /// /// Returns the first argument if the comparison determines them to be equal. diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 624b13d96472c..641621f492baf 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -513,7 +513,7 @@ impl AsRef for &mut T where T: AsRef // FIXME (#45742): replace the above impls for &/&mut with the following more general one: // // As lifts over Deref -// impl AsRef for D where D::Target: AsRef { +// impl>, U: ?Sized> AsRef for D { // fn as_ref(&self) -> &U { // self.deref().as_ref() // } @@ -530,7 +530,7 @@ impl AsMut for &mut T where T: AsMut // FIXME (#45742): replace the above impl for &mut with the following more general one: // // AsMut lifts over DerefMut -// impl AsMut for D where D::Target: AsMut { +// impl>, U: ?Sized> AsMut for D { // fn as_mut(&mut self) -> &mut U { // self.deref_mut().as_mut() // } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 5ad05b3824764..8d95e9de15849 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -115,6 +115,14 @@ pub trait Default: Sized { fn default() -> Self; } +/// Derive macro generating an impl of the trait `Default`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics)] +pub macro Default($item:item) { /* compiler built-in */ } + macro_rules! default_impl { ($t:ty, $v:expr, $doc:tt) => { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 4a7c6af7adab7..0ea01d4b84a2c 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -545,6 +545,21 @@ pub trait Debug { fn fmt(&self, f: &mut Formatter<'_>) -> Result; } +// Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. +#[cfg(not(bootstrap))] +pub(crate) mod macros { + /// Derive macro generating an impl of the trait `Debug`. + #[rustc_builtin_macro] + #[rustc_macro_transparency = "semitransparent"] + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] + #[allow_internal_unstable(core_intrinsics)] + pub macro Debug($item:item) { /* compiler built-in */ } +} +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(inline)] +pub use macros::Debug; + /// Format trait for an empty format, `{}`. /// /// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 593c01060ca49..f14ed38b9b0f2 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -111,8 +111,7 @@ impl Future for &mut F { #[stable(feature = "futures_api", since = "1.36.0")] impl

Future for Pin

where - P: Unpin + ops::DerefMut, - P::Target: Future, + P: Unpin + ops::DerefMut, { type Output = <

::Target as Future>::Output; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 38e3864284240..c4cbf40a93a15 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -198,6 +198,21 @@ pub trait Hash { } } +// Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. +#[cfg(not(bootstrap))] +pub(crate) mod macros { + /// Derive macro generating an impl of the trait `Hash`. + #[rustc_builtin_macro] + #[rustc_macro_transparency = "semitransparent"] + #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] + #[allow_internal_unstable(core_intrinsics)] + pub macro Hash($item:item) { /* compiler built-in */ } +} +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(inline)] +pub use macros::Hash; + /// A trait for hashing an arbitrary stream of bytes. /// /// Instances of `Hasher` usually represent state that is changed while hashing diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 56e45c3695f61..ceaa870d2b3f7 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -707,11 +707,26 @@ extern "rust-intrinsic" { they should be used through stabilized interfaces \ in the rest of the standard library", issue = "0")] - #[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUninit \ - instead", + #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")] pub fn init() -> T; + /// Creates an uninitialized value. + /// + /// `uninit` is unsafe because there is no guarantee of what its + /// contents are. In particular its drop-flag may be set to any + /// state, which means it may claim either dropped or + /// undropped. In the general case one must use `ptr::write` to + /// initialize memory previous set to the result of `uninit`. + #[unstable(feature = "core_intrinsics", + reason = "intrinsics are unlikely to ever be stabilized, instead \ + they should be used through stabilized interfaces \ + in the rest of the standard library", + issue = "0")] + #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", + since = "1.38.0")] + pub fn uninit() -> T; + /// Moves a value out of scope without running drop glue. pub fn forget(_: T); diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index 8c2aae477bf2a..d8d41a2a31ef6 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -24,15 +24,17 @@ impl U> FlatMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for FlatMap - where ::IntoIter: Clone +impl Clone for FlatMap +where + U: Clone + IntoIterator, { fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } } } #[stable(feature = "core_impl_debug", since = "1.9.0")] -impl fmt::Debug for FlatMap - where U::IntoIter: fmt::Debug +impl fmt::Debug for FlatMap +where + U: IntoIterator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FlatMap").field("inner", &self.inner).finish() @@ -68,9 +70,10 @@ impl Iterator for FlatMap #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for FlatMap - where F: FnMut(I::Item) -> U, - U: IntoIterator, - U::IntoIter: DoubleEndedIterator +where + F: FnMut(I::Item) -> U, + U: IntoIterator, + U::IntoIter: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } @@ -105,11 +108,13 @@ impl FusedIterator for FlatMap #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iterator_flatten", since = "1.29.0")] pub struct Flatten -where I::Item: IntoIterator { +where + I::Item: IntoIterator, +{ inner: FlattenCompat::IntoIter>, } -impl Flatten -where I::Item: IntoIterator { + +impl> Flatten { pub(in super::super) fn new(iter: I) -> Flatten { Flatten { inner: FlattenCompat::new(iter) } } @@ -117,8 +122,9 @@ where I::Item: IntoIterator { #[stable(feature = "iterator_flatten", since = "1.29.0")] impl fmt::Debug for Flatten - where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug, - I::Item: IntoIterator, +where + I: fmt::Debug + Iterator>, + U: fmt::Debug + Iterator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Flatten").field("inner", &self.inner).finish() @@ -127,16 +133,18 @@ impl fmt::Debug for Flatten #[stable(feature = "iterator_flatten", since = "1.29.0")] impl Clone for Flatten - where I: Iterator + Clone, U: Iterator + Clone, - I::Item: IntoIterator, +where + I: Clone + Iterator>, + U: Clone + Iterator, { fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } } } #[stable(feature = "iterator_flatten", since = "1.29.0")] impl Iterator for Flatten - where I: Iterator, U: Iterator, - I::Item: IntoIterator +where + I: Iterator>, + U: Iterator, { type Item = U::Item; @@ -163,8 +171,9 @@ impl Iterator for Flatten #[stable(feature = "iterator_flatten", since = "1.29.0")] impl DoubleEndedIterator for Flatten - where I: DoubleEndedIterator, U: DoubleEndedIterator, - I::Item: IntoIterator +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { self.inner.next_back() } @@ -186,8 +195,10 @@ impl DoubleEndedIterator for Flatten #[stable(feature = "iterator_flatten", since = "1.29.0")] impl FusedIterator for Flatten - where I: FusedIterator, U: Iterator, - I::Item: IntoIterator {} +where + I: FusedIterator>, + U: Iterator, +{} /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. @@ -205,8 +216,9 @@ impl FlattenCompat { } impl Iterator for FlattenCompat - where I: Iterator, U: Iterator, - I::Item: IntoIterator +where + I: Iterator>, + U: Iterator, { type Item = U::Item; @@ -274,8 +286,9 @@ impl Iterator for FlattenCompat } impl DoubleEndedIterator for FlattenCompat - where I: DoubleEndedIterator, U: DoubleEndedIterator, - I::Item: IntoIterator +where + I: DoubleEndedIterator>, + U: DoubleEndedIterator, { #[inline] fn next_back(&mut self) -> Option { diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 1865160bc3cf4..25439136b8538 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -195,8 +195,9 @@ pub trait FromIterator: Sized { /// /// ```rust /// fn collect_as_strings(collection: T) -> Vec -/// where T: IntoIterator, -/// T::Item: std::fmt::Debug, +/// where +/// T: IntoIterator, +/// T::Item: std::fmt::Debug, /// { /// collection /// .into_iter() diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4d627383fd7cc..678ff7687921b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -132,6 +132,7 @@ #![feature(maybe_uninit_slice, maybe_uninit_array)] #![feature(external_doc)] #![feature(mem_take)] +#![feature(associated_type_bounds)] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 09d2331b60fed..f9dc53874acb1 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -302,6 +302,7 @@ macro_rules! debug_assert_ne { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated(since = "1.39.0", reason = "use the `?` operator instead")] #[doc(alias = "?")] macro_rules! r#try { ($expr:expr) => (match $expr { @@ -713,9 +714,9 @@ pub(crate) mod builtin { /// [`panic!`]: ../std/macro.panic.html #[stable(feature = "compile_error_macro", since = "1.20.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro compile_error { - ($msg:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! compile_error { + ($msg:expr) => ({ /* compiler built-in */ }); ($msg:expr,) => ({ /* compiler built-in */ }) } @@ -767,9 +768,10 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro format_args { - ($fmt:expr) => ({ /* compiler built-in */ }), + #[macro_export] + #[rustc_macro_transparency = "opaque"] + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) } @@ -779,9 +781,10 @@ pub(crate) mod builtin { language use and is subject to change")] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro format_args_nl { - ($fmt:expr) => ({ /* compiler built-in */ }), + #[macro_export] + #[rustc_macro_transparency = "opaque"] + macro_rules! format_args_nl { + ($fmt:expr) => ({ /* compiler built-in */ }); ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) } @@ -818,9 +821,9 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro env { - ($name:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! env { + ($name:expr) => ({ /* compiler built-in */ }); ($name:expr,) => ({ /* compiler built-in */ }) } @@ -845,9 +848,9 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro option_env { - ($name:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! option_env { + ($name:expr) => ({ /* compiler built-in */ }); ($name:expr,) => ({ /* compiler built-in */ }) } @@ -878,9 +881,9 @@ pub(crate) mod builtin { #[unstable(feature = "concat_idents", issue = "29599", reason = "`concat_idents` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro concat_idents { - ($($e:ident),+) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! concat_idents { + ($($e:ident),+) => ({ /* compiler built-in */ }); ($($e:ident,)+) => ({ /* compiler built-in */ }) } @@ -901,9 +904,9 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro concat { - ($($e:expr),*) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! concat { + ($($e:expr),*) => ({ /* compiler built-in */ }); ($($e:expr,)*) => ({ /* compiler built-in */ }) } @@ -930,8 +933,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro line() { /* compiler built-in */ } + #[macro_export] + macro_rules! line { () => { /* compiler built-in */ } } /// Expands to the column number at which it was invoked. /// @@ -956,15 +959,15 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro column() { /* compiler built-in */ } + #[macro_export] + macro_rules! column { () => { /* compiler built-in */ } } /// Same as `column`, but less likely to be shadowed. #[unstable(feature = "__rust_unstable_column", issue = "0", reason = "internal implementation detail of the `panic` macro")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro __rust_unstable_column() { /* compiler built-in */ } + #[macro_export] + macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } } /// Expands to the file name in which it was invoked. /// @@ -988,8 +991,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro file() { /* compiler built-in */ } + #[macro_export] + macro_rules! file { () => { /* compiler built-in */ } } /// Stringifies its arguments. /// @@ -1008,8 +1011,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro stringify($($t:tt)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! stringify { ($($t:tt)*) => { /* compiler built-in */ } } /// Includes a utf8-encoded file as a string. /// @@ -1043,9 +1046,9 @@ pub(crate) mod builtin { /// Compiling 'main.rs' and running the resulting binary will print "adiรณs". #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro include_str { - ($file:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! include_str { + ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }) } @@ -1081,9 +1084,9 @@ pub(crate) mod builtin { /// Compiling 'main.rs' and running the resulting binary will print "adiรณs". #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro include_bytes { - ($file:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! include_bytes { + ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }) } @@ -1106,8 +1109,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro module_path() { /* compiler built-in */ } + #[macro_export] + macro_rules! module_path { () => { /* compiler built-in */ } } /// Evaluates boolean combinations of configuration flags at compile-time. /// @@ -1131,8 +1134,8 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro cfg($($cfg:tt)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! cfg { ($($cfg:tt)*) => { /* compiler built-in */ } } /// Parses a file as an expression or an item according to the context. /// @@ -1175,9 +1178,9 @@ pub(crate) mod builtin { /// "๐Ÿ™ˆ๐Ÿ™Š๐Ÿ™‰๐Ÿ™ˆ๐Ÿ™Š๐Ÿ™‰". #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro include { - ($file:expr) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! include { + ($file:expr) => ({ /* compiler built-in */ }); ($file:expr,) => ({ /* compiler built-in */ }) } @@ -1228,10 +1231,10 @@ pub(crate) mod builtin { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro assert { - ($cond:expr) => ({ /* compiler built-in */ }), - ($cond:expr,) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! assert { + ($cond:expr) => ({ /* compiler built-in */ }); + ($cond:expr,) => ({ /* compiler built-in */ }); ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ }) } @@ -1239,34 +1242,34 @@ pub(crate) mod builtin { #[unstable(feature = "asm", issue = "29722", reason = "inline assembly is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro asm("assembly template" - : $("output"(operand),)* - : $("input"(operand),)* - : $("clobbers",)* - : $("options",)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! asm { ("assembly template" + : $("output"(operand),)* + : $("input"(operand),)* + : $("clobbers",)* + : $("options",)*) => { /* compiler built-in */ } } /// Module-level inline assembly. #[unstable(feature = "global_asm", issue = "35119", reason = "`global_asm!` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro global_asm("assembly") { /* compiler built-in */ } + #[macro_export] + macro_rules! global_asm { ("assembly") => { /* compiler built-in */ } } /// Prints passed tokens into the standard output. #[unstable(feature = "log_syntax", issue = "29598", reason = "`log_syntax!` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro log_syntax($($arg:tt)*) { /* compiler built-in */ } + #[macro_export] + macro_rules! log_syntax { ($($arg:tt)*) => { /* compiler built-in */ } } /// Enables or disables tracing functionality used for debugging other macros. #[unstable(feature = "trace_macros", issue = "29598", reason = "`trace_macros` is not stable enough for use and is subject to change")] #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - pub macro trace_macros { - (true) => ({ /* compiler built-in */ }), + #[macro_export] + macro_rules! trace_macros { + (true) => ({ /* compiler built-in */ }); (false) => ({ /* compiler built-in */ }) } @@ -1300,69 +1303,6 @@ pub(crate) mod builtin { #[rustc_macro_transparency = "semitransparent"] pub macro global_allocator($item:item) { /* compiler built-in */ } - /// Derive macro generating an impl of the trait `Clone`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] - pub macro Clone($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Copy`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] - pub macro Copy($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Debug`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Debug($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Default`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Default($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Eq`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics, derive_eq)] - pub macro Eq($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Hash`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Hash($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `Ord`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro Ord($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `PartialEq`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro PartialEq($item:item) { /* compiler built-in */ } - - /// Derive macro generating an impl of the trait `PartialOrd`. - #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] - #[stable(feature = "rust1", since = "1.0.0")] - #[allow_internal_unstable(core_intrinsics)] - pub macro PartialOrd($item:item) { /* compiler built-in */ } - /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 79a188dbac99d..78a273611650c 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -288,6 +288,14 @@ pub trait Copy : Clone { // Empty. } +/// Derive macro generating an impl of the trait `Copy`. +#[cfg(not(bootstrap))] +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy)] +pub macro Copy($item:item) { /* compiler built-in */ } + /// Types for which it is safe to share references between threads. /// /// This trait is automatically implemented when the compiler determines diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 8d064de6f4751..1bbea02e0c7c9 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -13,6 +13,7 @@ use crate::mem::ManuallyDrop; /// ever gets used to access memory: /// /// ```rust,no_run +/// # #![allow(invalid_value)] /// use std::mem::{self, MaybeUninit}; /// /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! @@ -27,6 +28,7 @@ use crate::mem::ManuallyDrop; /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: /// /// ```rust,no_run +/// # #![allow(invalid_value)] /// use std::mem::{self, MaybeUninit}; /// /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! @@ -40,6 +42,7 @@ use crate::mem::ManuallyDrop; /// which otherwise can hold any *fixed* bit pattern: /// /// ```rust,no_run +/// # #![allow(invalid_value)] /// use std::mem::{self, MaybeUninit}; /// /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 86dae985fdb00..2534400b8334f 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -445,15 +445,19 @@ pub const fn needs_drop() -> bool { /// /// *Incorrect* usage of this function: initializing a reference with zero. /// -/// ```no_run +/// ```rust,no_run +/// # #![allow(invalid_value)] /// use std::mem; /// /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated)] pub unsafe fn zeroed() -> T { - MaybeUninit::zeroed().assume_init() + intrinsics::panic_if_uninhabited::(); + intrinsics::init() } /// Bypasses Rust's normal memory-initialization checks by pretending to @@ -477,8 +481,11 @@ pub unsafe fn zeroed() -> T { #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated)] pub unsafe fn uninitialized() -> T { - MaybeUninit::uninit().assume_init() + intrinsics::panic_if_uninhabited::(); + intrinsics::uninit() } /// Swaps the values at two mutable locations, without deinitializing either one. diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 271ddcc4662cf..6efeaf9ee7d2e 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -440,10 +440,7 @@ where } } -impl Pin

-where - P::Target: Unpin, -{ +impl> Pin

{ /// Construct a new `Pin

` around a pointer to some data of a type that /// implements [`Unpin`]. /// @@ -731,10 +728,7 @@ impl Deref for Pin

{ } #[stable(feature = "pin", since = "1.33.0")] -impl DerefMut for Pin

-where - P::Target: Unpin -{ +impl> DerefMut for Pin

{ fn deref_mut(&mut self) -> &mut P::Target { Pin::get_mut(Pin::as_mut(self)) } diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index c503d8c701938..84cf85f339c99 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -48,24 +48,20 @@ pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros #[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow(deprecated)] #[doc(no_inline)] -pub use crate::macros::builtin::{ - Clone, - Copy, - Debug, - Default, - Eq, - Hash, - Ord, - PartialEq, - PartialOrd, - RustcDecodable, - RustcEncodable, +pub use crate::fmt::macros::Debug; +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::hash::macros::Hash; + +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::{ __rust_unstable_column, asm, assert, - bench, cfg, column, compile_error, @@ -75,7 +71,6 @@ pub use crate::macros::builtin::{ file, format_args, format_args_nl, - global_allocator, global_asm, include, include_bytes, @@ -85,7 +80,18 @@ pub use crate::macros::builtin::{ module_path, option_env, stringify, + trace_macros, +}; + +#[cfg(not(bootstrap))] +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] +#[doc(no_inline)] +pub use crate::macros::builtin::{ + RustcDecodable, + RustcEncodable, + bench, + global_allocator, test, test_case, - trace_macros, }; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index d5a34ea2bd5a1..ce5af13d4ca90 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1364,6 +1364,17 @@ impl [T] { /// let r = s.binary_search(&1); /// assert!(match r { Ok(1..=4) => true, _ => false, }); /// ``` + /// + /// If you want to insert an item to a sorted vector, while maintaining + /// sort order: + /// + /// ``` + /// let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + /// let num = 42; + /// let idx = s.binary_search(&num).unwrap_or_else(|x| x); + /// s.insert(idx, num); + /// assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn binary_search(&self, x: &T) -> Result where T: Ord diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 4faf9ff4d2ee2..f20cb7bfbc3bd 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -851,8 +851,9 @@ unsafe impl TrustedRandomAccess for Bytes<'_> { /// wrapper types of the form X<'a, P> macro_rules! derive_pattern_clone { (clone $t:ident with |$s:ident| $e:expr) => { - impl<'a, P: Pattern<'a>> Clone for $t<'a, P> - where P::Searcher: Clone + impl<'a, P> Clone for $t<'a, P> + where + P: Pattern<'a, Searcher: Clone>, { fn clone(&self) -> Self { let $s = self; @@ -928,8 +929,9 @@ macro_rules! generate_pattern_iterators { pub struct $forward_iterator<'a, P: Pattern<'a>>($internal_iterator<'a, P>); $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> fmt::Debug for $forward_iterator<'a, P> - where P::Searcher: fmt::Debug + impl<'a, P> fmt::Debug for $forward_iterator<'a, P> + where + P: Pattern<'a, Searcher: fmt::Debug>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple(stringify!($forward_iterator)) @@ -949,8 +951,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> Clone for $forward_iterator<'a, P> - where P::Searcher: Clone + impl<'a, P> Clone for $forward_iterator<'a, P> + where + P: Pattern<'a, Searcher: Clone>, { fn clone(&self) -> Self { $forward_iterator(self.0.clone()) @@ -962,8 +965,9 @@ macro_rules! generate_pattern_iterators { pub struct $reverse_iterator<'a, P: Pattern<'a>>($internal_iterator<'a, P>); $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> fmt::Debug for $reverse_iterator<'a, P> - where P::Searcher: fmt::Debug + impl<'a, P> fmt::Debug for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: fmt::Debug>, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple(stringify!($reverse_iterator)) @@ -973,8 +977,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> Iterator for $reverse_iterator<'a, P> - where P::Searcher: ReverseSearcher<'a> + impl<'a, P> Iterator for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { type Item = $iterty; @@ -985,8 +990,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> Clone for $reverse_iterator<'a, P> - where P::Searcher: Clone + impl<'a, P> Clone for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: Clone>, { fn clone(&self) -> Self { $reverse_iterator(self.0.clone()) @@ -997,8 +1003,10 @@ macro_rules! generate_pattern_iterators { impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {} #[stable(feature = "fused", since = "1.26.0")] - impl<'a, P: Pattern<'a>> FusedIterator for $reverse_iterator<'a, P> - where P::Searcher: ReverseSearcher<'a> {} + impl<'a, P> FusedIterator for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, + {} generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*, $forward_iterator, @@ -1010,8 +1018,9 @@ macro_rules! generate_pattern_iterators { $reverse_iterator:ident, $iterty:ty } => { $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> DoubleEndedIterator for $forward_iterator<'a, P> - where P::Searcher: DoubleEndedSearcher<'a> + impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P> + where + P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, { #[inline] fn next_back(&mut self) -> Option<$iterty> { @@ -1020,8 +1029,9 @@ macro_rules! generate_pattern_iterators { } $(#[$common_stability_attribute])* - impl<'a, P: Pattern<'a>> DoubleEndedIterator for $reverse_iterator<'a, P> - where P::Searcher: DoubleEndedSearcher<'a> + impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P> + where + P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, { #[inline] fn next_back(&mut self) -> Option<$iterty> { @@ -1049,7 +1059,10 @@ struct SplitInternal<'a, P: Pattern<'a>> { finished: bool, } -impl<'a, P: Pattern<'a>> fmt::Debug for SplitInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for SplitInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SplitInternal") .field("start", &self.start) @@ -1166,7 +1179,10 @@ struct SplitNInternal<'a, P: Pattern<'a>> { count: usize, } -impl<'a, P: Pattern<'a>> fmt::Debug for SplitNInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for SplitNInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SplitNInternal") .field("iter", &self.iter) @@ -1222,7 +1238,10 @@ derive_pattern_clone!{ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher); -impl<'a, P: Pattern<'a>> fmt::Debug for MatchIndicesInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("MatchIndicesInternal") .field(&self.0) @@ -1273,7 +1292,10 @@ derive_pattern_clone!{ struct MatchesInternal<'a, P: Pattern<'a>>(P::Searcher); -impl<'a, P: Pattern<'a>> fmt::Debug for MatchesInternal<'a, P> where P::Searcher: fmt::Debug { +impl<'a, P> fmt::Debug for MatchesInternal<'a, P> +where + P: Pattern<'a, Searcher: fmt::Debug>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("MatchesInternal") .field(&self.0) @@ -2882,8 +2904,9 @@ impl str { /// assert!(!bananas.ends_with("nana")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool - where P::Searcher: ReverseSearcher<'a> + pub fn ends_with<'a, P>(&'a self, pat: P) -> bool + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { pat.is_suffix_of(self) } @@ -2975,8 +2998,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option - where P::Searcher: ReverseSearcher<'a> + pub fn rfind<'a, P>(&'a self, pat: P) -> Option + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { pat.into_searcher(self).next_match_back().map(|(i, _)| i) } @@ -3142,8 +3166,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rsplit<'a, P>(&'a self, pat: P) -> RSplit<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RSplit(self.split(pat).0) } @@ -3233,8 +3258,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rsplit_terminator<'a, P>(&'a self, pat: P) -> RSplitTerminator<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RSplitTerminator(self.split_terminator(pat).0) } @@ -3333,8 +3359,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rsplitn<'a, P>(&'a self, n: usize, pat: P) -> RSplitN<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RSplitN(self.splitn(n, pat).0) } @@ -3406,8 +3433,9 @@ impl str { /// ``` #[stable(feature = "str_matches", since = "1.2.0")] #[inline] - pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rmatches<'a, P>(&'a self, pat: P) -> RMatches<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RMatches(self.matches(pat).0) } @@ -3491,8 +3519,9 @@ impl str { /// ``` #[stable(feature = "str_match_indices", since = "1.5.0")] #[inline] - pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> - where P::Searcher: ReverseSearcher<'a> + pub fn rmatch_indices<'a, P>(&'a self, pat: P) -> RMatchIndices<'a, P> + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { RMatchIndices(self.match_indices(pat).0) } @@ -3700,8 +3729,9 @@ impl str { #[must_use = "this returns the trimmed string as a new slice, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: DoubleEndedSearcher<'a> + pub fn trim_matches<'a, P>(&'a self, pat: P) -> &'a str + where + P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>, { let mut i = 0; let mut j = 0; @@ -3792,8 +3822,9 @@ impl str { #[must_use = "this returns the trimmed string as a new slice, \ without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] - pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> + pub fn trim_end_matches<'a, P>(&'a self, pat: P) -> &'a str + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { let mut j = 0; let mut matcher = pat.into_searcher(self); @@ -3880,8 +3911,9 @@ impl str { reason = "superseded by `trim_end_matches`", suggestion = "trim_end_matches", )] - pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str - where P::Searcher: ReverseSearcher<'a> + pub fn trim_right_matches<'a, P>(&'a self, pat: P) -> &'a str + where + P: Pattern<'a, Searcher: ReverseSearcher<'a>>, { self.trim_end_matches(pat) } diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index 0e71426c64108..46eacb4200acc 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -77,6 +77,7 @@ fn infinity() { fn zero() { test_literal!(0.0); test_literal!(1e-325); + #[cfg(not(miri))] // Miri is too slow test_literal!(1e-326); #[cfg(not(miri))] // Miri is too slow test_literal!(1e-500); diff --git a/src/libcore/tests/num/flt2dec/estimator.rs b/src/libcore/tests/num/flt2dec/estimator.rs index 2dbb8e3a5f06e..c51451708f3ce 100644 --- a/src/libcore/tests/num/flt2dec/estimator.rs +++ b/src/libcore/tests/num/flt2dec/estimator.rs @@ -42,7 +42,12 @@ fn test_estimate_scaling_factor() { assert_almost_eq!(estimate_scaling_factor(1, -1074), -323); assert_almost_eq!(estimate_scaling_factor(0x1fffffffffffff, 971), 309); - for i in -1074..972 { + #[cfg(not(miri))] // Miri is too slow + let iter = -1074..972; + #[cfg(miri)] + let iter = (-1074..972).step_by(37); + + for i in iter { let expected = super::ldexp_f64(1.0, i).log10().ceil(); assert_almost_eq!(estimate_scaling_factor(1, i as i16), expected as i16); } diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs index f42f500c2df1d..c41d35efced6c 100644 --- a/src/libcore/tests/num/flt2dec/mod.rs +++ b/src/libcore/tests/num/flt2dec/mod.rs @@ -1,5 +1,3 @@ -#![cfg(not(miri))] // Miri does not implement ldexp, which most tests here need - use std::prelude::v1::*; use std::{str, i16, f32, f64, fmt}; @@ -257,6 +255,7 @@ pub fn f32_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) check_shortest!(f(minf32) => b"1", -44); } +#[cfg(not(miri))] // Miri is too slow pub fn f32_exact_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { let minf32 = ldexp_f32(1.0, -149); @@ -362,6 +361,7 @@ pub fn f64_shortest_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8]) check_shortest!(f(minf64) => b"5", -323); } +#[cfg(not(miri))] // Miri is too slow pub fn f64_exact_sanity_test(mut f: F) where F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { let minf64 = ldexp_f64(1.0, -1074); @@ -553,6 +553,10 @@ pub fn to_shortest_str_test(mut f_: F) assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", "")); assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", "")); + if cfg!(miri) { // Miri is too slow + return; + } + // very large output assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", "")); } @@ -807,6 +811,10 @@ pub fn to_exact_exp_str_test(mut f_: F) "1.401298464324817070923729583289916131280261941876515771757068283\ 8897910826858606014866381883621215820312500000000000000000000000e-45"); + if cfg!(miri) { // Miri is too slow + return; + } + assert_eq!(to_string(f, f64::MAX, Minus, 1, false), "2e308"); assert_eq!(to_string(f, f64::MAX, Minus, 2, false), "1.8e308"); assert_eq!(to_string(f, f64::MAX, Minus, 4, false), "1.798e308"); @@ -1040,6 +1048,10 @@ pub fn to_exact_fixed_str_test(mut f_: F) assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "340282346638528859811704183484516925440.00"); + if cfg!(miri) { // Miri is too slow + return; + } + let minf32 = ldexp_f32(1.0, -149); assert_eq!(to_string(f, minf32, Minus, 0, false), "0"); assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0"); diff --git a/src/libcore/tests/num/flt2dec/random.rs b/src/libcore/tests/num/flt2dec/random.rs index d56787b2819a7..d9543793397bf 100644 --- a/src/libcore/tests/num/flt2dec/random.rs +++ b/src/libcore/tests/num/flt2dec/random.rs @@ -109,8 +109,13 @@ pub fn f32_exhaustive_equivalence_test(f: F, g: G, k: usize) #[test] fn shortest_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_shortest as fallback; - f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); - f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, 10_000); + #[cfg(not(miri))] // Miri is too slow + const N: usize = 10_000; + #[cfg(miri)] + const N: usize = 10; + + f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, N); + f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, N); } #[test] #[ignore] // it is too expensive @@ -138,17 +143,27 @@ fn shortest_f64_hard_random_equivalence_test() { #[test] fn exact_f32_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_exact as fallback; + #[cfg(not(miri))] // Miri is too slow + const N: usize = 1_000; + #[cfg(miri)] + const N: usize = 3; + for k in 1..21 { f32_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); + |d, buf| fallback(d, buf, i16::MIN), k, N); } } #[test] fn exact_f64_random_equivalence_test() { use core::num::flt2dec::strategy::dragon::format_exact as fallback; + #[cfg(not(miri))] // Miri is too slow + const N: usize = 1_000; + #[cfg(miri)] + const N: usize = 3; + for k in 1..21 { f64_random_equivalence_test(|d, buf| format_exact_opt(d, buf, i16::MIN), - |d, buf| fallback(d, buf, i16::MIN), k, 1_000); + |d, buf| fallback(d, buf, i16::MIN), k, N); } } diff --git a/src/libcore/tests/num/flt2dec/strategy/dragon.rs b/src/libcore/tests/num/flt2dec/strategy/dragon.rs index 5e4cc23d33c8c..dc4d78bfae109 100644 --- a/src/libcore/tests/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/tests/num/flt2dec/strategy/dragon.rs @@ -23,6 +23,7 @@ fn shortest_sanity_test() { } #[test] +#[cfg(not(miri))] // Miri is too slow fn exact_sanity_test() { // This test ends up running what I can only assume is some corner-ish case // of the `exp2` library function, defined in whatever C runtime we're diff --git a/src/libcore/tests/num/flt2dec/strategy/grisu.rs b/src/libcore/tests/num/flt2dec/strategy/grisu.rs index f1afd7d4bf86f..f8bdddfe2e410 100644 --- a/src/libcore/tests/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/tests/num/flt2dec/strategy/grisu.rs @@ -36,6 +36,7 @@ fn shortest_sanity_test() { } #[test] +#[cfg(not(miri))] // Miri is too slow fn exact_sanity_test() { // See comments in dragon.rs's exact_sanity_test for why this test is // ignored on MSVC diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 1ef77f87ab7e2..4790152512a39 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -3,19 +3,19 @@ use core::result::Result::{Ok, Err}; #[test] fn test_position() { let b = [1, 2, 3, 5, 5]; - assert!(b.iter().position(|&v| v == 9) == None); - assert!(b.iter().position(|&v| v == 5) == Some(3)); - assert!(b.iter().position(|&v| v == 3) == Some(2)); - assert!(b.iter().position(|&v| v == 0) == None); + assert_eq!(b.iter().position(|&v| v == 9), None); + assert_eq!(b.iter().position(|&v| v == 5), Some(3)); + assert_eq!(b.iter().position(|&v| v == 3), Some(2)); + assert_eq!(b.iter().position(|&v| v == 0), None); } #[test] fn test_rposition() { let b = [1, 2, 3, 5, 5]; - assert!(b.iter().rposition(|&v| v == 9) == None); - assert!(b.iter().rposition(|&v| v == 5) == Some(4)); - assert!(b.iter().rposition(|&v| v == 3) == Some(2)); - assert!(b.iter().rposition(|&v| v == 0) == None); + assert_eq!(b.iter().rposition(|&v| v == 9), None); + assert_eq!(b.iter().rposition(|&v| v == 5), Some(4)); + assert_eq!(b.iter().rposition(|&v| v == 3), Some(2)); + assert_eq!(b.iter().rposition(|&v| v == 0), None); } #[test] @@ -1153,7 +1153,7 @@ fn test_rotate_right() { } #[test] -#[cfg(not(miri))] +#[cfg(not(miri))] // Miri is too slow fn brute_force_rotate_test_0() { // In case of edge cases involving multiple algorithms let n = 300; diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs index 6efd22572dc18..fac70c468c89d 100644 --- a/src/libcore/tests/time.rs +++ b/src/libcore/tests/time.rs @@ -2,7 +2,7 @@ use core::time::Duration; #[test] fn creation() { - assert!(Duration::from_secs(1) != Duration::from_secs(0)); + assert_ne!(Duration::from_secs(1), Duration::from_secs(0)); assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), Duration::from_secs(3)); assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), diff --git a/src/libcore/time.rs b/src/libcore/time.rs index 0f5f91f41a8cd..5a0e4388e0325 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -505,15 +505,14 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::new(2, 700_000_000); /// assert_eq!(dur.as_secs_f64(), 2.7); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub const fn as_secs_f64(&self) -> f64 { + pub fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64) } @@ -523,15 +522,14 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::new(2, 700_000_000); /// assert_eq!(dur.as_secs_f32(), 2.7); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] - pub const fn as_secs_f32(&self) -> f32 { + pub fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32) } @@ -543,13 +541,12 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::from_secs_f64(2.7); /// assert_eq!(dur, Duration::new(2, 700_000_000)); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn from_secs_f64(secs: f64) -> Duration { const MAX_NANOS_F64: f64 = @@ -579,13 +576,12 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::from_secs_f32(2.7); /// assert_eq!(dur, Duration::new(2, 700_000_000)); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn from_secs_f32(secs: f32) -> Duration { const MAX_NANOS_F32: f32 = @@ -614,14 +610,13 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::new(2, 700_000_000); /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000)); /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0)); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn mul_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(rhs * self.as_secs_f64()) @@ -634,7 +629,6 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::new(2, 700_000_000); @@ -643,7 +637,7 @@ impl Duration { /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_640)); /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847799, 969_120_256)); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn mul_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(rhs * self.as_secs_f32()) @@ -656,7 +650,6 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::new(2, 700_000_000); @@ -664,7 +657,7 @@ impl Duration { /// // note that truncation is used, not rounding /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598)); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn div_f64(self, rhs: f64) -> Duration { Duration::from_secs_f64(self.as_secs_f64() / rhs) @@ -677,7 +670,6 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] /// use std::time::Duration; /// /// let dur = Duration::new(2, 700_000_000); @@ -687,7 +679,7 @@ impl Duration { /// // note that truncation is used, not rounding /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_598)); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[stable(feature = "duration_float", since = "1.38.0")] #[inline] pub fn div_f32(self, rhs: f32) -> Duration { Duration::from_secs_f32(self.as_secs_f32() / rhs) @@ -697,14 +689,14 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] + /// #![feature(div_duration)] /// use std::time::Duration; /// /// let dur1 = Duration::new(2, 700_000_000); /// let dur2 = Duration::new(5, 400_000_000); /// assert_eq!(dur1.div_duration_f64(dur2), 0.5); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[unstable(feature = "div_duration", issue = "63139")] #[inline] pub fn div_duration_f64(self, rhs: Duration) -> f64 { self.as_secs_f64() / rhs.as_secs_f64() @@ -714,14 +706,14 @@ impl Duration { /// /// # Examples /// ``` - /// #![feature(duration_float)] + /// #![feature(div_duration)] /// use std::time::Duration; /// /// let dur1 = Duration::new(2, 700_000_000); /// let dur2 = Duration::new(5, 400_000_000); /// assert_eq!(dur1.div_duration_f32(dur2), 0.5); /// ``` - #[unstable(feature = "duration_float", issue = "54361")] + #[unstable(feature = "div_duration", issue = "63139")] #[inline] pub fn div_duration_f32(self, rhs: Duration) -> f32 { self.as_secs_f32() / rhs.as_secs_f32() diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs index bfe784afaa47d..3fae3a46ada6b 100644 --- a/src/libcore/unicode/tables.rs +++ b/src/libcore/unicode/tables.rs @@ -14,8 +14,8 @@ pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { micro: 0, _priv: (), }; -pub mod general_category { - pub const Cc_table: &super::SmallBoolTrie = &super::SmallBoolTrie { +pub(crate) mod general_category { + const Cc_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 0 ], @@ -28,7 +28,7 @@ pub mod general_category { Cc_table.lookup(c) } - pub const N_table: &super::BoolTrie = &super::BoolTrie { + const N_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x03ff000000000000, 0x0000000000000000, 0x720c000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, @@ -141,8 +141,8 @@ pub mod general_category { } -pub mod derived_property { - pub const Alphabetic_table: &super::BoolTrie = &super::BoolTrie { +pub(crate) mod derived_property { + const Alphabetic_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, @@ -327,7 +327,7 @@ pub mod derived_property { Alphabetic_table.lookup(c) } - pub const Case_Ignorable_table: &super::BoolTrie = &super::BoolTrie { + const Case_Ignorable_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0400408000000000, 0x0000000140000000, 0x0190a10000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, @@ -464,7 +464,7 @@ pub mod derived_property { Case_Ignorable_table.lookup(c) } - pub const Cased_table: &super::BoolTrie = &super::BoolTrie { + const Cased_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xf7ffffffffffffff, 0xfffffffffffffff0, @@ -565,7 +565,7 @@ pub mod derived_property { Cased_table.lookup(c) } - pub const Grapheme_Extend_table: &super::BoolTrie = &super::BoolTrie { + const Grapheme_Extend_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, @@ -689,7 +689,7 @@ pub mod derived_property { Grapheme_Extend_table.lookup(c) } - pub const Lowercase_table: &super::BoolTrie = &super::BoolTrie { + const Lowercase_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe00000000, 0x0420040000000000, 0xff7fffff80000000, 0x55aaaaaaaaaaaaaa, 0xd4aaaaaaaaaaab55, 0xe6512d2a4e243129, 0xaa29aaaab5555240, @@ -789,7 +789,7 @@ pub mod derived_property { Lowercase_table.lookup(c) } - pub const Uppercase_table: &super::BoolTrie = &super::BoolTrie { + const Uppercase_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x0000000007fffffe, 0x0000000000000000, 0x000000007f7fffff, 0xaa55555555555555, 0x2b555555555554aa, 0x11aed2d5b1dbced6, 0x55d255554aaaa490, @@ -890,7 +890,7 @@ pub mod derived_property { Uppercase_table.lookup(c) } - pub const XID_Continue_table: &super::BoolTrie = &super::BoolTrie { + const XID_Continue_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x03ff000000000000, 0x07fffffe87fffffe, 0x04a0040000000000, 0xff7fffffff7fffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, @@ -1068,7 +1068,7 @@ pub mod derived_property { XID_Continue_table.lookup(c) } - pub const XID_Start_table: &super::BoolTrie = &super::BoolTrie { + const XID_Start_table: &super::BoolTrie = &super::BoolTrie { r1: [ 0x0000000000000000, 0x07fffffe07fffffe, 0x0420040000000000, 0xff7fffffff7fffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, @@ -1250,8 +1250,8 @@ pub mod derived_property { } -pub mod property { - pub const Pattern_White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { +pub(crate) mod property { + const Pattern_White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1268,7 +1268,7 @@ pub mod property { Pattern_White_Space_table.lookup(c) } - pub const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { + const White_Space_table: &super::SmallBoolTrie = &super::SmallBoolTrie { r1: &[ 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1290,7 +1290,7 @@ pub mod property { } -pub mod conversions { +pub(crate) mod conversions { pub fn to_lower(c: char) -> [char; 3] { match bsearch_case_table(c, to_lowercase_table) { None => [c, '\0', '\0'], diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index 5389d1cf80383..6de5d9e033b93 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -606,7 +606,7 @@ def compute_trie(raw_data, chunk_size): return root, child_data -def generate_bool_trie(name, codepoint_ranges, is_pub=True): +def generate_bool_trie(name, codepoint_ranges, is_pub=False): # type: (str, List[Tuple[int, int]], bool) -> Iterator[str] """ Generate Rust code for BoolTrie struct. @@ -681,7 +681,7 @@ def generate_bool_trie(name, codepoint_ranges, is_pub=True): yield " };\n\n" -def generate_small_bool_trie(name, codepoint_ranges, is_pub=True): +def generate_small_bool_trie(name, codepoint_ranges, is_pub=False): # type: (str, List[Tuple[int, int]], bool) -> Iterator[str] """ Generate Rust code for `SmallBoolTrie` struct. @@ -726,7 +726,7 @@ def generate_property_module(mod, grouped_categories, category_subset): Generate Rust code for module defining properties. """ - yield "pub mod %s {\n" % mod + yield "pub(crate) mod %s {\n" % mod for cat in sorted(category_subset): if cat in ("Cc", "White_Space", "Pattern_White_Space"): generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat]) @@ -749,7 +749,7 @@ def generate_conversions_module(unicode_data): Generate Rust code for module defining conversions. """ - yield "pub mod conversions {" + yield "pub(crate) mod conversions {" yield """ pub fn to_lower(c: char) -> [char; 3] { match bsearch_case_table(c, to_lowercase_table) { diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 40992e927444b..f83fbcdc263b0 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -1,4 +1,4 @@ -use crate::hir::def_id::DefId; +use crate::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::util::nodemap::DefIdMap; use syntax::ast; use syntax::ext::base::MacroKind; @@ -81,9 +81,11 @@ pub enum DefKind { } impl DefKind { - pub fn descr(self) -> &'static str { + pub fn descr(self, def_id: DefId) -> &'static str { match self { DefKind::Fn => "function", + DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => + "crate", DefKind::Mod => "module", DefKind::Static => "static", DefKind::Enum => "enum", @@ -366,7 +368,7 @@ impl Res { /// A human readable name for the res kind ("function", "module", etc.). pub fn descr(&self) -> &'static str { match *self { - Res::Def(kind, _) => kind.descr(), + Res::Def(kind, def_id) => kind.descr(def_id), Res::SelfCtor(..) => "self constructor", Res::PrimTy(..) => "builtin type", Res::Local(..) => "local variable", diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 493083c680aad..fe69c9e634635 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -32,12 +32,15 @@ //! get confused if the spans from leaf AST nodes occur in multiple places //! in the HIR, especially for multiple identifiers. +mod expr; +mod item; + use crate::dep_graph::DepGraph; use crate::hir::{self, ParamName}; use crate::hir::HirVec; use crate::hir::map::{DefKey, DefPathData, Definitions}; use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; -use crate::hir::def::{Res, DefKind, PartialRes, PerNS}; +use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::hir::ptr::P; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, @@ -53,7 +56,7 @@ use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::sync::Lrc; -use std::collections::{BTreeSet, BTreeMap}; +use std::collections::BTreeMap; use std::mem; use smallvec::SmallVec; use syntax::attr; @@ -148,13 +151,6 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - /// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc. - fn resolve_ast_path( - &mut self, - path: &ast::Path, - is_value: bool, - ) -> Res; - /// Obtain resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; @@ -175,7 +171,7 @@ pub trait Resolver { span: Span, crate_root: Option, components: &[Symbol], - is_value: bool, + ns: Namespace, ) -> (ast::Path, Res); fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; @@ -568,90 +564,11 @@ impl<'a> LoweringContext<'a> { } } - struct ItemLowerer<'tcx, 'interner> { - lctx: &'tcx mut LoweringContext<'interner>, - } - - impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> { - fn with_trait_impl_ref(&mut self, trait_impl_ref: &Option, f: F) - where - F: FnOnce(&mut Self), - { - let old = self.lctx.is_in_trait_impl; - self.lctx.is_in_trait_impl = if let &None = trait_impl_ref { - false - } else { - true - }; - f(self); - self.lctx.is_in_trait_impl = old; - } - } - - impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { - fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) { - self.lctx.modules.insert(n, hir::ModuleItems { - items: BTreeSet::new(), - trait_items: BTreeSet::new(), - impl_items: BTreeSet::new(), - }); - - let old = self.lctx.current_module; - self.lctx.current_module = n; - visit::walk_mod(self, m); - self.lctx.current_module = old; - } - - fn visit_item(&mut self, item: &'tcx Item) { - let mut item_hir_id = None; - self.lctx.with_hir_id_owner(item.id, |lctx| { - if let Some(hir_item) = lctx.lower_item(item) { - item_hir_id = Some(hir_item.hir_id); - lctx.insert_item(hir_item); - } - }); - - if let Some(hir_id) = item_hir_id { - self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { - let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.node { - this.with_trait_impl_ref(opt_trait_ref, |this| { - visit::walk_item(this, item) - }); - } else { - visit::walk_item(this, item); - } - }); - } - } - - fn visit_trait_item(&mut self, item: &'tcx TraitItem) { - self.lctx.with_hir_id_owner(item.id, |lctx| { - let hir_item = lctx.lower_trait_item(item); - let id = hir::TraitItemId { hir_id: hir_item.hir_id }; - lctx.trait_items.insert(id, hir_item); - lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id); - }); - - visit::walk_trait_item(self, item); - } - - fn visit_impl_item(&mut self, item: &'tcx ImplItem) { - self.lctx.with_hir_id_owner(item.id, |lctx| { - let hir_item = lctx.lower_impl_item(item); - let id = hir::ImplItemId { hir_id: hir_item.hir_id }; - lctx.impl_items.insert(id, hir_item); - lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id); - }); - visit::walk_impl_item(self, item); - } - } - self.lower_node_id(CRATE_NODE_ID); debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == hir::CRATE_HIR_ID); visit::walk_crate(&mut MiscCollector { lctx: &mut self, hir_id_owner: None }, c); - visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c); + visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); let module = self.lower_mod(&c.module); let attrs = self.lower_attrs(&c.attrs); @@ -790,57 +707,6 @@ impl<'a> LoweringContext<'a> { }) } - fn generator_movability_for_fn( - &mut self, - decl: &ast::FnDecl, - fn_decl_span: Span, - generator_kind: Option, - movability: Movability, - ) -> Option { - match generator_kind { - Some(hir::GeneratorKind::Gen) => { - if !decl.inputs.is_empty() { - span_err!( - self.sess, - fn_decl_span, - E0628, - "generators cannot have explicit arguments" - ); - self.sess.abort_if_errors(); - } - Some(match movability { - Movability::Movable => hir::GeneratorMovability::Movable, - Movability::Static => hir::GeneratorMovability::Static, - }) - }, - Some(hir::GeneratorKind::Async) => { - bug!("non-`async` closure body turned `async` during lowering"); - }, - None => { - if movability == Movability::Static { - span_err!( - self.sess, - fn_decl_span, - E0697, - "closures cannot be static" - ); - } - None - }, - } - } - - fn record_body(&mut self, arguments: HirVec, value: hir::Expr) -> hir::BodyId { - let body = hir::Body { - generator_kind: self.generator_kind, - arguments, - value, - }; - let id = body.id(); - self.bodies.insert(id, body); - id - } - fn next_id(&mut self) -> hir::HirId { self.lower_node_id(self.sess.next_node_id()) } @@ -1044,38 +910,6 @@ impl<'a> LoweringContext<'a> { res } - // Same as the method above, but accepts `hir::GenericParam`s - // instead of `ast::GenericParam`s. - // This should only be used with generics that have already had their - // in-band lifetimes added. In practice, this means that this function is - // only used when lowering a child item of a trait or impl. - fn with_parent_item_lifetime_defs(&mut self, - parent_hir_id: hir::HirId, - f: F - ) -> T where - F: FnOnce(&mut LoweringContext<'_>) -> T, - { - let old_len = self.in_scope_lifetimes.len(); - - let parent_generics = match self.items.get(&parent_hir_id).unwrap().node { - hir::ItemKind::Impl(_, _, _, ref generics, ..) - | hir::ItemKind::Trait(_, _, ref generics, ..) => { - &generics.params[..] - } - _ => &[], - }; - let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()), - _ => None, - }); - self.in_scope_lifetimes.extend(lt_def_names); - - let res = f(self); - - self.in_scope_lifetimes.truncate(old_len); - res - } - /// Appends in-band lifetime defs and argument-position `impl /// Trait` defs to the existing set of generics. /// @@ -1137,131 +971,6 @@ impl<'a> LoweringContext<'a> { (lowered_generics, res) } - fn with_catch_scope(&mut self, catch_id: NodeId, f: F) -> T - where - F: FnOnce(&mut LoweringContext<'_>) -> T, - { - let len = self.catch_scopes.len(); - self.catch_scopes.push(catch_id); - - let result = f(self); - assert_eq!( - len + 1, - self.catch_scopes.len(), - "catch scopes should be added and removed in stack order" - ); - - self.catch_scopes.pop().unwrap(); - - result - } - - fn make_async_expr( - &mut self, - capture_clause: CaptureBy, - closure_node_id: NodeId, - ret_ty: Option>, - span: Span, - body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, - ) -> hir::ExprKind { - let capture_clause = self.lower_capture_clause(capture_clause); - let output = match ret_ty { - Some(ty) => FunctionRetTy::Ty(ty), - None => FunctionRetTy::Default(span), - }; - let ast_decl = FnDecl { - inputs: vec![], - output, - c_variadic: false - }; - let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); - let body_id = self.lower_fn_body(&ast_decl, |this| { - this.generator_kind = Some(hir::GeneratorKind::Async); - body(this) - }); - let generator = hir::Expr { - hir_id: self.lower_node_id(closure_node_id), - node: hir::ExprKind::Closure(capture_clause, decl, body_id, span, - Some(hir::GeneratorMovability::Static)), - span, - attrs: ThinVec::new(), - }; - - let unstable_span = self.mark_span_with_reason( - DesugaringKind::Async, - span, - self.allow_gen_future.clone(), - ); - let gen_future = self.expr_std_path( - unstable_span, &[sym::future, sym::from_generator], None, ThinVec::new()); - hir::ExprKind::Call(P(gen_future), hir_vec![generator]) - } - - fn lower_body( - &mut self, - f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec, hir::Expr), - ) -> hir::BodyId { - let prev_gen_kind = self.generator_kind.take(); - let (arguments, result) = f(self); - let body_id = self.record_body(arguments, result); - self.generator_kind = prev_gen_kind; - body_id - } - - fn lower_fn_body( - &mut self, - decl: &FnDecl, - body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr, - ) -> hir::BodyId { - self.lower_body(|this| ( - decl.inputs.iter().map(|x| this.lower_arg(x)).collect(), - body(this), - )) - } - - fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId { - self.lower_body(|this| (hir_vec![], this.lower_expr(expr))) - } - - fn with_loop_scope(&mut self, loop_id: NodeId, f: F) -> T - where - F: FnOnce(&mut LoweringContext<'_>) -> T, - { - // We're no longer in the base loop's condition; we're in another loop. - let was_in_loop_condition = self.is_in_loop_condition; - self.is_in_loop_condition = false; - - let len = self.loop_scopes.len(); - self.loop_scopes.push(loop_id); - - let result = f(self); - assert_eq!( - len + 1, - self.loop_scopes.len(), - "loop scopes should be added and removed in stack order" - ); - - self.loop_scopes.pop().unwrap(); - - self.is_in_loop_condition = was_in_loop_condition; - - result - } - - fn with_loop_condition_scope(&mut self, f: F) -> T - where - F: FnOnce(&mut LoweringContext<'_>) -> T, - { - let was_in_loop_condition = self.is_in_loop_condition; - self.is_in_loop_condition = true; - - let result = f(self); - - self.is_in_loop_condition = was_in_loop_condition; - - result - } - fn with_dyn_type_scope(&mut self, in_scope: bool, f: F) -> T where F: FnOnce(&mut LoweringContext<'_>) -> T, @@ -1302,36 +1011,6 @@ impl<'a> LoweringContext<'a> { } } - fn lower_label(&mut self, label: OptionRun"#, - url, test_escaped, channel, edition_string - )) - }); - - let tooltip = if ignore { - Some(("This example is not tested".to_owned(), "ignore")) - } else if compile_fail { - Some(("This example deliberately fails to compile".to_owned(), "compile_fail")) - } else if explicit_edition { - Some((format!("This code runs with edition {}", edition), "edition")) + // insert newline to clearly separate it from the + // previous block so we can shorten the html output + let mut s = String::from("\n"); + let playground_button = self.playground.as_ref().and_then(|playground| { + let krate = &playground.crate_name; + let url = &playground.url; + if url.is_empty() { + return None; + } + let test = origtext.lines() + .map(|l| map_line(l).for_code()) + .collect::>>().join("\n"); + let krate = krate.as_ref().map(|s| &**s); + let (test, _) = test::make_test(&test, krate, false, + &Default::default(), edition); + let channel = if test.contains("#![feature(") { + "&version=nightly" } else { - None + "" }; - if let Some((s1, s2)) = tooltip { - s.push_str(&highlight::render_with_highlighting( - &text, - Some(&format!("rust-example-rendered{}", - if ignore { " ignore" } - else if compile_fail { " compile_fail" } - else if explicit_edition { " edition " } - else { "" })), - playground_button.as_ref().map(String::as_str), - Some((s1.as_str(), s2)))); - Some(Event::Html(s.into())) - } else { - s.push_str(&highlight::render_with_highlighting( - &text, - Some(&format!("rust-example-rendered{}", - if ignore { " ignore" } - else if compile_fail { " compile_fail" } - else if explicit_edition { " edition " } - else { "" })), - playground_button.as_ref().map(String::as_str), - None)); - Some(Event::Html(s.into())) + let edition_string = format!("&edition={}", edition); + + // These characters don't need to be escaped in a URI. + // FIXME: use a library function for percent encoding. + fn dont_escape(c: u8) -> bool { + (b'a' <= c && c <= b'z') || + (b'A' <= c && c <= b'Z') || + (b'0' <= c && c <= b'9') || + c == b'-' || c == b'_' || c == b'.' || + c == b'~' || c == b'!' || c == b'\'' || + c == b'(' || c == b')' || c == b'*' + } + let mut test_escaped = String::new(); + for b in test.bytes() { + if dont_escape(b) { + test_escaped.push(char::from(b)); + } else { + write!(test_escaped, "%{:02X}", b).unwrap(); + } } - }) + Some(format!( + r#"Run"#, + url, test_escaped, channel, edition_string + )) + }); + + let tooltip = if ignore { + Some(("This example is not tested".to_owned(), "ignore")) + } else if compile_fail { + Some(("This example deliberately fails to compile".to_owned(), "compile_fail")) + } else if explicit_edition { + Some((format!("This code runs with edition {}", edition), "edition")) + } else { + None + }; + + if let Some((s1, s2)) = tooltip { + s.push_str(&highlight::render_with_highlighting( + &text, + Some(&format!("rust-example-rendered{}", + if ignore { " ignore" } + else if compile_fail { " compile_fail" } + else if explicit_edition { " edition " } + else { "" })), + playground_button.as_ref().map(String::as_str), + Some((s1.as_str(), s2)))); + Some(Event::Html(s.into())) + } else { + s.push_str(&highlight::render_with_highlighting( + &text, + Some(&format!("rust-example-rendered{}", + if ignore { " ignore" } + else if compile_fail { " compile_fail" } + else if explicit_edition { " edition " } + else { "" })), + playground_button.as_ref().map(String::as_str), + None)); + Some(Event::Html(s.into())) + } } } @@ -674,13 +686,12 @@ impl LangString { } } -impl<'a> fmt::Display for Markdown<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Markdown(md, links, ref ids, codes, edition) = *self; - let mut ids = ids.borrow_mut(); +impl Markdown<'_> { + pub fn to_string(self) -> String { + let Markdown(md, links, mut ids, codes, edition, playground) = self; // This is actually common enough to special-case - if md.is_empty() { return Ok(()) } + if md.is_empty() { return String::new(); } let replacer = |_: &str, s: &str| { if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) { Some((replace.clone(), s.to_owned())) @@ -695,18 +706,17 @@ impl<'a> fmt::Display for Markdown<'a> { let p = HeadingLinks::new(p, None, &mut ids); let p = LinkReplacer::new(p, links); - let p = CodeBlocks::new(p, codes, edition); + let p = CodeBlocks::new(p, codes, edition, playground); let p = Footnotes::new(p); html::push_html(&mut s, p); - fmt.write_str(&s) + s } } -impl<'a> fmt::Display for MarkdownWithToc<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let MarkdownWithToc(md, ref ids, codes, edition) = *self; - let mut ids = ids.borrow_mut(); +impl MarkdownWithToc<'_> { + pub fn to_string(self) -> String { + let MarkdownWithToc(md, mut ids, codes, edition, playground) = self; let p = Parser::new_ext(md, opts()); @@ -716,24 +726,21 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> { { let p = HeadingLinks::new(p, Some(&mut toc), &mut ids); - let p = CodeBlocks::new(p, codes, edition); + let p = CodeBlocks::new(p, codes, edition, playground); let p = Footnotes::new(p); html::push_html(&mut s, p); } - write!(fmt, "

", toc.into_toc())?; - - fmt.write_str(&s) + format!("{}", toc.into_toc(), s) } } -impl<'a> fmt::Display for MarkdownHtml<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let MarkdownHtml(md, ref ids, codes, edition) = *self; - let mut ids = ids.borrow_mut(); +impl MarkdownHtml<'_> { + pub fn to_string(self) -> String { + let MarkdownHtml(md, mut ids, codes, edition, playground) = self; // This is actually common enough to special-case - if md.is_empty() { return Ok(()) } + if md.is_empty() { return String::new(); } let p = Parser::new_ext(md, opts()); // Treat inline HTML as plain text. @@ -745,19 +752,19 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let mut s = String::with_capacity(md.len() * 3 / 2); let p = HeadingLinks::new(p, None, &mut ids); - let p = CodeBlocks::new(p, codes, edition); + let p = CodeBlocks::new(p, codes, edition, playground); let p = Footnotes::new(p); html::push_html(&mut s, p); - fmt.write_str(&s) + s } } -impl<'a> fmt::Display for MarkdownSummaryLine<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let MarkdownSummaryLine(md, links) = *self; +impl MarkdownSummaryLine<'_> { + pub fn to_string(self) -> String { + let MarkdownSummaryLine(md, links) = self; // This is actually common enough to special-case - if md.is_empty() { return Ok(()) } + if md.is_empty() { return String::new(); } let replacer = |_: &str, s: &str| { if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) { @@ -773,7 +780,7 @@ impl<'a> fmt::Display for MarkdownSummaryLine<'a> { html::push_html(&mut s, LinkReplacer::new(SummaryLine::new(p), links)); - fmt.write_str(&s) + s } } diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 681f363544a61..a95c29038d46f 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -73,8 +73,8 @@ fn test_lang_string_parse() { fn test_header() { fn t(input: &str, expect: &str) { let mut map = IdMap::new(); - let output = Markdown(input, &[], RefCell::new(&mut map), - ErrorCodes::Yes, DEFAULT_EDITION).to_string(); + let output = Markdown( + input, &[], &mut map, ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string(); assert_eq!(output, expect, "original: {}", input); } @@ -96,8 +96,8 @@ fn test_header() { fn test_header_ids_multiple_blocks() { let mut map = IdMap::new(); fn t(map: &mut IdMap, input: &str, expect: &str) { - let output = Markdown(input, &[], RefCell::new(map), - ErrorCodes::Yes, DEFAULT_EDITION).to_string(); + let output = Markdown(input, &[], map, + ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string(); assert_eq!(output, expect, "original: {}", input); } @@ -134,8 +134,8 @@ fn test_plain_summary_line() { fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { let mut idmap = IdMap::new(); - let output = MarkdownHtml(input, RefCell::new(&mut idmap), - ErrorCodes::Yes, DEFAULT_EDITION).to_string(); + let output = MarkdownHtml(input, &mut idmap, + ErrorCodes::Yes, DEFAULT_EDITION, &None).to_string(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b1cee0182052b..ea97cea942820 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -170,6 +170,7 @@ struct Context { /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, pub shared: Arc, + playground: Option, } struct SharedContext { @@ -185,8 +186,8 @@ struct SharedContext { pub include_sources: bool, /// The local file sources we've emitted and their respective url-paths. pub local_sources: FxHashMap, - /// All the passes that were run on this crate. - pub passes: FxHashSet, + /// Whether the collapsed pass ran + pub collapsed: bool, /// The base-URL of the issue tracker for when an item has been tagged with /// an issue number. pub issue_tracker_base_url: Option, @@ -229,15 +230,10 @@ impl SharedContext { } impl SharedContext { - /// Returns `true` if the `collapse-docs` pass was run on this crate. - pub fn was_collapsed(&self) -> bool { - self.passes.contains("collapse-docs") - } - /// Based on whether the `collapse-docs` pass was run, return either the `doc_value` or the /// `collapsed_doc_value` of the given item. pub fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option> { - if self.was_collapsed() { + if self.collapsed { item.collapsed_doc_value().map(|s| s.into()) } else { item.doc_value().map(|s| s.into()) @@ -526,7 +522,6 @@ pub fn initial_ids() -> Vec { /// Generates the documentation for `crate` into the directory `dst` pub fn run(mut krate: clean::Crate, options: RenderOptions, - passes: FxHashSet, renderinfo: RenderInfo, diag: &errors::Handler, edition: Edition) -> Result<(), Error> { @@ -557,8 +552,8 @@ pub fn run(mut krate: clean::Crate, }; let mut errors = Arc::new(ErrorStorage::new()); let mut scx = SharedContext { + collapsed: krate.collapsed, src_root, - passes, include_sources: true, local_sources: Default::default(), issue_tracker_base_url: None, @@ -580,9 +575,11 @@ pub fn run(mut krate: clean::Crate, }; // If user passed in `--playground-url` arg, we fill in crate name here + let mut playground = None; if let Some(url) = playground_url { - markdown::PLAYGROUND.with(|slot| { - *slot.borrow_mut() = Some((Some(krate.name.clone()), url)); + playground = Some(markdown::Playground { + crate_name: Some(krate.name.clone()), + url, }); } @@ -598,9 +595,9 @@ pub fn run(mut krate: clean::Crate, scx.layout.logo = s.to_string(); } (sym::html_playground_url, Some(s)) => { - markdown::PLAYGROUND.with(|slot| { - let name = krate.name.clone(); - *slot.borrow_mut() = Some((Some(name), s.to_string())); + playground = Some(markdown::Playground { + crate_name: Some(krate.name.clone()), + url: s.to_string(), }); } (sym::issue_tracker_base_url, Some(s)) => { @@ -624,6 +621,7 @@ pub fn run(mut krate: clean::Crate, edition, id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), + playground, }; // Crawl the crate to build various caches used for the output @@ -659,7 +657,7 @@ pub fn run(mut krate: clean::Crate, crate_version: krate.version.take(), orphan_impl_items: Vec::new(), orphan_trait_impls: Vec::new(), - traits: krate.external_traits.lock().replace(Default::default()), + traits: krate.external_traits.replace(Default::default()), deref_trait_did, deref_mut_trait_did, owned_box_did, @@ -2597,8 +2595,8 @@ fn render_markdown(w: &mut fmt::Formatter<'_>, write!(w, "
{}{}
", if is_hidden { " hidden" } else { "" }, prefix, - Markdown(md_text, &links, RefCell::new(&mut ids), - cx.codes, cx.edition)) + Markdown(md_text, &links, &mut ids, + cx.codes, cx.edition, &cx.playground).to_string()) } fn document_short( @@ -2868,7 +2866,7 @@ fn item_module(w: &mut fmt::Formatter<'_>, cx: &Context, ", name = *myitem.name.as_ref().unwrap(), stab_tags = stability_tags(myitem), - docs = MarkdownSummaryLine(doc_value, &myitem.links()), + docs = MarkdownSummaryLine(doc_value, &myitem.links()).to_string(), class = myitem.type_(), add = add, stab = stab.unwrap_or_else(|| String::new()), @@ -2963,8 +2961,8 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { if let Some(note) = note { let mut ids = cx.id_map.borrow_mut(); - let html = MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes, cx.edition); - message.push_str(&format!(": {}", html)); + let html = MarkdownHtml(¬e, &mut ids, error_codes, cx.edition, &cx.playground); + message.push_str(&format!(": {}", html.to_string())); } stability.push(format!("
{}
", message)); } @@ -3012,7 +3010,13 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { message = format!( "
{}{}
", message, - MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes, cx.edition) + MarkdownHtml( + &unstable_reason, + &mut ids, + error_codes, + cx.edition, + &cx.playground, + ).to_string() ); } @@ -4242,8 +4246,8 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { let mut ids = cx.id_map.borrow_mut(); write!(w, "
{}
", - Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), - cx.codes, cx.edition))?; + Markdown(&*dox, &i.impl_item.links(), &mut ids, + cx.codes, cx.edition, &cx.playground).to_string())?; } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 799b5d923ae89..e30b35937db9f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -44,7 +44,6 @@ use std::default::Default; use std::env; use std::panic; use std::process; -use std::sync::mpsc::channel; use rustc::session::{early_warn, early_error}; use rustc::session::config::{ErrorOutputType, RustcOptGroup}; @@ -80,7 +79,6 @@ struct Output { krate: clean::Crate, renderinfo: html::render::RenderInfo, renderopts: config::RenderOptions, - passes: Vec, } pub fn main() { @@ -419,14 +417,13 @@ fn main_options(options: config::Options) -> i32 { return rustc_driver::EXIT_SUCCESS; } - let Output { krate, passes, renderinfo, renderopts } = out; + let Output { krate, renderinfo, renderopts } = out; info!("going to format"); let (error_format, treat_err_as_bug, ui_testing, edition) = diag_opts; let diag = core::new_handler(error_format, None, treat_err_as_bug, ui_testing); match html::render::run( krate, renderopts, - passes.into_iter().collect(), renderinfo, &diag, edition, @@ -454,12 +451,10 @@ where R: 'static + Send, // First, parse the crate and extract all relevant information. info!("starting to run rustc"); - let (tx, rx) = channel(); - let result = rustc_driver::report_ices_to_stderr_if_any(move || { let crate_name = options.crate_name.clone(); let crate_version = options.crate_version.clone(); - let (mut krate, renderinfo, renderopts, passes) = core::run_core(options); + let (mut krate, renderinfo, renderopts) = core::run_core(options); info!("finished with rustc"); @@ -469,16 +464,15 @@ where R: 'static + Send, krate.version = crate_version; - tx.send(f(Output { + f(Output { krate: krate, renderinfo: renderinfo, renderopts, - passes: passes - })).unwrap(); + }) }); match result { - Ok(()) => rx.recv().unwrap(), + Ok(output) => output, Err(_) => panic::resume_unwind(Box::new(errors::FatalErrorMarker)), } } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 50a647f244db5..eaaae3261c728 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -1,7 +1,6 @@ use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; -use std::cell::RefCell; use errors; use testing; @@ -60,9 +59,10 @@ pub fn render( }; let playground_url = options.markdown_playground_url .or(options.playground_url); - if let Some(playground) = playground_url { - markdown::PLAYGROUND.with(|s| { *s.borrow_mut() = Some((None, playground)); }); - } + let playground = playground_url.map(|url| markdown::Playground { + crate_name: None, + url, + }); let mut out = match File::create(&output) { Err(e) => { @@ -82,9 +82,9 @@ pub fn render( let mut ids = IdMap::new(); let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); let text = if !options.markdown_no_toc { - MarkdownWithToc(text, RefCell::new(&mut ids), error_codes, edition).to_string() + MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).to_string() } else { - Markdown(text, &[], RefCell::new(&mut ids), error_codes, edition).to_string() + Markdown(text, &[], &mut ids, error_codes, edition, &playground).to_string() }; let err = write!( diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs index 144ff226c4283..31288345ce57b 100644 --- a/src/librustdoc/passes/collapse_docs.rs +++ b/src/librustdoc/passes/collapse_docs.rs @@ -30,7 +30,9 @@ impl DocFragment { } pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { - Collapser.fold_crate(krate) + let mut krate = Collapser.fold_crate(krate); + krate.collapsed = true; + krate } struct Collapser; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 84cfdd790b733..5c9fac7eab421 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -61,15 +61,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { { let cx = self.cx; - // In case we're in a module, try to resolve the relative - // path. - if let Some(id) = parent_id.or(self.mod_ids.last().cloned()) { - // FIXME: `with_scope` requires the `NodeId` of a module. - let node_id = cx.tcx.hir().hir_to_node_id(id); + // In case we're in a module, try to resolve the relative path. + if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) { + let module_id = cx.tcx.hir().hir_to_node_id(module_id); let result = cx.enter_resolver(|resolver| { - resolver.with_scope(node_id, |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns == ValueNS) - }) + resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); let result = match result { Ok((_, Res::Err)) => Err(()), @@ -85,6 +81,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { Res::Def(DefKind::AssocTy, _) => false, Res::Def(DefKind::Variant, _) => return handle_variant(cx, res), // Not a trait item; just return what we found. + Res::PrimTy(..) => return Ok((res, Some(path_str.to_owned()))), _ => return Ok((res, None)) }; @@ -133,11 +130,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .ok_or(()); } - // FIXME: `with_scope` requires the `NodeId` of a module. - let node_id = cx.tcx.hir().hir_to_node_id(id); - let (_, ty_res) = cx.enter_resolver(|resolver| resolver.with_scope(node_id, |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, &path, false) - }))?; + let (_, ty_res) = cx.enter_resolver(|resolver| { + resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id) + })?; if let Res::Err = ty_res { return Err(()); } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index cd488b9df78d2..86e4e9fd95637 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -4,7 +4,7 @@ use crate::fold::DocFolder; use super::Pass; use rustc::util::nodemap::FxHashSet; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{LOCAL_CRATE, DefId}; use syntax::symbol::sym; pub const COLLECT_TRAIT_IMPLS: Pass = Pass { @@ -116,7 +116,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations` // doesn't work with it anyway, so pull them from the HIR map instead - for &trait_did in cx.all_traits.iter() { + for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() { for &impl_node in cx.tcx.hir().trait_impls(trait_did) { let impl_did = cx.tcx.hir().local_def_id(impl_node); inline::build_impl(cx, impl_did, None, &mut new_items); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index ca40d6d02f86d..641a6df221446 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -10,7 +10,7 @@ use syntax_pos::{DUMMY_SP, InnerSpan, Span}; use std::ops::Range; use crate::clean::{self, GetDefId, Item}; -use crate::core::{DocContext, DocAccessLevels}; +use crate::core::DocContext; use crate::fold::{DocFolder, StripItem}; use crate::html::markdown::{find_testable_code, ErrorCodes, LangString}; @@ -57,8 +57,9 @@ pub struct Pass { pub description: &'static str, } + /// The full list of passes. -pub const PASSES: &'static [Pass] = &[ +pub const PASSES: &[Pass] = &[ CHECK_PRIVATE_ITEMS_DOC_TESTS, STRIP_HIDDEN, UNINDENT_COMMENTS, @@ -73,43 +74,43 @@ pub const PASSES: &'static [Pass] = &[ ]; /// The list of passes run by default. -pub const DEFAULT_PASSES: &[&str] = &[ - "collect-trait-impls", - "collapse-docs", - "unindent-comments", - "check-private-items-doc-tests", - "strip-hidden", - "strip-private", - "collect-intra-doc-links", - "check-code-block-syntax", - "propagate-doc-cfg", +pub const DEFAULT_PASSES: &[Pass] = &[ + COLLECT_TRAIT_IMPLS, + COLLAPSE_DOCS, + UNINDENT_COMMENTS, + CHECK_PRIVATE_ITEMS_DOC_TESTS, + STRIP_HIDDEN, + STRIP_PRIVATE, + COLLECT_INTRA_DOC_LINKS, + CHECK_CODE_BLOCK_SYNTAX, + PROPAGATE_DOC_CFG, ]; /// The list of default passes run with `--document-private-items` is passed to rustdoc. -pub const DEFAULT_PRIVATE_PASSES: &[&str] = &[ - "collect-trait-impls", - "collapse-docs", - "unindent-comments", - "check-private-items-doc-tests", - "strip-priv-imports", - "collect-intra-doc-links", - "check-code-block-syntax", - "propagate-doc-cfg", +pub const DEFAULT_PRIVATE_PASSES: &[Pass] = &[ + COLLECT_TRAIT_IMPLS, + COLLAPSE_DOCS, + UNINDENT_COMMENTS, + CHECK_PRIVATE_ITEMS_DOC_TESTS, + STRIP_PRIV_IMPORTS, + COLLECT_INTRA_DOC_LINKS, + CHECK_CODE_BLOCK_SYNTAX, + PROPAGATE_DOC_CFG, ]; /// The list of default passes run when `--doc-coverage` is passed to rustdoc. -pub const DEFAULT_COVERAGE_PASSES: &'static [&'static str] = &[ - "collect-trait-impls", - "strip-hidden", - "strip-private", - "calculate-doc-coverage", +pub const DEFAULT_COVERAGE_PASSES: &[Pass] = &[ + COLLECT_TRAIT_IMPLS, + STRIP_HIDDEN, + STRIP_PRIVATE, + CALCULATE_DOC_COVERAGE, ]; /// The list of default passes run when `--doc-coverage --document-private-items` is passed to /// rustdoc. -pub const PRIVATE_COVERAGE_PASSES: &'static [&'static str] = &[ - "collect-trait-impls", - "calculate-doc-coverage", +pub const PRIVATE_COVERAGE_PASSES: &[Pass] = &[ + COLLECT_TRAIT_IMPLS, + CALCULATE_DOC_COVERAGE, ]; /// A shorthand way to refer to which set of passes to use, based on the presence of @@ -124,7 +125,7 @@ pub enum DefaultPassOption { } /// Returns the given default set of passes. -pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] { +pub fn defaults(default_set: DefaultPassOption) -> &'static [Pass] { match default_set { DefaultPassOption::Default => DEFAULT_PASSES, DefaultPassOption::Private => DEFAULT_PRIVATE_PASSES, @@ -347,7 +348,7 @@ pub fn look_for_tests<'tcx>( diag.emit(); } else if check_missing_code == false && tests.found_tests > 0 && - !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) { + !cx.renderinfo.borrow().access_levels.is_public(item.def_id) { let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, hir_id, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 1ba2c0333d6bf..35b6d9972da06 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -6,8 +6,8 @@ use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::privacy::AccessLevel; use rustc::util::nodemap::{FxHashSet, FxHashMap}; +use rustc::ty::TyCtxt; use syntax::ast; -use syntax::attr; use syntax::ext::base::MacroKind; use syntax::source_map::Spanned; use syntax::symbol::sym; @@ -16,26 +16,37 @@ use syntax_pos::{self, Span}; use std::mem; use crate::core; -use crate::clean::{self, AttributesExt, NestedAttributesExt, def_id_to_path}; +use crate::clean::{self, AttributesExt, NestedAttributesExt}; use crate::doctree::*; - -// Looks to me like the first two of these are actually -// output parameters, maybe only mutated once; perhaps -// better simply to have the visit method return a tuple -// containing them? +// FIXME: Should this be replaced with tcx.def_path_str? +fn def_id_to_path( + tcx: TyCtxt<'_>, + did: DefId, +) -> Vec { + let crate_name = tcx.crate_name(did.krate).to_string(); + let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| { + // extern blocks have an empty name + let s = elem.data.to_string(); + if !s.is_empty() { + Some(s) + } else { + None + } + }); + std::iter::once(crate_name).chain(relative).collect() +} // Also, is there some reason that this doesn't use the 'visit' // framework from syntax?. pub struct RustdocVisitor<'a, 'tcx> { - pub module: Option>, - pub cx: &'a core::DocContext<'tcx>, + cx: &'a core::DocContext<'tcx>, view_item_stack: FxHashSet, inlining: bool, /// Are the current module and all of its parents public? inside_public_path: bool, - exact_paths: Option>>, + exact_paths: FxHashMap>, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { @@ -46,36 +57,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let mut stack = FxHashSet::default(); stack.insert(hir::CRATE_HIR_ID); RustdocVisitor { - module: None, cx, view_item_stack: stack, inlining: false, inside_public_path: true, - exact_paths: Some(FxHashMap::default()), + exact_paths: FxHashMap::default(), } } fn store_path(&mut self, did: DefId) { - // We can't use the entry API, as that keeps the mutable borrow of `self` active - // when we try to use `cx`. - let exact_paths = self.exact_paths.as_mut().unwrap(); - if exact_paths.get(&did).is_none() { - let path = def_id_to_path(self.cx, did, self.cx.crate_name.clone()); - exact_paths.insert(did, path); - } - } - - fn stability(&self, id: hir::HirId) -> Option { - self.cx.tcx.hir().opt_local_def_id(id) - .and_then(|def_id| self.cx.tcx.lookup_stability(def_id)).cloned() - } - - fn deprecation(&self, id: hir::HirId) -> Option { - self.cx.tcx.hir().opt_local_def_id(id) - .and_then(|def_id| self.cx.tcx.lookup_deprecation(def_id)) + let tcx = self.cx.tcx; + self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did)); } - pub fn visit(&mut self, krate: &'tcx hir::Crate) { + pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> { let mut module = self.visit_mod_contents(krate.span, &krate.attrs, &Spanned { span: syntax_pos::DUMMY_SP, @@ -88,12 +83,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { krate.exported_macros.iter().map(|def| self.visit_local_macro(def, None)), ); module.is_crate = true; - self.module = Some(module); - self.cx.renderinfo.borrow_mut().exact_paths = self.exact_paths.take().unwrap(); + self.cx.renderinfo.borrow_mut().exact_paths = self.exact_paths; + + module } - pub fn visit_variant_data(&mut self, item: &'tcx hir::Item, + fn visit_variant_data(&mut self, item: &'tcx hir::Item, name: ast::Name, sd: &'tcx hir::VariantData, generics: &'tcx hir::Generics) -> Struct<'tcx> { debug!("visiting struct"); @@ -103,8 +99,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { struct_type, name, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), attrs: &item.attrs, generics, fields: sd.fields(), @@ -112,7 +106,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub fn visit_union_data(&mut self, item: &'tcx hir::Item, + fn visit_union_data(&mut self, item: &'tcx hir::Item, name: ast::Name, sd: &'tcx hir::VariantData, generics: &'tcx hir::Generics) -> Union<'tcx> { debug!("visiting union"); @@ -122,8 +116,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { struct_type, name, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), attrs: &item.attrs, generics, fields: sd.fields(), @@ -131,7 +123,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub fn visit_enum_def(&mut self, it: &'tcx hir::Item, + fn visit_enum_def(&mut self, it: &'tcx hir::Item, name: ast::Name, def: &'tcx hir::EnumDef, generics: &'tcx hir::Generics) -> Enum<'tcx> { debug!("visiting enum"); @@ -141,14 +133,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name: v.node.ident.name, id: v.node.id, attrs: &v.node.attrs, - stab: self.stability(v.node.id), - depr: self.deprecation(v.node.id), def: &v.node.data, whence: v.span, }).collect(), vis: &it.vis, - stab: self.stability(it.hir_id), - depr: self.deprecation(it.hir_id), generics, attrs: &it.attrs, id: it.hir_id, @@ -156,7 +144,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub fn visit_fn(&mut self, om: &mut Module<'tcx>, item: &'tcx hir::Item, + fn visit_fn(&mut self, om: &mut Module<'tcx>, item: &'tcx hir::Item, name: ast::Name, decl: &'tcx hir::FnDecl, header: hir::FnHeader, generics: &'tcx hir::Generics, @@ -207,16 +195,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { helpers, attrs: &item.attrs, whence: item.span, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }); } None => { om.fns.push(Function { id: item.hir_id, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), attrs: &item.attrs, decl, name, @@ -229,16 +213,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub fn visit_mod_contents(&mut self, span: Span, attrs: &'tcx hir::HirVec, + fn visit_mod_contents(&mut self, span: Span, attrs: &'tcx hir::HirVec, vis: &'tcx hir::Visibility, id: hir::HirId, m: &'tcx hir::Mod, name: Option) -> Module<'tcx> { let mut om = Module::new(name, attrs, vis); om.where_outer = span; om.where_inner = m.inner; - om.stab = self.stability(id); - om.depr = self.deprecation(id); - om.id = self.cx.tcx.hir().hir_to_node_id(id); + om.id = id; // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; self.inside_public_path &= vis.node.is_pub(); @@ -369,7 +351,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ret } - pub fn visit_item(&mut self, item: &'tcx hir::Item, + fn visit_item(&mut self, item: &'tcx hir::Item, renamed: Option, om: &mut Module<'tcx>) { debug!("visiting item {:?}", item); let ident = renamed.unwrap_or(item.ident); @@ -467,8 +449,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: &item.attrs, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.typedefs.push(t); }, @@ -480,8 +460,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: &item.attrs, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.opaque_tys.push(t); }, @@ -495,8 +473,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: &item.attrs, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.statics.push(s); }, @@ -509,8 +485,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: &item.attrs, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.constants.push(s); }, @@ -529,8 +503,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: &item.attrs, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.traits.push(t); }, @@ -543,8 +515,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: &item.attrs, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.trait_aliases.push(t); }, @@ -574,8 +544,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { id: item.hir_id, whence: item.span, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), }; om.impls.push(i); } @@ -595,8 +563,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name: renamed.unwrap_or(item.ident).name, kind: &item.node, vis: &item.vis, - stab: self.stability(item.hir_id), - depr: self.deprecation(item.hir_id), attrs: &item.attrs, whence: item.span }); @@ -614,14 +580,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect(); Macro { - + hid: def.hir_id, def_id: self.cx.tcx.hir().local_def_id(def.hir_id), attrs: &def.attrs, name: renamed.unwrap_or(def.name), whence: def.span, matchers, - stab: self.stability(def.hir_id), - depr: self.deprecation(def.hir_id), imported_from: None, } } diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 80aeecb84d72b..d981740780e6f 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -9,10 +9,7 @@ use std::sync::Arc; use smallvec::{Array, SmallVec}; -impl Encodable for SmallVec - where A: Array, - A::Item: Encodable -{ +impl> Encodable for SmallVec { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { @@ -23,10 +20,7 @@ impl Encodable for SmallVec } } -impl Decodable for SmallVec - where A: Array, - A::Item: Decodable -{ +impl> Decodable for SmallVec { fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { let mut vec = SmallVec::with_capacity(len); diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 2ad85c603d1e4..67a48ca4af902 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -13,6 +13,7 @@ Core encoding and decoding interfaces. #![feature(specialization)] #![feature(never_type)] #![feature(nll)] +#![feature(associated_type_bounds)] #![cfg_attr(test, feature(test))] pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 6e111f2423659..512839a12c0e4 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -195,6 +195,12 @@ pub struct CString { /// [`from_ptr`]: #method.from_ptr #[derive(Hash)] #[stable(feature = "rust1", since = "1.0.0")] +// FIXME: +// `fn from` in `impl From<&CStr> for Box` current implementation relies +// on `CStr` being layout-compatible with `[u8]`. +// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`. +// Anyway, `CStr` representation and layout are considered implementation detail, are +// not documented and must not be relied upon. pub struct CStr { // FIXME: this should not be represented with a DST slice but rather with // just a raw `c_char` along with some form of marker to make diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 54e1c876f4caa..1f384cbada3da 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -97,6 +97,12 @@ pub struct OsString { /// [`String`]: ../string/struct.String.html /// [conversions]: index.html#conversions #[stable(feature = "rust1", since = "1.0.0")] +// FIXME: +// `OsStr::from_inner` current implementation relies +// on `OsStr` being layout-compatible with `Slice`. +// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`. +// Anyway, `OsStr` representation and layout are considered implementation detail, are +// not documented and must not be relied upon. pub struct OsStr { inner: Slice } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index cfee49a7b555c..ba80d1b70049a 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -238,6 +238,7 @@ #![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(asm)] +#![feature(associated_type_bounds)] #![feature(bind_by_move_pattern_guards)] #![feature(box_syntax)] #![feature(c_variadic)] @@ -326,12 +327,6 @@ use prelude::v1::*; // Access to Bencher, etc. #[cfg(test)] extern crate test; -// Re-export a few macros from core -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne}; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::{unreachable, unimplemented, write, writeln, r#try, todo}; - #[allow(unused_imports)] // macros from `alloc` are not used on all platforms #[macro_use] extern crate alloc as alloc_crate; @@ -516,33 +511,52 @@ mod std_detect; #[cfg(not(test))] pub use std_detect::detect; -// Document built-in macros in the crate root for consistency with libcore and existing tradition. -// FIXME: Attribute and derive macros are not reexported because rustdoc renders them -// as reexports rather than as macros, and that's not what we want. -#[cfg(rustdoc)] +// Re-export macros defined in libcore. +#[stable(feature = "rust1", since = "1.0.0")] +#[allow(deprecated_in_future)] +pub use core::{ + // Stable + assert_eq, + assert_ne, + debug_assert_eq, + debug_assert_ne, + debug_assert, + r#try, + unimplemented, + unreachable, + write, + writeln, + // Unstable + todo, +}; + +// Re-export built-in macros defined through libcore. +#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::prelude::v1::{ - __rust_unstable_column, - asm, +pub use core::{ + // Stable assert, cfg, column, compile_error, concat, - concat_idents, env, file, format_args, - format_args_nl, - global_asm, include, include_bytes, include_str, line, - log_syntax, module_path, option_env, stringify, + // Unstable + __rust_unstable_column, + asm, + concat_idents, + format_args_nl, + global_asm, + log_syntax, trace_macros, }; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 87c071b512ac7..fd6ff1032bb81 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1123,6 +1123,12 @@ impl FusedIterator for Ancestors<'_> {} /// Which method works best depends on what kind of situation you're in. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] +// FIXME: +// `PathBuf::as_mut_vec` current implementation relies +// on `PathBuf` being layout-compatible with `Vec`. +// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`. +// Anyway, `PathBuf` representation and layout are considered implementation detail, are +// not documented and must not be relied upon. pub struct PathBuf { inner: OsString, } @@ -1745,6 +1751,12 @@ impl AsRef for PathBuf { /// assert_eq!(extension, Some(OsStr::new("txt"))); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +// FIXME: +// `Path::new` current implementation relies +// on `Path` being layout-compatible with `OsStr`. +// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`. +// Anyway, `Path` representation and layout are considered implementation detail, are +// not documented and must not be relied upon. pub struct Path { inner: OsStr, } diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index c9ff53d0a4fd6..75dd0d429c214 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -522,7 +522,11 @@ impl Drop for User where T: UserSafe { impl, U> CoerceUnsized> for UserRef {} #[unstable(feature = "sgx_platform", issue = "56975")] -impl> Index for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe { +impl Index for UserRef<[T]> +where + [T]: UserSafe, + I: SliceIndex<[T], Output: UserSafe>, +{ type Output = UserRef; #[inline] @@ -538,7 +542,11 @@ impl> Index for UserRef<[T]> where [T]: UserSafe, I::Ou } #[unstable(feature = "sgx_platform", issue = "56975")] -impl> IndexMut for UserRef<[T]> where [T]: UserSafe, I::Output: UserSafe { +impl IndexMut for UserRef<[T]> +where + [T]: UserSafe, + I: SliceIndex<[T], Output: UserSafe>, +{ #[inline] fn index_mut(&mut self, index: I) -> &mut UserRef { unsafe { diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index a4961974d89ab..d734f412bf886 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -18,6 +18,12 @@ pub(crate) struct Buf { pub inner: Vec } +// FIXME: +// `Buf::as_slice` current implementation relies +// on `Slice` being layout-compatible with `[u8]`. +// When attribute privacy is implemented, `Slice` should be annotated as `#[repr(transparent)]`. +// Anyway, `Slice` representation and layout are considered implementation detail, are +// not documented and must not be relied upon. pub(crate) struct Slice { pub inner: [u8] } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 964c81dd46641..9a3195b1165b1 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -6,6 +6,7 @@ use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::proc_macro::collect_derives; use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind}; +use crate::ext::tt::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; @@ -686,12 +687,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ); } - fn parse_ast_fragment(&mut self, - toks: TokenStream, - kind: AstFragmentKind, - path: &Path, - span: Span) - -> AstFragment { + fn parse_ast_fragment( + &mut self, + toks: TokenStream, + kind: AstFragmentKind, + path: &Path, + span: Span, + ) -> AstFragment { let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::>()); match parser.parse_ast_fragment(kind, false) { Ok(fragment) => { @@ -700,6 +702,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(mut err) => { err.set_span(span); + annotate_err_with_kind(&mut err, kind, span); err.emit(); self.cx.trace_macros_diag(); kind.dummy(span) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 7401f25641236..b057a9ad44d0b 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -17,7 +17,7 @@ use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use crate::{ast, attr, attr::TransparencyError}; -use errors::FatalError; +use errors::{DiagnosticBuilder, FatalError}; use log::debug; use syntax_pos::Span; @@ -43,6 +43,18 @@ pub struct ParserAnyMacro<'a> { arm_span: Span, } +pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragmentKind, span: Span) { + match kind { + AstFragmentKind::Ty => { + err.span_label(span, "this macro call doesn't expand to a type"); + } + AstFragmentKind::Pat => { + err.span_label(span, "this macro call doesn't expand to a pattern"); + } + _ => {} + }; +} + impl<'a> ParserAnyMacro<'a> { pub fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; @@ -70,6 +82,32 @@ impl<'a> ParserAnyMacro<'a> { } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() { e.span_label(site_span, "in this macro invocation"); } + match kind { + AstFragmentKind::Pat if macro_ident.name == sym::vec => { + let mut suggestion = None; + if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) { + if let Some(bang) = code.find('!') { + suggestion = Some(code[bang + 1..].to_string()); + } + } + if let Some(suggestion) = suggestion { + e.span_suggestion( + site_span, + "use a slice pattern here instead", + suggestion, + Applicability::MachineApplicable, + ); + } else { + e.span_label( + site_span, + "use a slice pattern here instead", + ); + } + e.help("for more information, see https://doc.rust-lang.org/edition-guide/\ + rust-2018/slice-patterns.html"); + } + _ => annotate_err_with_kind(&mut e, kind, site_span), + }; e })); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d85c2df16a350..1c1428c5713f7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,47 +1,25 @@ -// ignore-tidy-filelength - -use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy}; -use crate::ast::{GenericBound, TraitBoundModifier}; -use crate::ast::Unsafety; -use crate::ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind}; -use crate::ast::Block; -use crate::ast::{BlockCheckMode, CaptureBy, Movability}; -use crate::ast::{Constness, Crate}; -use crate::ast::Defaultness; -use crate::ast::EnumDef; -use crate::ast::{Expr, ExprKind, RangeLimits}; -use crate::ast::{Field, FnDecl, FnHeader}; -use crate::ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; -use crate::ast::{GenericParam, GenericParamKind}; -use crate::ast::GenericArg; -use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; -use crate::ast::{Label, Lifetime}; -use crate::ast::Local; -use crate::ast::MacStmtStyle; -use crate::ast::{Mac, Mac_, MacDelimiter}; -use crate::ast::{MutTy, Mutability}; -use crate::ast::{Pat, PatKind, PathSegment}; -use crate::ast::{PolyTraitRef, QSelf}; -use crate::ast::{Stmt, StmtKind}; -use crate::ast::{VariantData, StructField}; -use crate::ast::StrStyle; -use crate::ast::SelfKind; -use crate::ast::{TraitItem, TraitRef, TraitObjectSyntax}; -use crate::ast::{Ty, TyKind, AssocTyConstraint, AssocTyConstraintKind, GenericBounds}; -use crate::ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; -use crate::ast::{UseTree, UseTreeKind}; -use crate::ast::{BinOpKind, UnOp}; -use crate::ast::{RangeEnd, RangeSyntax}; -use crate::{ast, attr}; -use crate::ext::base::DummyResult; +mod expr; +mod pat; +mod item; +pub use item::AliasKind; +mod module; +pub use module::{ModulePath, ModulePathSuccess}; +mod ty; +mod path; +pub use path::PathStyle; +mod stmt; +mod generics; + +use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind}; +use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind}; +use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar}; use crate::ext::hygiene::SyntaxContext; -use crate::source_map::{self, SourceMap, Spanned, respan}; -use crate::parse::{SeqSep, classify, literal, token}; +use crate::source_map::{self, respan}; +use crate::parse::{SeqSep, literal, token}; use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::token::{Token, TokenKind, DelimToken}; -use crate::parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; -use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; +use crate::parse::{ParseSess, Directory, DirectoryOwnership}; use crate::print::pprust; use crate::ptr::P; use crate::parse::PResult; @@ -50,25 +28,14 @@ use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; use crate::symbol::{kw, sym, Symbol}; use crate::parse::diagnostics::{Error, dummy_arg}; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; +use errors::{Applicability, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; use syntax_pos::{Span, BytePos, DUMMY_SP, FileName}; use log::debug; use std::borrow::Cow; -use std::cmp; -use std::mem; -use std::path::{self, Path, PathBuf}; -use std::slice; - -#[derive(Debug)] -/// Whether the type alias or associated type is a concrete type or an opaque type -pub enum AliasKind { - /// Just a new name for the same type - Weak(P), - /// Only trait impls of the type will be usable, not the actual type itself - OpaqueTy(GenericBounds), -} +use std::{cmp, mem, slice}; +use std::path::PathBuf; bitflags::bitflags! { struct Restrictions: u8 { @@ -77,31 +44,6 @@ bitflags::bitflags! { } } -type ItemInfo = (Ident, ItemKind, Option>); - -/// Specifies how to parse a path. -#[derive(Copy, Clone, PartialEq)] -pub enum PathStyle { - /// In some contexts, notably in expressions, paths with generic arguments are ambiguous - /// with something else. For example, in expressions `segment < ....` can be interpreted - /// as a comparison and `segment ( ....` can be interpreted as a function call. - /// In all such contexts the non-path interpretation is preferred by default for practical - /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g. - /// `x` - comparisons, `x::` - unambiguously a path. - Expr, - /// In other contexts, notably in types, no ambiguity exists and paths can be written - /// without the disambiguator, e.g., `x` - unambiguously a path. - /// Paths with disambiguators are still accepted, `x::` - unambiguously a path too. - Type, - /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports, - /// visibilities or attributes. - /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead - /// (paths in "mod" contexts have to be checked later for absence of generic arguments - /// anyway, due to macros), but it is used to avoid weird suggestions about expected - /// tokens when something goes wrong. - Mod, -} - #[derive(Clone, Copy, PartialEq, Debug)] crate enum SemiColonMode { Break, @@ -115,42 +57,8 @@ crate enum BlockMode { Ignore, } -/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression -/// dropped into the token stream, which happens while parsing the result of -/// macro expansion). Placement of these is not as complex as I feared it would -/// be. The important thing is to make sure that lookahead doesn't balk at -/// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr { - ($p:expr) => { - if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - $p.bump(); - return Ok(e); - } - token::NtPath(path) => { - let path = path.clone(); - $p.bump(); - return Ok($p.mk_expr( - $p.token.span, ExprKind::Path(None, path), ThinVec::new() - )); - } - token::NtBlock(block) => { - let block = block.clone(); - $p.bump(); - return Ok($p.mk_expr( - $p.token.span, ExprKind::Block(block, None), ThinVec::new() - )); - } - // N.B: `NtIdent(ident)` is normalized to `Ident` in `fn bump`. - _ => {}, - }; - } - } -} - /// As maybe_whole_expr, but for things other than expressions +#[macro_export] macro_rules! maybe_whole { ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { if let token::Interpolated(nt) = &$p.token.kind { @@ -164,6 +72,7 @@ macro_rules! maybe_whole { } /// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. +#[macro_export] macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.look_ahead(1, |t| t == &token::ModSep) { @@ -415,52 +324,6 @@ impl TokenType { } } -/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT`, -/// `IDENT<::AssocTy>`. -/// -/// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes -/// that `IDENT` is not the ident of a fn trait. -fn can_continue_type_after_non_fn_ident(t: &Token) -> bool { - t == &token::ModSep || t == &token::Lt || - t == &token::BinOp(token::Shl) -} - -/// Information about the path to a module. -pub struct ModulePath { - name: String, - path_exists: bool, - pub result: Result, -} - -pub struct ModulePathSuccess { - pub path: PathBuf, - pub directory_ownership: DirectoryOwnership, - warn: bool, -} - -#[derive(Debug)] -enum LhsExpr { - NotYetParsed, - AttributesParsed(ThinVec), - AlreadyParsed(P), -} - -impl From>> for LhsExpr { - fn from(o: Option>) -> Self { - if let Some(attrs) = o { - LhsExpr::AttributesParsed(attrs) - } else { - LhsExpr::NotYetParsed - } - } -} - -impl From> for LhsExpr { - fn from(expr: P) -> Self { - LhsExpr::AlreadyParsed(expr) - } -} - #[derive(Copy, Clone, Debug)] crate enum TokenExpectType { Expect, @@ -602,20 +465,6 @@ impl<'a> Parser<'a> { } } - /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. - fn interpolated_or_expr_span( - &self, - expr: PResult<'a, P>, - ) -> PResult<'a, (Span, P)> { - expr.map(|e| { - if self.prev_token_kind == PrevTokenKind::Interpolated { - (self.prev_span, e) - } else { - (e.span, e) - } - }) - } - pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { self.parse_ident_common(true) } @@ -755,7 +604,6 @@ impl<'a> Parser<'a> { } } - /// Checks to see if the next token is either `+` or `+=`. /// Otherwise returns `false`. fn check_plus(&mut self) -> bool { @@ -1085,50 +933,6 @@ impl<'a> Parser<'a> { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) } - /// Is the current token one of the keywords that signals a bare function type? - fn token_is_bare_fn_keyword(&mut self) -> bool { - self.check_keyword(kw::Fn) || - self.check_keyword(kw::Unsafe) || - self.check_keyword(kw::Extern) - } - - /// Parses a `TyKind::BareFn` type. - fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'a, TyKind> { - /* - - [unsafe] [extern "ABI"] fn (S) -> T - ^~~~^ ^~~~^ ^~^ ^ - | | | | - | | | Return type - | | Argument types - | | - | ABI - Function Style - */ - - let unsafety = self.parse_unsafety(); - let abi = if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()?.unwrap_or(Abi::C) - } else { - Abi::Rust - }; - - self.expect_keyword(kw::Fn)?; - let (inputs, c_variadic) = self.parse_fn_args(false, true)?; - let ret_ty = self.parse_ret_ty(false)?; - let decl = P(FnDecl { - inputs, - output: ret_ty, - c_variadic, - }); - Ok(TyKind::BareFn(P(BareFnTy { - abi, - unsafety, - generic_params, - decl, - }))) - } - /// Parses asyncness: `async` or nothing. fn parse_asyncness(&mut self) -> IsAsync { if self.eat_keyword(kw::Async) { @@ -1150,350 +954,6 @@ impl<'a> Parser<'a> { } } - /// Parses the items in a trait declaration. - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { - maybe_whole!(self, NtTraitItem, |x| x); - let attrs = self.parse_outer_attributes()?; - let mut unclosed_delims = vec![]; - let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_trait_item_(at_end, attrs); - unclosed_delims.append(&mut this.unclosed_delims); - item - })?; - self.unclosed_delims.append(&mut unclosed_delims); - // See `parse_item` for why this clause is here. - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - Ok(item) - } - - fn parse_trait_item_(&mut self, - at_end: &mut bool, - mut attrs: Vec) -> PResult<'a, TraitItem> { - let lo = self.token.span; - self.eat_bad_pub(); - let (name, node, generics) = if self.eat_keyword(kw::Type) { - self.parse_trait_item_assoc_ty()? - } else if self.is_const_item() { - self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let default = if self.eat(&token::Eq) { - let expr = self.parse_expr()?; - self.expect(&token::Semi)?; - Some(expr) - } else { - self.expect(&token::Semi)?; - None - }; - (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) - } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { - // trait item macro. - (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) - } else { - let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; - - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - - let decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { - // This is somewhat dubious; We don't want to allow - // argument names to be left off if there is a - // definition... - - // We don't allow argument names to be left off in edition 2018. - let is_name_required = p.token.span.rust_2018(); - p.parse_arg_general(true, false, |_| is_name_required) - })?; - generics.where_clause = self.parse_where_clause()?; - - let sig = ast::MethodSig { - header: FnHeader { - unsafety, - constness, - abi, - asyncness, - }, - decl, - }; - - let body = match self.token.kind { - token::Semi => { - self.bump(); - *at_end = true; - debug!("parse_trait_methods(): parsing required method"); - None - } - token::OpenDelim(token::Brace) => { - debug!("parse_trait_methods(): parsing provided method"); - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - token::Interpolated(ref nt) => { - match **nt { - token::NtBlock(..) => { - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - _ => { - return self.expected_semi_or_open_brace(); - } - } - } - _ => { - return self.expected_semi_or_open_brace(); - } - }; - (ident, ast::TraitItemKind::Method(sig, body), generics) - }; - - Ok(TraitItem { - id: ast::DUMMY_NODE_ID, - ident: name, - attrs, - generics, - node, - span: lo.to(self.prev_span), - tokens: None, - }) - } - - /// Parses an optional return type `[ -> TY ]` in a function declaration. - fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { - if self.eat(&token::RArrow) { - Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true, false)?)) - } else { - Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo())) - } - } - - /// Parses a type. - pub fn parse_ty(&mut self) -> PResult<'a, P> { - self.parse_ty_common(true, true, false) - } - - /// Parses a type in restricted contexts where `+` is not permitted. - /// - /// Example 1: `&'a TYPE` - /// `+` is prohibited to maintain operator priority (P(+) < P(&)). - /// Example 2: `value1 as TYPE + value2` - /// `+` is prohibited to avoid interactions with expression grammar. - fn parse_ty_no_plus(&mut self) -> PResult<'a, P> { - self.parse_ty_common(false, true, false) - } - - fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool, - allow_c_variadic: bool) -> PResult<'a, P> { - maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - maybe_whole!(self, NtTy, |x| x); - - let lo = self.token.span; - let mut impl_dyn_multi = false; - let node = if self.eat(&token::OpenDelim(token::Paren)) { - // `(TYPE)` is a parenthesized type. - // `(TYPE,)` is a tuple with a single field of type TYPE. - let mut ts = vec![]; - let mut last_comma = false; - while self.token != token::CloseDelim(token::Paren) { - ts.push(self.parse_ty()?); - if self.eat(&token::Comma) { - last_comma = true; - } else { - last_comma = false; - break; - } - } - let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus; - self.expect(&token::CloseDelim(token::Paren))?; - - if ts.len() == 1 && !last_comma { - let ty = ts.into_iter().nth(0).unwrap().into_inner(); - let maybe_bounds = allow_plus && self.token.is_like_plus(); - match ty.node { - // `(TY_BOUND_NOPAREN) + BOUND + ...`. - TyKind::Path(None, ref path) if maybe_bounds => { - self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)? - } - TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) - if maybe_bounds && bounds.len() == 1 && !trailing_plus => { - let path = match bounds[0] { - GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(), - GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"), - }; - self.parse_remaining_bounds(Vec::new(), path, lo, true)? - } - // `(TYPE)` - _ => TyKind::Paren(P(ty)) - } - } else { - TyKind::Tup(ts) - } - } else if self.eat(&token::Not) { - // Never type `!` - TyKind::Never - } else if self.eat(&token::BinOp(token::Star)) { - // Raw pointer - TyKind::Ptr(self.parse_ptr()?) - } else if self.eat(&token::OpenDelim(token::Bracket)) { - // Array or slice - let t = self.parse_ty()?; - // Parse optional `; EXPR` in `[TYPE; EXPR]` - let t = match self.maybe_parse_fixed_length_of_vec()? { - None => TyKind::Slice(t), - Some(length) => TyKind::Array(t, AnonConst { - id: ast::DUMMY_NODE_ID, - value: length, - }), - }; - self.expect(&token::CloseDelim(token::Bracket))?; - t - } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) { - // Reference - self.expect_and()?; - self.parse_borrowed_pointee()? - } else if self.eat_keyword_noexpect(kw::Typeof) { - // `typeof(EXPR)` - // In order to not be ambiguous, the type must be surrounded by parens. - self.expect(&token::OpenDelim(token::Paren))?; - let e = AnonConst { - id: ast::DUMMY_NODE_ID, - value: self.parse_expr()?, - }; - self.expect(&token::CloseDelim(token::Paren))?; - TyKind::Typeof(e) - } else if self.eat_keyword(kw::Underscore) { - // A type to be inferred `_` - TyKind::Infer - } else if self.token_is_bare_fn_keyword() { - // Function pointer type - self.parse_ty_bare_fn(Vec::new())? - } else if self.check_keyword(kw::For) { - // Function pointer type or bound list (trait object type) starting with a poly-trait. - // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` - // `for<'lt> Trait1<'lt> + Trait2 + 'a` - let lo = self.token.span; - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; - if self.token_is_bare_fn_keyword() { - self.parse_ty_bare_fn(lifetime_defs)? - } else { - let path = self.parse_path(PathStyle::Type)?; - let parse_plus = allow_plus && self.check_plus(); - self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? - } - } else if self.eat_keyword(kw::Impl) { - // Always parse bounds greedily for better error recovery. - let bounds = self.parse_generic_bounds(None)?; - impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; - TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) - } else if self.check_keyword(kw::Dyn) && - (self.token.span.rust_2018() || - self.look_ahead(1, |t| t.can_begin_bound() && - !can_continue_type_after_non_fn_ident(t))) { - self.bump(); // `dyn` - // Always parse bounds greedily for better error recovery. - let bounds = self.parse_generic_bounds(None)?; - impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; - TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) - } else if self.check(&token::Question) || - self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) { - // Bound list (trait object type) - TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?, - TraitObjectSyntax::None) - } else if self.eat_lt() { - // Qualified path - let (qself, path) = self.parse_qpath(PathStyle::Type)?; - TyKind::Path(Some(qself), path) - } else if self.token.is_path_start() { - // Simple path - let path = self.parse_path(PathStyle::Type)?; - if self.eat(&token::Not) { - // Macro invocation in type position - let (delim, tts) = self.expect_delimited_token_tree()?; - let node = Mac_ { - path, - tts, - delim, - prior_type_ascription: self.last_type_ascription, - }; - TyKind::Mac(respan(lo.to(self.prev_span), node)) - } else { - // Just a type path or bound list (trait object type) starting with a trait. - // `Type` - // `Trait1 + Trait2 + 'a` - if allow_plus && self.check_plus() { - self.parse_remaining_bounds(Vec::new(), path, lo, true)? - } else { - TyKind::Path(None, path) - } - } - } else if self.check(&token::DotDotDot) { - if allow_c_variadic { - self.eat(&token::DotDotDot); - TyKind::CVarArgs - } else { - return Err(self.fatal( - "only foreign functions are allowed to be C-variadic" - )); - } - } else { - let msg = format!("expected type, found {}", self.this_token_descr()); - let mut err = self.fatal(&msg); - err.span_label(self.token.span, "expected type"); - self.maybe_annotate_with_ascription(&mut err, true); - return Err(err); - }; - - let span = lo.to(self.prev_span); - let ty = P(Ty { node, span, id: ast::DUMMY_NODE_ID }); - - // Try to recover from use of `+` with incorrect priority. - self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); - self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?; - self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery) - } - - fn parse_remaining_bounds(&mut self, generic_params: Vec, path: ast::Path, - lo: Span, parse_plus: bool) -> PResult<'a, TyKind> { - let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); - let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; - if parse_plus { - self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded - bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?); - } - Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) - } - - fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { - let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None }; - let mutbl = self.parse_mutability(); - let ty = self.parse_ty_no_plus()?; - return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl })); - } - - fn parse_ptr(&mut self) -> PResult<'a, MutTy> { - let mutbl = if self.eat_keyword(kw::Mut) { - Mutability::Mutable - } else if self.eat_keyword(kw::Const) { - Mutability::Immutable - } else { - let span = self.prev_span; - let msg = "expected mut or const in raw pointer type"; - self.struct_span_err(span, msg) - .span_label(span, msg) - .help("use `*mut T` or `*const T` as appropriate") - .emit(); - Mutability::Immutable - }; - let t = self.parse_ty_no_plus()?; - Ok(MutTy { ty: t, mutbl }) - } - fn is_named_argument(&self) -> bool { let offset = match self.token.kind { token::Interpolated(ref nt) => match **nt { @@ -1563,12 +1023,8 @@ impl<'a> Parser<'a> { match ty { Ok(ty) => { let ident = Ident::new(kw::Invalid, self.prev_span); - let pat = P(Pat { - id: ast::DUMMY_NODE_ID, - node: PatKind::Ident( - BindingMode::ByValue(Mutability::Immutable), ident, None), - span: ty.span, - }); + let bm = BindingMode::ByValue(Mutability::Immutable); + let pat = self.mk_pat_ident(ty.span, bm, ident); (pat, ty) } Err(mut err) => { @@ -1590,288 +1046,6 @@ impl<'a> Parser<'a> { Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty }) } - /// Parses an argument in a lambda header (e.g., `|arg, arg|`). - fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { - let lo = self.token.span; - let attrs = self.parse_arg_attributes()?; - let pat = self.parse_pat(Some("argument name"))?; - let t = if self.eat(&token::Colon) { - self.parse_ty()? - } else { - P(Ty { - id: ast::DUMMY_NODE_ID, - node: TyKind::Infer, - span: self.prev_span, - }) - }; - let span = lo.to(self.token.span); - Ok(Arg { - attrs: attrs.into(), - ty: t, - pat, - span, - id: ast::DUMMY_NODE_ID - }) - } - - fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option>> { - if self.eat(&token::Semi) { - Ok(Some(self.parse_expr()?)) - } else { - Ok(None) - } - } - - /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). - crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - maybe_whole_expr!(self); - - let minus_lo = self.token.span; - let minus_present = self.eat(&token::BinOp(token::Minus)); - let lo = self.token.span; - let literal = self.parse_lit()?; - let hi = self.prev_span; - let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new()); - - if minus_present { - let minus_hi = self.prev_span; - let unary = self.mk_unary(UnOp::Neg, expr); - Ok(self.mk_expr(minus_lo.to(minus_hi), unary, ThinVec::new())) - } else { - Ok(expr) - } - } - - fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> { - match self.token.kind { - token::Ident(name, _) if name.is_path_segment_keyword() => { - let span = self.token.span; - self.bump(); - Ok(Ident::new(name, span)) - } - _ => self.parse_ident(), - } - } - - fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { - match self.token.kind { - token::Ident(name, false) if name == kw::Underscore => { - let span = self.token.span; - self.bump(); - Ok(Ident::new(name, span)) - } - _ => self.parse_ident(), - } - } - - /// Parses a qualified path. - /// Assumes that the leading `<` has been parsed already. - /// - /// `qualified_path = ::path` - /// - /// # Examples - /// `::default` - /// `::a` - /// `::F::a` (without disambiguator) - /// `::F::a::` (with disambiguator) - fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> { - let lo = self.prev_span; - let ty = self.parse_ty()?; - - // `path` will contain the prefix of the path up to the `>`, - // if any (e.g., `U` in the `::*` examples - // above). `path_span` has the span of that path, or an empty - // span in the case of something like `::Bar`. - let (mut path, path_span); - if self.eat_keyword(kw::As) { - let path_lo = self.token.span; - path = self.parse_path(PathStyle::Type)?; - path_span = path_lo.to(self.prev_span); - } else { - path_span = self.token.span.to(self.token.span); - path = ast::Path { segments: Vec::new(), span: path_span }; - } - - // See doc comment for `unmatched_angle_bracket_count`. - self.expect(&token::Gt)?; - if self.unmatched_angle_bracket_count > 0 { - self.unmatched_angle_bracket_count -= 1; - debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count); - } - - self.expect(&token::ModSep)?; - - let qself = QSelf { ty, path_span, position: path.segments.len() }; - self.parse_path_segments(&mut path.segments, style)?; - - Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) })) - } - - /// Parses simple paths. - /// - /// `path = [::] segment+` - /// `segment = ident | ident[::] | ident[::](args) [-> type]` - /// - /// # Examples - /// `a::b::C` (without disambiguator) - /// `a::b::C::` (with disambiguator) - /// `Fn(Args)` (without disambiguator) - /// `Fn::(Args)` (with disambiguator) - pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - maybe_whole!(self, NtPath, |path| { - if style == PathStyle::Mod && - path.segments.iter().any(|segment| segment.args.is_some()) { - self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); - } - path - }); - - let lo = self.meta_var_span.unwrap_or(self.token.span); - let mut segments = Vec::new(); - let mod_sep_ctxt = self.token.span.ctxt(); - if self.eat(&token::ModSep) { - segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); - } - self.parse_path_segments(&mut segments, style)?; - - Ok(ast::Path { segments, span: lo.to(self.prev_span) }) - } - - /// Like `parse_path`, but also supports parsing `Word` meta items into paths for - /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]` - /// attributes. - pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - let meta_ident = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtMeta(ref meta) => match meta.node { - ast::MetaItemKind::Word => Some(meta.path.clone()), - _ => None, - }, - _ => None, - }, - _ => None, - }; - if let Some(path) = meta_ident { - self.bump(); - return Ok(path); - } - self.parse_path(style) - } - - crate fn parse_path_segments(&mut self, - segments: &mut Vec, - style: PathStyle) - -> PResult<'a, ()> { - loop { - let segment = self.parse_path_segment(style)?; - if style == PathStyle::Expr { - // In order to check for trailing angle brackets, we must have finished - // recursing (`parse_path_segment` can indirectly call this function), - // that is, the next token must be the highlighted part of the below example: - // - // `Foo::>::Qux` - // ^ here - // - // As opposed to the below highlight (if we had only finished the first - // recursion): - // - // `Foo::>::Qux` - // ^ here - // - // `PathStyle::Expr` is only provided at the root invocation and never in - // `parse_path_segment` to recurse and therefore can be checked to maintain - // this invariant. - self.check_trailing_angle_brackets(&segment, token::ModSep); - } - segments.push(segment); - - if self.is_import_coupler() || !self.eat(&token::ModSep) { - return Ok(()); - } - } - } - - fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { - let ident = self.parse_path_segment_ident()?; - - let is_args_start = |token: &Token| match token.kind { - token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) - | token::LArrow => true, - _ => false, - }; - let check_args_start = |this: &mut Self| { - this.expected_tokens.extend_from_slice( - &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))] - ); - is_args_start(&this.token) - }; - - Ok(if style == PathStyle::Type && check_args_start(self) || - style != PathStyle::Mod && self.check(&token::ModSep) - && self.look_ahead(1, |t| is_args_start(t)) { - // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If - // it isn't, then we reset the unmatched angle bracket count as we're about to start - // parsing a new path. - if style == PathStyle::Expr { - self.unmatched_angle_bracket_count = 0; - self.max_angle_bracket_count = 0; - } - - // Generic arguments are found - `<`, `(`, `::<` or `::(`. - self.eat(&token::ModSep); - let lo = self.token.span; - let args = if self.eat_lt() { - // `<'a, T, A = U>` - let (args, constraints) = - self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?; - self.expect_gt()?; - let span = lo.to(self.prev_span); - AngleBracketedArgs { args, constraints, span }.into() - } else { - // `(T, U) -> R` - let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; - let span = lo.to(self.prev_span); - let output = if self.eat(&token::RArrow) { - Some(self.parse_ty_common(false, false, false)?) - } else { - None - }; - ParenthesizedArgs { inputs, output, span }.into() - }; - - PathSegment { ident, args, id: ast::DUMMY_NODE_ID } - } else { - // Generic arguments are not found. - PathSegment::from_ident(ident) - }) - } - - crate fn check_lifetime(&mut self) -> bool { - self.expected_tokens.push(TokenType::Lifetime); - self.token.is_lifetime() - } - - /// Parses a single lifetime `'a` or panics. - crate fn expect_lifetime(&mut self) -> Lifetime { - if let Some(ident) = self.token.lifetime() { - let span = self.token.span; - self.bump(); - Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID } - } else { - self.span_bug(self.token.span, "not a lifetime") - } - } - - fn eat_label(&mut self) -> Option