diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9867113e48f43..7826ac9471806 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1184,8 +1184,19 @@ impl Step for Compiletest { Err(_) => p, } }) - .filter(|p| p.starts_with(suite_path) && p.is_file()) - .map(|p| p.strip_prefix(suite_path).unwrap().to_str().unwrap()) + .filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file())) + .filter_map(|p| { + // Since test suite paths are themselves directories, if we don't + // specify a directory or file, we'll get an empty string here + // (the result of the test suite directory without its suite prefix). + // Therefore, we need to filter these out, as only the first --test-args + // flag is respected, so providing an empty --test-args conflicts with + // any following it. + match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) { + Some(s) if s != "" => Some(s), + _ => None, + } + }) .collect(); test_args.append(&mut builder.config.cmd.test_args()); diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index c355361b53c46..39fcfaa789377 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -992,6 +992,11 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1047,6 +1052,11 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1093,6 +1103,11 @@ impl Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 6b079fc87cc78..414abb00ef1fa 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1193,6 +1193,11 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } } #[stable(feature = "fused", since = "1.26.0")] @@ -1253,6 +1258,11 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a mut V)> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1359,6 +1369,11 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } + + #[inline] + fn last(mut self) -> Option<(K, V)> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1421,6 +1436,11 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a K> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1458,6 +1478,11 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a V> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1495,6 +1520,11 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { unsafe { Some(self.next_unchecked()) } } } + + #[inline] + fn last(mut self) -> Option<(&'a K, &'a V)> { + self.next_back() + } } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1508,6 +1538,11 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a mut V> { + self.next_back() + } } #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1626,6 +1661,11 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { unsafe { Some(self.next_unchecked()) } } } + + #[inline] + fn last(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 16a96ca19b824..6f2467dfd6b51 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -1019,6 +1019,11 @@ impl<'a, T> Iterator for Iter<'a, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> DoubleEndedIterator for Iter<'a, T> { @@ -1044,6 +1049,11 @@ impl Iterator for IntoIter { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for IntoIter { @@ -1073,6 +1083,11 @@ impl<'a, T> Iterator for Range<'a, T> { fn next(&mut self) -> Option<&'a T> { self.iter.next().map(|(k, _)| k) } + + #[inline] + fn last(mut self) -> Option<&'a T> { + self.next_back() + } } #[stable(feature = "btree_range", since = "1.17.0")] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 3fdcf95ccaa3f..63f7769fee56a 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2377,6 +2377,10 @@ impl Iterator for Drain<'_> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 073d3ab593703..c0cdffe596bab 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2395,6 +2395,11 @@ impl Iterator for IntoIter { fn count(self) -> usize { self.len() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2514,6 +2519,11 @@ impl Iterator for Drain<'_, T> { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "drain", since = "1.6.0")] @@ -2583,6 +2593,10 @@ impl Iterator for Splice<'_, I> { fn size_hint(&self) -> (usize, Option) { self.drain.size_hint() } + + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "vec_splice", since = "1.21.0")] diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index c0ab364380fbd..ddee02ea232d1 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -117,6 +117,8 @@ impl Iterator for EscapeDefault { type Item = u8; fn next(&mut self) -> Option { self.range.next().map(|i| self.data[i]) } fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 504330a023b31..3f76ac20192ba 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -23,7 +23,7 @@ use crate::task::{Context, Poll}; /// When using a future, you generally won't call `poll` directly, but instead /// `await!` the value. #[doc(spotlight)] -#[must_use = "futures do nothing unless polled"] +#[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] pub trait Future { /// The type of value produced on completion. diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 518442efe7417..64e588f65b468 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -73,6 +73,11 @@ impl Iterator for Rev where I: DoubleEndedIterator { { self.iter.position(predicate) } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f48675356..d06d107d32a41 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -359,6 +359,10 @@ impl [T] { /// The caller must ensure that the slice outlives the pointer this /// function returns, or else it will end up pointing to garbage. /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// /// Modifying the container referenced by this slice may cause its buffer /// to be reallocated, which would also make any pointers to it invalid. /// @@ -374,6 +378,8 @@ impl [T] { /// } /// } /// ``` + /// + /// [`as_mut_ptr`]: #method.as_mut_ptr #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub const fn as_ptr(&self) -> *const T { @@ -3541,6 +3547,11 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool { (1, Some(self.v.len() + 1)) } } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3639,6 +3650,11 @@ impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool { (1, Some(self.v.len() + 1)) } } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -3704,6 +3720,11 @@ impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "slice_rsplit", since = "1.27.0")] @@ -3768,6 +3789,11 @@ impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "slice_rsplit", since = "1.27.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 45421848cec5d..0e8a2da3c110d 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1333,6 +1333,11 @@ impl<'a> Iterator for Lines<'a> { fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1379,6 +1384,11 @@ impl<'a> Iterator for LinesAny<'a> { fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -2188,7 +2198,11 @@ impl str { /// [`u8`]. This pointer will be pointing to the first byte of the string /// slice. /// + /// The caller must ensure that the returned pointer is never written to. + /// If you need to mutate the contents of the string slice, use [`as_mut_ptr`]. + /// /// [`u8`]: primitive.u8.html + /// [`as_mut_ptr`]: #method.as_mut_ptr /// /// # Examples /// @@ -4217,6 +4231,11 @@ impl<'a> Iterator for SplitWhitespace<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "split_whitespace", since = "1.1.0")] @@ -4243,6 +4262,11 @@ impl<'a> Iterator for SplitAsciiWhitespace<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index d68e2be9ea086..c4be85050dbc2 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -43,6 +43,7 @@ use crate::hir; use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; +use std::cell::Cell; use std::cmp; use std::fmt::{self, Display}; use std::iter; @@ -153,6 +154,36 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { /// selection-context's freshener. Used to check for recursion. fresh_trait_ref: ty::PolyTraitRef<'tcx>, + /// Starts out as false -- if, during evaluation, we encounter a + /// cycle, then we will set this flag to true for all participants + /// in the cycle (apart from the "head" node). These participants + /// will then forego caching their results. This is not the most + /// efficient solution, but it addresses #60010. The problem we + /// are trying to prevent: + /// + /// - If you have `A: AutoTrait` requires `B: AutoTrait` and `C: NonAutoTrait` + /// - `B: AutoTrait` requires `A: AutoTrait` (coinductive cycle, ok) + /// - `C: NonAutoTrait` requires `A: AutoTrait` (non-coinductive cycle, not ok) + /// + /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait` + /// is `EvaluatedToOk`; this is because they were only considered + /// ok on the premise that if `A: AutoTrait` held, but we indeed + /// encountered a problem (later on) with `A: AutoTrait. So we + /// currently set a flag on the stack node for `B: AutoTrait` (as + /// well as the second instance of `A: AutoTrait`) to supress + /// caching. + /// + /// This is a simple, targeted fix. A more-performant fix requires + /// deeper changes, but would permit more caching: we could + /// basically defer caching until we have fully evaluated the + /// tree, and then cache the entire tree at once. In any case, the + /// performance impact here shouldn't be so horrible: every time + /// this is hit, we do cache at least one trait, so we only + /// evaluate each member of a cycle up to N times, where N is the + /// length of the cycle. This means the performance impact is + /// bounded and we shouldn't have any terrible worst-cases. + in_cycle: Cell, + previous: TraitObligationStackList<'prev, 'tcx>, } @@ -840,8 +871,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack)); let result = result?; - debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result); - self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); + if !stack.in_cycle.get() { + debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result); + self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); + } else { + debug!( + "evaluate_trait_predicate_recursively: skipping cache because {:?} \ + is a cycle participant", + fresh_trait_ref, + ); + } Ok(result) } @@ -948,6 +987,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); + // If we have a stack like `A B C D E A`, where the top of + // the stack is the final `A`, then this will iterate over + // `A, E, D, C, B` -- i.e., all the participants apart + // from the cycle head. We mark them as participating in a + // cycle. This suppresses caching for those nodes. See + // `in_cycle` field for more details. + for item in stack.iter().take(rec_index + 1) { + debug!("evaluate_stack: marking {:?} as cycle participant", item.fresh_trait_ref); + item.in_cycle.set(true); + } + // Subtle: when checking for a coinductive cycle, we do // not compare using the "freshened trait refs" (which // have erased regions) but rather the fully explicit @@ -3690,6 +3740,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { TraitObligationStack { obligation, fresh_trait_ref, + in_cycle: Cell::new(false), previous: previous_stack, } } diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 9dd343b6c8de8..53364e72bfe3a 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -14,7 +14,7 @@ pub fn opts() -> TargetOptions { // // Here we detect what version is being requested, defaulting to 10.7. ELF // TLS is flagged as enabled if it looks to be supported. - let version = macos_deployment_target().unwrap_or((10, 7)); + let version = macos_deployment_target(); TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections @@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions { } } -fn macos_deployment_target() -> Option<(u32, u32)> { +fn macos_deployment_target() -> (u32, u32) { let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); let version = deployment_target.as_ref().and_then(|s| { let mut i = s.splitn(2, '.'); @@ -44,17 +44,10 @@ fn macos_deployment_target() -> Option<(u32, u32)> { a.parse::().and_then(|a| b.parse::().map(|b| (a, b))).ok() }); - version + version.unwrap_or((10, 7)) } pub fn macos_llvm_target(arch: &str) -> String { - let version = macos_deployment_target(); - let llvm_target = match version { - Some((major, minor)) => { - format!("{}-apple-macosx{}.{}.0", arch, major, minor) - }, - None => format!("{}-apple-darwin", arch) - }; - - llvm_target + let (major, minor) = macos_deployment_target(); + format!("{}-apple-macosx{}.{}.0", arch, major, minor) } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index ecb8e09ec2461..13baf667808f8 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -466,6 +466,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id); + debug_assert!(!instantiated_ty.has_escaping_bound_vars()); + let generics = self.tcx().generics_of(def_id); let definition_ty = if generics.parent.is_some() { @@ -524,8 +526,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { }, lt_op: |region| { match region { - // ignore static regions - ty::ReStatic => region, + // Skip static and bound regions: they don't + // require substitution. + ty::ReStatic | ty::ReLateBound(..) => region, _ => { trace!("checking {:?}", region); for (subst, p) in opaque_defn.substs.iter().zip(&generics.params) { diff --git a/src/libstd/env.rs b/src/libstd/env.rs index c0d0c23e46968..39896ac2fcd27 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -746,6 +746,10 @@ impl Iterator for Args { self.inner.next().map(|s| s.into_string().unwrap()) } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "env", since = "1.0.0")] @@ -781,6 +785,8 @@ impl Iterator for ArgsOs { type Item = OsString; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } #[stable(feature = "env", since = "1.0.0")] diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index f93583dff818f..5c6c43017cf64 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -43,7 +43,9 @@ use crate::sys; /// `CString` implements a [`as_ptr`] method through the [`Deref`] /// trait. This method will give you a `*const c_char` which you can /// feed directly to extern functions that expect a nul-terminated -/// string, like C's `strdup()`. +/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a +/// read-only pointer; if the C code writes to it, that causes +/// undefined behavior. /// /// # Extracting a slice of the whole C string /// @@ -61,7 +63,7 @@ use crate::sys; /// /// Once you have the kind of slice you need (with or without a nul /// terminator), you can call the slice's own -/// [`as_ptr`][slice.as_ptr] method to get a raw pointer to pass to +/// [`as_ptr`][slice.as_ptr] method to get a read-only raw pointer to pass to /// extern functions. See the documentation for that function for a /// discussion on ensuring the lifetime of the raw pointer. /// @@ -1043,6 +1045,9 @@ impl CStr { /// /// **WARNING** /// + /// The returned pointer is read-only; writing to it (including passing it + /// to C code that writes to it) causes undefined behavior. + /// /// It is your responsibility to make sure that the underlying memory is not /// freed too early. For example, the following code will cause undefined /// behavior when `ptr` is used inside the `unsafe` block: diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 126bc3754dabc..59f9e439add24 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -888,6 +888,11 @@ impl<'a> Iterator for Iter<'a> { fn next(&mut self) -> Option<&'a OsStr> { self.inner.next().map(Component::as_os_str) } + + #[inline] + fn last(mut self) -> Option<&'a OsStr> { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -951,6 +956,11 @@ impl<'a> Iterator for Components<'a> { } None } + + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 18de1096df2a2..f0594bb21bd83 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -35,6 +35,8 @@ impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } impl ExactSizeIterator for Args { diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index e923b9aa29b01..77f1439e17b10 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -13,7 +13,6 @@ pub fn hashmap_random_keys() -> (u64, u64) { #[cfg(all(unix, not(target_os = "ios"), - not(all(target_os = "macos", miri)), not(target_os = "openbsd"), not(target_os = "freebsd"), not(target_os = "fuchsia")))] @@ -107,9 +106,7 @@ mod imp { // once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is // only used on iOS where direct access to `/dev/urandom` is blocked by the // sandbox. -// HACK: However, we do use this when running in Miri on macOS; intercepting this is much -// easier than intercepting accesses to /dev/urandom. -#[cfg(any(target_os = "ios", all(target_os = "macos", miri)))] +#[cfg(target_os = "ios")] mod imp { use crate::io; use crate::ptr; diff --git a/src/libstd/sys/wasm/args.rs b/src/libstd/sys/wasm/args.rs index b3c77b8699563..6766099c1ece1 100644 --- a/src/libstd/sys/wasm/args.rs +++ b/src/libstd/sys/wasm/args.rs @@ -37,6 +37,10 @@ impl Iterator for Args { fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn last(mut self) -> Option { + self.next_back() + } } impl ExactSizeIterator for Args { diff --git a/src/libstd/sys/windows/args.rs b/src/libstd/sys/windows/args.rs index b04bb484eedb9..744d7ec59d3a3 100644 --- a/src/libstd/sys/windows/args.rs +++ b/src/libstd/sys/windows/args.rs @@ -181,6 +181,8 @@ impl Iterator for Args { type Item = OsString; fn next(&mut self) -> Option { self.parsed_args_list.next() } fn size_hint(&self) -> (usize, Option) { self.parsed_args_list.size_hint() } + #[inline] + fn last(mut self) -> Option { self.next_back() } } impl DoubleEndedIterator for Args { diff --git a/src/test/codegen/i686-no-macosx-deployment-target.rs b/src/test/codegen/i686-no-macosx-deployment-target.rs index eb826590523b7..1cebc49236fee 100644 --- a/src/test/codegen/i686-no-macosx-deployment-target.rs +++ b/src/test/codegen/i686-no-macosx-deployment-target.rs @@ -19,7 +19,7 @@ pub struct Bool { b: bool, } -// CHECK: target triple = "i686-apple-darwin" +// CHECK: target triple = "i686-apple-macosx10.7.0" #[no_mangle] pub extern "C" fn structbool() -> Bool { Bool { b: true } diff --git a/src/test/codegen/x86_64-no-macosx-deployment-target.rs b/src/test/codegen/x86_64-no-macosx-deployment-target.rs index 58a11d1095bbe..c5ac73b54e186 100644 --- a/src/test/codegen/x86_64-no-macosx-deployment-target.rs +++ b/src/test/codegen/x86_64-no-macosx-deployment-target.rs @@ -19,7 +19,7 @@ pub struct Bool { b: bool, } -// CHECK: target triple = "x86_64-apple-darwin" +// CHECK: target triple = "x86_64-apple-macosx10.7.0" #[no_mangle] pub extern "C" fn structbool() -> Bool { Bool { b: true } diff --git a/src/test/ui/existential_types/issue-60655-latebound-regions.rs b/src/test/ui/existential_types/issue-60655-latebound-regions.rs new file mode 100644 index 0000000000000..a4fe86501299f --- /dev/null +++ b/src/test/ui/existential_types/issue-60655-latebound-regions.rs @@ -0,0 +1,30 @@ +// Test that existential types are allowed to contain late-bound regions. + +// compile-pass +// edition:2018 + +#![feature(async_await, existential_type)] + +use std::future::Future; + +pub existential type Func: Sized; + +// Late bound region should be allowed to escape the function, since it's bound +// in the type. +fn null_function_ptr() -> Func { + None:: fn(&'a ())> +} + +async fn async_nop(_: &u8) {} + +pub existential type ServeFut: Future; + +// Late bound regions occur in the generator witness type here. +fn serve() -> ServeFut { + async move { + let x = 5; + async_nop(&x).await + } +} + +fn main() {} diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs new file mode 100644 index 0000000000000..45aa1b3c52239 --- /dev/null +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -0,0 +1,71 @@ +// Test that we properly detect the cycle amongst the traits +// here and report an error. + +use std::panic::RefUnwindSafe; + +trait Database { + type Storage; +} +trait HasQueryGroup {} +trait Query { + type Data; +} +trait SourceDatabase { + fn parse(&self) { + loop {} + } +} + +struct ParseQuery; +struct RootDatabase { + _runtime: Runtime, +} +struct Runtime { + _storage: Box, +} +struct SalsaStorage { + _parse: >::Data, //~ ERROR overflow +} + +impl Database for RootDatabase { //~ ERROR overflow + type Storage = SalsaStorage; +} +impl HasQueryGroup for RootDatabase {} +impl Query for ParseQuery +where + DB: SourceDatabase, + DB: Database, +{ + type Data = RootDatabase; +} +impl SourceDatabase for T +where + T: RefUnwindSafe, + T: HasQueryGroup, +{ +} + +pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 { + // This is not satisfied: + // + // - `RootDatabase: SourceDatabase` + // - requires `RootDatabase: RefUnwindSafe` + `RootDatabase: HasQueryGroup` + // - `RootDatabase: RefUnwindSafe` + // - requires `Runtime: RefUnwindSafe` + // - `Runtime: RefUnwindSafe` + // - requires `DB::Storage: RefUnwindSafe` (`SalsaStorage: RefUnwindSafe`) + // - `SalsaStorage: RefUnwindSafe` + // - requires `>::Data: RefUnwindSafe`, + // which means `ParseQuery: Query` + // - `ParseQuery: Query` + // - requires `RootDatabase: SourceDatabase`, + // - `RootDatabase: SourceDatabase` is already on the stack, so we have a + // cycle with non-coinductive participants + // + // we used to fail to report an error here because we got the + // caching wrong. + SourceDatabase::parse(db); + 22 +} + +fn main() {} diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr new file mode 100644 index 0000000000000..9192f7ba2e3b0 --- /dev/null +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -0,0 +1,20 @@ +error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` + --> $DIR/cycle-cache-err-60010.rs:27:5 + | +LL | _parse: >::Data, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because of the requirements on the impl of `Query` for `ParseQuery` + +error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase` + --> $DIR/cycle-cache-err-60010.rs:30:6 + | +LL | impl Database for RootDatabase { + | ^^^^^^^^ + | + = note: required because of the requirements on the impl of `Query` for `ParseQuery` + = note: required because it appears within the type `SalsaStorage` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/tools/clippy b/src/tools/clippy index 3710ec5996229..ad3269c4b510b 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 3710ec59962295336ab4aed100267b584dd7df7d +Subproject commit ad3269c4b510b94b7c0082f4bb341bee6ed1eca4 diff --git a/src/tools/miri b/src/tools/miri index 053aa694990a2..bc0c76d861a17 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 053aa694990a212ad8942dd72101ede23597c0e9 +Subproject commit bc0c76d861a178911f3f506196a7404eda1e690d