Auto merge of #87413 - JohnTitor:rollup-dht22jk, r=JohnTitor
Rollup of 14 pull requests Successful merges: - #86410 (VecMap::get_value_matching should return just one element) - #86790 (Document iteration order of `retain` functions) - #87171 (Remove Option from BufWriter) - #87175 (Stabilize `into_parts()` and `into_error()`) - #87185 (Fix panics on Windows when the build was cancelled) - #87191 (Package LLVM libs for the target rather than the build host) - #87255 (better support for running libcore tests with Miri) - #87266 (Add testcase for 87076) - #87283 (Add `--codegen-backends=foo,bar` configure flag) - #87322 (fix: clarify suggestion that `&T` must refer to `T: Sync` for `&T: Send`) - #87358 (Fix `--dry-run` when download-ci-llvm is set) - #87380 (Don't default to `submodules = true` unless the rust repo has a .git directory) - #87398 (Add test for fonts used for module items) - #87412 (Add missing article) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
67b03007cf
54 changed files with 213 additions and 44 deletions
|
@ -1,4 +1,5 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
@ -12,7 +13,8 @@ pub struct VecMap<K, V>(Vec<(K, V)>);
|
||||||
|
|
||||||
impl<K, V> VecMap<K, V>
|
impl<K, V> VecMap<K, V>
|
||||||
where
|
where
|
||||||
K: PartialEq,
|
K: Debug + PartialEq,
|
||||||
|
V: Debug,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
VecMap(Default::default())
|
VecMap(Default::default())
|
||||||
|
@ -37,14 +39,31 @@ where
|
||||||
self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
|
self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value corresponding to the supplied predicate filter.
|
/// Returns the any value corresponding to the supplied predicate filter.
|
||||||
///
|
///
|
||||||
/// The supplied predicate will be applied to each (key, value) pair and it will return a
|
/// The supplied predicate will be applied to each (key, value) pair and it will return a
|
||||||
/// reference to the values where the predicate returns `true`.
|
/// reference to the values where the predicate returns `true`.
|
||||||
pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
|
pub fn any_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
|
||||||
self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
|
self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the value corresponding to the supplied predicate filter. It crashes if there's
|
||||||
|
/// more than one matching element.
|
||||||
|
///
|
||||||
|
/// The supplied predicate will be applied to each (key, value) pair and it will return a
|
||||||
|
/// reference to the value where the predicate returns `true`.
|
||||||
|
pub fn get_value_matching(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
|
||||||
|
let mut filter = self.0.iter().filter(|kv| predicate(kv));
|
||||||
|
let (_, value) = filter.next()?;
|
||||||
|
// This should return just one element, otherwise it's a bug
|
||||||
|
assert!(
|
||||||
|
filter.next().is_none(),
|
||||||
|
"Collection {:?} should have just one matching element",
|
||||||
|
self
|
||||||
|
);
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if the map contains a value for the specified key.
|
/// Returns `true` if the map contains a value for the specified key.
|
||||||
///
|
///
|
||||||
/// The key may be any borrowed form of the map's key type,
|
/// The key may be any borrowed form of the map's key type,
|
||||||
|
@ -131,7 +150,7 @@ impl<K, V> IntoIterator for VecMap<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: PartialEq, V> Extend<(K, V)> for VecMap<K, V> {
|
impl<K: PartialEq + Debug, V: Debug> Extend<(K, V)> for VecMap<K, V> {
|
||||||
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
|
fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
|
||||||
for (k, v) in iter {
|
for (k, v) in iter {
|
||||||
self.insert(k, v);
|
self.insert(k, v);
|
||||||
|
|
|
@ -1857,12 +1857,37 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
|
GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
|
||||||
|
// `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
|
||||||
|
let refers_to_non_sync = match target_ty.kind() {
|
||||||
|
ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
|
||||||
|
Ok(eval) if !eval.may_apply() => Some(ref_ty),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (span_label, span_note) = match refers_to_non_sync {
|
||||||
|
// if `target_ty` is `&T` and `T` fails to impl `Sync`,
|
||||||
|
// include suggestions to make `T: Sync` so that `&T: Send`
|
||||||
|
Some(ref_ty) => (
|
||||||
|
format!(
|
||||||
|
"has type `{}` which {}, because `{}` is not `Sync`",
|
||||||
|
target_ty, trait_explanation, ref_ty
|
||||||
|
),
|
||||||
|
format!(
|
||||||
|
"captured value {} because `&` references cannot be sent unless their referent is `Sync`",
|
||||||
|
trait_explanation
|
||||||
|
),
|
||||||
|
),
|
||||||
|
None => (
|
||||||
|
format!("has type `{}` which {}", target_ty, trait_explanation),
|
||||||
|
format!("captured value {}", trait_explanation),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
let mut span = MultiSpan::from_span(upvar_span);
|
let mut span = MultiSpan::from_span(upvar_span);
|
||||||
span.push_span_label(
|
span.push_span_label(upvar_span, span_label);
|
||||||
upvar_span,
|
err.span_note(span, &span_note);
|
||||||
format!("has type `{}` which {}", target_ty, trait_explanation),
|
|
||||||
);
|
|
||||||
err.span_note(span, &format!("captured value {}", trait_explanation));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -364,7 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
let concrete_ty = tcx
|
let concrete_ty = tcx
|
||||||
.mir_borrowck(owner.expect_local())
|
.mir_borrowck(owner.expect_local())
|
||||||
.concrete_opaque_types
|
.concrete_opaque_types
|
||||||
.get_by(|(key, _)| key.def_id == def_id.to_def_id())
|
.get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
|
||||||
.map(|concrete_ty| *concrete_ty)
|
.map(|concrete_ty| *concrete_ty)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
tcx.sess.delay_span_bug(
|
tcx.sess.delay_span_bug(
|
||||||
|
@ -512,8 +512,15 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
|
|
||||||
struct ConstraintLocator<'tcx> {
|
struct ConstraintLocator<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
|
||||||
|
/// def_id of the opaque type whose defining uses are being checked
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
// (first found type span, actual type)
|
|
||||||
|
/// as we walk the defining uses, we are checking that all of them
|
||||||
|
/// define the same hidden type. This variable is set to `Some`
|
||||||
|
/// with the first type that we find, and then later types are
|
||||||
|
/// checked against it (we also carry the span of that first
|
||||||
|
/// type).
|
||||||
found: Option<(Span, Ty<'tcx>)>,
|
found: Option<(Span, Ty<'tcx>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +538,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
|
||||||
.tcx
|
.tcx
|
||||||
.typeck(def_id)
|
.typeck(def_id)
|
||||||
.concrete_opaque_types
|
.concrete_opaque_types
|
||||||
.get_by(|(key, _)| key.def_id == self.def_id)
|
.any_value_matching(|(key, _)| key.def_id == self.def_id)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
debug!("no constraints in typeck results");
|
debug!("no constraints in typeck results");
|
||||||
|
|
|
@ -38,7 +38,7 @@ changelog-seen = 2
|
||||||
# This is false by default so that distributions don't unexpectedly download
|
# This is false by default so that distributions don't unexpectedly download
|
||||||
# LLVM from the internet.
|
# LLVM from the internet.
|
||||||
#
|
#
|
||||||
# All tier 1 targets are currently supported; set this to `"if-supported"` if
|
# All tier 1 targets are currently supported; set this to `"if-available"` if
|
||||||
# you are not sure whether you're on a tier 1 target.
|
# you are not sure whether you're on a tier 1 target.
|
||||||
#
|
#
|
||||||
# We also currently only support this when building LLVM for the build triple.
|
# We also currently only support this when building LLVM for the build triple.
|
||||||
|
|
|
@ -935,6 +935,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
///
|
///
|
||||||
/// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
|
/// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
|
||||||
|
/// The elements are visited in ascending key order.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -846,6 +846,7 @@ impl<T> BTreeSet<T> {
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
///
|
///
|
||||||
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
|
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
|
||||||
|
/// The elements are visited in ascending order.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -56,6 +56,10 @@
|
||||||
//! [`Rc`]: rc
|
//! [`Rc`]: rc
|
||||||
//! [`RefCell`]: core::cell
|
//! [`RefCell`]: core::cell
|
||||||
|
|
||||||
|
// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
|
||||||
|
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
|
||||||
|
// rustc itself never sets the feature, so this line has no affect there.
|
||||||
|
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
|
||||||
#![allow(unused_attributes)]
|
#![allow(unused_attributes)]
|
||||||
#![stable(feature = "alloc", since = "1.36.0")]
|
#![stable(feature = "alloc", since = "1.36.0")]
|
||||||
#![doc(
|
#![doc(
|
||||||
|
|
|
@ -49,6 +49,10 @@
|
||||||
//
|
//
|
||||||
// This cfg won't affect doc tests.
|
// This cfg won't affect doc tests.
|
||||||
#![cfg(not(test))]
|
#![cfg(not(test))]
|
||||||
|
// To run libcore tests without x.py without ending up with two copies of libcore, Miri needs to be
|
||||||
|
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
|
||||||
|
// rustc itself never sets the feature, so this line has no affect there.
|
||||||
|
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
|
||||||
#![stable(feature = "core", since = "1.6.0")]
|
#![stable(feature = "core", since = "1.6.0")]
|
||||||
#![doc(
|
#![doc(
|
||||||
html_playground_url = "https://play.rust-lang.org/",
|
html_playground_url = "https://play.rust-lang.org/",
|
||||||
|
|
|
@ -934,6 +934,7 @@ where
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
///
|
///
|
||||||
/// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
|
/// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
|
||||||
|
/// The elements are visited in unsorted (and unspecified) order.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -912,6 +912,7 @@ where
|
||||||
/// Retains only the elements specified by the predicate.
|
/// Retains only the elements specified by the predicate.
|
||||||
///
|
///
|
||||||
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
|
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
|
||||||
|
/// The elements are visited in unsorted (and unspecified) order.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
|
|
@ -68,7 +68,7 @@ use crate::ptr;
|
||||||
/// [`flush`]: BufWriter::flush
|
/// [`flush`]: BufWriter::flush
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct BufWriter<W: Write> {
|
pub struct BufWriter<W: Write> {
|
||||||
inner: Option<W>,
|
inner: W,
|
||||||
// The buffer. Avoid using this like a normal `Vec` in common code paths.
|
// The buffer. Avoid using this like a normal `Vec` in common code paths.
|
||||||
// That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
|
// That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
|
||||||
// methods that require bounds checking or the like. This makes an enormous
|
// methods that require bounds checking or the like. This makes an enormous
|
||||||
|
@ -112,7 +112,7 @@ impl<W: Write> BufWriter<W> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
|
pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
|
||||||
BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
|
BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send data in our local buffer into the inner writer, looping as
|
/// Send data in our local buffer into the inner writer, looping as
|
||||||
|
@ -161,10 +161,9 @@ impl<W: Write> BufWriter<W> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut guard = BufGuard::new(&mut self.buf);
|
let mut guard = BufGuard::new(&mut self.buf);
|
||||||
let inner = self.inner.as_mut().unwrap();
|
|
||||||
while !guard.done() {
|
while !guard.done() {
|
||||||
self.panicked = true;
|
self.panicked = true;
|
||||||
let r = inner.write(guard.remaining());
|
let r = self.inner.write(guard.remaining());
|
||||||
self.panicked = false;
|
self.panicked = false;
|
||||||
|
|
||||||
match r {
|
match r {
|
||||||
|
@ -212,7 +211,7 @@ impl<W: Write> BufWriter<W> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get_ref(&self) -> &W {
|
pub fn get_ref(&self) -> &W {
|
||||||
self.inner.as_ref().unwrap()
|
&self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the underlying writer.
|
/// Gets a mutable reference to the underlying writer.
|
||||||
|
@ -232,7 +231,7 @@ impl<W: Write> BufWriter<W> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get_mut(&mut self) -> &mut W {
|
pub fn get_mut(&mut self) -> &mut W {
|
||||||
self.inner.as_mut().unwrap()
|
&mut self.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the internally buffered data.
|
/// Returns a reference to the internally buffered data.
|
||||||
|
@ -308,7 +307,7 @@ impl<W: Write> BufWriter<W> {
|
||||||
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
|
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
|
||||||
match self.flush_buf() {
|
match self.flush_buf() {
|
||||||
Err(e) => Err(IntoInnerError::new(self, e)),
|
Err(e) => Err(IntoInnerError::new(self, e)),
|
||||||
Ok(()) => Ok(self.inner.take().unwrap()),
|
Ok(()) => Ok(self.into_raw_parts().0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +338,12 @@ impl<W: Write> BufWriter<W> {
|
||||||
pub fn into_raw_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
|
pub fn into_raw_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
|
||||||
let buf = mem::take(&mut self.buf);
|
let buf = mem::take(&mut self.buf);
|
||||||
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
|
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
|
||||||
(self.inner.take().unwrap(), buf)
|
|
||||||
|
// SAFETY: forget(self) prevents double dropping inner
|
||||||
|
let inner = unsafe { ptr::read(&mut self.inner) };
|
||||||
|
mem::forget(self);
|
||||||
|
|
||||||
|
(inner, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this function does not get inlined into `write`, so that it
|
// Ensure this function does not get inlined into `write`, so that it
|
||||||
|
@ -643,7 +647,7 @@ where
|
||||||
{
|
{
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fmt.debug_struct("BufWriter")
|
fmt.debug_struct("BufWriter")
|
||||||
.field("writer", &self.inner.as_ref().unwrap())
|
.field("writer", &self.inner)
|
||||||
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
|
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
@ -663,7 +667,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<W: Write> Drop for BufWriter<W> {
|
impl<W: Write> Drop for BufWriter<W> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.inner.is_some() && !self.panicked {
|
if !self.panicked {
|
||||||
// dtors should not panic, so we ignore a failed flush
|
// dtors should not panic, so we ignore a failed flush
|
||||||
let _r = self.flush_buf();
|
let _r = self.flush_buf();
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,6 @@ impl<W> IntoInnerError<W> {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(io_into_inner_error_parts)]
|
|
||||||
/// use std::io::{BufWriter, ErrorKind, Write};
|
/// use std::io::{BufWriter, ErrorKind, Write};
|
||||||
///
|
///
|
||||||
/// let mut not_enough_space = [0u8; 10];
|
/// let mut not_enough_space = [0u8; 10];
|
||||||
|
@ -143,7 +142,7 @@ impl<W> IntoInnerError<W> {
|
||||||
/// let err = into_inner_err.into_error();
|
/// let err = into_inner_err.into_error();
|
||||||
/// assert_eq!(err.kind(), ErrorKind::WriteZero);
|
/// assert_eq!(err.kind(), ErrorKind::WriteZero);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
|
#[stable(feature = "io_into_inner_error_parts", since = "1.55.0")]
|
||||||
pub fn into_error(self) -> Error {
|
pub fn into_error(self) -> Error {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
|
@ -156,7 +155,6 @@ impl<W> IntoInnerError<W> {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(io_into_inner_error_parts)]
|
|
||||||
/// use std::io::{BufWriter, ErrorKind, Write};
|
/// use std::io::{BufWriter, ErrorKind, Write};
|
||||||
///
|
///
|
||||||
/// let mut not_enough_space = [0u8; 10];
|
/// let mut not_enough_space = [0u8; 10];
|
||||||
|
@ -167,7 +165,7 @@ impl<W> IntoInnerError<W> {
|
||||||
/// assert_eq!(err.kind(), ErrorKind::WriteZero);
|
/// assert_eq!(err.kind(), ErrorKind::WriteZero);
|
||||||
/// assert_eq!(recovered_writer.buffer(), b"t be actually written");
|
/// assert_eq!(recovered_writer.buffer(), b"t be actually written");
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
|
#[stable(feature = "io_into_inner_error_parts", since = "1.55.0")]
|
||||||
pub fn into_parts(self) -> (Error, W) {
|
pub fn into_parts(self) -> (Error, W) {
|
||||||
(self.1, self.0)
|
(self.1, self.0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//!
|
//!
|
||||||
//! This module contains some of the real meat in the rustbuild build system
|
//! This module contains some of the real meat in the rustbuild build system
|
||||||
//! which is where Cargo is used to compile the standard library, libtest, and
|
//! which is where Cargo is used to compile the standard library, libtest, and
|
||||||
//! compiler. This module is also responsible for assembling the sysroot as it
|
//! the compiler. This module is also responsible for assembling the sysroot as it
|
||||||
//! goes along from the output of the previous stage.
|
//! goes along from the output of the previous stage.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::cache::{Interned, INTERNER};
|
use crate::cache::{Interned, INTERNER};
|
||||||
|
use crate::channel::GitInfo;
|
||||||
pub use crate::flags::Subcommand;
|
pub use crate::flags::Subcommand;
|
||||||
use crate::flags::{Color, Flags};
|
use crate::flags::{Color, Flags};
|
||||||
use crate::util::exe;
|
use crate::util::exe;
|
||||||
|
@ -48,7 +49,7 @@ pub struct Config {
|
||||||
/// Call Build::ninja() instead of this.
|
/// Call Build::ninja() instead of this.
|
||||||
pub ninja_in_file: bool,
|
pub ninja_in_file: bool,
|
||||||
pub verbose: usize,
|
pub verbose: usize,
|
||||||
pub submodules: bool,
|
pub submodules: Option<bool>,
|
||||||
pub fast_submodules: bool,
|
pub fast_submodules: bool,
|
||||||
pub compiler_docs: bool,
|
pub compiler_docs: bool,
|
||||||
pub docs_minification: bool,
|
pub docs_minification: bool,
|
||||||
|
@ -552,7 +553,7 @@ impl Config {
|
||||||
config.backtrace = true;
|
config.backtrace = true;
|
||||||
config.rust_optimize = true;
|
config.rust_optimize = true;
|
||||||
config.rust_optimize_tests = true;
|
config.rust_optimize_tests = true;
|
||||||
config.submodules = true;
|
config.submodules = None;
|
||||||
config.fast_submodules = true;
|
config.fast_submodules = true;
|
||||||
config.docs = true;
|
config.docs = true;
|
||||||
config.docs_minification = true;
|
config.docs_minification = true;
|
||||||
|
@ -658,11 +659,11 @@ impl Config {
|
||||||
config.npm = build.npm.map(PathBuf::from);
|
config.npm = build.npm.map(PathBuf::from);
|
||||||
config.gdb = build.gdb.map(PathBuf::from);
|
config.gdb = build.gdb.map(PathBuf::from);
|
||||||
config.python = build.python.map(PathBuf::from);
|
config.python = build.python.map(PathBuf::from);
|
||||||
|
config.submodules = build.submodules;
|
||||||
set(&mut config.low_priority, build.low_priority);
|
set(&mut config.low_priority, build.low_priority);
|
||||||
set(&mut config.compiler_docs, build.compiler_docs);
|
set(&mut config.compiler_docs, build.compiler_docs);
|
||||||
set(&mut config.docs_minification, build.docs_minification);
|
set(&mut config.docs_minification, build.docs_minification);
|
||||||
set(&mut config.docs, build.docs);
|
set(&mut config.docs, build.docs);
|
||||||
set(&mut config.submodules, build.submodules);
|
|
||||||
set(&mut config.fast_submodules, build.fast_submodules);
|
set(&mut config.fast_submodules, build.fast_submodules);
|
||||||
set(&mut config.locked_deps, build.locked_deps);
|
set(&mut config.locked_deps, build.locked_deps);
|
||||||
set(&mut config.vendor, build.vendor);
|
set(&mut config.vendor, build.vendor);
|
||||||
|
@ -792,8 +793,16 @@ impl Config {
|
||||||
|
|
||||||
// CI-built LLVM can be either dynamic or static.
|
// CI-built LLVM can be either dynamic or static.
|
||||||
let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm");
|
let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm");
|
||||||
let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt")));
|
config.llvm_link_shared = if config.dry_run {
|
||||||
config.llvm_link_shared = link_type == "dynamic";
|
// just assume dynamic for now
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let link_type = t!(
|
||||||
|
std::fs::read_to_string(ci_llvm.join("link-type.txt")),
|
||||||
|
format!("CI llvm missing: {}", ci_llvm.display())
|
||||||
|
);
|
||||||
|
link_type == "dynamic"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.llvm_thin_lto {
|
if config.llvm_thin_lto {
|
||||||
|
@ -1075,6 +1084,10 @@ impl Config {
|
||||||
pub fn llvm_enabled(&self) -> bool {
|
pub fn llvm_enabled(&self) -> bool {
|
||||||
self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
|
self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn submodules(&self, rust_info: &GitInfo) -> bool {
|
||||||
|
self.submodules.unwrap_or(rust_info.is_git())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set<T>(field: &mut T, val: Option<T>) {
|
fn set<T>(field: &mut T, val: Option<T>) {
|
||||||
|
|
|
@ -160,6 +160,7 @@ o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of tw
|
||||||
o("extended", "build.extended", "build an extended rust tool set")
|
o("extended", "build.extended", "build an extended rust tool set")
|
||||||
|
|
||||||
v("tools", None, "List of extended tools will be installed")
|
v("tools", None, "List of extended tools will be installed")
|
||||||
|
v("codegen-backends", None, "List of codegen backends to build")
|
||||||
v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
|
v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
|
||||||
v("host", None, "GNUs ./configure syntax LLVM host triples")
|
v("host", None, "GNUs ./configure syntax LLVM host triples")
|
||||||
v("target", None, "GNUs ./configure syntax LLVM target triples")
|
v("target", None, "GNUs ./configure syntax LLVM target triples")
|
||||||
|
@ -339,6 +340,8 @@ for key in known_args:
|
||||||
set('target.{}.llvm-filecheck'.format(build()), value)
|
set('target.{}.llvm-filecheck'.format(build()), value)
|
||||||
elif option.name == 'tools':
|
elif option.name == 'tools':
|
||||||
set('build.tools', value.split(','))
|
set('build.tools', value.split(','))
|
||||||
|
elif option.name == 'codegen-backends':
|
||||||
|
set('rust.codegen-backends', value.split(','))
|
||||||
elif option.name == 'host':
|
elif option.name == 'host':
|
||||||
set('build.host', value.split(','))
|
set('build.host', value.split(','))
|
||||||
elif option.name == 'target':
|
elif option.name == 'target':
|
||||||
|
|
|
@ -1955,8 +1955,16 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
|
||||||
cmd.arg("--libfiles");
|
cmd.arg("--libfiles");
|
||||||
builder.verbose(&format!("running {:?}", cmd));
|
builder.verbose(&format!("running {:?}", cmd));
|
||||||
let files = output(&mut cmd);
|
let files = output(&mut cmd);
|
||||||
|
let build_llvm_out = &builder.llvm_out(builder.config.build);
|
||||||
|
let target_llvm_out = &builder.llvm_out(target);
|
||||||
for file in files.trim_end().split(' ') {
|
for file in files.trim_end().split(' ') {
|
||||||
builder.install(Path::new(file), dst_libdir, 0o644);
|
// If we're not using a custom LLVM, make sure we package for the target.
|
||||||
|
let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
|
||||||
|
target_llvm_out.join(relative_path)
|
||||||
|
} else {
|
||||||
|
PathBuf::from(file)
|
||||||
|
};
|
||||||
|
builder.install(&file, dst_libdir, 0o644);
|
||||||
}
|
}
|
||||||
!builder.config.dry_run
|
!builder.config.dry_run
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -103,12 +103,20 @@ pub unsafe fn setup(build: &mut Build) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
|
let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
|
||||||
assert!(
|
|
||||||
!parent.is_null(),
|
// If we get a null parent pointer here, it is possible that either
|
||||||
"PID `{}` doesn't seem to exist: {}",
|
// we have got an invalid pid or the parent process has been closed.
|
||||||
pid,
|
// Since the first case rarely happens
|
||||||
io::Error::last_os_error()
|
// (only when wrongly setting the environmental variable),
|
||||||
);
|
// so it might be better to improve the experience of the second case
|
||||||
|
// when users have interrupted the parent process and we don't finish
|
||||||
|
// duplicating the handle yet.
|
||||||
|
// We just need close the job object if that occurs.
|
||||||
|
if parent.is_null() {
|
||||||
|
CloseHandle(job);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let mut parent_handle = ptr::null_mut();
|
let mut parent_handle = ptr::null_mut();
|
||||||
let r = DuplicateHandle(
|
let r = DuplicateHandle(
|
||||||
GetCurrentProcess(),
|
GetCurrentProcess(),
|
||||||
|
|
|
@ -486,7 +486,7 @@ impl Build {
|
||||||
t!(std::fs::read_dir(dir)).next().is_none()
|
t!(std::fs::read_dir(dir)).next().is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.config.submodules {
|
if !self.config.submodules(&self.rust_info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +562,7 @@ impl Build {
|
||||||
"library/stdarch",
|
"library/stdarch",
|
||||||
];
|
];
|
||||||
// Avoid running git when there isn't a git checkout.
|
// Avoid running git when there isn't a git checkout.
|
||||||
if !self.config.submodules {
|
if !self.config.submodules(&self.rust_info) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let output = output(
|
let output = output(
|
||||||
|
|
4
src/test/rustdoc-gui/module-items-font.goml
Normal file
4
src/test/rustdoc-gui/module-items-font.goml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
// This test checks that the correct font is used on module items (in index.html pages).
|
||||||
|
goto: file://|DOC_PATH|/test_docs/index.html
|
||||||
|
assert-css: (".item-table .module-item a", {"font-family": '"Fira Sans", Arial, sans-serif'}, ALL)
|
||||||
|
assert-css: (".item-table .docblock-short", {"font-family": '"Source Serif 4", "Noto Sans KR", serif'}, ALL)
|
25
src/test/ui/async-await/issue-86507.rs
Normal file
25
src/test/ui/async-await/issue-86507.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
use ::core::pin::Pin;
|
||||||
|
use ::core::future::Future;
|
||||||
|
use ::core::marker::Send;
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn bar<'me, 'async_trait, T: Send>(x: &'me T)
|
||||||
|
-> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
|
||||||
|
where 'me: 'async_trait;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for () {
|
||||||
|
fn bar<'me, 'async_trait, T: Send>(x: &'me T)
|
||||||
|
-> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
|
||||||
|
where 'me:'async_trait {
|
||||||
|
Box::pin( //~ ERROR future cannot be sent between threads safely
|
||||||
|
async move {
|
||||||
|
let x = x;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
23
src/test/ui/async-await/issue-86507.stderr
Normal file
23
src/test/ui/async-await/issue-86507.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
error: future cannot be sent between threads safely
|
||||||
|
--> $DIR/issue-86507.rs:17:13
|
||||||
|
|
|
||||||
|
LL | / Box::pin(
|
||||||
|
LL | | async move {
|
||||||
|
LL | | let x = x;
|
||||||
|
LL | | }
|
||||||
|
LL | | )
|
||||||
|
| |_____________^ future created by async block is not `Send`
|
||||||
|
|
|
||||||
|
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
|
||||||
|
--> $DIR/issue-86507.rs:19:29
|
||||||
|
|
|
||||||
|
LL | let x = x;
|
||||||
|
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
|
||||||
|
= note: required for the cast to the object type `dyn Future<Output = ()> + Send`
|
||||||
|
help: consider further restricting type parameter `T`
|
||||||
|
|
|
||||||
|
LL | where 'me:'async_trait, T: std::marker::Sync {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
20
src/test/ui/const-generics/issues/issue-87076.rs
Normal file
20
src/test/ui/const-generics/issues/issue-87076.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// build-pass
|
||||||
|
|
||||||
|
#![feature(const_generics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub struct UnitDims {
|
||||||
|
pub time: u8,
|
||||||
|
pub length: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UnitValue<const DIMS: UnitDims>;
|
||||||
|
|
||||||
|
impl<const DIMS: UnitDims> UnitValue<DIMS> {
|
||||||
|
fn crash() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
UnitValue::<{ UnitDims { time: 1, length: 2 } }>::crash();
|
||||||
|
}
|
|
@ -55,11 +55,11 @@ note: captured value is not `Send`
|
||||||
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
|
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
|
||||||
| ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
|
| ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
|
||||||
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
|
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
|
||||||
note: captured value is not `Send`
|
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
|
||||||
--> $DIR/future_not_send.rs:20:40
|
--> $DIR/future_not_send.rs:20:40
|
||||||
|
|
|
|
||||||
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
|
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
|
||||||
| ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`
|
| ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
|
||||||
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
|
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
|
||||||
|
|
||||||
error: future cannot be sent between threads safely
|
error: future cannot be sent between threads safely
|
||||||
|
|
Loading…
Add table
Reference in a new issue