<ins> // Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! POSIX file path handling use container::Container; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::Eq; use from_str::FromStr; use iter::{AdditiveIterator, Extendable, Iterator}; use option::{Option, None, Some}; use str; use str::Str; use util; use vec; use vec::CopyableVector; use vec::{Vector, VectorVector}; use super::{GenericPath, GenericPathUnsafe}; /// Iterator that yields successive components of a Path pub type ComponentIter<'self> = vec::SplitIterator<'self, u8>; /// Represents a POSIX file path #[deriving(Clone, DeepClone)] pub struct Path { priv repr: ~[u8], // assumed to never be empty or contain NULs priv sepidx: Option<uint> // index of the final separator in repr } /// The standard path separator character pub static sep: u8 = '/' as u8; /// Returns whether the given byte is a path separator #[inline] pub fn is_sep(u: &u8) -> bool { *u == sep } impl Eq for Path { #[inline] fn eq(&self, other: &Path) -> bool { self.repr == other.repr } } impl FromStr for Path { fn from_str(s: &str) -> Option<Path> { let v = s.as_bytes(); if contains_nul(v) { None } else { Some(unsafe { GenericPathUnsafe::from_vec_unchecked(v) }) } } } impl ToCStr for Path { #[inline] fn to_c_str(&self) -> CString { // The Path impl guarantees no internal NUL unsafe { self.as_vec().to_c_str_unchecked() } } #[inline] unsafe fn to_c_str_unchecked(&self) -> CString { self.as_vec().to_c_str_unchecked() } } impl GenericPathUnsafe for Path { unsafe fn from_vec_unchecked(path: &[u8]) -> Path { let path = Path::normalize(path); assert!(!path.is_empty()); let idx = path.rposition_elem(&sep); Path{ repr: path, sepidx: idx } } unsafe fn set_dirname_unchecked(&mut self, dirname: &[u8]) { match self.sepidx { None if bytes!(".") == self.repr || bytes!("..") == self.repr => { self.repr = Path::normalize(dirname); } None => { let mut v = vec::with_capacity(dirname.len() + self.repr.len() + 1); v.push_all(dirname); v.push(sep); v.push_all(self.repr); self.repr = Path::normalize(v); } Some(0) if self.repr.len() == 1 && self.repr[0] == sep => { self.repr = Path::normalize(dirname); } Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => { self.repr = Path::normalize(dirname); } Some(idx) if dirname.is_empty() => { let v = Path::normalize(self.repr.slice_from(idx+1)); self.repr = v; } Some(idx) => { let mut v = vec::with_capacity(dirname.len() + self.repr.len() - idx); v.push_all(dirname); v.push_all(self.repr.slice_from(idx)); self.repr = Path::normalize(v); } } self.sepidx = self.repr.rposition_elem(&sep); } unsafe fn set_filename_unchecked(&mut self, filename: &[u8]) { match self.sepidx { None if bytes!("..") == self.repr => { let mut v = vec::with_capacity(3 + filename.len()); v.push_all(dot_dot_static); v.push(sep); v.push_all(filename); self.repr = Path::normalize(v); } None => { self.repr = Path::normalize(filename); } Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => { let mut v = vec::with_capacity(self.repr.len() + 1 + filename.len()); v.push_all(self.repr); v.push(sep); v.push_all(filename); self.repr = Path::normalize(v); } Some(idx) => { let mut v = vec::with_capacity(idx + 1 + filename.len()); v.push_all(self.repr.slice_to(idx+1)); v.push_all(filename); self.repr = Path::normalize(v); } } self.sepidx = self.repr.rposition_elem(&sep); } unsafe fn push_unchecked(&mut self, path: &[u8]) { if !path.is_empty() { if path[0] == sep { self.repr = Path::normalize(path); }  else { let mut v = vec::with_capacity(self.repr.len() + path.len() + 1); v.push_all(self.repr); v.push(sep); v.push_all(path); self.repr = Path::normalize(v); } self.sepidx = self.repr.rposition_elem(&sep); } } } impl GenericPath for Path { #[inline] fn as_vec<'a>(&'a self) -> &'a [u8] { self.repr.as_slice() } fn dirname<'a>(&'a self) -> &'a [u8] { match self.sepidx { None if bytes!("..") == self.repr => self.repr.as_slice(), None => dot_static, Some(0) => self.repr.slice_to(1), Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => self.repr.as_slice(), Some(idx) => self.repr.slice_to(idx) } } fn filename<'a>(&'a self) -> &'a [u8] { match self.sepidx { None if bytes!(".") == self.repr || bytes!("..") == self.repr => &[], None => self.repr.as_slice(), Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => &[], Some(idx) => self.repr.slice_from(idx+1) } } fn pop_opt(&mut self) -> Option<~[u8]> { match self.sepidx { None if bytes!(".") == self.repr => None, None => { let mut v = ~['.' as u8]; util::swap(&mut v, &mut self.repr); self.sepidx = None; Some(v) } Some(0) if bytes!("/") == self.repr => None, Some(idx) => { let v = self.repr.slice_from(idx+1).to_owned(); if idx == 0 { self.repr.truncate(idx+1); } else { self.repr.truncate(idx); } self.sepidx = self.repr.rposition_elem(&sep); Some(v) } } } #[inline] fn is_absolute(&self) -> bool { self.repr[0] == sep } fn is_ancestor_of(&self, other: &Path) -> bool { if self.is_absolute() != other.is_absolute() { false } else { let mut ita = self.component_iter(); let mut itb = other.component_iter(); if bytes!(".") == self.repr { return itb.next() != Some(bytes!("..")); } loop { match (ita.next(), itb.next()) { (None, _) => break, (Some(a), Some(b)) if a == b => { loop }, (Some(a), _) if a == bytes!("..") => { // if ita contains only .. components, it's an ancestor return ita.all(|x| x == bytes!("..")); } _ => return false } } true } } fn path_relative_from(&self, base: &Path) -> Option<Path> { if self.is_absolute() != base.is_absolute() { if self.is_absolute() { Some(self.clone()) } else { None } } else { let mut ita = self.component_iter(); let mut itb = base.component_iter(); let mut comps = ~[]; loop { match (ita.next(), itb.next()) { (None, None) => break, (Some(a), None) => { comps.push(a); comps.extend(&mut ita); break; } (None, _) => comps.push(dot_dot_static), (Some(a), Some(b)) if comps.is_empty() && a == b => (), (Some(a), Some(b)) if b == bytes!(".") => comps.push(a), (Some(_), Some(b)) if b == bytes!("..") => return None, (Some(a), Some(_)) => { comps.push(dot_dot_static); for _ in itb { comps.push(dot_dot_static); } comps.push(a); comps.extend(&mut ita); break; } } } Some(Path::new(comps.connect_vec(&sep))) } } } impl Path { /// Returns a new Path from a byte vector /// /// # Failure /// /// Raises the `null_byte` condition if the vector contains a NUL. #[inline] pub fn new(v: &[u8]) -> Path { GenericPath::from_vec(v) } /// Returns a new Path from a string /// /// # Failure /// /// Raises the `null_byte` condition if the str contains a NUL. #[inline] pub fn from_str(s: &str) -> Path { GenericPath::from_str(s) } /// Converts the Path into an owned byte vector pub fn into_vec(self) -> ~[u8] { self.repr } /// Converts the Path into an owned string, if possible pub fn into_str(self) -> Option<~str> { str::from_utf8_owned_opt(self.repr) } /// Returns a normalized byte vector representation of a path, by removing all empty /// components, and unnecessary . and .. components. pub fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] { // borrowck is being very picky let val = { let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == sep; let v_ = if is_abs { v.as_slice().slice_from(1) } else { v.as_slice() }; let comps = normalize_helper(v_, is_abs); match comps { None => None, Some(comps) => { if is_abs && comps.is_empty() { Some(~[sep]) } else { let n = if is_abs { comps.len() } else { comps.len() - 1} + comps.iter().map(|v| v.len()).sum(); let mut v = vec::with_capacity(n); let mut it = comps.move_iter(); if !is_abs { match it.next() { None => (), Some(comp) => v.push_all(comp) } } for comp in it { v.push(sep); v.push_all(comp); } Some(v) } } } }; match val { None => v.into_owned(), Some(val) => val } } /// Returns an iterator that yields each component of the path in turn. /// Does not distinguish between absolute and relative paths, e.g. /// /a/b/c and a/b/c yield the same set of components. /// A path of "/" yields no components. A path of "." yields one component. pub fn component_iter<'a>(&'a self) -> ComponentIter<'a> { let v = if self.repr[0] == sep { self.repr.slice_from(1) } else { self.repr.as_slice() }; let mut ret = v.split_iter(is_sep); if v.is_empty() { // consume the empty "" component ret.next(); } ret } } // None result means the byte vector didn't need normalizing fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<~[&'a [u8]]> { if is_abs && v.as_slice().is_empty() { return None; } let mut comps: ~[&'a [u8]] = ~[]; let mut n_up = 0u; let mut changed = false; for comp in v.split_iter(is_sep) { if comp.is_empty() { changed = true } else if comp == bytes!(".") { changed = true } else if comp == bytes!("..") { if is_abs && comps.is_empty() { changed = true } else if comps.len() == n_up { comps.push(dot_dot_static); n_up += 1 } else { comps.pop_opt(); changed = true } } else { comps.push(comp) } } if changed { if comps.is_empty() && !is_abs { if v == bytes!(".") { return None; } comps.push(dot_static); } Some(comps) } else { None } } // FIXME (#8169): Pull this into parent module once visibility works #[inline(always)] fn contains_nul(v: &[u8]) -> bool { v.iter().any(|&x| x == 0) } static dot_static: &'static [u8] = &'static ['.' as u8]; static dot_dot_static: &'static [u8] = &'static ['.' as u8, '.' as u8]; #[cfg(test)] mod tests { use super::*; use option::{Some, None}; use iter::Iterator; use str; use vec::Vector; macro_rules! t( (s: $path:expr, $exp:expr) => ( { let path = $path; assert_eq!(path.as_str(), Some($exp)); } ); (v: $path:expr, $exp:expr) => ( { let path = $path; assert_eq!(path.as_vec(), $exp); } ) ) macro_rules! b( ($($arg:expr),+) => ( bytes!($($arg),+) ) ) #[test] fn test_paths() { t!(v: Path::new([]), b!(".")); t!(v: Path::new(b!("/")), b!("/")); t!(v: Path::new(b!("a/b/c")), b!("a/b/c")); t!(v: Path::new(b!("a/b/c", 0xff)), b!("a/b/c", 0xff)); t!(v: Path::new(b!(0xff, "/../foo", 0x80)), b!("foo", 0x80)); let p = Path::new(b!("a/b/c", 0xff)); assert_eq!(p.as_str(), None); t!(s: Path::from_str(""), "."); t!(s: Path::from_str("/"), "/"); t!(s: Path::from_str("hi"), "hi"); t!(s: Path::from_str("hi/"), "hi"); t!(s: Path::from_str("/lib"), "/lib"); t!(s: Path::from_str("/lib/"), "/lib"); t!(s: Path::from_str("hi/there"), "hi/there"); t!(s: Path::from_str("hi/there.txt"), "hi/there.txt"); t!(s: Path::from_str("hi/there/"), "hi/there"); t!(s: Path::from_str("hi/../there"), "there"); t!(s: Path::from_str("../hi/there"), "../hi/there"); t!(s: Path::from_str("/../hi/there"), "/hi/there"); t!(s: Path::from_str("foo/.."), "."); t!(s: Path::from_str("/foo/.."), "/"); t!(s: Path::from_str("/foo/../.."), "/"); t!(s: Path::from_str("/foo/../../bar"), "/bar"); t!(s: Path::from_str("/./hi/./there/."), "/hi/there"); t!(s: Path::from_str("/./hi/./there/./.."), "/hi"); t!(s: Path::from_str("foo/../.."), ".."); t!(s: Path::from_str("foo/../../.."), "../.."); t!(s: Path::from_str("foo/../../bar"), "../bar"); assert_eq!(Path::new(b!("foo/bar")).into_vec(), b!("foo/bar").to_owned()); assert_eq!(Path::new(b!("/foo/../../bar")).into_vec(), b!("/bar").to_owned()); assert_eq!(Path::from_str("foo/bar").into_str(), Some(~"foo/bar")); assert_eq!(Path::from_str("/foo/../../bar").into_str(), Some(~"/bar")); let p = Path::new(b!("foo/bar", 0x80)); assert_eq!(p.as_str(), None); assert_eq!(Path::new(b!("foo", 0xff, "/bar")).into_str(), None); } #[test] fn test_null_byte() { use path2::null_byte::cond; let mut handled = false; let mut p = do cond.trap(|v| { handled = true; assert_eq!(v.as_slice(), b!("foo/bar", 0)); (b!("/bar").to_owned()) }).inside { Path::new(b!("foo/bar", 0)) }; assert!(handled); assert_eq!(p.as_vec(), b!("/bar")); handled = false; do cond.trap(|v| { handled = true; assert_eq!(v.as_slice(), b!("f", 0, "o")); (b!("foo").to_owned()) }).inside { p.set_filename(b!("f", 0, "o")) }; assert!(handled); assert_eq!(p.as_vec(), b!("/foo")); handled = false; do cond.trap(|v| { handled = true; assert_eq!(v.as_slice(), b!("null/", 0, "/byte")); (b!("null/byte").to_owned()) }).inside { p.set_dirname(b!("null/", 0, "/byte")); }; assert!(handled); assert_eq!(p.as_vec(), b!("null/byte/foo")); handled = false; do cond.trap(|v| { handled = true; assert_eq!(v.as_slice(), b!("f", 0, "o")); (b!("foo").to_owned()) }).inside { p.push(b!("f", 0, "o")); }; assert!(handled); assert_eq!(p.as_vec(), b!("null/byte/foo/foo")); } #[test] fn test_null_byte_fail() { use path2::null_byte::cond; use task; macro_rules! t( ($name:expr => $code:block) => ( { let mut t = task::task(); t.supervised(); t.name($name); let res = do t.try $code; assert!(res.is_err()); } ) ) t!(~"new() w/nul" => { do cond.trap(|_| { (b!("null", 0).to_owned()) }).inside { Path::new(b!("foo/bar", 0)) }; }) t!(~"set_filename w/nul" => { let mut p = Path::new(b!("foo/bar")); do cond.trap(|_| { (b!("null", 0).to_owned()) }).inside { p.set_filename(b!("foo", 0)) }; }) t!(~"set_dirname w/nul" => { let mut p = Path::new(b!("foo/bar")); do cond.trap(|_| { (b!("null", 0).to_owned()) }).inside { p.set_dirname(b!("foo", 0)) }; }) t!(~"push w/nul" => { let mut p = Path::new(b!("foo/bar")); do cond.trap(|_| { (b!("null", 0).to_owned()) }).inside { p.push(b!("foo", 0)) }; }) } #[test] fn test_components() { macro_rules! t( (s: $path:expr, $op:ident, $exp:expr) => ( { let path = Path::from_str($path); assert_eq!(path.$op(), ($exp).as_bytes()); } ); (s: $path:expr, $op:ident, $exp:expr, opt) => ( { let path = Path::from_str($path); let left = path.$op().map(|&x| str::from_utf8_slice(x)); assert_eq!(left, $exp); } ); (v: $path:expr, $op:ident, $exp:expr) => ( { let path = Path::new($path); assert_eq!(path.$op(), $exp); } ) ) t!(v: b!("a/b/c"), filename, b!("c")); t!(v: b!("a/b/c", 0xff), filename, b!("c", 0xff)); t!(v: b!("a/b", 0xff, "/c"), filename, b!("c")); t!(s: "a/b/c", filename, "c"); t!(s: "/a/b/c", filename, "c"); t!(s: "a", filename, "a"); t!(s: "/a", filename, "a"); t!(s: ".", filename, ""); t!(s: "/", filename, ""); t!(s: "..", filename, ""); t!(s: "../..", filename, ""); t!(v: b!("a/b/c"), dirname, b!("a/b")); t!(v: b!("a/b/c", 0xff), dirname, b!("a/b")); t!(v: b!("a/b", 0xff, "/c"), dirname, b!("a/b", 0xff)); t!(s: "a/b/c", dirname, "a/b"); t!(s: "/a/b/c", dirname, "/a/b"); t!(s: "a", dirname, "."); t!(s: "/a", dirname, "/"); t!(s: ".", dirname, "."); t!(s: "/", dirname, "/"); t!(s: "..", dirname, ".."); t!(s: "../..", dirname, "../.."); t!(v: b!("hi/there.txt"), filestem, b!("there")); t!(v: b!("hi/there", 0x80, ".txt"), filestem, b!("there", 0x80)); t!(v: b!("hi/there.t", 0x80, "xt"), filestem, b!("there")); t!(s: "hi/there.txt", filestem, "there"); t!(s: "hi/there", filestem, "there"); t!(s: "there.txt", filestem, "there"); t!(s: "there", filestem, "there"); t!(s: ".", filestem, ""); t!(s: "/", filestem, ""); t!(s: "foo/.bar", filestem, ".bar"); t!(s: ".bar", filestem, ".bar"); t!(s: "..bar", filestem, "."); t!(s: "hi/there..txt", filestem, "there."); t!(s: "..", filestem, ""); t!(s: "../..", filestem, ""); t!(v: b!("hi/there.txt"), extension, Some(b!("txt"))); t!(v: b!("hi/there", 0x80, ".txt"), extension, Some(b!("txt"))); t!(v: b!("hi/there.t", 0x80, "xt"), extension, Some(b!("t", 0x80, "xt"))); t!(v: b!("hi/there"), extension, None); t!(v: b!("hi/there", 0x80), extension, None); t!(s: "hi/there.txt", extension, Some("txt"), opt); t!(s: "hi/there", extension, None, opt); t!(s: "there.txt", extension, Some("txt"), opt); t!(s: "there", extension, None, opt); t!(s: ".", extension, None, opt); t!(s: "/", extension, None, opt); t!(s: "foo/.bar", extension, None, opt); t!(s: ".bar", extension, None, opt); t!(s: "..bar", extension, Some("bar"), opt); t!(s: "hi/there..txt", extension, Some("txt"), opt); t!(s: "..", extension, None, opt); t!(s: "../..", extension, None, opt); } #[test] fn test_push() { macro_rules! t( (s: $path:expr, $join:expr) => ( { let path = ($path); let join = ($join); let mut p1 = Path::from_str(path); let p2 = p1.clone(); p1.push_str(join); assert_eq!(p1, p2.join_str(join)); } ) ) t!(s: "a/b/c", ".."); t!(s: "/a/b/c", "d"); t!(s: "a/b", "c/d"); t!(s: "a/b", "/c/d"); } #[test] fn test_push_path() { macro_rules! t( (s: $path:expr, $push:expr, $exp:expr) => ( { let mut p = Path::from_str($path); let push = Path::from_str($push); p.push_path(&push); assert_eq!(p.as_str(), Some($exp)); } ) ) t!(s: "a/b/c", "d", "a/b/c/d"); t!(s: "/a/b/c", "d", "/a/b/c/d"); t!(s: "a/b", "c/d", "a/b/c/d"); t!(s: "a/b", "/c/d", "/c/d"); t!(s: "a/b", ".", "a/b"); t!(s: "a/b", "../c", "a/c"); } #[test] fn test_pop() { macro_rules! t( (s: $path:expr, $left:expr, $right:expr) => ( { let mut p = Path::from_str($path); let file = p.pop_opt_str(); assert_eq!(p.as_str(), Some($left)); assert_eq!(file.map(|s| s.as_slice()), $right); } ); (v: [$($path:expr),+], [$($left:expr),+], Some($($right:expr),+)) => ( { let mut p = Path::new(b!($($path),+)); let file = p.pop_opt(); assert_eq!(p.as_vec(), b!($($left),+)); assert_eq!(file.map(|v| v.as_slice()), Some(b!($($right),+))); } ); (v: [$($path:expr),+], [$($left:expr),+], None) => ( { let mut p = Path::new(b!($($path),+)); let file = p.pop_opt(); assert_eq!(p.as_vec(), b!($($left),+)); assert_eq!(file, None); } ) ) t!(v: ["a/b/c"], ["a/b"], Some("c")); t!(v: ["a"], ["."], Some("a")); t!(v: ["."], ["."], None); t!(v: ["/a"], ["/"], Some("a")); t!(v: ["/"], ["/"], None); t!(v: ["a/b/c", 0x80], ["a/b"], Some("c", 0x80)); t!(v: ["a/b", 0x80, "/c"], ["a/b", 0x80], Some("c")); t!(v: [0xff], ["."], Some(0xff)); t!(v: ["/", 0xff], ["/"], Some(0xff)); t!(s: "a/b/c", "a/b", Some("c")); t!(s: "a", ".", Some("a")); t!(s: ".", ".", None); t!(s: "/a", "/", Some("a")); t!(s: "/", "/", None); assert_eq!(Path::new(b!("foo/bar", 0x80)).pop_opt_str(), None); assert_eq!(Path::new(b!("foo", 0x80, "/bar")).pop_opt_str(), Some(~"bar")); } #[test] fn test_join() { t!(v: Path::new(b!("a/b/c")).join(b!("..")), b!("a/b")); t!(v: Path::new(b!("/a/b/c")).join(b!("d")), b!("/a/b/c/d")); t!(v: Path::new(b!("a/", 0x80, "/c")).join(b!(0xff)), b!("a/", 0x80, "/c/", 0xff)); t!(s: Path::from_str("a/b/c").join_str(".."), "a/b"); t!(s: Path::from_str("/a/b/c").join_str("d"), "/a/b/c/d"); t!(s: Path::from_str("a/b").join_str("c/d"), "a/b/c/d"); t!(s: Path::from_str("a/b").join_str("/c/d"), "/c/d"); t!(s: Path::from_str(".").join_str("a/b"), "a/b"); t!(s: Path::from_str("/").join_str("a/b"), "/a/b"); } #[test] fn test_join_path() { macro_rules! t( (s: $path:expr, $join:expr, $exp:expr) => ( { let path = Path::from_str($path); let join = Path::from_str($join); let res = path.join_path(&join); assert_eq!(res.as_str(), Some($exp)); } ) ) t!(s: "a/b/c", "..", "a/b"); t!(s: "/a/b/c", "d", "/a/b/c/d"); t!(s: "a/b", "c/d", "a/b/c/d"); t!(s: "a/b", "/c/d", "/c/d"); t!(s: ".", "a/b", "a/b"); t!(s: "/", "a/b", "/a/b"); } #[test] fn test_with_helpers() { t!(v: Path::new(b!("a/b/c")).with_dirname(b!("d")), b!("d/c")); t!(v: Path::new(b!("a/b/c")).with_dirname(b!("d/e")), b!("d/e/c")); t!(v: Path::new(b!("a/", 0x80, "b/c")).with_dirname(b!(0xff)), b!(0xff, "/c")); t!(v: Path::new(b!("a/b/", 0x80)).with_dirname(b!("/", 0xcd)), b!("/", 0xcd, "/", 0x80)); t!(s: Path::from_str("a/b/c").with_dirname_str("d"), "d/c"); t!(s: Path::from_str("a/b/c").with_dirname_str("d/e"), "d/e/c"); t!(s: Path::from_str("a/b/c").with_dirname_str(""), "c"); t!(s: Path::from_str("a/b/c").with_dirname_str("/"), "/c"); t!(s: Path::from_str("a/b/c").with_dirname_str("."), "c"); t!(s: Path::from_str("a/b/c").with_dirname_str(".."), "../c"); t!(s: Path::from_str("/").with_dirname_str("foo"), "foo"); t!(s: Path::from_str("/").with_dirname_str(""), "."); t!(s: Path::from_str("/foo").with_dirname_str("bar"), "bar/foo"); t!(s: Path::from_str("..").with_dirname_str("foo"), "foo"); t!(s: Path::from_str("../..").with_dirname_str("foo"), "foo"); t!(s: Path::from_str("..").with_dirname_str(""), "."); t!(s: Path::from_str("../..").with_dirname_str(""), "."); t!(s: Path::from_str("foo").with_dirname_str(".."), "../foo"); t!(s: Path::from_str("foo").with_dirname_str("../.."), "../../foo"); t!(v: Path::new(b!("a/b/c")).with_filename(b!("d")), b!("a/b/d")); t!(v: Path::new(b!("a/b/c", 0xff)).with_filename(b!(0x80)), b!("a/b/", 0x80)); t!(v: Path::new(b!("/", 0xff, "/foo")).with_filename(b!(0xcd)), b!("/", 0xff, "/", 0xcd)); t!(s: Path::from_str("a/b/c").with_filename_str("d"), "a/b/d"); t!(s: Path::from_str(".").with_filename_str("foo"), "foo"); t!(s: Path::from_str("/a/b/c").with_filename_str("d"), "/a/b/d"); t!(s: Path::from_str("/").with_filename_str("foo"), "/foo"); t!(s: Path::from_str("/a").with_filename_str("foo"), "/foo"); t!(s: Path::from_str("foo").with_filename_str("bar"), "bar"); t!(s: Path::from_str("/").with_filename_str("foo/"), "/foo"); t!(s: Path::from_str("/a").with_filename_str("foo/"), "/foo"); t!(s: Path::from_str("a/b/c").with_filename_str(""), "a/b"); t!(s: Path::from_str("a/b/c").with_filename_str("."), "a/b"); t!(s: Path::from_str("a/b/c").with_filename_str(".."), "a"); t!(s: Path::from_str("/a").with_filename_str(""), "/"); t!(s: Path::from_str("foo").with_filename_str(""), "."); t!(s: Path::from_str("a/b/c").with_filename_str("d/e"), "a/b/d/e"); t!(s: Path::from_str("a/b/c").with_filename_str("/d"), "a/b/d"); t!(s: Path::from_str("..").with_filename_str("foo"), "../foo"); t!(s: Path::from_str("../..").with_filename_str("foo"), "../../foo"); t!(s: Path::from_str("..").with_filename_str(""), ".."); t!(s: Path::from_str("../..").with_filename_str(""), "../.."); t!(v: Path::new(b!("hi/there", 0x80, ".txt")).with_filestem(b!(0xff)), b!("hi/", 0xff, ".txt")); t!(v: Path::new(b!("hi/there.txt", 0x80)).with_filestem(b!(0xff)), b!("hi/", 0xff, ".txt", 0x80)); t!(v: Path::new(b!("hi/there", 0xff)).with_filestem(b!(0x80)), b!("hi/", 0x80)); t!(v: Path::new(b!("hi", 0x80, "/there")).with_filestem([]), b!("hi", 0x80)); t!(s: Path::from_str("hi/there.txt").with_filestem_str("here"), "hi/here.txt"); t!(s: Path::from_str("hi/there.txt").with_filestem_str(""), "hi/.txt"); t!(s: Path::from_str("hi/there.txt").with_filestem_str("."), "hi/..txt"); t!(s: Path::from_str("hi/there.txt").with_filestem_str(".."), "hi/...txt"); t!(s: Path::from_str("hi/there.txt").with_filestem_str("/"), "hi/.txt"); t!(s: Path::from_str("hi/there.txt").with_filestem_str("foo/bar"), "hi/foo/bar.txt"); t!(s: Path::from_str("hi/there.foo.txt").with_filestem_str("here"), "hi/here.txt"); t!(s: Path::from_str("hi/there").with_filestem_str("here"), "hi/here"); t!(s: Path::from_str("hi/there").with_filestem_str(""), "hi"); t!(s: Path::from_str("hi").with_filestem_str(""), "."); t!(s: Path::from_str("/hi").with_filestem_str(""), "/"); t!(s: Path::from_str("hi/there").with_filestem_str(".."), "."); t!(s: Path::from_str("hi/there").with_filestem_str("."), "hi"); t!(s: Path::from_str("hi/there.").with_filestem_str("foo"), "hi/foo."); t!(s: Path::from_str("hi/there.").with_filestem_str(""), "hi"); t!(s: Path::from_str("hi/there.").with_filestem_str("."), "."); t!(s: Path::from_str("hi/there.").with_filestem_str(".."), "hi/..."); t!(s: Path::from_str("/").with_filestem_str("foo"), "/foo"); t!(s: Path::from_str(".").with_filestem_str("foo"), "foo"); t!(s: Path::from_str("hi/there..").with_filestem_str("here"), "hi/here."); t!(s: Path::from_str("hi/there..").with_filestem_str(""), "hi"); t!(v: Path::new(b!("hi/there", 0x80, ".txt")).with_extension(b!("exe")), b!("hi/there", 0x80, ".exe")); t!(v: Path::new(b!("hi/there.txt", 0x80)).with_extension(b!(0xff)), b!("hi/there.", 0xff)); t!(v: Path::new(b!("hi/there", 0x80)).with_extension(b!(0xff)), b!("hi/there", 0x80, ".", 0xff)); t!(v: Path::new(b!("hi/there.", 0xff)).with_extension([]), b!("hi/there")); t!(s: Path::from_str("hi/there.txt").with_extension_str("exe"), "hi/there.exe"); t!(s: Path::from_str("hi/there.txt").with_extension_str(""), "hi/there"); t!(s: Path::from_str("hi/there.txt").with_extension_str("."), "hi/there.."); t!(s: Path::from_str("hi/there.txt").with_extension_str(".."), "hi/there..."); t!(s: Path::from_str("hi/there").with_extension_str("txt"), "hi/there.txt"); t!(s: Path::from_str("hi/there").with_extension_str("."), "hi/there.."); t!(s: Path::from_str("hi/there").with_extension_str(".."), "hi/there..."); t!(s: Path::from_str("hi/there.").with_extension_str("txt"), "hi/there.txt"); t!(s: Path::from_str("hi/.foo").with_extension_str("txt"), "hi/.foo.txt"); t!(s: Path::from_str("hi/there.txt").with_extension_str(".foo"), "hi/there..foo"); t!(s: Path::from_str("/").with_extension_str("txt"), "/"); t!(s: Path::from_str("/").with_extension_str("."), "/"); t!(s: Path::from_str("/").with_extension_str(".."), "/"); t!(s: Path::from_str(".").with_extension_str("txt"), "."); } #[test] fn test_setters() { macro_rules! t( (s: $path:expr, $set:ident, $with:ident, $arg:expr) => ( { let path = $path; let arg = $arg; let mut p1 = Path::from_str(path); p1.$set(arg); let p2 = Path::from_str(path); assert_eq!(p1, p2.$with(arg)); } ); (v: $path:expr, $set:ident, $with:ident, $arg:expr) => ( { let path = $path; let arg = $arg; let mut p1 = Path::new(path); p1.$set(arg); let p2 = Path::new(path); assert_eq!(p1, p2.$with(arg)); } ) ) t!(v: b!("a/b/c"), set_dirname, with_dirname, b!("d")); t!(v: b!("a/b/c"), set_dirname, with_dirname, b!("d/e")); t!(v: b!("a/", 0x80, "/c"), set_dirname, with_dirname, b!(0xff)); t!(s: "a/b/c", set_dirname_str, with_dirname_str, "d"); t!(s: "a/b/c", set_dirname_str, with_dirname_str, "d/e"); t!(s: "/", set_dirname_str, with_dirname_str, "foo"); t!(s: "/foo", set_dirname_str, with_dirname_str, "bar"); t!(s: "a/b/c", set_dirname_str, with_dirname_str, ""); t!(s: "../..", set_dirname_str, with_dirname_str, "x"); t!(s: "foo", set_dirname_str, with_dirname_str, "../.."); t!(v: b!("a/b/c"), set_filename, with_filename, b!("d")); t!(v: b!("/"), set_filename, with_filename, b!("foo")); t!(v: b!(0x80), set_filename, with_filename, b!(0xff)); t!(s: "a/b/c", set_filename_str, with_filename_str, "d"); t!(s: "/", set_filename_str, with_filename_str, "foo"); t!(s: ".", set_filename_str, with_filename_str, "foo"); t!(s: "a/b", set_filename_str, with_filename_str, ""); t!(s: "a", set_filename_str, with_filename_str, ""); t!(v: b!("hi/there.txt"), set_filestem, with_filestem, b!("here")); t!(v: b!("hi/there", 0x80, ".txt"), set_filestem, with_filestem, b!("here", 0xff)); t!(s: "hi/there.txt", set_filestem_str, with_filestem_str, "here"); t!(s: "hi/there.", set_filestem_str, with_filestem_str, "here"); t!(s: "hi/there", set_filestem_str, with_filestem_str, "here"); t!(s: "hi/there.txt", set_filestem_str, with_filestem_str, ""); t!(s: "hi/there", set_filestem_str, with_filestem_str, ""); t!(v: b!("hi/there.txt"), set_extension, with_extension, b!("exe")); t!(v: b!("hi/there.t", 0x80, "xt"), set_extension, with_extension, b!("exe", 0xff)); t!(s: "hi/there.txt", set_extension_str, with_extension_str, "exe"); t!(s: "hi/there.", set_extension_str, with_extension_str, "txt"); t!(s: "hi/there", set_extension_str, with_extension_str, "txt"); t!(s: "hi/there.txt", set_extension_str, with_extension_str, ""); t!(s: "hi/there", set_extension_str, with_extension_str, ""); t!(s: ".", set_extension_str, with_extension_str, "txt"); } #[test] fn test_getters() { macro_rules! t( (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; assert_eq!(path.filename_str(), $filename); assert_eq!(path.dirname_str(), $dirname); assert_eq!(path.filestem_str(), $filestem); assert_eq!(path.extension_str(), $ext); } ); (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => ( { let path = $path; assert_eq!(path.filename(), $filename); assert_eq!(path.dirname(), $dirname); assert_eq!(path.filestem(), $filestem); assert_eq!(path.extension(), $ext); } ) ) t!(v: Path::new(b!("a/b/c")), b!("c"), b!("a/b"), b!("c"), None); t!(v: Path::new(b!("a/b/", 0xff)), b!(0xff), b!("a/b"), b!(0xff), None); t!(v: Path::new(b!("hi/there.", 0xff)), b!("there.", 0xff), b!("hi"), b!("there"), Some(b!(0xff))); t!(s: Path::from_str("a/b/c"), Some("c"), Some("a/b"), Some("c"), None); t!(s: Path::from_str("."), Some(""), Some("."), Some(""), None); t!(s: Path::from_str("/"), Some(""), Some("/"), Some(""), None); t!(s: Path::from_str(".."), Some(""), Some(".."), Some(""), None); t!(s: Path::from_str("../.."), Some(""), Some("../.."), Some(""), None); t!(s: Path::from_str("hi/there.txt"), Some("there.txt"), Some("hi"), Some("there"), Some("txt")); t!(s: Path::from_str("hi/there"), Some("there"), Some("hi"), Some("there"), None); t!(s: Path::from_str("hi/there."), Some("there."), Some("hi"), Some("there"), Some("")); t!(s: Path::from_str("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None); t!(s: Path::from_str("hi/..there"), Some("..there"), Some("hi"), Some("."), Some("there")); t!(s: Path::new(b!("a/b/", 0xff)), None, Some("a/b"), None, None); t!(s: Path::new(b!("a/b/", 0xff, ".txt")), None, Some("a/b"), None, Some("txt")); t!(s: Path::new(b!("a/b/c.", 0x80)), None, Some("a/b"), Some("c"), None); t!(s: Path::new(b!(0xff, "/b")), Some("b"), None, Some("b"), None); } #[test] fn test_dir_file_path() { t!(v: Path::new(b!("hi/there", 0x80)).dir_path(), b!("hi")); t!(v: Path::new(b!("hi", 0xff, "/there")).dir_path(), b!("hi", 0xff)); t!(s: Path::from_str("hi/there").dir_path(), "hi"); t!(s: Path::from_str("hi").dir_path(), "."); t!(s: Path::from_str("/hi").dir_path(), "/"); t!(s: Path::from_str("/").dir_path(), "/"); t!(s: Path::from_str("..").dir_path(), ".."); t!(s: Path::from_str("../..").dir_path(), "../.."); macro_rules! t( (s: $path:expr, $exp:expr) => ( { let path = $path; let left = path.and_then_ref(|p| p.as_str()); assert_eq!(left, $exp); } ); (v: $path:expr, $exp:expr) => ( { let path = $path; let left = path.map(|p| p.as_vec()); assert_eq!(left, $exp); } ) ) t!(v: Path::new(b!("hi/there", 0x80)).file_path(), Some(b!("there", 0x80))); t!(v: Path::new(b!("hi", 0xff, "/there")).file_path(), Some(b!("there"))); t!(s: Path::from_str("hi/there").file_path(), Some("there")); t!(s: Path::from_str("hi").file_path(), Some("hi")); t!(s: Path::from_str(".").file_path(), None); t!(s: Path::from_str("/").file_path(), None); t!(s: Path::from_str("..").file_path(), None); t!(s: Path::from_str("../..").file_path(), None); } #[test] fn test_is_absolute() { assert_eq!(Path::from_str("a/b/c").is_absolute(), false); assert_eq!(Path::from_str("/a/b/c").is_absolute(), true); assert_eq!(Path::from_str("a").is_absolute(), false); assert_eq!(Path::from_str("/a").is_absolute(), true); assert_eq!(Path::from_str(".").is_absolute(), false); assert_eq!(Path::from_str("/").is_absolute(), true); assert_eq!(Path::from_str("..").is_absolute(), false); assert_eq!(Path::from_str("../..").is_absolute(), false); } #[test] fn test_is_ancestor_of() { macro_rules! t( (s: $path:expr, $dest:expr, $exp:expr) => ( { let path = Path::from_str($path); let dest = Path::from_str($dest); assert_eq!(path.is_ancestor_of(&dest), $exp); } ) ) t!(s: "a/b/c", "a/b/c/d", true); t!(s: "a/b/c", "a/b/c", true); t!(s: "a/b/c", "a/b", false); t!(s: "/a/b/c", "/a/b/c", true); t!(s: "/a/b", "/a/b/c", true); t!(s: "/a/b/c/d", "/a/b/c", false); t!(s: "/a/b", "a/b/c", false); t!(s: "a/b", "/a/b/c", false); t!(s: "a/b/c", "a/b/d", false); t!(s: "../a/b/c", "a/b/c", false); t!(s: "a/b/c", "../a/b/c", false); t!(s: "a/b/c", "a/b/cd", false); t!(s: "a/b/cd", "a/b/c", false); t!(s: "../a/b", "../a/b/c", true); t!(s: ".", "a/b", true); t!(s: ".", ".", true); t!(s: "/", "/", true); t!(s: "/", "/a/b", true); t!(s: "..", "a/b", true); t!(s: "../..", "a/b", true); } #[test] fn test_path_relative_from() { macro_rules! t( (s: $path:expr, $other:expr, $exp:expr) => ( { let path = Path::from_str($path); let other = Path::from_str($other); let res = path.path_relative_from(&other); assert_eq!(res.and_then_ref(|x| x.as_str()), $exp); } ) ) t!(s: "a/b/c", "a/b", Some("c")); t!(s: "a/b/c", "a/b/d", Some("../c")); t!(s: "a/b/c", "a/b/c/d", Some("..")); t!(s: "a/b/c", "a/b/c", Some(".")); t!(s: "a/b/c", "a/b/c/d/e", Some("../..")); t!(s: "a/b/c", "a/d/e", Some("../../b/c")); t!(s: "a/b/c", "d/e/f", Some("../../../a/b/c")); t!(s: "a/b/c", "/a/b/c", None); t!(s: "/a/b/c", "a/b/c", Some("/a/b/c")); t!(s: "/a/b/c", "/a/b/c/d", Some("..")); t!(s: "/a/b/c", "/a/b", Some("c")); t!(s: "/a/b/c", "/a/b/c/d/e", Some("../..")); t!(s: "/a/b/c", "/a/d/e", Some("../../b/c")); t!(s: "/a/b/c", "/d/e/f", Some("../../../a/b/c")); t!(s: "hi/there.txt", "hi/there", Some("../there.txt")); t!(s: ".", "a", Some("..")); t!(s: ".", "a/b", Some("../..")); t!(s: ".", ".", Some(".")); t!(s: "a", ".", Some("a")); t!(s: "a/b", ".", Some("a/b")); t!(s: "..", ".", Some("..")); t!(s: "a/b/c", "a/b/c", Some(".")); t!(s: "/a/b/c", "/a/b/c", Some(".")); t!(s: "/", "/", Some(".")); t!(s: "/", ".", Some("/")); t!(s: "../../a", "b", Some("../../../a")); t!(s: "a", "../../b", None); t!(s: "../../a", "../../b", Some("../a")); t!(s: "../../a", "../../a/b", Some("..")); t!(s: "../../a/b", "../../a", Some("b")); } #[test] fn test_component_iter() { macro_rules! t( (s: $path:expr, $exp:expr) => ( { let path = Path::from_str($path); let comps = path.component_iter().to_owned_vec(); let exp: &[&str] = $exp; let exps = exp.iter().map(|x| x.as_bytes()).to_owned_vec(); assert_eq!(comps, exps); } ); (v: [$($arg:expr),+], [$([$($exp:expr),*]),*]) => ( { let path = Path::new(b!($($arg),+)); let comps = path.component_iter().to_owned_vec(); let exp: &[&[u8]] = [$(b!($($exp),*)),*]; assert_eq!(comps.as_slice(), exp); } ) ) t!(v: ["a/b/c"], [["a"], ["b"], ["c"]]); t!(v: ["/", 0xff, "/a/", 0x80], [[0xff], ["a"], [0x80]]); t!(v: ["../../foo", 0xcd, "bar"], [[".."], [".."], ["foo", 0xcd, "bar"]]); t!(s: "a/b/c", ["a", "b", "c"]); t!(s: "a/b/d", ["a", "b", "d"]); t!(s: "a/b/cd", ["a", "b", "cd"]); t!(s: "/a/b/c", ["a", "b", "c"]); t!(s: "a", ["a"]); t!(s: "/a", ["a"]); t!(s: "/", []); t!(s: ".", ["."]); t!(s: "..", [".."]); t!(s: "../..", ["..", ".."]); t!(s: "../../foo", ["..", "..", "foo"]); } } </ins>


is_ty_must_use(cx, boxed_ty, expr, span) .map(|inner| MustUsePath::Boxed(Box::new(inner))) } <ins> ty::Adt(def, args) if cx.tcx.lang_items().pin_type() == Some(def.did()) => { let pinned_ty = args.type_at(0); is_ty_must_use(cx, pinned_ty, expr, span) .map(|inner| MustUsePath::Pinned(Box::new(inner))) } </ins> ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { elaborate(


<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(dead_code)] enum FooMode { Check = 0x1001, } enum BarMode { Check = 0x2001, } enum Mode { Foo(FooMode), Bar(BarMode), } #[inline(never)] fn broken(mode: &Mode) -> u32 { for _ in 0..1 { if let Mode::Foo(FooMode::Check) = *mode { return 17 } if let Mode::Bar(BarMode::Check) = *mode { return 19 } } return 42; } fn main() { let mode = Mode::Bar(BarMode::Check); assert_eq!(broken(&mode), 19); } </ins>


<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[derive(Clone, Debug, PartialEq)] enum Expression { Dummy, Add(Box<Expression>), } use Expression::*; fn simplify(exp: Expression) -> Expression { match exp { Add(n) => *n.clone(), _ => Dummy } } fn main() { assert_eq!(simplify(Add(Box::new(Dummy))), Dummy); } </ins>


} } <del> //use private::Future; </del> <ins> #[cfg(imported)] use private::Future; </ins> fn bar(arg: Box<dyn private::Future>) { <ins> // Importing the trait means that we don't autoderef `Box<dyn Future>` </ins> arg.wait(); <del> //~^ ERROR the `wait` method cannot be invoked on a trait object </del> <ins> //[unimported]~^ ERROR the `wait` method cannot be invoked on a trait object </ins> } <del> fn main() { } </del> <ins> fn main() {} </ins>


InvocationKind::Derive { ref path, .. } => path.span, } } <ins> pub fn attr_id(&self) -> Option<ast::AttrId> { match self.kind { InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id), _ => None, } } </ins> } pub struct MacroExpander<'a, 'b:'a> {


} fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> { <del> let root = metadata.get_root(); if let Some(is_proc_macro) = self.is_proc_macro { if root.macro_derive_registrar.is_some() != is_proc_macro { return None; } } </del> let rustc_version = rustc_version(); <del> if root.rustc_version != rustc_version { </del> <ins> let found_version = metadata.get_rustc_version(); if found_version != rustc_version { </ins> info!("Rejecting via version: expected {} got {}", rustc_version, <del> root.rustc_version); </del> <ins> found_version); </ins> self.rejected_via_version.push(CrateMismatch { path: libpath.to_path_buf(), <del> got: root.rustc_version, </del> <ins> got: found_version, </ins> }); return None; } <ins> let root = metadata.get_root(); if let Some(is_proc_macro) = self.is_proc_macro { if root.macro_derive_registrar.is_some() != is_proc_macro { return None; } } </ins> if self.should_match_name { if self.crate_name != root.name { info!("Rejecting via crate name");


fn foo<'a>() -> &'a () { Hash([0; HASH_LEN]); init_hash(&mut [0; HASH_LEN]); <ins> let (_array,) = ([0; HASH_LEN],); </ins> &() }


<del> Subproject commit 732825dcff6d1f115225305ce5e0c9c9d876a0ff </del> <ins> Subproject commit e8642c7a2900bed28003a98d4db8b62290ac802f </ins>


<ins> error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 | LL |     f(data, identity) |     ^ implementation of `FnOnce` is not general enough | = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` error: aborting due to previous error </ins>


// stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. <del> #![warn(unused_parens)] </del> <ins> #![deny(unused_parens)] </ins> #![allow(unreachable_code)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not // the malformed `1 / (2 + 3` <del> let _a = (1 / (2 + 3)); </del> <ins> let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses </ins> f(); }


/// # Examples /// /// ``` <del> /// #![feature(mutex_unpoison)] /// </del> /// use std::sync::{Arc, RwLock}; /// use std::thread; ///


// FIXME(valtrees): check whether const qualifs should behave the same // way for type and mir constants. let uneval = match constant.literal { <del> ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None, </del> <ins> ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_)) => { None } </ins> ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c), ConstantKind::Unevaluated(uv, _) => Some(uv), ConstantKind::Val(..) => None,


} // At this point, we are calling a function, `callee`, whose `DefId` is known... if is_lang_panic_fn(tcx, callee) { self.check_op(ops::Panic); <ins> // const-eval of the `begin_panic` fn assumes the argument is `&str` if Some(callee) == tcx.lang_items().begin_panic_fn() { match args[0].ty(&self.ccx.body.local_decls, tcx).kind() { ty::Ref(_, ty, _) if ty.is_str() => (), _ => self.check_op(ops::PanicNonStr), } } </ins> return; }


let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![ proc_macro, bridge, client, proc_macro_ty, method, ])); <del> custom_derives.iter().map(|cd| { cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ cx.expr_str(cd.span, cd.trait_name), cx.expr_vec_slice( span, cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>() ), local_path(cd.span, cd.function_name), ]) }).chain(custom_attrs.iter().map(|ca| { cx.expr_call(span, proc_macro_ty_method_path(attr), vec![ cx.expr_str(ca.span, ca.function_name.name), local_path(ca.span, ca.function_name), ]) })).chain(custom_macros.iter().map(|cm| { cx.expr_call(span, proc_macro_ty_method_path(bang), vec![ cx.expr_str(cm.span, cm.function_name.name), local_path(cm.span, cm.function_name), ]) })).collect() </del> <ins> macros.iter().map(|m| { match m { ProcMacro::Derive(cd) => { cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![ cx.expr_str(cd.span, cd.trait_name), cx.expr_vec_slice( span, cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>() ), local_path(cd.span, cd.function_name), ]) }, ProcMacro::Def(ca) => { let ident = match ca.def_type { ProcMacroDefType::Attr => attr, ProcMacroDefType::Bang => bang }; cx.expr_call(span, proc_macro_ty_method_path(ident), vec![ cx.expr_str(ca.span, ca.function_name.name), local_path(ca.span, ca.function_name), ]) } } }).collect() </ins> }; let decls_static = cx.item_static(


} } <ins> fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] { vec::map(libs, |a| get_absolute_rpath(a) ) } pub fn get_absolute_rpath(lib: &Path) -> Path { os::make_absolute(lib).dir_path() } </ins> #[cfg(stage0)] pub fn get_install_prefix_rpath(target_triple: &str) -> Path { let install_prefix = env!("CFG_PREFIX");


let attrs = self.parse_inner_attributes()?; let post_attr_lo = self.token.span; <del> let mut items = ThinVec::new(); while let Some(item) = self.parse_item(ForceCollect::No)? { self.maybe_consume_incorrect_semicolon(Some(&item)); </del> <ins> let mut items: ThinVec<P<_>> = ThinVec::new(); // There shouldn't be any stray semicolons before or after items. // `parse_item` consumes the appropriate semicolons so any leftover is an error. loop { while self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {} // Eat all bad semicolons let Some(item) = self.parse_item(ForceCollect::No)? else { break; }; </ins> items.push(item); }


# use this rustfmt binary instead as the stage0 snapshot rustfmt. #rustfmt = "/path/to/rustfmt" <ins> # Instead of downloading the src/stage0 version of cargo-clippy specified, # use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy. # # Note that this option should be used with the same toolchain as the `rustc` option above. # Otherwise, clippy is likely to fail due to a toolchain conflict. #cargo-clippy = "/path/to/cargo-clippy" </ins> # Whether to build documentation by default. If false, rustdoc and # friends will still be compiled but they will not be used to generate any # documentation.


LL |         y.foo(); |         ^ value used here after move <del> error[E0382]: use of moved value: `*x` </del> <ins> error[E0382]: use of moved value: `x` </ins> --> $DIR/double-move.rs:45:9 | LL |         let _y = *x; |                  -- value moved here LL |         x.foo(); <del> |         ^ value used here after move </del> <ins> |         ^ value used here after partial move </ins> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait error[E0382]: use of moved value: `*x` --> $DIR/double-move.rs:51:18 | <ins> LL |         let x = "hello".to_owned().into_boxed_str(); |             - move occurs because `x` has type `std::boxed::Box<str>`, which does not implement the `Copy` trait </ins> LL |         x.foo(); |         - value moved here LL |         let _y = *x; |                  ^^ value used here after move <del> | = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait </del> error: aborting due to 6 previous errors


# Complete! <del> At this point, you have successfully built the Guessing Game! Congratulations! </del> <ins> This project showed you a lot: `let`, `match`, methods, associated functions, using external crates, and more. </ins> <del> This first project showed you a lot: `let`, `match`, methods, associated functions, using external crates, and more. Our next project will show off even more. </del> <ins> At this point, you have successfully built the Guessing Game! Congratulations! </ins>


LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod) { report_fatal_error("ThinLTO not available"); } <ins> extern "C" void LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) { report_fatal_error("ThinLTO not available"); } </ins> #endif // LLVM_VERSION_GE(4, 0)


(&self_ty.kind, parent_pred) { if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind { <del> let id = self.tcx.hir().as_local_hir_id(def.did).unwrap(); let node = self.tcx.hir().get(id); </del> <ins> let node = self .tcx .hir() .as_local_hir_id(def.did) .map(|id| self.tcx.hir().get(id)); </ins> match node { <del> hir::Node::Item(hir::Item { kind, .. }) => { </del> <ins> Some(hir::Node::Item(hir::Item { kind, .. })) => { </ins> if let Some(g) = kind.generics() { let key = match &g.where_clause.predicates[..] { [.., pred] => {


/// Unix-specific extensions to `Permissions` #[stable(feature = "fs_ext", since = "1.1.0")] pub trait PermissionsExt { <del> /// Returns the underlying raw `mode_t` bits that are the standard Unix /// permissions for this file. </del> <ins> /// Returns the underlying raw `st_mode` bits that contain the standard /// Unix permissions for this file. </ins> /// /// # Examples ///


let ty::CoroutineClosure(_, parent_args) = *tcx.type_of(parent_def_id).instantiate_identity().kind() else { <del> bug!(); </del> <ins> bug!("coroutine's parent was not a coroutine-closure"); </ins> }; if parent_args.references_error() { return coroutine_def_id.to_def_id();


/// Sets the platform-specific value of errno #[cfg(all(not(target_os = "linux"), not(target_os = "dragonfly")))] // needed for readdir and syscall! <ins> #[allow(dead_code)] // but not all target cfgs actually end up using it </ins> pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } }


assert!(rows.iter().all(|r| r.len() == v.len())); <del> // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476). let ty = matrix.heads().next().map_or(v.head().ty(), |r| r.ty()); </del> <ins> let ty = v.head().ty(); </ins> let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty); let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };


let mut out = output.stderr.clone(); out.extend(&output.stdout); let out = String::from_utf8_lossy(&out); <ins> // Check to see if the link failed with "unrecognized command line option: // '-no-pie'" for gcc or "unknown argument: '-no-pie'" for clang. If so, // reperform the link step without the -no-pie option. This is safe because // if the linker doesn't support -no-pie then it should not default to // linking executables as pie. Different versions of gcc seem to use // different quotes in the error message so don't check for them. if sess.target.target.options.linker_is_gnu && (out.contains("unrecognized command line option") || out.contains("unknown argument")) && out.contains("-no-pie") && cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") { info!("linker output: {:?}", out); warn!("Linker does not support -no-pie command line option. Retrying without."); for arg in cmd.take_args() { if arg.to_string_lossy() != "-no-pie" { cmd.arg(arg); } } info!("{:?}", &cmd); continue; } if !retry_on_segfault || i > 3 { break } </ins> let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11"; let msg_bus  = "clang: error: unable to execute command: Bus error: 10"; if !(out.contains(msg_segv) || out.contains(msg_bus)) {


| LL |     let Alias::Braced = panic!(); |         ^^^^^^^^^^^^^ not a unit struct, unit variant or constant <ins> | help: use the struct variant pattern syntax | LL |     let Alias::Braced {} = panic!(); |                       ++ </ins> error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced` --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 | LL |     let Alias::Braced(..) = panic!(); |         ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant <ins> | help: use the struct variant pattern syntax | LL |     let Alias::Braced {} = panic!(); |                       ~~ </ins> error[E0618]: expected function, found enum variant `Alias::Unit` --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5


<ins> // run-rustfix struct Foo { first: Bar, _second: u32, _third: u32, } struct Bar { bar: C, } struct C { c: D, } struct D { test: E, } struct E { _e: F, } struct F { _f: u32, } fn main() { let f = F { _f: 6 }; let e = E { _e: f }; let d = D { test: e }; let c = C { c: d }; let bar = Bar { bar: c }; let fooer = Foo { first: bar, _second: 4, _third: 5 }; let _test = &fooer.first.bar.c; //~^ ERROR no field let _test2 = fooer.first.bar.c.test; //~^ ERROR no field } </ins>


// the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. <ins> let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque; </ins> if approx_env_bounds.is_empty() && trait_bounds.is_empty() <del> && (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque) </del> <ins> && (alias_ty.needs_infer() || is_opaque) </ins> { debug!("no declared bounds"); <del> self.substs_must_outlive(alias_ty.substs, origin, region); </del> <ins> let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id)); self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances); </ins> return; }


[stackoverflow]: http://stackoverflow.com/questions/tagged/rust This installer also installs a copy of the documentation locally, so we can <del> read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. On Windows, it's in a `share/doc` directory, inside the directory to which Rust was installed. </del> <ins> read it offline. It's only a `rustup doc` away! </ins> # Hello, world!


.emit(); } let key = BindingKey::new(target, ns); <del> let mut resolution = this.resolution(parent, key).borrow_mut(); resolution.single_imports.remove(&Interned::new_unchecked(import)); </del> <ins> this.update_resolution(parent, key, |_, resolution| { resolution.single_imports.remove(&Interned::new_unchecked(import)); }); </ins> } } }


<ins> - // MIR for `call` before Inline + // MIR for `call` after Inline fn call(_1: &T) -> TypeId { debug s => _1; let mut _0: std::any::TypeId; let mut _2: &T; bb0: { StorageLive(_2); _2 = &(*_1); _0 = <T as Any>::type_id(move _2) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_2); return; } } </ins>


debug!(?closure_sig); <del> // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is </del> <ins> // NOTE: The self-type is an unboxed closure type and hence is </ins> // in fact unparameterized (or at least does not reference any <del> // regions bound in the obligation). Still probably some // refactoring could make this nicer. </del> <ins> // regions bound in the obligation). let self_ty = obligation .predicate .self_ty() .no_bound_vars() .expect("unboxed closure type should not capture bound vars from the predicate"); </ins> closure_trait_ref_and_return_type( self.tcx(), obligation.predicate.def_id(), <del> obligation.predicate.skip_binder().self_ty(), // (1) </del> <ins> self_ty, </ins> closure_sig, util::TupleArgumentsFlag::No, )


<ins> #![feature(doc_cfg)] #![feature(no_core)] #![crate_name = "foo"] #![no_core] // @has 'foo/index.html' // @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'foobar' // @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'bar' #[doc(cfg(feature = "foobar"))] mod imp_priv { // @has 'foo/struct.BarPriv.html' // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]'  //    'Available on crate feature foobar only.' pub struct BarPriv {} impl BarPriv { pub fn test() {} } } #[doc(cfg(feature = "foobar"))] pub use crate::imp_priv::*; pub mod bar { // @has 'foo/bar/struct.Bar.html' // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]'  //    'Available on crate feature bar only.' #[doc(cfg(feature = "bar"))] pub struct Bar; } #[doc(cfg(feature = "bar"))] pub use bar::Bar; </ins>


<ins> #![feature(return_position_impl_trait_in_trait)] trait Extend { fn extend(_: &str) -> (impl Sized + '_, &'static str); } impl Extend for () { fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { //~^ ERROR in type `&'static &()`, reference has a longer lifetime than the data it references (None, s) } } // This indirection is not necessary for reproduction, // but it makes this test future-proof against #114936. fn extend<T: Extend>(s: &str) -> &'static str { <T as Extend>::extend(s).1 } fn main() { let use_after_free = extend::<()>(&String::from("temporary")); println!("{}", use_after_free); } </ins>


setTimeout(() => { window.location.replace("#" + item.id); }, 0); <ins> return true; </ins> } }, ); <del> } </del> <ins> }); </ins> } } }


<ins> error[E0308]: mismatched types --> $DIR/str-as-char-non-lit.rs:6:19 | LL |     let _: &str = ('a'); |            ----   ^^^^^ expected `&str`, found `char` |            | |            expected due to this error[E0308]: mismatched types --> $DIR/str-as-char-non-lit.rs:8:19 | LL |     let _: &str = token(); |            ----   ^^^^^^^ expected `&str`, found `char` |            | |            expected due to this error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. </ins>


<ins> //! Normalizes MIR in RevealAll mode. use crate::MirPass; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RevealAll; impl<'tcx> MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // This pass must run before inlining, since we insert callee bodies in RevealAll mode. // Do not apply this transformation to generators. if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx)) && body.generator.is_none() { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); RevealAllVisitor { tcx, param_env }.visit_body(body); } } } struct RevealAllVisitor<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, } impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } #[inline] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { *ty = self.tcx.normalize_erasing_regions(self.param_env, ty); } #[inline] fn process_projection_elem( &mut self, elem: PlaceElem<'tcx>, _: Location, ) -> Option<PlaceElem<'tcx>> { match elem { PlaceElem::Field(field, ty) => { let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty); if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } } // None of those contain a Ty. PlaceElem::Index(..) | PlaceElem::Deref | PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. } | PlaceElem::Downcast(..) => None, } } } </ins>


<ins> //@ check-pass #![deny(rustdoc::redundant_explicit_links)] mod bar { /// [`Rc`](std::rc::Rc) pub enum Baz {} } pub use bar::*; use std::rc::Rc; /// [`Rc::allocator`] [foo](std::rc::Rc) pub fn winit_runner() {} </ins>


impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); let impl_ty_value = tcx.type_of(impl_ty.def_id); <del> // Map the predicate from the trait to the corresponding one for the impl. // For example: </del> <ins> let param_env = tcx.param_env(impl_ty.def_id); // When checking something like </ins> // <del> // trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; } // impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; } </del> <ins> // trait X { type Y: PartialEq<<Self as X>::Y> } // impl X for T { default type Y = S; } </ins> // <del> // For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this // function would translate and partially normalize // `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`. let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| { tcx.mk_substs( iter::once(impl_ty_value.into()) .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))), ) </del> <ins> // We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case // we want <T as X>::Y to normalize to S. This is valid because we are // checking the default value specifically here. Add this equality to the // ParamEnv for normalization specifically. let normalize_param_env = { let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>(); predicates.push( ty::Binder::dummy(ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { item_def_id: trait_ty.def_id, substs: rebased_substs, }, ty: impl_ty_value, }) .to_predicate(tcx), ); ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing, None) </ins> }; tcx.infer_ctxt().enter(move |infcx| {


TypeLimits, MissingDoc, MissingDebugImplementations, <ins> ExternCrate, </ins> ); add_lint_group!(sess,


sess.abort_if_errors() } } <del> a.add_file(&bc, false); </del> <ins> a.add_file(&bc_deflated, false); remove(sess, &bc_deflated); </ins> if !sess.opts.cg.save_temps && !sess.opts.output_types.contains(&OutputTypeBitcode) { remove(sess, &bc);


/// assert_eq!(&l_ptr[..2], "0x"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] <ins> #[rustc_diagnostic_item = "pointer_trait"] </ins> pub trait Pointer { /// Formats the value using the given formatter. #[stable(feature = "rust1", since = "1.0.0")] <ins> #[rustc_diagnostic_item = "pointer_trait_fmt"] </ins> fn fmt(&self, f: &mut Formatter<'_>) -> Result; }


<ins> // Issue #117720 #![feature(let_chains)] fn main() { if let () = () && let () = (); //~ERROR && let () = () { } } fn foo() { if let () = () && () == (); //~ERROR && 1 < 0 { } } fn bar() { if let () = () && () == (); //~ERROR && let () = () { } } </ins>


} fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { <ins> use middle::ty::TypeVariants::{TyEnum, TyStruct}; // If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar` self.tcx.tables.borrow().item_substs.get(id) .and_then(|substs| substs.substs.self_ty()) .map(|ty| match ty.sty { TyEnum(tyid, _) | TyStruct(tyid, _) => self.check_def_id(tyid.did), _ => (), }); </ins> self.tcx.def_map.borrow().get(id).map(|def| { match def.full_def() { def::DefConst(_) | def::DefAssociatedConst(..) => {


// Finally we construct the actual value of the associated type. let term = match assoc_def.item.kind { ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()), <del> ty::AssocKind::Const => bug!("associated const projection is not supported yet"), </del> <ins> ty::AssocKind::Const => { if tcx.features().associated_const_equality { bug!("associated const projection is not supported yet") } else { ty::EarlyBinder::bind( ty::Const::new_error_with_message( tcx, tcx.type_of(assoc_def.item.def_id).instantiate_identity(), DUMMY_SP, "associated const projection is not supported yet", ) .into(), ) } } </ins> ty::AssocKind::Fn => unreachable!("we should never project to a fn"), };


that warns about any item named `lintme`. ```rust,ignore (requires-stage-2) <del> #![feature(box_syntax, rustc_private)] </del> <ins> #![feature(rustc_private)] </ins> extern crate rustc_ast;


} } <ins> fn foreign_item_scope_tag(item: &hir::ForeignItem<'_>) -> &'static str { match item.kind { hir::ForeignItemKind::Fn(..) => "method body", hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => "associated item", } } </ins> fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option<Span>) { let lo = tcx.sess.source_map().lookup_char_pos(span.lo()); (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))


.map(|r| VerifyBound::OutlivedBy(r)); // see the extensive comment in projection_must_outlive <del> let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); let recursive_bound = self.recursive_bound(ty.into(), visited); </del> <ins> let recursive_bound = { let mut components = smallvec![]; let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs); compute_components_recursive(self.tcx, ty.into(), &mut components, visited); self.bound_from_components(&components, visited) }; </ins> VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound) } <del> fn recursive_bound( </del> <ins> fn bound_from_components( </ins> &self, <del> parent: GenericArg<'tcx>, </del> <ins> components: &[Component<'tcx>], </ins> visited: &mut SsoHashSet<GenericArg<'tcx>>, ) -> VerifyBound<'tcx> { <del> let mut bounds = parent .walk_shallow(visited) .filter_map(|child| match child.unpack() { GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)), GenericArgKind::Lifetime(lt) => { // Ignore late-bound regions. if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None } } GenericArgKind::Const(_) => Some(self.recursive_bound(child, visited)), }) </del> <ins> let mut bounds = components .iter() .map(|component| self.bound_from_single_component(component, visited)) </ins> .filter(|bound| { // Remove bounds that must hold, since they are not interesting. !bound.must_hold()


<ins> error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20 | LL |     assert_is_send(&bar); |                    ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely ... LL | fn assert_is_send<T: Send>(_: &T) {} |                      ---- required by this bound in `assert_is_send` | = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar` help: introduce a type parameter with a trait bound instead of using `impl Trait` | LL | async fn run<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send { |             ^^^^^^^^              ^                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20 | LL |     assert_is_send(&bar); |                    ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely ... LL | fn assert_is_send<T: Send>(_: &T) {} |                      ---- required by this bound in `assert_is_send` | = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar` help: introduce a type parameter with a trait bound instead of using `impl Trait` | LL | async fn run2<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send { |              ^^^^^^^^              ^                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. </ins>


check_expr(fcx, &**idx); let raw_base_t = fcx.expr_ty(&**base); let idx_t = fcx.expr_ty(&**idx); <del> if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) { </del> <ins> if ty::type_is_error(raw_base_t) { </ins> fcx.write_ty(id, raw_base_t); <del> } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) { </del> <ins> } else if ty::type_is_error(idx_t) { </ins> fcx.write_ty(id, idx_t); } else { let (_, autoderefs, field_ty) = autoderef(fcx, expr.span, raw_base_t, Some(base.id), lvalue_pref, |base_t, _| ty::index(base_t)); match field_ty { <del> Some(ty) => { </del> <ins> Some(ty) if !ty::type_is_bot(ty) => { </ins> check_expr_has_type(fcx, &**idx, ty::mk_uint()); fcx.write_ty(id, ty); fcx.write_autoderef_adjustment(base.id, base.span, autoderefs); } <del> None => { </del> <ins> _ => { </ins> // This is an overloaded method. let base_t = structurally_resolved_type(fcx, expr.span,


path = self.parse_path(PathStyle::Type)?; path_span = path_lo.to(self.prev_span); } else { <del> path = ast::Path { segments: Vec::new(), span: DUMMY_SP }; </del> path_span = self.span.to(self.span); <ins> path = ast::Path { segments: Vec::new(), span: path_span }; </ins> } // See doc comment for `unmatched_angle_bracket_count`.


res } <ins> // Clears (and restores) the `in_scope_lifetimes` field. Used when // visiting nested items, which never inherit in-scope lifetimes // from their surrounding environment. fn without_in_scope_lifetime_defs<T>( &mut self, f: impl FnOnce(&mut LoweringContext<'_>) -> T, ) -> T { let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]); // this vector is only used when walking over impl headers, // input types, and the like, and should not be non-empty in // between items assert!(self.lifetimes_to_define.is_empty()); let res = f(self); assert!(self.in_scope_lifetimes.is_empty()); self.in_scope_lifetimes = old_in_scope_lifetimes; res } </ins> pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner,


} pub fn is(&self, mode: mode_t) -> bool { <del> self.mode & libc::S_IFMT == mode </del> <ins> self.masked() == mode } fn masked(&self) -> mode_t { self.mode & libc::S_IFMT </ins> } }


<ins> error: pattern on wrong side of `@` --> $DIR/intersection-patterns.rs:13:9 | LL |         Some(x) @ y => {} |         -------^^^- |         |         | |         |         binding on the right, should be on the left |         pattern on the left, should be on the right |         help: switch the order: `y @ Some(x)` error: left-hand side of `@` must be a binding --> $DIR/intersection-patterns.rs:23:9 | LL |         Some(x) @ Some(y) => {} |         -------^^^------- |         |         | |         |         also a pattern |         interpreted as a pattern, not a binding | = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` error: pattern on wrong side of `@` --> $DIR/intersection-patterns.rs:32:9 | LL |         1 ..= 5 @ e => {} |         -------^^^- |         |         | |         |         binding on the right, should be on the left |         pattern on the left, should be on the right |         help: switch the order: `e @ 1 ..=5` error: aborting due to 3 previous errors </ins>


def::DefVariant(_, variant_id, _) => { for field in fields { self.check_field(expr.span, variant_id, <del> NamedField(field.ident.node)); </del> <ins> NamedField(field.ident.node.name)); </ins> } } _ => self.tcx.sess.span_bug(expr.span,


self.opts.debugging_opts.print_enum_sizes } pub fn nonzeroing_move_hints(&self) -> bool { <del> !self.opts.debugging_opts.disable_nonzeroing_move_hints </del> <ins> self.opts.debugging_opts.enable_nonzeroing_move_hints </ins> } pub fn sysroot<'a>(&'a self) -> &'a Path { match self.opts.maybe_sysroot {


format!("*{}", code) }; return Some(( <del> sp, </del> <ins> expr.span, </ins> message, suggestion, Applicability::MachineApplicable,


// Encode the command and arguments in a command line string such // that the spawned process may recover them using CommandLineToArgvW. let mut cmd: Vec<u16> = Vec::new(); <ins> // CreateFileW has special handling for .bat and .cmd files, which means we // need to add an extra pair of quotes surrounding the whole command line // so they are properly passed on to the script. // See issue #91991. let is_batch_file = Path::new(prog) .extension() .map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat")) .unwrap_or(false); if is_batch_file { cmd.push(b'"' as u16); } </ins> // Always quote the program name so CreateProcess doesn't interpret args as // part of the name if the binary wasn't found first time. append_arg(&mut cmd, prog, Quote::Always)?;


<ins> // revisions: explicit implicit //[implicit] check-pass #![forbid(coherence_leak_check)] #![feature(negative_impls, with_negative_coherence)] pub trait Marker {} #[cfg(implicit)] impl<T: ?Sized> !Marker for &T {} #[cfg(explicit)] impl<'a, T: ?Sized + 'a> !Marker for &'a T {} trait FnMarker {} // Unifying these two impls below results in a `T: '!0` obligation // that we shouldn't need to care about. Ideally, we'd treat that // as an assumption when proving `&'!0 T: Marker`... impl<T: ?Sized + Marker> FnMarker for fn(T) {} impl<T: ?Sized> FnMarker for fn(&T) {} //[explicit]~^ ERROR conflicting implementations of trait `FnMarker` for type `fn(&_)` //[explicit]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! fn main() {} </ins>


// on the GAT itself. for (region_b, region_b_idx) in &regions { // Again, skip `'static` because it outlives everything. Also, we trivially <del> // know that a region outlives itself. if ty::ReStatic == **region_b || region_a == region_b { </del> <ins> // know that a region outlives itself. Also ignore `ReError`, to avoid // knock-down errors. if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b { </ins> continue; } if region_known_to_outlive(


35 |     #[unstable = "1200"] impl S { } |     ^^^^^^^^^^^^^^^^^^^^ <del> error: aborting due to 9 previous errors </del> <ins> error: aborting due to 8 previous errors </ins>


"byteorder", "cargo_metadata 0.9.1", "colored", <del> "compiletest_rs", </del> <ins> "compiletest_rs 0.4.0", </ins> "directories", "env_logger 0.7.1", "getrandom",


let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); <del> this.arena.alloc(this.expr(span, expr_break, ThinVec::new())) </del> <ins> this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new())) </ins> }); self.arm(ready_pat, break_x) };


use std::mem; use crate::errors::{ <del> ChangeFieldsToBeOfUnitType, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment, </del> <ins> ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment, </ins> }; // Any local node that may call something in its body block should be


// A rest pattern `..`. self.bump(); // `..` PatKind::Rest <ins> } else if self.check(&token::DotDotDot) && !self.is_pat_range_end_start(1) { self.recover_dotdotdot_rest_pat(lo) </ins> } else if let Some(form) = self.parse_range_end() { self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`. } else if self.eat_keyword(kw::Underscore) {


unsafe { let mut fds = [0, 0]; <del> // Like above, see if we can set cloexec atomically #[cfg(target_os = "linux")] { match cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr())) { Ok(_) => { return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1])))); } Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {} Err(e) => return Err(e), </del> <ins> cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { // Like above, set cloexec atomically cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?; Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1])))) } else { cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?; let a = FileDesc::new(fds[0]); let b = FileDesc::new(fds[1]); a.set_cloexec()?; b.set_cloexec()?; Ok((Socket(a), Socket(b))) </ins> } } <del> cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?; let a = FileDesc::new(fds[0]); let b = FileDesc::new(fds[1]); a.set_cloexec()?; b.set_cloexec()?; Ok((Socket(a), Socket(b))) </del> } }


<ins> error[E0309]: the parameter type `T` may not live long enough --> $DIR/min-choice-reject-ambiguous.rs:17:5 | LL |     type_test::<'_, T>() // This should pass if we pick 'b. |     ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | LL |     T: 'b + 'a, |           ++++ error[E0309]: the parameter type `T` may not live long enough --> $DIR/min-choice-reject-ambiguous.rs:28:5 | LL |     type_test::<'_, T>() // This should pass if we pick 'c. |     ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound... | LL |     T: 'c + 'a, |           ++++ error[E0700]: hidden type for `impl Cap<'b> + Cap<'c>` captures lifetime that does not appear in bounds --> $DIR/min-choice-reject-ambiguous.rs:39:5 | LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> |                   -- hidden type `&'a u8` captures the lifetime `'a` as defined here ... LL |     s |     ^ | help: to declare that `impl Cap<'b> + Cap<'c>` captures `'a`, you can add an explicit `'a` lifetime bound | LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> + 'a |                                                                    ++++ error: aborting due to 3 previous errors Some errors have detailed explanations: E0309, E0700. For more information about an error, try `rustc --explain E0309`. </ins>


<ins> // This is a non-regression test for issue #117146, where NLL and `-Zpolonius=next` computed // different loan scopes when a region flowed into an SCC whose representative was an existential // region. // revisions: nll polonius // [polonius] compile-flags: -Zpolonius=next fn main() { let a = (); let b = |_| &a; //[nll]~^ ERROR `a` does not live long enough //[polonius]~^^ ERROR `a` does not live long enough bad(&b); //[nll]~^ ERROR implementation of `Fn` //[nll]~| ERROR implementation of `FnOnce` //[polonius]~^^^ ERROR implementation of `Fn` //[polonius]~| ERROR implementation of `FnOnce` } fn bad<F: Fn(&()) -> &()>(_: F) {} </ins>


Some((ident.name, ns)), ) } <ins> /// Construct the list of in-scope lifetime parameters for async lowering. /// We include all lifetime parameters, either named or "Fresh". /// The order of those parameters does not matter, as long as it is /// deterministic. fn record_lifetime_params_for_async( &mut self, fn_id: NodeId, async_node_id: Option<(NodeId, Span)>, ) { if let Some((async_node_id, _)) = async_node_id { let mut extra_lifetime_params = self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); for rib in self.lifetime_ribs.iter().rev() { extra_lifetime_params.extend( rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)), ); match rib.kind { LifetimeRibKind::Item => break, LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) { extra_lifetime_params.extend(earlier_fresh); } } _ => {} } } self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); } } </ins> } struct LifetimeCountVisitor<'a, 'b> {


fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVector<P<ast::Item>>> { let mut ret = SmallVector::zero(); <del> loop { </del> <ins> while self.p.token != token::Eof { </ins> match self.p.parse_item_with_outer_attributes() { Some(item) => ret.push(item), <del> None => break </del> <ins> None => self.p.span_fatal( self.p.span, &format!("expected item, found `{}`", self.p.this_token_to_string())[] ) </ins> } } Some(ret)


self.tcx().mk_region(ReScope(lub)) } <del> (&ReEarlyBound(_), &ReEarlyBound(_) | &ReFree(_)) | (&ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => { </del> <ins> (&ReEarlyBound(_) | &ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => { </ins> self.region_rels.lub_free_regions(a, b) }


<ins> error[E0277]: the trait bound `K: Hash` is not satisfied --> $DIR/bad-index-due-to-nested.rs:20:5 | LL |     map[k] |     ^^^ the trait `Hash` is not implemented for `K` | note: required by a bound in `<HashMap<K, V> as Index<&K>>` --> $DIR/bad-index-due-to-nested.rs:9:8 | LL |     K: Hash, |        ^^^^ required by this bound in `<HashMap<K, V> as Index<&K>>` help: consider restricting type parameter `K` | LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { |               +++++++++++++++++ error[E0277]: the trait bound `V: Copy` is not satisfied --> $DIR/bad-index-due-to-nested.rs:20:5 | LL |     map[k] |     ^^^ the trait `Copy` is not implemented for `V` | note: required by a bound in `<HashMap<K, V> as Index<&K>>` --> $DIR/bad-index-due-to-nested.rs:10:8 | LL |     V: Copy, |        ^^^^ required by this bound in `<HashMap<K, V> as Index<&K>>` help: consider restricting type parameter `V` | LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V { |                  +++++++++++++++++++ error[E0308]: mismatched types --> $DIR/bad-index-due-to-nested.rs:20:9 | LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { |              - this type parameter LL |     map[k] |         ^ |         | |         expected `&K`, found type parameter `K` |         help: consider borrowing here: `&k` | = note:   expected reference `&K` found type parameter `K` error[E0308]: mismatched types --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { |                 - this type parameter               ----- expected `&'a V` because of return type LL |     map[k] |     ^^^^^^ |     | |     expected `&V`, found type parameter `V` |     help: consider borrowing here: `&map[k]` | = note:   expected reference `&'a V` found type parameter `V` error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. </ins>


<ins> // #124563 use std::marker::PhantomData; pub trait Trait {} pub trait Foo { type Trait: Trait; type Bar: Bar; fn foo(&mut self); } pub struct FooImpl<'a, 'b, A: Trait>(PhantomData<&'a &'b A>); impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T> where T: Trait, { type Trait = T; type Bar = BarImpl<'a, 'b, T>; //~ ERROR lifetime bound not satisfied fn foo(&mut self) { self.enter_scope(|ctx| { //~ ERROR lifetime may not live long enough BarImpl(ctx); //~ ERROR lifetime may not live long enough }); } } impl<'a, 'b, T> FooImpl<'a, 'b, T> where T: Trait, { fn enter_scope(&mut self, _scope: impl FnOnce(&mut Self)) {} } pub trait Bar { type Foo: Foo; } pub struct BarImpl<'a, 'b, T: Trait>(&'b mut FooImpl<'a, 'b, T>); impl<'a, 'b, T> Bar for BarImpl<'a, 'b, T> where T: Trait, { type Foo = FooImpl<'a, 'b, T>; } fn main() {} </ins>


<ins> // This test is a regression test for #34792 // check-pass pub struct A; pub struct B; pub trait Foo { type T: PartialEq<A> + PartialEq<B>; } pub fn generic<F: Foo>(t: F::T, a: A, b: B) -> bool { t == a && t == b } pub fn main() {} </ins>


return; } <ins> // #90113: Do not count an inaccessible reexported item as a candidate. if let NameBindingKind::Import { binding, .. } = name_binding.kind { if this.is_accessible_from(binding.vis, parent_scope.module) && !this.is_accessible_from(name_binding.vis, parent_scope.module) { return; } } </ins> // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving if ident.name == lookup_ident.name


hir_typeck_convert_to_str = try converting the passed type into a `&str` <ins> hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private </ins> hir_typeck_expected_default_return_type = expected `()` because of default return type hir_typeck_expected_return_type = expected `{$expected}` because of return type


<ins> //@ run-pass // Tests against a regression surfaced by crater in https://github.com/rust-lang/rust/issues/125193 // Unwind Safety is not a very coherent concept, but we'd prefer no regressions until we kibosh it // and this is an unstable feature anyways sooo... use std::panic::UnwindSafe; use std::task::Context; fn unwind_safe<T: UnwindSafe>() {} fn main() { unwind_safe::<Context<'_>>(); // test UnwindSafe unwind_safe::<&Context<'_>>(); // test RefUnwindSafe } </ins>


<ins> #![feature(half_open_range_patterns)] fn main() { match [1, 2] { [a.., a] => {} //~ ERROR cannot find value `a` in this scope } } </ins>


//! The various pretty-printing routines. <ins> use crate::session_diagnostics::UnprettyDumpFail; </ins> use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_errors::ErrorGuaranteed;


_ => unreachable!(), }; <del> write_or_print(&out, ofile); </del> <ins> write_or_print(&out, ofile, tcx.sess); </ins> } // In an ideal world, this would be a public function called by the driver after


<ins> // check-pass #![feature(generic_associated_types)] pub trait Foo { type Assoc<'c>; fn function() -> for<'x> fn(Self::Assoc<'x>); } fn main() {} </ins>


// Confirm the `type Output: Sized;` bound that is present on `FnOnce` let cause = obligation.derived_cause(BuiltinDerivedObligation); <del> // The binder on the Fn obligation is "less" important than the one on // the signature, as evidenced by how we treat it during projection. // The safe thing to do here is to liberate it, though, which should // have no worse effect than skipping the binder here. let liberated_fn_ty = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty)); let output_ty = self .infcx .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output()); </del> <ins> let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output()); </ins> let output_ty = normalize_with_depth_to( self, obligation.param_env,


use syntax_pos::symbol::Symbol; use rustc::session::Session; use rustc::session::config::PrintRequest; <ins> use rustc_data_structures::fx::FxHashSet; </ins> use rustc_target::spec::{MergeFunctions, PanicStrategy}; use libc::c_int; use std::ffi::CString;


<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // aux-build:issue-11908-1.rs // ignore-android this test is incompatible with the android test runner // error-pattern: multiple dylib candidates for `collections` found // This test ensures that if you have the same rlib or dylib at two locations // in the same path that you don't hit an assertion in the compiler. // // Note that this relies on `libcollections` to be in the path somewhere else, // and then our aux-built libraries will collide with libcollections (they have // the same version listed) extern crate collections; fn main() {} </ins>


<ins> error[E0284]: type annotations needed: cannot satisfy `<Bar as Foo>::T == ()` --> $DIR/coherence-constrained.rs:14:5 | LL |     async fn foo(&self) {} |     ^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Bar as Foo>::T == ()` error[E0284]: type annotations needed: cannot satisfy `<Bar as Foo>::T == ()` --> $DIR/coherence-constrained.rs:22:5 | LL |     async fn foo(&self) {} |     ^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Bar as Foo>::T == ()` error[E0119]: conflicting implementations of trait `Foo` for type `Bar` --> $DIR/coherence-constrained.rs:18:1 | LL | impl Foo for Bar { | ---------------- first implementation here ... LL | impl Foo for Bar { | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar` error: aborting due to 3 previous errors Some errors have detailed explanations: E0119, E0284. For more information about an error, try `rustc --explain E0119`. </ins>


pub static G: fn() = G0; pub static H: &(dyn Fn() + Sync) = &h; pub static I: fn() = Helper(j).mk(); <ins> pub static K: fn() -> fn() = { #[inline(never)] fn k() {} #[inline(always)] || -> fn() { k } }; </ins> static X: u32 = 42; static G0: fn() = g;


<ins> fn main() {} #[cfg(FALSE)] fn container() { const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } //~^ ERROR expected `fn` //~| ERROR `const extern fn` definitions are unstable } </ins>


} } <ins> #[doc(hidden)] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> { unsafe { let mut v = Vec::with_capacity(n); let mut ptr = v.as_mut_ptr(); // Write all elements except the last one for i in 1..n { ptr::write(ptr, Clone::clone(&elem)); ptr = ptr.offset(1); v.set_len(i); // Increment the length in every step in case Clone::clone() panics } if n > 0 { // We can write the last element directly without cloning needlessly ptr::write(ptr, elem); v.set_len(n); } v } } </ins> //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec ////////////////////////////////////////////////////////////////////////////////


<ins> #![feature(marker_trait_attr)] #[marker] trait Marker {} impl Marker for &'_ () {} //~ ERROR type annotations needed impl Marker for &'_ () {} //~ ERROR type annotations needed fn main() {} </ins>


<ins> // astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects. // This `FreshTy(0)` can leak into substs, causing ICEs in several places. // Using `save-analysis` triggers type-checking `f` that would be normally skipped // as `type_of` emitted an error. // // compile-flags: -Zsave-analysis </ins> #![feature(trait_alias)] pub trait SelfInput = Fn(&mut Self);


/// Basic usage: /// /// ``` <del> /// #![feature(nonzero_leading_trailing_zeros)] </del> #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] /// /// assert_eq!(n.trailing_zeros(), 3); /// ``` <del> #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")] </del> <ins> #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] </ins> #[inline] pub const fn trailing_zeros(self) -> u32 { // SAFETY: since `self` can not be zero it is safe to call cttz_nonzero


pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, item_attrs: &[ast::Attribute], <ins> is_const: bool, </ins> f: F) { let prev_overflow_checks = self.overflow_checks_enabled; <del> if attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") { </del> <ins> if is_const || attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") { </ins> self.overflow_checks_enabled = true; } let prev_hash_node_ids = self.node_id_hashing_mode;


} /// Parse a 'for' .. 'in' expression ('for' token already eaten) <del> pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> { </del> <ins> pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>, span_lo: BytePos) -> PResult<P<Expr>> { </ins> // Parse: `for <src_pat> in <src_expr> <src_loop_block>` <del> let lo = self.last_span.lo; </del> let pat = try!(self.parse_pat_nopanic()); try!(self.expect_keyword(keywords::In)); let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)); let loop_block = try!(self.parse_block()); let hi = self.last_span.hi; <del> Ok(self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))) </del> <ins> Ok(self.mk_expr(span_lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))) </ins> } /// Parse a 'while' or 'while let' expression ('while' token already eaten) <del> pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> { </del> <ins> pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>, span_lo: BytePos) -> PResult<P<Expr>> { </ins> if self.token.is_keyword(keywords::Let) { <del> return self.parse_while_let_expr(opt_ident); </del> <ins> return self.parse_while_let_expr(opt_ident, span_lo); </ins> } <del> let lo = self.last_span.lo; </del> let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)); let body = try!(self.parse_block()); let hi = body.span.hi; <del> return Ok(self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident))); </del> <ins> return Ok(self.mk_expr(span_lo, hi, ExprWhile(cond, body, opt_ident))); </ins> } /// Parse a 'while let' expression ('while' token already eaten) <del> pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> { let lo = self.last_span.lo; </del> <ins> pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>, span_lo: BytePos) -> PResult<P<Expr>> { </ins> try!(self.expect_keyword(keywords::Let)); let pat = try!(self.parse_pat_nopanic()); try!(self.expect(&token::Eq)); let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)); let body = try!(self.parse_block()); let hi = body.span.hi; <del> return Ok(self.mk_expr(lo, hi, ExprWhileLet(pat, expr, body, opt_ident))); </del> <ins> return Ok(self.mk_expr(span_lo, hi, ExprWhileLet(pat, expr, body, opt_ident))); </ins> } <del> pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> { let lo = self.last_span.lo; </del> <ins> pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>, span_lo: BytePos) -> PResult<P<Expr>> { </ins> let body = try!(self.parse_block()); let hi = body.span.hi; <del> Ok(self.mk_expr(lo, hi, ExprLoop(body, opt_ident))) </del> <ins> Ok(self.mk_expr(span_lo, hi, ExprLoop(body, opt_ident))) </ins> } fn parse_match_expr(&mut self) -> PResult<P<Expr>> {


<ins> // Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // include file for issue-21146.rs parse_error </ins>


"list" will list all of the available passes", "NAMES"), optopt("", "llvm-args", "A list of arguments to pass to llvm, comma  separated", "ARGS"), <ins> optflag("", "no-rpath", "Disables setting the rpath in libs/exes"), </ins> optopt( "",  "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),


<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // Test that attempts to implicitly coerce a value into an // object respect the lifetime bound on the object type. fn a(v: &[u8]) -> Box<Clone + 'static> { let x: Box<Clone + 'static> = box v; //~ ERROR does not outlive x } fn b(v: &[u8]) -> Box<Clone + 'static> { box v //~ ERROR does not outlive } fn c(v: &[u8]) -> Box<Clone> { box v // OK thanks to lifetime elision } fn d<'a,'b>(v: &'a [u8]) -> Box<Clone+'b> { box v //~ ERROR does not outlive } fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Clone+'b> { box v // OK, thanks to 'a:'b } fn main() { } </ins>


// down as much as possible (without going negative), and then // adding back in whatever we couldn't factor into steals. Some(data) => { <del> self.steals += 1; </del> if self.steals > MAX_STEALS { match self.cnt.swap(0, atomics::SeqCst) { DISCONNECTED => {


/// # Example /// /// ```rust <ins> /// # #![allow(deprecated)] </ins> /// use url::encode; /// /// let url = encode("https://example.com/Rust (programming language)");


#[allow(unused_variables)] fn main() { let x2: i8 = --128; //~ error: literal out of range for i8 <ins> //~^ error: attempted to negate with overflow </ins> let x = -3.40282348e+38_f32; //~ error: literal out of range for f32 let x =  3.40282348e+38_f32; //~ error: literal out of range for f32


/// # Example /// /// ```no_run <del> /// #![feature(seek_rewind)] </del> /// use std::io::{Read, Seek, Write}; /// use std::fs::OpenOptions; ///


pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"]; <del> pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "os", "imp", "unix", "fs", "PermissionsExt", "from_mode"]; </del> <ins> pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"]; </ins> pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"]; pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];


use super::{ForceCollect, Parser, TrailingToken}; use rustc_ast::token; <del> use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause}; </del> <ins> use rustc_ast::{ self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, }; </ins> use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::kw;


# LLVM more often than necessary. # # This git command finds that commit SHA, looking for bors-authored <del> # merges that modified src/llvm-project or other relevant version </del> <ins> # commits that modified src/llvm-project or other relevant version </ins> # stamp files. # # This works even in a repository that has not yet initialized


match *source { CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else <del> // the impl, if local to crate (item may be defaulted), else the call site. </del> <ins> // the impl, if local to crate (item may be defaulted), else nothing. </ins> let item = impl_item(fcx.tcx(), impl_did, item_name) .or_else(|| { trait_item(


<del> // compile-flags: --error-format pretty-json -Zunstable-options // build-pass </del> <ins> // compile-flags: --error-format json -Zunstable-options </ins> // run-rustfix // The output for humans should just highlight the whole span without showing


/// # Example /// /// ```rust <ins> /// # #![allow(deprecated)] </ins> /// let query = vec![("title".to_string(), "The Village".to_string()), ///                  ("north".to_string(), "52.91".to_string()), ///                  ("west".to_string(), "4.10".to_string())];


} }; <del> span_note!(err, item_span, "candidate #{} is defined in an impl{} for the type `{}`", idx + 1, insertion, impl_ty); </del> <ins> let note_str = format!("candidate #{} is defined in an impl{}  for the type `{}`", idx + 1, insertion, impl_ty); if let Some(note_span) = note_span { // We have a span pointing to the method. Show note with snippet. err.span_note(note_span, &note_str); } else { err.note(&note_str); } </ins> } CandidateSource::TraitSource(trait_did) => { let item = trait_item(fcx.tcx(), trait_did, item_name).unwrap();


base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]); <del> base.link_env.extend(super::apple_base::macos_link_env("arm64")); </del> base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); // Clang automatically chooses a more specific target based on


<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // -C no-prepopulate-passes #![crate_type="staticlib"] #[repr(C)] pub struct Foo(u64); // CHECK: define {{.*}} @foo( #[no_mangle] pub extern fn foo(_: Foo) -> Foo { loop {} } </ins>


<ins> // edition:2018 use std::convert::{TryFrom, TryInto}; use std::io; pub struct MyStream; pub struct OtherStream; pub async fn connect() -> io::Result<MyStream> { let stream: MyStream = OtherStream.try_into()?; Ok(stream) } impl TryFrom<OtherStream> for MyStream {} //~^ ERROR: missing fn main() {} </ins>


<ins> // Nested impl-traits can impose different member constraints on the same region variable. // check-fail trait Cap<'a> {} impl<T> Cap<'_> for T {} // Assuming the hidden type is `[&'_#15r u8; 1]`, we have two distinct member constraints: // - '_#15r member ['static, 'a, 'b] // from outer impl-trait // - '_#15r member ['static, 'a, 'b] // from inner impl-trait // To satisfy both we can choose 'a or 'b, so it's a failure due to ambiguity. fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> where 's: 'a, 's: 'b, { [a] //~^ E0700 //~| E0700 } // Same as the above but with late-bound regions. fn fail_late_bound<'s, 'a, 'b>( a: &'s u8, _: &'a &'s u8, _: &'b &'s u8, ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> { [a] //~^ E0700 //~| E0700 } fn main() {} </ins>


<ins> error: `panic_impl` language item function is not allowed to have `#[target_feature]` --> $DIR/panic-handler-with-target-feature.rs:11:1 | LL | #[target_feature(enable = "avx2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn panic(info: &PanicInfo) -> ! { | ------------------------------- `panic_impl` language item function is not allowed to have `#[target_feature]` error: aborting due to previous error </ins>


"arch": "x86_64", "cpu": "x86-64", "crt-static-respected": true, <del> "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", </del> <ins> "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", </ins> "dynamic-linking": true, "env": "gnu", "executables": true,


<ins> // run-pass #![allow(dead_code)] enum E { A, B } fn main() { match &&E::A { &&E::A => { } &&E::B => { } }; } </ins>


<ins> error[E0311]: the parameter type `T` may not live long enough --> $DIR/issue-86483.rs:6:1 | LL |   pub trait IceIce<T> |   ^                - help: consider adding an explicit lifetime bound...: `T: 'a` |  _| | | LL | | where LL | |     for<'a> T: 'a, LL | | { ...  | LL | | LL | | } | |_^ ...so that the type `T` will meet its required lifetime bounds error[E0311]: the parameter type `T` may not live long enough --> $DIR/issue-86483.rs:10:5 | LL | pub trait IceIce<T> |                  - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL |     type Ice<'v>: IntoIterator<Item = &'v T>; |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/issue-86483.rs:10:32 | LL | pub trait IceIce<T> |                  - help: consider adding an explicit lifetime bound...: `T: 'v` ... LL |     type Ice<'v>: IntoIterator<Item = &'v T>; |                                ^^^^^^^^^^^^ ...so that the reference type `&'v T` does not outlive the data it points at error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0309`. </ins>