Auto merge of #60834 - Centril:rollup-fikyi9i, r=Centril
Rollup of 9 pull requests Successful merges: - #60130 (Add implementations of last in terms of next_back on a bunch of DoubleEndedIterators) - #60443 (as_ptr returns a read-only pointer) - #60444 (forego caching for all participants in cycles, apart from root node) - #60719 (Allow subdirectories to be tested by x.py test) - #60780 (fix Miri) - #60788 (default to $ARCH-apple-macosx10.7.0 LLVM triple for darwin targets) - #60799 (Allow late-bound regions in existential types) - #60808 (Improve the "must use" lint for `Future`) - #60819 (submodules: update clippy from3710ec59
toad3269c4
) Failed merges: r? @ghost
This commit is contained in:
commit
372be4f360
@ -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());
|
||||
|
@ -992,6 +992,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
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<T> Iterator for IntoIter<T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<T> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -1093,6 +1103,11 @@ impl<T> Iterator for Drain<'_, T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<T> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
|
@ -1193,6 +1193,11 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(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<usize>) {
|
||||
(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<K, V> Iterator for IntoIter<K, V> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(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<usize>) {
|
||||
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<usize>) {
|
||||
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<usize>) {
|
||||
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> {
|
||||
|
@ -1019,6 +1019,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
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<T> Iterator for IntoIter<T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<T> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> DoubleEndedIterator for IntoIter<T> {
|
||||
@ -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")]
|
||||
|
@ -2377,6 +2377,10 @@ impl Iterator for Drain<'_> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<char> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
|
@ -2395,6 +2395,11 @@ impl<T> Iterator for IntoIter<T> {
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<T> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -2514,6 +2519,11 @@ impl<T> Iterator for Drain<'_, T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<T> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
@ -2583,6 +2593,10 @@ impl<I: Iterator> Iterator for Splice<'_, I> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.drain.size_hint()
|
||||
}
|
||||
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "vec_splice", since = "1.21.0")]
|
||||
|
@ -117,6 +117,8 @@ impl Iterator for EscapeDefault {
|
||||
type Item = u8;
|
||||
fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<u8> { self.next_back() }
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl DoubleEndedIterator for EscapeDefault {
|
||||
|
@ -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.
|
||||
|
@ -73,6 +73,11 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
|
||||
{
|
||||
self.iter.position(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -359,6 +359,10 @@ impl<T> [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> [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::Item> {
|
||||
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::Item> {
|
||||
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<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
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<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "slice_rsplit", since = "1.27.0")]
|
||||
|
@ -1333,6 +1333,11 @@ impl<'a> Iterator for Lines<'a> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
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<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
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<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
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<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
|
||||
|
@ -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<bool>,
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -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::<u32>().and_then(|a| b.parse::<u32>().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)
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -746,6 +746,10 @@ impl Iterator for Args {
|
||||
self.inner.next().map(|s| s.into_string().unwrap())
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<String> {
|
||||
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<OsString> { self.inner.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<OsString> { self.next_back() }
|
||||
}
|
||||
|
||||
#[stable(feature = "env", since = "1.0.0")]
|
||||
|
@ -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:
|
||||
|
@ -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::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -35,6 +35,8 @@ impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<OsString> { self.next_back() }
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
|
@ -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;
|
||||
|
@ -37,6 +37,10 @@ impl Iterator for Args {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<OsString> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
|
@ -181,6 +181,8 @@ impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.parsed_args_list.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.parsed_args_list.size_hint() }
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<OsString> { self.next_back() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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::<for<'a> fn(&'a ())>
|
||||
}
|
||||
|
||||
async fn async_nop(_: &u8) {}
|
||||
|
||||
pub existential type ServeFut: Future<Output=()>;
|
||||
|
||||
// Late bound regions occur in the generator witness type here.
|
||||
fn serve() -> ServeFut {
|
||||
async move {
|
||||
let x = 5;
|
||||
async_nop(&x).await
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
71
src/test/ui/traits/cycle-cache-err-60010.rs
Normal file
71
src/test/ui/traits/cycle-cache-err-60010.rs
Normal file
@ -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<DB> {
|
||||
type Data;
|
||||
}
|
||||
trait SourceDatabase {
|
||||
fn parse(&self) {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
struct ParseQuery;
|
||||
struct RootDatabase {
|
||||
_runtime: Runtime<RootDatabase>,
|
||||
}
|
||||
struct Runtime<DB: Database> {
|
||||
_storage: Box<DB::Storage>,
|
||||
}
|
||||
struct SalsaStorage {
|
||||
_parse: <ParseQuery as Query<RootDatabase>>::Data, //~ ERROR overflow
|
||||
}
|
||||
|
||||
impl Database for RootDatabase { //~ ERROR overflow
|
||||
type Storage = SalsaStorage;
|
||||
}
|
||||
impl HasQueryGroup for RootDatabase {}
|
||||
impl<DB> Query<DB> for ParseQuery
|
||||
where
|
||||
DB: SourceDatabase,
|
||||
DB: Database,
|
||||
{
|
||||
type Data = RootDatabase;
|
||||
}
|
||||
impl<T> 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<RootDatabase>: RefUnwindSafe`
|
||||
// - `Runtime<RootDatabase>: RefUnwindSafe`
|
||||
// - requires `DB::Storage: RefUnwindSafe` (`SalsaStorage: RefUnwindSafe`)
|
||||
// - `SalsaStorage: RefUnwindSafe`
|
||||
// - requires `<ParseQuery as Query<RootDatabase>>::Data: RefUnwindSafe`,
|
||||
// which means `ParseQuery: Query<RootDatabase>`
|
||||
// - `ParseQuery: Query<RootDatabase>`
|
||||
// - 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() {}
|
20
src/test/ui/traits/cycle-cache-err-60010.stderr
Normal file
20
src/test/ui/traits/cycle-cache-err-60010.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase`
|
||||
--> $DIR/cycle-cache-err-60010.rs:27:5
|
||||
|
|
||||
LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Query<RootDatabase>` 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<RootDatabase>` 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`.
|
@ -1 +1 @@
|
||||
Subproject commit 3710ec59962295336ab4aed100267b584dd7df7d
|
||||
Subproject commit ad3269c4b510b94b7c0082f4bb341bee6ed1eca4
|
@ -1 +1 @@
|
||||
Subproject commit 053aa694990a212ad8942dd72101ede23597c0e9
|
||||
Subproject commit bc0c76d861a178911f3f506196a7404eda1e690d
|
Loading…
Reference in New Issue
Block a user