diff --git a/.mailmap b/.mailmap index a160f2f4fbf..3d4d4711939 100644 --- a/.mailmap +++ b/.mailmap @@ -246,6 +246,7 @@ Philipp Brüschweiler Philipp Krones flip1995 Philipp Krones Philipp Matthias Schäfer +pierwill <19642016+pierwill@users.noreply.github.com> Przemysław Wesołek Przemek Wesołek Rafael Ávila de Espíndola Rafael Avila de Espindola Ralph Giles Ralph Giles diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 4a83cdb917c..dfdf3c93842 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -491,7 +491,7 @@ impl BTreeSet { /// ``` /// 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 BTreeSet { /// ``` /// 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 BTreeSet { /// ``` /// 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 BTreeSet { /// ``` /// 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 BTreeSet { /// ``` /// 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 BTreeSet { /// ``` /// 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 BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let xs = [1, 2, 3, 4, 5, 6]; - /// let mut set: BTreeSet = 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 BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [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 BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [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 IntoIterator for BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [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 Sub<&BTreeSet> for &BTreeSet { /// ``` /// 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 BitXor<&BTreeSet> for &BTreeSet { /// ``` /// 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 BitAnd<&BTreeSet> for &BTreeSet { /// ``` /// 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 BitOr<&BTreeSet> for &BTreeSet { /// ``` /// 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(); diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index c8aad4877e9..4a07d5d4bed 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -417,7 +417,7 @@ impl LinkedList { /// let list: LinkedList = 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 { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 408c3cb8577..b6b11b75c99 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -822,7 +822,7 @@ impl Vec { /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity exceeds `isize::MAX` bytes. /// /// # Examples /// diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 8c6a7a56966..f45ee7b6ee8 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -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`, diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 32bd22846e7..6ec1c93908f 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -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. diff --git a/library/core/src/stream/stream/mod.rs b/library/core/src/stream/stream.rs similarity index 100% rename from library/core/src/stream/stream/mod.rs rename to library/core/src/stream/stream.rs diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 3f264ee6732..a1e28c0b0a6 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -233,7 +233,7 @@ impl HashSet { /// ``` /// 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 = 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 = 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 = 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 { /// ``` /// use std::collections::HashSet; /// -/// let mut a: HashSet = 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 = 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 = 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 = 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 = 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 = 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); /// ``` diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ca7ad532030..5df3d0bde6d 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -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") diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6ba1b1b6036..952a65a4286 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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 } diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 3216c1af267..3b73dc1c7df 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -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(()); } diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 182fb0fb067..88359fff191 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -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" diff --git a/src/doc/unstable-book/src/language-features/asm-const.md b/src/doc/unstable-book/src/language-features/asm-const.md new file mode 100644 index 00000000000..1063c23b6df --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-const.md @@ -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 ` operand type to `asm!` and `global_asm!`. +- `` must be an integer constant expression. +- The value of the expression is formatted as a string and substituted directly into the asm template string. diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md new file mode 100644 index 00000000000..ec97eaa8b2b --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -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`. diff --git a/src/doc/unstable-book/src/language-features/asm-sym.md b/src/doc/unstable-book/src/language-features/asm-sym.md new file mode 100644 index 00000000000..7544e20807e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-sym.md @@ -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 ` operand type to `asm!` and `global_asm!`. +- `` 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). +- `` 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. diff --git a/src/doc/unstable-book/src/language-features/asm-unwind.md b/src/doc/unstable-book/src/language-features/asm-unwind.md new file mode 100644 index 00000000000..414193fe801 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-unwind.md @@ -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. diff --git a/src/test/ui/const-generics/issues/issue-79674.rs b/src/test/ui/const-generics/issues/issue-79674.rs new file mode 100644 index 00000000000..2f196533dd8 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-79674.rs @@ -0,0 +1,28 @@ +#![feature(const_fn_trait_bound, generic_const_exprs)] +#![allow(incomplete_features)] + +trait MiniTypeId { + const TYPE_ID: u64; +} + +impl MiniTypeId for T { + const TYPE_ID: u64 = 0; +} + +enum Lift {} + +trait IsFalse {} +impl IsFalse for Lift {} + +const fn is_same_type() -> bool { + T::TYPE_ID == U::TYPE_ID +} + +fn requires_distinct(_a: A, _b: B) where + A: MiniTypeId, B: MiniTypeId, + Lift<{is_same_type::()}>: IsFalse {} + +fn main() { + requires_distinct("str", 12); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/const-generics/issues/issue-79674.stderr b/src/test/ui/const-generics/issues/issue-79674.stderr new file mode 100644 index 00000000000..8c029289cbb --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-79674.stderr @@ -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`. diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs new file mode 100644 index 00000000000..68536348d38 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.rs @@ -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; + fn lazy_updim(&self, size : [usize;NEWDIM] ) -> + LazyUpdim + { + assert!(NEWDIM >= Self::DIM, + "Updimmed tensor cannot have fewer indices than the initial one."); + LazyUpdim {size,reference:&self} + } + fn bmap T>(&self,foo : F) -> BMap{ + 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 { + //~^ 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 { + //~^ ERROR method not compatible with trait + self.reference.bget(index).map(&self.closure) + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types + } +} + +impl TensorDimension for Vec { + const DIM : usize = 1; +} +impl TensorSize for Vec { + fn size(&self) -> [usize;1] {[self.len()]} +} +impl Broadcastable for Vec { + type Element = T; + fn bget(& self,index : [usize;1]) -> Option { + 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.")); +} diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr new file mode 100644 index 00000000000..a49f850717f --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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; + | ^^^^^^^^^ 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`. diff --git a/src/test/ui/const-generics/issues/issue-86033.rs b/src/test/ui/const-generics/issues/issue-86033.rs new file mode 100644 index 00000000000..cf08f722fbb --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-86033.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait IsTrue {} +impl IsTrue for () {} + +pub trait IsZST {} + +impl IsZST for T +where + (): IsTrue<{ std::mem::size_of::() == 0 }> +{} + +fn _func() -> impl IsZST { + || {} +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-88468.rs b/src/test/ui/const-generics/issues/issue-88468.rs new file mode 100644 index 00000000000..914047236ab --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-88468.rs @@ -0,0 +1,13 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub struct Assert(); +pub trait IsTrue {} +impl IsTrue for Assert {} + +pub trait IsNotZST {} +impl IsNotZST for T where Assert<{ std::mem::size_of::() > 0 }>: IsTrue {} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-90318.rs b/src/test/ui/const-generics/issues/issue-90318.rs new file mode 100644 index 00000000000..0c640a5ef71 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-90318.rs @@ -0,0 +1,32 @@ +#![feature(const_type_id)] +#![feature(generic_const_exprs)] +#![feature(core_intrinsics)] +#![allow(incomplete_features)] + +use std::any::TypeId; + +struct If; +pub trait True {} +impl True for If {} + +fn consume(_val: T) +where + If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + //~^ ERROR: overly complex generic constant + //~| ERROR: calls in constants are limited to constant functions +{ +} + +fn test() +where + If<{ TypeId::of::() != 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); +} diff --git a/src/test/ui/const-generics/issues/issue-90318.stderr b/src/test/ui/const-generics/issues/issue-90318.stderr new file mode 100644 index 00000000000..2b8afe2ef09 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-90318.stderr @@ -0,0 +1,37 @@ +error: overly complex generic constant + --> $DIR/issue-90318.rs:14:8 + | +LL | If<{ TypeId::of::() != 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::() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: overly complex generic constant + --> $DIR/issue-90318.rs:22:8 + | +LL | If<{ TypeId::of::() != 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::() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0015`.