diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 82a755c7892b1..1949d70e5deea 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -184,6 +184,7 @@ def default_build_triple(): ostype = require(["uname", "-s"], exit=required) cputype = require(['uname', '-m'], exit=required) + # If we do not have `uname`, assume Windows. if ostype is None or cputype is None: return 'x86_64-pc-windows-msvc' @@ -236,6 +237,11 @@ def default_build_triple(): if ostype.endswith('WOW64'): cputype = 'x86_64' ostype = 'pc-windows-gnu' + elif sys.platform == 'win32': + # Some Windows platforms might have a `uname` command that returns a + # non-standard string (e.g. gnuwin32 tools returns `windows32`). In + # these cases, fall back to using sys.platform. + return 'x86_64-pc-windows-msvc' else: err = "unknown OS type: {}".format(ostype) sys.exit(err) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 0208dc8ba5eb6..b07ff21755e0c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -131,26 +131,13 @@ fn copy_third_party_objects( compiler: &Compiler, target: Interned, ) -> Vec<(PathBuf, DependencyType)> { - let libdir = builder.sysroot_libdir(*compiler, target); let mut target_deps = vec![]; - // Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx. - // - // This target needs to be linked to Fortanix's port of llvm's libunwind. - // libunwind requires support for rwlock and printing to stderr, - // which is provided by std for this target. + // FIXME: remove this in 2021 if target == "x86_64-fortanix-unknown-sgx" { - let src_path_env = "X86_FORTANIX_SGX_LIBS"; - let src = - env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env)); - copy_and_stamp( - builder, - &*libdir, - Path::new(&src), - "libunwind.a", - &mut target_deps, - DependencyType::Target, - ); + if env::var_os("X86_FORTANIX_SGX_LIBS").is_some() { + builder.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild"); + } } if builder.config.sanitizers && compiler.stage != 0 { diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index 43f5581f996ea..1f1c246002352 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -71,9 +71,7 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ COPY dist-various-2/x86_64-fortanix-unknown-sgx-clang-wrap.sh /usr/bin/x86_64-fortanix-unknown-sgx-clang-11 RUN ln -s /usr/bin/x86_64-fortanix-unknown-sgx-clang-11 /usr/bin/x86_64-fortanix-unknown-sgx-clang++-11 -# We pass the commit id of the port of LLVM's libunwind to the build script. -# Any update to the commit id here, should cause the container image to be re-built from this point on. -RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "800f95131fe6acd20b96b6f4723ca3c820f3d379" +RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh COPY dist-various-2/build-wasi-toolchain.sh /tmp/ RUN /tmp/build-wasi-toolchain.sh @@ -105,8 +103,6 @@ ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi -ENV X86_FORTANIX_SGX_LIBS="/x86_64-fortanix-unknown-sgx/lib/" - # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-7 (for gnux32) but not in the search path of the # cross compilers. diff --git a/src/ci/docker/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh b/src/ci/docker/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh index 4294b1ef93dd8..78bf4527feff1 100755 --- a/src/ci/docker/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh @@ -3,14 +3,7 @@ set -eu source shared.sh -if [ -z "$1" ]; then - echo "Usage: ${0} " - exit -1 -fi - target="x86_64-fortanix-unknown-sgx" -url="https://github.com/fortanix/llvm-project/archive/${1}.tar.gz" -repo_name="llvm-project" install_prereq() { curl https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add - @@ -24,39 +17,4 @@ install_prereq() { clang-11 } -build_unwind() { - set -x - dir_name="${target}_temp" - rm -rf ${dir_name} - mkdir -p ${dir_name} - pushd ${dir_name} - - # Clone Fortanix's fork of llvm-project which has a port of libunwind - fetch_github_commit_archive "$repo_name" "$url" - cd "${repo_name}/libunwind" - - # Build libunwind - mkdir -p build - cd build - target_CC="CC_${target//-/_}" - target_CXX="CXX_${target//-/_}" - target_CFLAGS="CFLAGS_${target//-/_}" - target_CXXFLAGS="CXXFLAGS_${target//-/_}" - cmake -DCMAKE_BUILD_TYPE="RELEASE" -DRUST_SGX=1 -G "Unix Makefiles" \ - -DCMAKE_C_COMPILER="${!target_CC}" -DCMAKE_CXX_COMPILER="${!target_CXX}" \ - -DCMAKE_C_FLAGS="${!target_CFLAGS}" -DCMAKE_CXX_FLAGS="${!target_CXXFLAGS}" \ - -DCMAKE_C_COMPILER_TARGET=$target -DCMAKE_CXX_COMPILER_TARGET=$target \ - -DLLVM_ENABLE_WARNINGS=1 -DLIBUNWIND_ENABLE_WERROR=1 -DLIBUNWIND_ENABLE_PEDANTIC=0 \ - -DLLVM_PATH=../../llvm/ ../ - make unwind_static - install -D "lib/libunwind.a" "/${target}/lib/libunwind.a" - - popd - rm -rf ${dir_name} - - { set +x; } 2>/dev/null -} - -set -x hide_output install_prereq -build_unwind diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 34cacebe79636..bb9091a66594b 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1396,6 +1396,14 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { fn last(mut self) -> Option<(&'a K, &'a V)> { self.next_back() } + + fn min(mut self) -> Option<(&'a K, &'a V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1458,6 +1466,14 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { fn last(mut self) -> Option<(&'a K, &'a mut V)> { self.next_back() } + + fn min(mut self) -> Option<(&'a K, &'a mut V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1595,6 +1611,14 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { fn last(mut self) -> Option<&'a K> { self.next_back() } + + fn min(mut self) -> Option<&'a K> { + self.next() + } + + fn max(mut self) -> Option<&'a K> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1768,6 +1792,14 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { fn last(mut self) -> Option<(&'a K, &'a V)> { self.next_back() } + + fn min(mut self) -> Option<(&'a K, &'a V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1853,6 +1885,14 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { fn last(mut self) -> Option<(&'a K, &'a mut V)> { self.next_back() } + + fn min(mut self) -> Option<(&'a K, &'a mut V)> { + self.next() + } + + fn max(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } } impl<'a, K, V> RangeMut<'a, K, V> { diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 525ef38c32fa2..d8959966fe5ad 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -1291,12 +1291,22 @@ impl<'a, T> Iterator for Iter<'a, T> { fn next(&mut self) -> Option<&'a T> { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + fn last(mut self) -> Option<&'a T> { self.next_back() } + + fn min(mut self) -> Option<&'a T> { + self.next() + } + + fn max(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> DoubleEndedIterator for Iter<'a, T> { @@ -1321,6 +1331,7 @@ impl Iterator for IntoIter { fn next(&mut self) -> Option { self.iter.next().map(|(k, _)| k) } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } @@ -1359,6 +1370,14 @@ impl<'a, T> Iterator for Range<'a, T> { fn last(mut self) -> Option<&'a T> { self.next_back() } + + fn min(mut self) -> Option<&'a T> { + self.next() + } + + fn max(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "btree_range", since = "1.17.0")] @@ -1429,6 +1448,10 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { }; (self_len.saturating_sub(other_len), Some(self_len)) } + + fn min(mut self) -> Option<&'a T> { + self.next() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1460,6 +1483,10 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { // the number of elements to less than half the range of usize. (0, Some(a_len + b_len)) } + + fn min(mut self) -> Option<&'a T> { + self.next() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1516,6 +1543,10 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { IntersectionInner::Answer(Some(_)) => (1, Some(1)), } } + + fn min(mut self) -> Option<&'a T> { + self.next() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1541,6 +1572,10 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { // No checked_add - see SymmetricDifference::size_hint. (max(a_len, b_len), Some(a_len + b_len)) } + + fn min(mut self) -> Option<&'a T> { + self.next() + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index 6418c4a9823f2..5408faa079c15 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -12,7 +12,6 @@ fn allocator_param() { // // Instead, this just checks that the `RawVec` methods do at // least go through the Allocator API when it reserves - // storage. // A dumb allocator that consumes a fixed amount of fuel diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 731a1b5f875b7..682d829d219f3 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -309,6 +309,41 @@ fn test_iter_mixed() { test(size, map.into_iter()); } +#[test] +fn test_iter_min_max() { + let mut a = BTreeMap::new(); + assert_eq!(a.iter().min(), None); + assert_eq!(a.iter().max(), None); + assert_eq!(a.iter_mut().min(), None); + assert_eq!(a.iter_mut().max(), None); + assert_eq!(a.range(..).min(), None); + assert_eq!(a.range(..).max(), None); + assert_eq!(a.range_mut(..).min(), None); + assert_eq!(a.range_mut(..).max(), None); + assert_eq!(a.keys().min(), None); + assert_eq!(a.keys().max(), None); + assert_eq!(a.values().min(), None); + assert_eq!(a.values().max(), None); + assert_eq!(a.values_mut().min(), None); + assert_eq!(a.values_mut().max(), None); + a.insert(1, 42); + a.insert(2, 24); + assert_eq!(a.iter().min(), Some((&1, &42))); + assert_eq!(a.iter().max(), Some((&2, &24))); + assert_eq!(a.iter_mut().min(), Some((&1, &mut 42))); + assert_eq!(a.iter_mut().max(), Some((&2, &mut 24))); + assert_eq!(a.range(..).min(), Some((&1, &42))); + assert_eq!(a.range(..).max(), Some((&2, &24))); + assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42))); + assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24))); + assert_eq!(a.keys().min(), Some(&1)); + assert_eq!(a.keys().max(), Some(&2)); + assert_eq!(a.values().min(), Some(&24)); + assert_eq!(a.values().max(), Some(&42)); + assert_eq!(a.values_mut().min(), Some(&mut 24)); + assert_eq!(a.values_mut().max(), Some(&mut 42)); +} + fn range_keys(map: &BTreeMap, range: impl RangeBounds) -> Vec { map.range(range) .map(|(&k, &v)| { diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 75251ca0d51e9..b6c34b7c6c346 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -33,6 +33,37 @@ fn test_hash() { assert_eq!(hash(&x), hash(&y)); } +#[test] +fn test_iter_min_max() { + let mut a = BTreeSet::new(); + assert_eq!(a.iter().min(), None); + assert_eq!(a.iter().max(), None); + assert_eq!(a.range(..).min(), None); + assert_eq!(a.range(..).max(), None); + assert_eq!(a.difference(&BTreeSet::new()).min(), None); + assert_eq!(a.difference(&BTreeSet::new()).max(), None); + assert_eq!(a.intersection(&a).min(), None); + assert_eq!(a.intersection(&a).max(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None); + assert_eq!(a.union(&a).min(), None); + assert_eq!(a.union(&a).max(), None); + a.insert(1); + a.insert(2); + assert_eq!(a.iter().min(), Some(&1)); + assert_eq!(a.iter().max(), Some(&2)); + assert_eq!(a.range(..).min(), Some(&1)); + assert_eq!(a.range(..).max(), Some(&2)); + assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1)); + assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.intersection(&a).min(), Some(&1)); + assert_eq!(a.intersection(&a).max(), Some(&2)); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1)); + assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.union(&a).min(), Some(&1)); + assert_eq!(a.union(&a).max(), Some(&2)); +} + fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) where F: FnOnce(&BTreeSet, &BTreeSet, &mut dyn FnMut(&i32) -> bool) -> bool, diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 1265d0e56b576..c2cf64393adf8 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1801,6 +1801,21 @@ impl SpecFromElem for T { } } +impl SpecFromElem for i8 { + #[inline] + fn from_elem(elem: i8, n: usize) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed(n), len: n }; + } + unsafe { + let mut v = Vec::with_capacity(n); + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + v + } + } +} + impl SpecFromElem for u8 { #[inline] fn from_elem(elem: u8, n: usize) -> Vec { @@ -1845,7 +1860,6 @@ macro_rules! impl_is_zero { }; } -impl_is_zero!(i8, |x| x == 0); impl_is_zero!(i16, |x| x == 0); impl_is_zero!(i32, |x| x == 0); impl_is_zero!(i64, |x| x == 0); diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 1bd7ae3a34ebb..46e6ea7cd1866 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -358,12 +358,13 @@ pub fn size_of_val(val: &T) -> usize { /// - an (unstable) [extern type], then this function is always safe to /// call, but may panic or otherwise return the wrong value, as the /// extern type's layout is not known. This is the same behavior as -/// [`size_of_val`] on a reference to an extern type tail. +/// [`size_of_val`] on a reference to a type with an extern type tail. /// - otherwise, it is conservatively not allowed to call this function. /// /// [slice]: ../../std/primitive.slice.html /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html +/// [`size_of_val`]: ../../core/mem/fn.size_of_val.html /// /// # Examples /// @@ -492,12 +493,13 @@ pub fn align_of_val(val: &T) -> usize { /// - an (unstable) [extern type], then this function is always safe to /// call, but may panic or otherwise return the wrong value, as the /// extern type's layout is not known. This is the same behavior as -/// [`align_of_val`] on a reference to an extern type tail. +/// [`align_of_val`] on a reference to a type with an extern type tail. /// - otherwise, it is conservatively not allowed to call this function. /// /// [slice]: ../../std/primitive.slice.html /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html +/// [`align_of_val`]: ../../core/mem/fn.align_of_val.html /// /// # Examples /// diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 5f0a12678ff43..7aca6af3de6f3 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -142,11 +142,6 @@ use crate::{ ops::{self, Deref, DerefMut}, }; -// Note that this is not a lang item per se, but it has a hidden dependency on -// `Iterator`, which is one. The compiler assumes that the `next` method of -// `Iterator` is an enumeration with one type parameter and two variants, -// which basically means it must be `Option`. - /// The `Option` type. See [the module level documentation](index.html) for more. #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[rustc_diagnostic_item = "option_type"] diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 14cddd11c438d..e9a8b9095bf72 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -617,12 +617,22 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { a: &Self, b: &Self, ) -> RelateResult<'tcx, Self> { - if a.len() != b.len() { + let tcx = relation.tcx(); + + // FIXME: this is wasteful, but want to do a perf run to see how slow it is. + // We need to perform this deduplication as we sometimes generate duplicate projections + // in `a`. + let mut a_v: Vec<_> = a.into_iter().collect(); + let mut b_v: Vec<_> = b.into_iter().collect(); + a_v.sort_by(|a, b| a.stable_cmp(tcx, b)); + a_v.dedup(); + b_v.sort_by(|a, b| a.stable_cmp(tcx, b)); + b_v.dedup(); + if a_v.len() != b_v.len() { return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); } - let tcx = relation.tcx(); - let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| { + let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| { use crate::ty::ExistentialPredicate::*; match (ep_a, ep_b) { (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 19337c520f907..e1c5a4f5b1885 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -350,14 +350,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } fn get_const(&self, place: Place<'tcx>) -> Option> { - let op = self.ecx.eval_place_to_op(place, None).ok(); + let op = match self.ecx.eval_place_to_op(place, None) { + Ok(op) => op, + Err(e) => { + trace!("get_const failed: {}", e); + return None; + } + }; // Try to read the local as an immediate so that if it is representable as a scalar, we can // handle it as such, but otherwise, just return the value as is. - match op.map(|ret| self.ecx.try_read_immediate(ret)) { - Some(Ok(Ok(imm))) => Some(imm.into()), + Some(match self.ecx.try_read_immediate(op) { + Ok(Ok(imm)) => imm.into(), _ => op, - } + }) } /// Remove `local` from the pool of `Locals`. Allows writing to them, @@ -872,8 +878,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) { let can_const_prop = self.can_const_prop[place.local]; if let Some(()) = self.const_prop(rval, place_layout, source_info, place) { - // This will return None for variables that are from other blocks, - // so it should be okay to propagate from here on down. + // This will return None if the above `const_prop` invocation only "wrote" a + // type whose creation requires no write. E.g. a generator whose initial state + // consists solely of uninitialized memory (so it doesn't capture any locals). if let Some(value) = self.get_const(place) { if self.should_const_prop(value) { trace!("replacing {:?} with {:?}", rval, value); diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index 81974769cafb8..d01545619c8fa 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -48,8 +48,10 @@ pub fn target() -> Result { "ENCLAVE_SIZE", "CFGDATA_BASE", "DEBUG", - "EH_FRM_HDR_BASE", - "EH_FRM_HDR_SIZE", + "EH_FRM_HDR_OFFSET", + "EH_FRM_HDR_LEN", + "EH_FRM_OFFSET", + "EH_FRM_LEN", "TEXT_BASE", "TEXT_SIZE", ]; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 5dbcc5c9ec8b9..35b15cf717cee 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -123,10 +123,6 @@ pub struct Options { /// /// Be aware: This option can come both from the CLI and from crate attributes! pub default_passes: DefaultPassOption, - /// Document items that have lower than `pub` visibility. - pub document_private: bool, - /// Document items that have `doc(hidden)`. - pub document_hidden: bool, /// Any passes manually selected by the user. /// /// Be aware: This option can come both from the CLI and from crate attributes! @@ -177,8 +173,6 @@ impl fmt::Debug for Options { .field("test_args", &self.test_args) .field("persist_doctests", &self.persist_doctests) .field("default_passes", &self.default_passes) - .field("document_private", &self.document_private) - .field("document_hidden", &self.document_hidden) .field("manual_passes", &self.manual_passes) .field("display_warnings", &self.display_warnings) .field("show_coverage", &self.show_coverage) @@ -250,6 +244,10 @@ pub struct RenderOptions { pub generate_search_filter: bool, /// Option (disabled by default) to generate files used by RLS and some other tools. pub generate_redirect_pages: bool, + /// Document items that have lower than `pub` visibility. + pub document_private: bool, + /// Document items that have `doc(hidden)`. + pub document_hidden: bool, } impl Options { @@ -567,8 +565,6 @@ impl Options { should_test, test_args, default_passes, - document_private, - document_hidden, manual_passes, display_warnings, show_coverage, @@ -597,6 +593,8 @@ impl Options { markdown_playground_url, generate_search_filter, generate_redirect_pages, + document_private, + document_hidden, }, output_format, }) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1690b946bb625..8ab6c74289d17 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -62,6 +62,8 @@ pub struct DocContext<'tcx> { // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set. pub generated_synthetics: RefCell, DefId)>>, pub auto_traits: Vec, + /// The options given to rustdoc that could be relevant to a pass. + pub render_options: RenderOptions, } impl<'tcx> DocContext<'tcx> { @@ -281,8 +283,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt describe_lints, lint_cap, mut default_passes, - mut document_private, - document_hidden, mut manual_passes, display_warnings, render_options, @@ -448,6 +448,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt .cloned() .filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id)) .collect(), + render_options, }; debug!("crate: {:?}", tcx.hir().krate()); @@ -524,7 +525,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } if attr.is_word() && name == sym::document_private_items { - document_private = true; + ctxt.render_options.document_private = true; } } @@ -544,9 +545,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt for p in passes { let run = match p.condition { Always => true, - WhenDocumentPrivate => document_private, - WhenNotDocumentPrivate => !document_private, - WhenNotDocumentHidden => !document_hidden, + WhenDocumentPrivate => ctxt.render_options.document_private, + WhenNotDocumentPrivate => !ctxt.render_options.document_private, + WhenNotDocumentHidden => !ctxt.render_options.document_hidden, }; if run { debug!("running pass {}", p.pass.name); @@ -556,7 +557,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt ctxt.sess().abort_if_errors(); - (krate, ctxt.renderinfo.into_inner(), render_options) + (krate, ctxt.renderinfo.into_inner(), ctxt.render_options) }) }) }) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e60ff37fd279a..a453a8b3dcb2a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -468,7 +468,7 @@ impl clean::Path { pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { let cache = cache(); - if !did.is_local() && !cache.access_levels.is_public(did) { + if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private { return None; } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1681b73d0c257..04c4685213b2e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -469,6 +469,7 @@ pub fn run( static_root_path, generate_search_filter, generate_redirect_pages, + document_private, .. } = options; @@ -546,7 +547,7 @@ pub fn run( scx.ensure_dir(&dst)?; krate = sources::render(&dst, &mut scx, krate)?; let (new_crate, index, cache) = - Cache::from_krate(renderinfo, &extern_html_root_urls, &dst, krate); + Cache::from_krate(renderinfo, document_private, &extern_html_root_urls, &dst, krate); krate = new_crate; let cache = Arc::new(cache); let mut cx = Context { diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 225940773413e..1b5c8a9378e41 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -91,6 +91,10 @@ crate struct Cache { /// The version of the crate being documented, if given from the `--crate-version` flag. pub crate_version: Option, + /// Whether to document private items. + /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions. + pub document_private: bool, + // Private fields only used when initially crawling a crate to build a cache stack: Vec, parent_stack: Vec, @@ -126,6 +130,7 @@ crate struct Cache { impl Cache { pub fn from_krate( renderinfo: RenderInfo, + document_private: bool, extern_html_root_urls: &BTreeMap, dst: &Path, mut krate: clean::Crate, @@ -160,6 +165,7 @@ impl Cache { stripped_mod: false, access_levels, crate_version: krate.version.take(), + document_private, orphan_impl_items: Vec::new(), orphan_trait_impls: Vec::new(), traits: krate.external_traits.replace(Default::default()), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f5b2f1bb5b178..8da74f375d9ce 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -178,6 +178,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { let result = cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); + debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns); let result = match result { Ok((_, Res::Err)) => Err(ErrorKind::ResolutionFailure), _ => result.map_err(|_| ErrorKind::ResolutionFailure), @@ -202,7 +203,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { } return Ok((res, Some(path_str.to_owned()))); } - _ => return Ok((res, extra_fragment.clone())), + other => { + debug!( + "failed to resolve {} in namespace {:?} (got {:?})", + path_str, ns, other + ); + return Ok((res, extra_fragment.clone())); + } }; if value != (ns == ValueNS) { @@ -555,12 +562,13 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } else { (parts[0].to_owned(), None) }; + let resolved_self; + let mut path_str; let (res, fragment) = { let mut kind = None; - let mut path_str = if let Some(prefix) = - ["struct@", "enum@", "type@", "trait@", "union@"] - .iter() - .find(|p| link.starts_with(**p)) + path_str = if let Some(prefix) = ["struct@", "enum@", "type@", "trait@", "union@"] + .iter() + .find(|p| link.starts_with(**p)) { kind = Some(TypeNS); link.trim_start_matches(prefix) @@ -614,7 +622,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let base_node = if item.is_mod() && item.attrs.inner_docs { None } else { parent_node }; - let resolved_self; // replace `Self` with suitable item's parent name if path_str.starts_with("Self::") { if let Some(ref name) = parent_name { @@ -760,6 +767,32 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Res::PrimTy(_) = res { item.attrs.links.push((ori_link, None, fragment)); } else { + debug!("intra-doc link to {} resolved to {:?}", path_str, res); + if let Some(local) = res.opt_def_id().and_then(|def_id| def_id.as_local()) { + use rustc_hir::def_id::LOCAL_CRATE; + + let hir_id = self.cx.tcx.hir().as_local_hir_id(local); + if !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_id) + && !self.cx.render_options.document_private + { + let item_name = item.name.as_deref().unwrap_or(""); + let err_msg = format!( + "public documentation for `{}` links to a private item", + item_name + ); + build_diagnostic( + cx, + &item, + path_str, + &dox, + link_range, + &err_msg, + "this item is private", + None, + ); + continue; + } + } let id = register_res(cx, res); item.attrs.links.push((ori_link, Some(id), fragment)); } diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index f987eb67ea5f2..d972cf6db18cf 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1217,11 +1217,66 @@ mod self_keyword {} /// The implementing type within a [`trait`] or [`impl`] block, or the current type within a type /// definition. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// Within a type definition: +/// +/// ``` +/// # #![allow(dead_code)] +/// struct Node { +/// elem: i32, +/// // `Self` is a `Node` here. +/// next: Option>, +/// } +/// ``` +/// +/// In an [`impl`] block: +/// +/// ``` +/// struct Foo(i32); +/// +/// impl Foo { +/// fn new() -> Self { +/// Self(0) +/// } +/// } +/// +/// assert_eq!(Foo::new().0, Foo(0).0); +/// ``` +/// +/// Generic parameters are implicit with `Self`: +/// +/// ``` +/// # #![allow(dead_code)] +/// struct Wrap { +/// elem: T, +/// } +/// +/// impl Wrap { +/// fn new(elem: T) -> Self { +/// Self { elem } +/// } +/// } +/// ``` +/// +/// In a [`trait`] definition and related [`impl`] block: +/// +/// ``` +/// trait Example { +/// fn example() -> Self; +/// } +/// +/// struct Foo(i32); +/// +/// impl Example for Foo { +/// fn example() -> Self { +/// Self(42) +/// } +/// } +/// +/// assert_eq!(Foo::example().0, Foo(42).0); +/// ``` /// /// [`impl`]: keyword.impl.html /// [`trait`]: keyword.trait.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod self_upper_keyword {} #[doc(keyword = "static")] @@ -1345,10 +1400,26 @@ mod struct_keyword {} // /// The parent of the current [module]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// ```rust +/// # #![allow(dead_code)] +/// # fn main() {} +/// mod a { +/// pub fn foo() {} +/// } +/// mod b { +/// pub fn foo() { +/// super::a::foo(); // call a's foo function +/// } +/// } +/// ``` +/// +/// It is also possible to use `super` multiple times: `super::super::foo`, +/// going up the ancestor chain. +/// +/// See the [Reference] for more information. /// /// [module]: ../reference/items/modules.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// [Reference]: ../reference/paths.html#super mod super_keyword {} #[doc(keyword = "trait")] diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index fc6ce5770338e..f61bcf06f0815 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -11,7 +11,7 @@ IMAGE_BASE: .long 1 /* type = NT_VERSION */ 0: .asciz "toolchain-version" /* name */ 1: .align 4 -2: .long 0 /* desc - toolchain version number, 32-bit LE */ +2: .long 1 /* desc - toolchain version number, 32-bit LE */ 3: .align 4 .section .rodata @@ -60,10 +60,14 @@ IMAGE_BASE: globvar TEXT_BASE 8 /* The size in bytes of enclacve text section */ globvar TEXT_SIZE 8 - /* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */ - globvar EH_FRM_HDR_BASE 8 - /* The size in bytes of enclacve EH_FRM_HDR section */ - globvar EH_FRM_HDR_SIZE 8 + /* The base address (relative to enclave start) of the enclave .eh_frame_hdr section */ + globvar EH_FRM_HDR_OFFSET 8 + /* The size in bytes of enclave .eh_frame_hdr section */ + globvar EH_FRM_HDR_LEN 8 + /* The base address (relative to enclave start) of the enclave .eh_frame section */ + globvar EH_FRM_OFFSET 8 + /* The size in bytes of enclacve .eh_frame section */ + globvar EH_FRM_LEN 8 .org .Lxsave_clear+512 .Lxsave_header: diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index f6f16f686e557..31d235cf679db 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -9,6 +9,8 @@ fn main() { { // Build the unwinding from libunwind C/C++ source code. llvm_libunwind::compile(); + } else if target.contains("x86_64-fortanix-unknown-sgx") { + llvm_libunwind::compile(); } else if target.contains("linux") { if target.contains("musl") { // linking for musl is handled in lib.rs @@ -55,6 +57,7 @@ mod llvm_libunwind { /// Compile the libunwind C/C++ source code. pub fn compile() { + let target = env::var("TARGET").expect("TARGET was not set"); let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap(); let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big"; @@ -75,6 +78,35 @@ mod llvm_libunwind { cfg.flag("/EHsc"); cfg.define("_CRT_SECURE_NO_WARNINGS", None); cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None); + } else if target.contains("x86_64-fortanix-unknown-sgx") { + cfg.cpp(false); + + cfg.static_flag(true); + cfg.opt_level(3); + + cfg.flag("-nostdinc++"); + cfg.flag("-fno-exceptions"); + cfg.flag("-fno-rtti"); + cfg.flag("-fstrict-aliasing"); + cfg.flag("-funwind-tables"); + cfg.flag("-fvisibility=hidden"); + cfg.flag("-fno-stack-protector"); + cfg.flag("-ffreestanding"); + cfg.flag("-fexceptions"); + + // easiest way to undefine since no API available in cc::Build to undefine + cfg.flag("-U_FORTIFY_SOURCE"); + cfg.define("_FORTIFY_SOURCE", "0"); + + cfg.flag_if_supported("-fvisibility-global-new-delete-hidden"); + + cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None); + cfg.define("RUST_SGX", "1"); + cfg.define("__NO_STRING_INLINES", None); + cfg.define("__NO_MATH_INLINES", None); + cfg.define("_LIBUNWIND_IS_BAREMETAL", None); + cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None); + cfg.define("NDEBUG", None); } else { cfg.flag("-std=c99"); cfg.flag("-std=c++11"); @@ -103,6 +135,10 @@ mod llvm_libunwind { unwind_sources.push("Unwind_AppleExtras.cpp"); } + if target.contains("x86_64-fortanix-unknown-sgx") { + unwind_sources.push("UnwindRustSgx.c"); + } + let root = Path::new("../llvm-project/libunwind"); cfg.include(root.join("include")); for src in unwind_sources { diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-links-private.public.stderr new file mode 100644 index 0000000000000..0a8dafdaf9466 --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-private.public.stderr @@ -0,0 +1,10 @@ +warning: `[DontDocMe]` public documentation for `DocMe` links to a private item + --> $DIR/intra-links-private.rs:6:11 + | +LL | /// docs [DontDocMe] + | ^^^^^^^^^ this item is private + | + = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/rustdoc-ui/intra-links-private.rs b/src/test/rustdoc-ui/intra-links-private.rs new file mode 100644 index 0000000000000..b7906aba5b1a9 --- /dev/null +++ b/src/test/rustdoc-ui/intra-links-private.rs @@ -0,0 +1,10 @@ +// check-pass +// revisions: public private +// [private]compile-flags: --document-private-items +#![cfg_attr(private, deny(intra_doc_resolution_failure))] + +/// docs [DontDocMe] +//[public]~^ WARNING `[DontDocMe]` public documentation for `DocMe` links to a private item +// FIXME: for [private] we should also make sure the link was actually generated +pub struct DocMe; +struct DontDocMe; diff --git a/src/test/rustdoc-ui/reference-link-has-one-warning.rs b/src/test/rustdoc-ui/reference-link-has-one-warning.rs new file mode 100644 index 0000000000000..21cb7eb9040bd --- /dev/null +++ b/src/test/rustdoc-ui/reference-link-has-one-warning.rs @@ -0,0 +1,6 @@ +// ignore-test +// check-pass + +/// docs [label][with#anchor#error] +//~^ WARNING has an issue with the link anchor +pub struct S; diff --git a/src/test/rustdoc-ui/reference-link-has-one-warning.stderr b/src/test/rustdoc-ui/reference-link-has-one-warning.stderr new file mode 100644 index 0000000000000..5bbc62b76dd04 --- /dev/null +++ b/src/test/rustdoc-ui/reference-link-has-one-warning.stderr @@ -0,0 +1,10 @@ +warning: `[with#anchor#error]` has an issue with the link anchor. + --> $DIR/reference-link-has-one-warning.rs:3:18 + | +LL | /// docs [label][with#anchor#error] + | ^^^^^^^^^^^^^^^^^ only one `#` is allowed in a link + | + = note: `#[warn(intra_doc_link_resolution_failure)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-59326.rs b/src/test/ui/issues/issue-59326.rs new file mode 100644 index 0000000000000..c0e8837749eb4 --- /dev/null +++ b/src/test/ui/issues/issue-59326.rs @@ -0,0 +1,26 @@ +// check-pass +trait Service { + type S; +} + +trait Framing { + type F; +} + +impl Framing for () { + type F = (); +} + +trait HttpService: Service {} + +type BoxService = Box>; + +fn build_server BoxService>(_: F) {} + +fn make_server() -> Box> { + unimplemented!() +} + +fn main() { + build_server(|| make_server()) +}