Auto merge of #91761 - matthiaskrgr:rollup-bjowmvz, r=matthiaskrgr

Rollup of 11 pull requests

Successful merges:

 - #91668 (Remove the match on `ErrorKind::Other`)
 - #91678 (Add tests fixed by #90023)
 - #91679 (Move core/stream/stream/mod.rs to core/stream/stream.rs)
 - #91681 (fix typo in `intrinsics::raw_eq` docs)
 - #91686 (Fix `Vec::reserve_exact` documentation)
 - #91697 (Delete Utf8Lossy::from_str)
 - #91706 (Add unstable book entries for parts of asm that are not being stabilized)
 - #91709 (Replace iterator-based set construction by *Set::From<[T; N]>)
 - #91716 (Improve x.py logging and defaults a bit more)
 - #91747 (Add pierwill to .mailmap)
 - #91755 (Fix since attribute for const_linked_list_new feature)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-12-11 03:52:12 +00:00
commit c185610ebc
24 changed files with 614 additions and 76 deletions

View File

@ -246,6 +246,7 @@ Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch>
Philipp Krones <hello@philkrones.com> flip1995 <hello@philkrones.com>
Philipp Krones <hello@philkrones.com> <philipp.krones@embecosm.com>
Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
pierwill <pierwill@users.noreply.github.com> <19642016+pierwill@users.noreply.github.com>
Przemysław Wesołek <jest@go.art.pl> Przemek Wesołek <jest@go.art.pl>
Rafael Ávila de Espíndola <respindola@mozilla.com> Rafael Avila de Espindola <espindola@dream.(none)>
Ralph Giles <giles@thaumas.net> Ralph Giles <giles@mozilla.com>

View File

@ -491,7 +491,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
/// let set = BTreeSet::from([1, 2, 3]);
/// assert_eq!(set.contains(&1), true);
/// assert_eq!(set.contains(&4), false);
/// ```
@ -515,7 +515,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
/// let set = BTreeSet::from([1, 2, 3]);
/// assert_eq!(set.get(&2), Some(&2));
/// assert_eq!(set.get(&4), None);
/// ```
@ -536,7 +536,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
/// let a = BTreeSet::from([1, 2, 3]);
/// let mut b = BTreeSet::new();
///
/// assert_eq!(a.is_disjoint(&b), true);
@ -562,7 +562,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
/// let sup = BTreeSet::from([1, 2, 3]);
/// let mut set = BTreeSet::new();
///
/// assert_eq!(set.is_subset(&sup), true);
@ -639,7 +639,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect();
/// let sub = BTreeSet::from([1, 2]);
/// let mut set = BTreeSet::new();
///
/// assert_eq!(set.is_superset(&sub), false);
@ -853,7 +853,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
/// let mut set = BTreeSet::from([1, 2, 3]);
/// assert_eq!(set.take(&2), Some(2));
/// assert_eq!(set.take(&2), None);
/// ```
@ -876,8 +876,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let xs = [1, 2, 3, 4, 5, 6];
/// let mut set: BTreeSet<i32> = xs.iter().cloned().collect();
/// let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]);
/// // Keep only the even numbers.
/// set.retain(|&k| k % 2 == 0);
/// assert!(set.iter().eq([2, 4, 6].iter()));
@ -1009,7 +1008,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<usize> = [1, 2, 3].iter().cloned().collect();
/// let set = BTreeSet::from([1, 2, 3]);
/// let mut set_iter = set.iter();
/// assert_eq!(set_iter.next(), Some(&1));
/// assert_eq!(set_iter.next(), Some(&2));
@ -1022,7 +1021,7 @@ impl<T> BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<usize> = [3, 1, 2].iter().cloned().collect();
/// let set = BTreeSet::from([3, 1, 2]);
/// let mut set_iter = set.iter();
/// assert_eq!(set_iter.next(), Some(&1));
/// assert_eq!(set_iter.next(), Some(&2));
@ -1124,7 +1123,7 @@ impl<T> IntoIterator for BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
/// let set = BTreeSet::from([1, 2, 3, 4]);
///
/// let v: Vec<_> = set.into_iter().collect();
/// assert_eq!(v, [1, 2, 3, 4]);
@ -1243,8 +1242,8 @@ impl<T: Ord + Clone> Sub<&BTreeSet<T>> for &BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect();
/// let a = BTreeSet::from([1, 2, 3]);
/// let b = BTreeSet::from([3, 4, 5]);
///
/// let result = &a - &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
@ -1266,8 +1265,8 @@ impl<T: Ord + Clone> BitXor<&BTreeSet<T>> for &BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect();
/// let a = BTreeSet::from([1, 2, 3]);
/// let b = BTreeSet::from([2, 3, 4]);
///
/// let result = &a ^ &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
@ -1289,8 +1288,8 @@ impl<T: Ord + Clone> BitAnd<&BTreeSet<T>> for &BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect();
/// let a = BTreeSet::from([1, 2, 3]);
/// let b = BTreeSet::from([2, 3, 4]);
///
/// let result = &a & &b;
/// let result_vec: Vec<_> = result.into_iter().collect();
@ -1312,8 +1311,8 @@ impl<T: Ord + Clone> BitOr<&BTreeSet<T>> for &BTreeSet<T> {
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect();
/// let a = BTreeSet::from([1, 2, 3]);
/// let b = BTreeSet::from([3, 4, 5]);
///
/// let result = &a | &b;
/// let result_vec: Vec<_> = result.into_iter().collect();

View File

@ -417,7 +417,7 @@ impl<T> LinkedList<T> {
/// let list: LinkedList<u32> = LinkedList::new();
/// ```
#[inline]
#[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")]
#[rustc_const_stable(feature = "const_linked_list_new", since = "1.39.0")]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
pub const fn new() -> Self {

View File

@ -822,7 +822,7 @@ impl<T, A: Allocator> Vec<T, A> {
///
/// # Panics
///
/// Panics if the new capacity overflows `usize`.
/// Panics if the new capacity exceeds `isize::MAX` bytes.
///
/// # Examples
///

View File

@ -1919,7 +1919,7 @@ extern "rust-intrinsic" {
/// Determines whether the raw bytes of the two values are equal.
///
/// The is particularly handy for arrays, since it allows things like just
/// This is particularly handy for arrays, since it allows things like just
/// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`.
///
/// Above some backend-decided threshold this will emit calls to `memcmp`,

View File

@ -12,11 +12,6 @@ pub struct Utf8Lossy {
}
impl Utf8Lossy {
#[must_use]
pub fn from_str(s: &str) -> &Utf8Lossy {
Utf8Lossy::from_bytes(s.as_bytes())
}
#[must_use]
pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
// SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required.

View File

@ -233,7 +233,7 @@ impl<T, S> HashSet<T, S> {
/// ```
/// use std::collections::HashSet;
///
/// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let mut set = HashSet::from([1, 2, 3]);
/// assert!(!set.is_empty());
///
/// // print 1, 2, 3 in an arbitrary order
@ -489,8 +489,8 @@ where
///
/// ```
/// use std::collections::HashSet;
/// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// // Can be seen as `a - b`.
/// for x in a.difference(&b) {
@ -518,8 +518,8 @@ where
///
/// ```
/// use std::collections::HashSet;
/// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// // Print 1, 4 in arbitrary order.
/// for x in a.symmetric_difference(&b) {
@ -548,8 +548,8 @@ where
///
/// ```
/// use std::collections::HashSet;
/// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// // Print 2, 3 in arbitrary order.
/// for x in a.intersection(&b) {
@ -576,8 +576,8 @@ where
///
/// ```
/// use std::collections::HashSet;
/// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// // Print 1, 2, 3, 4 in arbitrary order.
/// for x in a.union(&b) {
@ -608,7 +608,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let set = HashSet::from([1, 2, 3]);
/// assert_eq!(set.contains(&1), true);
/// assert_eq!(set.contains(&4), false);
/// ```
@ -633,7 +633,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let set = HashSet::from([1, 2, 3]);
/// assert_eq!(set.get(&2), Some(&2));
/// assert_eq!(set.get(&4), None);
/// ```
@ -657,7 +657,7 @@ where
///
/// use std::collections::HashSet;
///
/// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let mut set = HashSet::from([1, 2, 3]);
/// assert_eq!(set.len(), 3);
/// assert_eq!(set.get_or_insert(2), &2);
/// assert_eq!(set.get_or_insert(100), &100);
@ -744,7 +744,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let mut b = HashSet::new();
///
/// assert_eq!(a.is_disjoint(&b), true);
@ -770,7 +770,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let sup = HashSet::from([1, 2, 3]);
/// let mut set = HashSet::new();
///
/// assert_eq!(set.is_subset(&sup), true);
@ -792,7 +792,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let sub: HashSet<_> = [1, 2].iter().cloned().collect();
/// let sub = HashSet::from([1, 2]);
/// let mut set = HashSet::new();
///
/// assert_eq!(set.is_superset(&sub), false);
@ -893,7 +893,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
/// let mut set = HashSet::from([1, 2, 3]);
/// assert_eq!(set.take(&2), Some(2));
/// assert_eq!(set.take(&2), None);
/// ```
@ -917,8 +917,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let xs = [1, 2, 3, 4, 5, 6];
/// let mut set: HashSet<i32> = xs.iter().cloned().collect();
/// let mut set = HashSet::from([1, 2, 3, 4, 5, 6]);
/// set.retain(|&k| k % 2 == 0);
/// assert_eq!(set.len(), 3);
/// ```
@ -1097,8 +1096,8 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([3, 4, 5]);
///
/// let set = &a | &b;
///
@ -1130,8 +1129,8 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([2, 3, 4]);
///
/// let set = &a & &b;
///
@ -1163,8 +1162,8 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([3, 4, 5]);
///
/// let set = &a ^ &b;
///
@ -1196,8 +1195,8 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([3, 4, 5]);
///
/// let set = &a - &b;
///
@ -1226,7 +1225,7 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let a = HashSet::from([1, 2, 3]);
///
/// let mut iter = a.iter();
/// ```
@ -1248,7 +1247,7 @@ pub struct Iter<'a, K: 'a> {
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let a = HashSet::from([1, 2, 3]);
///
/// let mut iter = a.into_iter();
/// ```
@ -1269,7 +1268,7 @@ pub struct IntoIter<K> {
/// ```
/// use std::collections::HashSet;
///
/// let mut a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let mut a = HashSet::from([1, 2, 3]);
///
/// let mut drain = a.drain();
/// ```
@ -1291,7 +1290,7 @@ pub struct Drain<'a, K: 'a> {
///
/// use std::collections::HashSet;
///
/// let mut a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let mut a = HashSet::from([1, 2, 3]);
///
/// let mut drain_filtered = a.drain_filter(|v| v % 2 == 0);
/// ```
@ -1315,8 +1314,8 @@ where
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let mut intersection = a.intersection(&b);
/// ```
@ -1342,8 +1341,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> {
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let mut difference = a.difference(&b);
/// ```
@ -1369,8 +1368,8 @@ pub struct Difference<'a, T: 'a, S: 'a> {
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let mut intersection = a.symmetric_difference(&b);
/// ```
@ -1393,8 +1392,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
/// ```
/// use std::collections::HashSet;
///
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
/// let a = HashSet::from([1, 2, 3]);
/// let b = HashSet::from([4, 2, 3, 4]);
///
/// let mut union_iter = a.union(&b);
/// ```

View File

@ -189,11 +189,11 @@ def default_build_triple(verbose):
host = next(x for x in version.split('\n') if x.startswith("host: "))
triple = host.split("host: ")[1]
if verbose:
print("detected default triple {}".format(triple))
print("detected default triple {} from pre-installed rustc".format(triple))
return triple
except Exception as e:
if verbose:
print("rustup not detected: {}".format(e))
print("pre-installed rustc not detected: {}".format(e))
print("falling back to auto-detect")
required = sys.platform != 'win32'
@ -726,12 +726,15 @@ class RustBuild(object):
status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler, library])
if status != 0:
if download_rustc == "if-unchanged":
if self.verbose:
print("warning: saw changes to compiler/ or library/ since {}; " \
"ignoring `download-rustc`".format(commit))
return None
print("warning: `download-rustc` is enabled, but there are changes to \
compiler/ or library/")
print("warning: `download-rustc` is enabled, but there are changes to " \
"compiler/ or library/")
if self.verbose:
print("using downloaded stage1 artifacts from CI (commit {})".format(commit))
print("using downloaded stage2 artifacts from CI (commit {})".format(commit))
self.rustc_commit = commit
# FIXME: support downloading artifacts from the beta channel
self.download_toolchain(False, "nightly")

View File

@ -1578,11 +1578,11 @@ impl<'a> Builder<'a> {
panic!("{}", out);
}
if let Some(out) = self.cache.get(&step) {
self.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step));
self.verbose_than(1, &format!("{}c {:?}", " ".repeat(stack.len()), step));
return out;
}
self.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step));
self.verbose_than(1, &format!("{}> {:?}", " ".repeat(stack.len()), step));
stack.push(Box::new(step.clone()));
}
@ -1605,7 +1605,7 @@ impl<'a> Builder<'a> {
let cur_step = stack.pop().expect("step stack empty");
assert_eq!(cur_step.downcast_ref(), Some(&step));
}
self.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.verbose_than(1, &format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.cache.put(step, out.clone());
out
}

View File

@ -75,10 +75,10 @@ fn rm_rf(path: &Path) {
do_op(path, "remove dir", |p| {
fs::remove_dir(p).or_else(|e| {
// Check for dir not empty on Windows
// FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized,
// match on `e.kind()` instead.
#[cfg(windows)]
if matches!(e.kind(), std::io::ErrorKind::Other)
&& e.raw_os_error() == Some(145)
{
if e.raw_os_error() == Some(145) {
return Ok(());
}

View File

@ -11,6 +11,10 @@ incremental = true
# This cuts compile times by almost 60x, but means you can't modify the compiler.
download-rustc = "if-unchanged"
[build]
# Document with the in-tree rustdoc by default, since `download-rustc` makes it quick to compile.
doc-stage = 2
[llvm]
# Will download LLVM from CI if available on your platform.
download-ci-llvm = "if-available"

View File

@ -0,0 +1,11 @@
# `asm_const`
The tracking issue for this feature is: [#72016]
[#72016]: https://github.com/rust-lang/rust/issues/72016
------------------------
This feature adds a `const <expr>` operand type to `asm!` and `global_asm!`.
- `<expr>` must be an integer constant expression.
- The value of the expression is formatted as a string and substituted directly into the asm template string.

View File

@ -0,0 +1,117 @@
# `asm_experimental_arch`
The tracking issue for this feature is: [#72016]
[#72016]: https://github.com/rust-lang/rust/issues/72016
------------------------
This feature tracks `asm!` and `global_asm!` support for the following architectures:
- NVPTX
- PowerPC
- Hexagon
- MIPS32r2 and MIPS64r2
- wasm32
- BPF
- SPIR-V
- AVR
## Register classes
| Architecture | Register class | Registers | LLVM constraint code |
| ------------ | -------------- | ---------------------------------- | -------------------- |
| MIPS | `reg` | `$[2-25]` | `r` |
| MIPS | `freg` | `$f[0-31]` | `f` |
| NVPTX | `reg16` | None\* | `h` |
| NVPTX | `reg32` | None\* | `r` |
| NVPTX | `reg64` | None\* | `l` |
| Hexagon | `reg` | `r[0-28]` | `r` |
| PowerPC | `reg` | `r[0-31]` | `r` |
| PowerPC | `reg_nonzero` | `r[1-31]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` |
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
| PowerPC | `xer` | `xer` | Only clobbers |
| wasm32 | `local` | None\* | `r` |
| BPF | `reg` | `r[0-10]` | `r` |
| BPF | `wreg` | `w[0-10]` | `w` |
| AVR | `reg` | `r[2-25]`, `XH`, `XL`, `ZH`, `ZL` | `r` |
| AVR | `reg_upper` | `r[16-25]`, `XH`, `XL`, `ZH`, `ZL` | `d` |
| AVR | `reg_pair` | `r3r2` .. `r25r24`, `X`, `Z` | `r` |
| AVR | `reg_iw` | `r25r24`, `X`, `Z` | `w` |
| AVR | `reg_ptr` | `X`, `Z` | `e` |
> **Notes**:
> - NVPTX doesn't have a fixed register set, so named registers are not supported.
>
> - WebAssembly doesn't have registers, so named registers are not supported.
# Register class supported types
| Architecture | Register class | Target feature | Allowed types |
| ------------ | ------------------------------- | -------------- | --------------------------------------- |
| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| MIPS32 | `freg` | None | `f32`, `f64` |
| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
| MIPS64 | `freg` | None | `f32`, `f64` |
| NVPTX | `reg16` | None | `i8`, `i16` |
| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
| PowerPC | `freg` | None | `f32`, `f64` |
| PowerPC | `cr` | N/A | Only clobbers |
| PowerPC | `xer` | N/A | Only clobbers |
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
| AVR | `reg`, `reg_upper` | None | `i8` |
| AVR | `reg_pair`, `reg_iw`, `reg_ptr` | None | `i16` |
## Register aliases
| Architecture | Base register | Aliases |
| ------------ | ------------- | --------- |
| Hexagon | `r29` | `sp` |
| Hexagon | `r30` | `fr` |
| Hexagon | `r31` | `lr` |
| BPF | `r[0-10]` | `w[0-10]` |
| AVR | `XH` | `r27` |
| AVR | `XL` | `r26` |
| AVR | `ZH` | `r31` |
| AVR | `ZL` | `r30` |
## Unsupported registers
| Architecture | Unsupported register | Reason |
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |
| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR) | The frame pointer cannot be used as an input or output. |
| All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
| MIPS | `$1` or `$at` | Reserved for assembler. |
| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
| MIPS | `$ra` | Return address cannot be used as inputs or outputs. |
| Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. |
## Template modifiers
| Architecture | Register class | Modifier | Example output | LLVM modifier |
| ------------ | -------------- | -------- | -------------- | ------------- |
| MIPS | `reg` | None | `$2` | None |
| MIPS | `freg` | None | `$f0` | None |
| NVPTX | `reg16` | None | `rs0` | None |
| NVPTX | `reg32` | None | `r0` | None |
| NVPTX | `reg64` | None | `rd0` | None |
| Hexagon | `reg` | None | `r0` | None |
| PowerPC | `reg` | None | `0` | None |
| PowerPC | `reg_nonzero` | None | `3` | `b` |
| PowerPC | `freg` | None | `0` | None |
# Flags covered by `preserves_flags`
These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set:
- AVR
- The status register `SREG`.

View File

@ -0,0 +1,13 @@
# `asm_sym`
The tracking issue for this feature is: [#72016]
[#72016]: https://github.com/rust-lang/rust/issues/72016
------------------------
This feature adds a `sym <path>` operand type to `asm!` and `global_asm!`.
- `<path>` must refer to a `fn` or `static`.
- A mangled symbol name referring to the item is substituted into the asm template string.
- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
- `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.

View File

@ -0,0 +1,9 @@
# `asm_unwind`
The tracking issue for this feature is: [#72016]
[#72016]: https://github.com/rust-lang/rust/issues/72016
------------------------
This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now.

View File

@ -0,0 +1,28 @@
#![feature(const_fn_trait_bound, generic_const_exprs)]
#![allow(incomplete_features)]
trait MiniTypeId {
const TYPE_ID: u64;
}
impl<T> MiniTypeId for T {
const TYPE_ID: u64 = 0;
}
enum Lift<const V: bool> {}
trait IsFalse {}
impl IsFalse for Lift<false> {}
const fn is_same_type<T: MiniTypeId, U: MiniTypeId>() -> bool {
T::TYPE_ID == U::TYPE_ID
}
fn requires_distinct<A, B>(_a: A, _b: B) where
A: MiniTypeId, B: MiniTypeId,
Lift<{is_same_type::<A, B>()}>: IsFalse {}
fn main() {
requires_distinct("str", 12);
//~^ ERROR mismatched types
}

View File

@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/issue-79674.rs:26:5
|
LL | requires_distinct("str", 12);
| ^^^^^^^^^^^^^^^^^ expected `true`, found `false`
|
= note: expected type `true`
found type `false`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,115 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
trait TensorDimension {
const DIM : usize;
const ISSCALAR : bool = Self::DIM == 0;
fn is_scalar(&self) -> bool {Self::ISSCALAR}
}
trait TensorSize : TensorDimension {
fn size(&self) -> [usize;Self::DIM];
fn inbounds(&self,index : [usize;Self::DIM]) -> bool {
index.iter().zip(self.size().iter()).all(|(i,s)| i < s)
}
}
trait Broadcastable: TensorSize + Sized {
type Element;
fn bget(&self, index:[usize;Self::DIM]) -> Option<Self::Element>;
fn lazy_updim<const NEWDIM : usize>(&self, size : [usize;NEWDIM] ) ->
LazyUpdim<Self,{Self::DIM},NEWDIM>
{
assert!(NEWDIM >= Self::DIM,
"Updimmed tensor cannot have fewer indices than the initial one.");
LazyUpdim {size,reference:&self}
}
fn bmap<T,F :Fn(Self::Element) -> T>(&self,foo : F) -> BMap<T,Self,F,{Self::DIM}>{
BMap {reference:self,closure : foo}
}
}
struct LazyUpdim<'a,T : Broadcastable,const OLDDIM : usize, const DIM : usize> {
size : [usize;DIM],
reference : &'a T
}
impl<'a,T : Broadcastable,const DIM : usize> TensorDimension for LazyUpdim<'a,T,{T::DIM},DIM> {
const DIM : usize = DIM;
}
impl<'a,T : Broadcastable,const DIM : usize> TensorSize for LazyUpdim<'a,T,{T::DIM},DIM> {
fn size(&self) -> [usize;DIM] {self.size}
//~^ ERROR method not compatible with trait
}
impl<'a,T : Broadcastable,const DIM : usize> Broadcastable for LazyUpdim<'a,T,{T::DIM},DIM>
{
type Element = T::Element;
fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> {
//~^ ERROR method not compatible with trait
assert!(DIM >= T::DIM);
if !self.inbounds(index) {return None}
//~^ ERROR unconstrained generic constant
//~| ERROR mismatched types
let size = self.size();
//~^ ERROR unconstrained generic constant
let newindex : [usize;T::DIM] = Default::default();
//~^ ERROR the trait bound `[usize; _]: Default` is not satisfied
self.reference.bget(newindex)
}
}
struct BMap<'a,R, T : Broadcastable, F : Fn(T::Element) -> R , const DIM: usize> {
reference : &'a T,
closure : F
}
impl<'a,R, T : Broadcastable, F : Fn(T::Element) -> R,
const DIM: usize> TensorDimension for BMap<'a,R,T,F,DIM> {
const DIM : usize = DIM;
}
impl<'a,R, T : Broadcastable, F : Fn(T::Element) -> R ,
const DIM: usize> TensorSize for BMap<'a,R,T,F,DIM> {
fn size(&self) -> [usize;DIM] {self.reference.size()}
//~^ ERROR unconstrained generic constant
//~| ERROR mismatched types
//~| ERROR method not compatible with trait
}
impl<'a,R, T : Broadcastable, F : Fn(T::Element) -> R ,
const DIM: usize> Broadcastable for BMap<'a,R,T,F,DIM> {
type Element = R;
fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> {
//~^ ERROR method not compatible with trait
self.reference.bget(index).map(&self.closure)
//~^ ERROR unconstrained generic constant
//~| ERROR mismatched types
}
}
impl<T> TensorDimension for Vec<T> {
const DIM : usize = 1;
}
impl<T> TensorSize for Vec<T> {
fn size(&self) -> [usize;1] {[self.len()]}
}
impl<T: Clone> Broadcastable for Vec<T> {
type Element = T;
fn bget(& self,index : [usize;1]) -> Option<T> {
self.get(index[0]).cloned()
}
}
fn main() {
let v = vec![1,2,3];
let bv = v.lazy_updim([3,4]);
let bbv = bv.bmap(|x| x*x);
println!("The size of v is {:?}",bbv.bget([0,2]).expect("Out of bounds."));
}

View File

@ -0,0 +1,130 @@
error[E0308]: method not compatible with trait
--> $DIR/issue-83765.rs:44:5
|
LL | fn size(&self) -> [usize;DIM] {self.size}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
= note: expected type `Self::DIM`
found type `DIM`
error[E0308]: method not compatible with trait
--> $DIR/issue-83765.rs:51:5
|
LL | fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
= note: expected type `Self::DIM`
found type `DIM`
error[E0308]: method not compatible with trait
--> $DIR/issue-83765.rs:78:5
|
LL | fn size(&self) -> [usize;DIM] {self.reference.size()}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
= note: expected type `Self::DIM`
found type `DIM`
error[E0308]: method not compatible with trait
--> $DIR/issue-83765.rs:88:5
|
LL | fn bget(&self,index:[usize;DIM]) -> Option<Self::Element> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
= note: expected type `Self::DIM`
found type `DIM`
error: unconstrained generic constant
--> $DIR/issue-83765.rs:54:18
|
LL | if !self.inbounds(index) {return None}
| ^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
note: required by a bound in `TensorSize::inbounds`
--> $DIR/issue-83765.rs:12:38
|
LL | fn inbounds(&self,index : [usize;Self::DIM]) -> bool {
| ^^^^^^^^^ required by this bound in `TensorSize::inbounds`
error[E0308]: mismatched types
--> $DIR/issue-83765.rs:54:27
|
LL | if !self.inbounds(index) {return None}
| ^^^^^ expected `Self::DIM`, found `DIM`
|
= note: expected type `Self::DIM`
found type `DIM`
error: unconstrained generic constant
--> $DIR/issue-83765.rs:57:25
|
LL | let size = self.size();
| ^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
note: required by a bound in `TensorSize::size`
--> $DIR/issue-83765.rs:11:30
|
LL | fn size(&self) -> [usize;Self::DIM];
| ^^^^^^^^^ required by this bound in `TensorSize::size`
error[E0277]: the trait bound `[usize; _]: Default` is not satisfied
--> $DIR/issue-83765.rs:59:41
|
LL | let newindex : [usize;T::DIM] = Default::default();
| ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[usize; _]`
|
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
LL | impl<'a,T : Broadcastable,const DIM : usize> Broadcastable for LazyUpdim<'a,T,{T::DIM},DIM> where [usize; _]: Default
| +++++++++++++++++++++++++
error: unconstrained generic constant
--> $DIR/issue-83765.rs:78:51
|
LL | fn size(&self) -> [usize;DIM] {self.reference.size()}
| ^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
note: required by a bound in `TensorSize::size`
--> $DIR/issue-83765.rs:11:30
|
LL | fn size(&self) -> [usize;Self::DIM];
| ^^^^^^^^^ required by this bound in `TensorSize::size`
error[E0308]: mismatched types
--> $DIR/issue-83765.rs:78:36
|
LL | fn size(&self) -> [usize;DIM] {self.reference.size()}
| ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
|
= note: expected type `DIM`
found type `Self::DIM`
error: unconstrained generic constant
--> $DIR/issue-83765.rs:90:24
|
LL | self.reference.bget(index).map(&self.closure)
| ^^^^
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
note: required by a bound in `Broadcastable::bget`
--> $DIR/issue-83765.rs:20:33
|
LL | fn bget(&self, index:[usize;Self::DIM]) -> Option<Self::Element>;
| ^^^^^^^^^ required by this bound in `Broadcastable::bget`
error[E0308]: mismatched types
--> $DIR/issue-83765.rs:90:29
|
LL | self.reference.bget(index).map(&self.closure)
| ^^^^^ expected `Self::DIM`, found `DIM`
|
= note: expected type `Self::DIM`
found type `DIM`
error: aborting due to 12 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

View File

@ -0,0 +1,20 @@
// check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
pub trait IsTrue<const T: bool> {}
impl IsTrue<true> for () {}
pub trait IsZST {}
impl<T> IsZST for T
where
(): IsTrue<{ std::mem::size_of::<T>() == 0 }>
{}
fn _func() -> impl IsZST {
|| {}
}
fn main() {}

View File

@ -0,0 +1,13 @@
// check-pass
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
pub struct Assert<const COND: bool>();
pub trait IsTrue {}
impl IsTrue for Assert<true> {}
pub trait IsNotZST {}
impl<T> IsNotZST for T where Assert<{ std::mem::size_of::<T>() > 0 }>: IsTrue {}
fn main() {}

View File

@ -0,0 +1,32 @@
#![feature(const_type_id)]
#![feature(generic_const_exprs)]
#![feature(core_intrinsics)]
#![allow(incomplete_features)]
use std::any::TypeId;
struct If<const B: bool>;
pub trait True {}
impl True for If<true> {}
fn consume<T: 'static>(_val: T)
where
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
//~^ ERROR: overly complex generic constant
//~| ERROR: calls in constants are limited to constant functions
{
}
fn test<T: 'static>()
where
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
//~^ ERROR: overly complex generic constant
//~| ERROR: calls in constants are limited to constant functions
{
}
fn main() {
let a = ();
consume(0i32);
consume(a);
}

View File

@ -0,0 +1,37 @@
error: overly complex generic constant
--> $DIR/issue-90318.rs:14:8
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowing is not supported in generic constants
|
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-90318.rs:14:10
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: overly complex generic constant
--> $DIR/issue-90318.rs:22:8
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowing is not supported in generic constants
|
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-90318.rs:22:10
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0015`.