Question: unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { <ins> // jemalloc provides alignment less than MIN_ALIGN for small allocations. // So only rely on MIN_ALIGN if size >= align. // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. </ins> if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else {

These only need to be aligned at an boundary. If you believe this is incorrect, please show a counter-example for which this doesn't work.
AFAIK it is a normal way of using to make it override the symbol? Don't we still do that in rustc, or when using "jemallocator"? I don't say it is incorrect, I say it is awfully indirect. It's like reading tea leaves. I am looking for a clear definite statement. That doesn't seem to exist though. :( There clearly is some kind of "non-continuity" where all allocations are aligned MINALIGN except for small ones. Or vice versa, all allocations are aligned "size rounded down to power of 2" except for big ones. You are convincingly deriving that non-continuity from standard wording. I don't say you are wrong, but this feels like interpreting ancient scripture. A clear spec looks different. Also, an object of size 2 with alignment requirement 4 is "fundamental" according to your definition, and yet rounding down the size to the next power of 2 does not give the right alignment. So your rule does have exceptions, namely types marked .
Can you show such an object in C and/or Rust ? It's probably the most common way of switching allocators. What does is it requires to be linked to your binary, allowing (and making use of) jemalloc-specific APIs. If you do this, when using directly (not ), you can obviously rely on assumptions that only hold for . But cannot do that because, then it wouldn't work with other allocators.
The goal is not to rely on assumptions that only hold for . The goal is to make sure that we do not make assumptions that don't hold for . Because that's what we used to do, before got fixed. We were assuming something that was true for system but not for : that all allocations, no matter the size, are aligned. To make sure we don't do that again, I want to be sure that all assumptions we are making hold for . That's why I'd like jemalloc to spell out what we can assume.
Ah I forgot about the stride vs. size thing. So such an object does not exist.


Question: unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { <ins> // jemalloc provides alignment less than MIN_ALIGN for small allocations. // So only rely on MIN_ALIGN if size >= align. // Also see <https://github.com/rust-lang/rust/issues/45955> and // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. </ins> if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { libc::malloc(layout.size()) as *mut u8 } else {

But such a exists, and it is something we want to support in our allocator API (we even have a test for that). And we do have objects with align size, namely all ZST.
Yeah, I agree. The only cases for which the "round to the previous power of two approach" doesn't work is for ZSTs, and types (or allocations) with align size. Since those just cannot happen in C, the C standard doesn't mention them as exceptions. That is, we can only call when that holds, and if it that doesn't hold, we need to call a different API that supports the align size case.


Question: <ins> fn s() -> String { let a = String::new(); dbg!(a); return a; //~ ERROR use of moved value: } fn m() -> String { let a = String::new(); dbg!(1, 2, a, 1, 2); return a; //~ ERROR use of moved value: } fn t(a: String) -> String { let b: String = "".to_string(); dbg!(a, b); return b; //~ ERROR use of moved value: } fn x(a: String) -> String { let b: String = "".to_string(); dbg!(a, b); return a; //~ ERROR use of moved value: } macro_rules! my_dbg { () => { eprintln!("[{}:{}:{}]", file!(), line!(), column!()) }; ($val:expr $(,)?) => { match $val { tmp => { eprintln!("[{}:{}:{}] {} = {:#?}", file!(), line!(), column!(), stringify!($val), &tmp); tmp } } }; ($($val:expr),+ $(,)?) => { ($(my_dbg!($val)),+,) }; } fn test_my_dbg() -> String { let b: String = "".to_string(); my_dbg!(b, 1); return b; //~ ERROR use of moved value: } fn test_not_macro() -> String { let a = String::new(); let _b = match a { tmp => { eprintln!("dbg: {}", tmp); tmp } }; return a; //~ ERROR use of moved value: } fn get_expr(_s: String) {} fn test() { let a: String = "".to_string(); let _res = get_expr(dbg!(a)); let _l = a.len(); //~ ERROR borrow of moved value } fn main() {} </ins>

No response No response No response
I thought the intent with was to use it in a passthrough style, so you can insert it into existing expressions ie. becomes . In which case, maybe the lint should be for not using the value resulting from evaluating .
Not sure about the majority of users but for me is a convenience over . I use it without using the return value almost all of the time.
Probably a common thing to do, sure, but if we're talking about adding a lint, why not nudge the user in the direction of the intended and documented usage? You could at least do both: "insert into an existing expression or pass it a borrow" etc.
The fix in will only report a hint when there is already a happened. For example this code: before this fix the error is: with the fix, since there is already a error, the lint will try to find out the original macro, and suggest a borrow: The suggestion is not 100% right, since if we change it to , we need one more extra fix now(the return type is not expecting a reference), but there is a different issue, at least we have already moved one step on. If the original code is: Then suggest a borrow is a great and correct hint.
Similar in the scenario of function argument: original error is: new errors from the fix:
Would not also be a good hint? The suggestion wouldn't compile anyway right? Because would need to change to take ? Without involved, the compiler does indeed suggest that: Once that's addressed (whichever way it's done), once again becomes transparent, and eg. or works. does not, however, and I see why a "consider borrowing" hint would be good there. However, if you make the change first and leave as-is, the resulting error does not include the suggestion to change , which is unhelpful. (I agree that the message is even less helpful though, I'm not disputing that.)
Yes, it's a good hint, but from the implementation view of a hint, it's much harder to analyze the following code from the error point and then construct a new expression. Even it seems an easy thing for humans. You are right, the suggestion is not 100% right, we may need an extra follow-up fix after applying the hint, which is also a common thing in rustc diagnostics.


Question: //! Performs various peephole optimizations. use crate::transform::{MirPass, MirSource}; <del> use rustc_data_structures::fx::FxHashMap; </del> <ins> use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::Mutability; </ins> use rustc_index::vec::Idx; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::{ <del> Body, Constant, Local, Location, Mutability, Operand, Place, PlaceRef, ProjectionElem, Rvalue, </del> <ins> Body, Constant, Local, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, </ins> }; use rustc_middle::ty::{self, TyCtxt}; use std::mem;

Since InstCombine can now introduce where there was none before, without checking that the value is in fact not used afterwards. This may cause a value to be marked as uninitialized by the dataflow, but still be used in that uninitialized state. If InstCombine ran before the generator transform this would be acutely unsound and could probably be exploited directly, but other than that transform I don't think we rely on this property yet. This impacts , which does run after InstCombine and relies on the dataflow. I've observed this on , where it produces this diff: The second use of occurs despite the first move deinitializing the local. cc
Maybe we should stop making instcombine convert to ? This could be done in the pre-codegen cleanups, but for MIR it is wrong to use or on such values in general. Alternatively instcombine needs to start using dataflow to only insert moves when the site is the last use of the local.


Question: /// Declare a static `LintArray` and return it as an expression. #[macro_export] <del> macro_rules! lint_array { ($( $lint:expr ),*) => ( { static ARRAY: LintArray = &[ $( &$lint ),* ]; ARRAY } ) } </del> <ins> macro_rules! lint_array { ($( $lint:expr ),*,) => { lint_array!( $( $lint ),* ) }; ($( $lint:expr ),*) => {{ static ARRAY: LintArray = &[ $( &$lint ),* ]; ARRAY }} } </ins> pub type LintArray = &'static [&'static &'static Lint];

Basically just change this macro to recognize and discard the trailing comma.
That macro declaration is formatted in a weird way. But anyway it should be enough to add to the rule (unless accepting multiple trailing commas is undesired). I could mentor.
How about this:
Out of curiosity, why doesn't rust allow trailing commas after automatically? Does it make it hard to write some macros? Alternately, why isn't there a (optional) repetition specification (e.g. would be 0 or 1 times)?
The extra rule is fine too. It's just more annoying (extra repetition). And there's no technical reason not to support one-or-none patterns as far as I'm aware.
Made a PR :)


Question: <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. //! Cross-platform file path handling (re-write) use container::Container; use c_str::CString; use clone::Clone; use iter::Iterator; use option::{Option, None, Some}; use str; use str::StrSlice; use vec; use vec::{CopyableVector, OwnedCopyableVector, OwnedVector}; use vec::{ImmutableEqVector, ImmutableVector}; pub mod posix; pub mod windows; /// Typedef for POSIX file paths. /// See `posix::Path` for more info. pub type PosixPath = posix::Path; /// Typedef for Windows file paths. /// See `windows::Path` for more info. pub type WindowsPath = windows::Path; /// Typedef for the platform-native path type #[cfg(unix)] pub type Path = PosixPath; /// Typedef for the platform-native path type #[cfg(windows)] pub type Path = WindowsPath; /// Typedef for the POSIX path component iterator. /// See `posix::ComponentIter` for more info. pub type PosixComponentIter<'self> = posix::ComponentIter<'self>; // /// Typedef for the Windows path component iterator. // /// See `windows::ComponentIter` for more info. // pub type WindowsComponentIter<'self> = windows::ComponentIter<'self>; /// Typedef for the platform-native component iterator #[cfg(unix)] pub type ComponentIter<'self> = PosixComponentIter<'self>; // /// Typedef for the platform-native component iterator //#[cfg(windows)] //pub type ComponentIter<'self> = WindowsComponentIter<'self>; // Condition that is raised when a NUL is found in a byte vector given to a Path function condition! { // this should be a &[u8] but there's a lifetime issue null_byte: ~[u8] -> ~[u8]; } /// A trait that represents the generic operations available on paths pub trait GenericPath: Clone + GenericPathUnsafe { /// Creates a new Path from a byte vector. /// The resulting Path will always be normalized. /// /// # Failure /// /// Raises the `null_byte` condition if the path contains a NUL. /// /// See individual Path impls for additional restrictions. #[inline] fn from_vec(path: &[u8]) -> Self { if contains_nul(path) { let path = self::null_byte::cond.raise(path.to_owned()); assert!(!contains_nul(path)); unsafe { GenericPathUnsafe::from_vec_unchecked(path) } } else { unsafe { GenericPathUnsafe::from_vec_unchecked(path) } } } /// Creates a new Path from a string. /// The resulting Path will always be normalized. /// /// # Failure /// /// Raises the `null_byte` condition if the path contains a NUL. #[inline] fn from_str(path: &str) -> Self { let v = path.as_bytes(); if contains_nul(v) { GenericPath::from_vec(path.as_bytes()) // let from_vec handle the condition } else { unsafe { GenericPathUnsafe::from_str_unchecked(path) } } } /// Creates a new Path from a CString. /// The resulting Path will always be normalized. /// /// See individual Path impls for potential restrictions. #[inline] fn from_c_str(path: CString) -> Self { // CStrings can't contain NULs unsafe { GenericPathUnsafe::from_vec_unchecked(path.as_bytes()) } } /// Returns the path as a string, if possible. /// If the path is not representable in utf-8, this returns None. #[inline] fn as_str<'a>(&'a self) -> Option<&'a str> { str::from_utf8_slice_opt(self.as_vec()) } /// Returns the path as a byte vector fn as_vec<'a>(&'a self) -> &'a [u8]; /// Returns the directory component of `self`, as a byte vector (with no trailing separator). /// If `self` has no directory component, returns ['.']. fn dirname<'a>(&'a self) -> &'a [u8]; /// Returns the directory component of `self`, as a string, if possible. /// See `dirname` for details. #[inline] fn dirname_str<'a>(&'a self) -> Option<&'a str> { str::from_utf8_slice_opt(self.dirname()) } /// Returns the file component of `self`, as a byte vector. /// If `self` represents the root of the file hierarchy, returns the empty vector. /// If `self` is ".", returns the empty vector. fn filename<'a>(&'a self) -> &'a [u8]; /// Returns the file component of `self`, as a string, if possible. /// See `filename` for details. #[inline] fn filename_str<'a>(&'a self) -> Option<&'a str> { str::from_utf8_slice_opt(self.filename()) } /// Returns the stem of the filename of `self`, as a byte vector. /// The stem is the portion of the filename just before the last '.'. /// If there is no '.', the entire filename is returned. fn filestem<'a>(&'a self) -> &'a [u8] { let name = self.filename(); let dot = '.' as u8; match name.rposition_elem(&dot) { None | Some(0) => name, Some(1) if name == bytes!("..") => name, Some(pos) => name.slice_to(pos) } } /// Returns the stem of the filename of `self`, as a string, if possible. /// See `filestem` for details. #[inline] fn filestem_str<'a>(&'a self) -> Option<&'a str> { str::from_utf8_slice_opt(self.filestem()) } /// Returns the extension of the filename of `self`, as an optional byte vector. /// The extension is the portion of the filename just after the last '.'. /// If there is no extension, None is returned. /// If the filename ends in '.', the empty vector is returned. fn extension<'a>(&'a self) -> Option<&'a [u8]> { let name = self.filename(); let dot = '.' as u8; match name.rposition_elem(&dot) { None | Some(0) => None, Some(1) if name == bytes!("..") => None, Some(pos) => Some(name.slice_from(pos+1)) } } /// Returns the extension of the filename of `self`, as a string, if possible. /// See `extension` for details. #[inline] fn extension_str<'a>(&'a self) -> Option<&'a str> { self.extension().and_then(|v| str::from_utf8_slice_opt(v)) } /// Replaces the directory portion of the path with the given byte vector. /// If `self` represents the root of the filesystem hierarchy, the last path component /// of the given byte vector becomes the filename. /// /// # Failure /// /// Raises the `null_byte` condition if the dirname contains a NUL. #[inline] fn set_dirname(&mut self, dirname: &[u8]) { if contains_nul(dirname) { let dirname = self::null_byte::cond.raise(dirname.to_owned()); assert!(!contains_nul(dirname)); unsafe { self.set_dirname_unchecked(dirname) } } else { unsafe { self.set_dirname_unchecked(dirname) } } } /// Replaces the directory portion of the path with the given string. /// See `set_dirname` for details. #[inline] fn set_dirname_str(&mut self, dirname: &str) { if contains_nul(dirname.as_bytes()) { self.set_dirname(dirname.as_bytes()) // triggers null_byte condition } else { unsafe { self.set_dirname_str_unchecked(dirname) } } } /// Replaces the filename portion of the path with the given byte vector. /// If the replacement name is [], this is equivalent to popping the path. /// /// # Failure /// /// Raises the `null_byte` condition if the filename contains a NUL. #[inline] fn set_filename(&mut self, filename: &[u8]) { if contains_nul(filename) { let filename = self::null_byte::cond.raise(filename.to_owned()); assert!(!contains_nul(filename)); unsafe { self.set_filename_unchecked(filename) } } else { unsafe { self.set_filename_unchecked(filename) } } } /// Replaces the filename portion of the path with the given string. /// See `set_filename` for details. #[inline] fn set_filename_str(&mut self, filename: &str) { if contains_nul(filename.as_bytes()) { self.set_filename(filename.as_bytes()) // triggers null_byte condition } else { unsafe { self.set_filename_str_unchecked(filename) } } } /// Replaces the filestem with the given byte vector. /// If there is no extension in `self` (or `self` has no filename), this is equivalent /// to `set_filename`. Otherwise, if the given byte vector is [], the extension (including /// the preceding '.') becomes the new filename. /// /// # Failure /// /// Raises the `null_byte` condition if the filestem contains a NUL. fn set_filestem(&mut self, filestem: &[u8]) { // borrowck is being a pain here let val = { let name = self.filename(); if !name.is_empty() { let dot = '.' as u8; match name.rposition_elem(&dot) { None | Some(0) => None, Some(idx) => { let mut v; if contains_nul(filestem) { let filestem = self::null_byte::cond.raise(filestem.to_owned()); assert!(!contains_nul(filestem)); v = vec::with_capacity(filestem.len() + name.len() - idx); v.push_all(filestem); } else { v = vec::with_capacity(filestem.len() + name.len() - idx); v.push_all(filestem); } v.push_all(name.slice_from(idx)); Some(v) } } } else { None } }; match val { None => self.set_filename(filestem), Some(v) => unsafe { self.set_filename_unchecked(v) } } } /// Replaces the filestem with the given string. /// See `set_filestem` for details. #[inline] fn set_filestem_str(&mut self, filestem: &str) { self.set_filestem(filestem.as_bytes()) } /// Replaces the extension with the given byte vector. /// If there is no extension in `self`, this adds one. /// If the given byte vector is [], this removes the extension. /// If `self` has no filename, this is a no-op. /// /// # Failure /// /// Raises the `null_byte` condition if the extension contains a NUL. fn set_extension(&mut self, extension: &[u8]) { // borrowck causes problems here too let val = { let name = self.filename(); if !name.is_empty() { let dot = '.' as u8; match name.rposition_elem(&dot) { None | Some(0) => { if extension.is_empty() { None } else { let mut v; if contains_nul(extension) { let extension = self::null_byte::cond.raise(extension.to_owned()); assert!(!contains_nul(extension)); v = vec::with_capacity(name.len() + extension.len() + 1); v.push_all(name); v.push(dot); v.push_all(extension); } else { v = vec::with_capacity(name.len() + extension.len() + 1); v.push_all(name); v.push(dot); v.push_all(extension); } Some(v) } } Some(idx) => { if extension.is_empty() { Some(name.slice_to(idx).to_owned()) } else { let mut v; if contains_nul(extension) { let extension = self::null_byte::cond.raise(extension.to_owned()); assert!(!contains_nul(extension)); v = vec::with_capacity(idx + extension.len() + 1); v.push_all(name.slice_to(idx+1)); v.push_all(extension); } else { v = vec::with_capacity(idx + extension.len() + 1); v.push_all(name.slice_to(idx+1)); v.push_all(extension); } Some(v) } } } } else { None } }; match val { None => (), Some(v) => unsafe { self.set_filename_unchecked(v) } } } /// Replaces the extension with the given string. /// See `set_extension` for details. #[inline] fn set_extension_str(&mut self, extension: &str) { self.set_extension(extension.as_bytes()) } /// Returns a new Path constructed by replacing the dirname with the given byte vector. /// See `set_dirname` for details. /// /// # Failure /// /// Raises the `null_byte` condition if the dirname contains a NUL. #[inline] fn with_dirname(&self, dirname: &[u8]) -> Self { let mut p = self.clone(); p.set_dirname(dirname); p } /// Returns a new Path constructed by replacing the dirname with the given string. /// See `set_dirname` for details. #[inline] fn with_dirname_str(&self, dirname: &str) -> Self { let mut p = self.clone(); p.set_dirname_str(dirname); p } /// Returns a new Path constructed by replacing the filename with the given byte vector. /// See `set_filename` for details. /// /// # Failure /// /// Raises the `null_byte` condition if the filename contains a NUL. #[inline] fn with_filename(&self, filename: &[u8]) -> Self { let mut p = self.clone(); p.set_filename(filename); p } /// Returns a new Path constructed by replacing the filename with the given string. /// See `set_filename` for details. #[inline] fn with_filename_str(&self, filename: &str) -> Self { let mut p = self.clone(); p.set_filename_str(filename); p } /// Returns a new Path constructed by setting the filestem to the given byte vector. /// See `set_filestem` for details. /// /// # Failure /// /// Raises the `null_byte` condition if the filestem contains a NUL. #[inline] fn with_filestem(&self, filestem: &[u8]) -> Self { let mut p = self.clone(); p.set_filestem(filestem); p } /// Returns a new Path constructed by setting the filestem to the given string. /// See `set_filestem` for details. #[inline] fn with_filestem_str(&self, filestem: &str) -> Self { let mut p = self.clone(); p.set_filestem_str(filestem); p } /// Returns a new Path constructed by setting the extension to the given byte vector. /// See `set_extension` for details. /// /// # Failure /// /// Raises the `null_byte` condition if the extension contains a NUL. #[inline] fn with_extension(&self, extension: &[u8]) -> Self { let mut p = self.clone(); p.set_extension(extension); p } /// Returns a new Path constructed by setting the extension to the given string. /// See `set_extension` for details. #[inline] fn with_extension_str(&self, extension: &str) -> Self { let mut p = self.clone(); p.set_extension_str(extension); p } /// Returns the directory component of `self`, as a Path. /// If `self` represents the root of the filesystem hierarchy, returns `self`. fn dir_path(&self) -> Self { // self.dirname() returns a NUL-free vector unsafe { GenericPathUnsafe::from_vec_unchecked(self.dirname()) } } /// Returns the file component of `self`, as a relative Path. /// If `self` represents the root of the filesystem hierarchy, returns None. fn file_path(&self) -> Option<Self> { // self.filename() returns a NUL-free vector match self.filename() { [] => None, v => Some(unsafe { GenericPathUnsafe::from_vec_unchecked(v) }) } } /// Pushes a path (as a byte vector) onto `self`. /// If the argument represents an absolute path, it replaces `self`. /// /// # Failure /// /// Raises the `null_byte` condition if the path contains a NUL. #[inline] fn push(&mut self, path: &[u8]) { if contains_nul(path) { let path = self::null_byte::cond.raise(path.to_owned()); assert!(!contains_nul(path)); unsafe { self.push_unchecked(path) } } else { unsafe { self.push_unchecked(path) } } } /// Pushes a path (as a string) onto `self. /// See `push` for details. #[inline] fn push_str(&mut self, path: &str) { if contains_nul(path.as_bytes()) { self.push(path.as_bytes()) // triggers null_byte condition } else { unsafe { self.push_str_unchecked(path) } } } /// Pushes a Path onto `self`. /// If the argument represents an absolute path, it replaces `self`. #[inline] fn push_path(&mut self, path: &Self) { self.push(path.as_vec()) } /// Pops the last path component off of `self` and returns it. /// If `self` represents the root of the file hierarchy, None is returned. fn pop_opt(&mut self) -> Option<~[u8]>; /// Pops the last path component off of `self` and returns it as a string, if possible. /// `self` will still be modified even if None is returned. /// See `pop_opt` for details. #[inline] fn pop_opt_str(&mut self) -> Option<~str> { self.pop_opt().and_then(|v| str::from_utf8_owned_opt(v)) } /// Returns a new Path constructed by joining `self` with the given path (as a byte vector). /// If the given path is absolute, the new Path will represent just that. /// /// # Failure /// /// Raises the `null_byte` condition if the path contains a NUL. #[inline] fn join(&self, path: &[u8]) -> Self { let mut p = self.clone(); p.push(path); p } /// Returns a new Path constructed by joining `self` with the given path (as a string). /// See `join` for details. #[inline] fn join_str(&self, path: &str) -> Self { let mut p = self.clone(); p.push_str(path); p } /// Returns a new Path constructed by joining `self` with the given path. /// If the given path is absolute, the new Path will represent just that. #[inline] fn join_path(&self, path: &Self) -> Self { let mut p = self.clone(); p.push_path(path); p } /// Returns whether `self` represents an absolute path. /// An absolute path is defined as one that, when joined to another path, will /// yield back the same absolute path. fn is_absolute(&self) -> bool; /// Returns whether `self` is equal to, or is an ancestor of, the given path. /// If both paths are relative, they are compared as though they are relative /// to the same parent path. fn is_ancestor_of(&self, other: &Self) -> bool; /// Returns the Path that, were it joined to `base`, would yield `self`. /// If no such path exists, None is returned. /// If `self` is absolute and `base` is relative, or on Windows if both /// paths refer to separate drives, an absolute path is returned. fn path_relative_from(&self, base: &Self) -> Option<Self>; } /// A trait that represents the unsafe operations on GenericPaths pub trait GenericPathUnsafe { /// Creates a new Path from a byte vector without checking for null bytes. /// The resulting Path will always be normalized. unsafe fn from_vec_unchecked(path: &[u8]) -> Self; /// Creates a new Path from a str without checking for null bytes. /// The resulting Path will always be normalized. #[inline] unsafe fn from_str_unchecked(path: &str) -> Self { GenericPathUnsafe::from_vec_unchecked(path.as_bytes()) } /// Replaces the directory portion of the path with the given byte vector without /// checking for null bytes. /// See `set_dirname` for details. unsafe fn set_dirname_unchecked(&mut self, dirname: &[u8]); /// Replaces the directory portion of the path with the given str without /// checking for null bytes. /// See `set_dirname_str` for details. #[inline] unsafe fn set_dirname_str_unchecked(&mut self, dirname: &str) { self.set_dirname_unchecked(dirname.as_bytes()) } /// Replaces the filename portion of the path with the given byte vector without /// checking for null bytes. /// See `set_filename` for details. unsafe fn set_filename_unchecked(&mut self, filename: &[u8]); /// Replaces the filename portion of the path with the given str without /// checking for null bytes. /// See `set_filename_str` for details. #[inline] unsafe fn set_filename_str_unchecked(&mut self, filename: &str) { self.set_filename_unchecked(filename.as_bytes()) } /// Pushes a byte vector onto `self` without checking for null bytes. /// See `push` for details. unsafe fn push_unchecked(&mut self, path: &[u8]); /// Pushes a str onto `self` without checking for null bytes. /// See `push_str` for details. #[inline] unsafe fn push_str_unchecked(&mut self, path: &str) { self.push_unchecked(path.as_bytes()) } } #[inline(always)] fn contains_nul(v: &[u8]) -> bool { v.iter().any(|&x| x == 0) } </ins>

and all interfaces directly with the file-system should probably use rather than trying to coerce to handle these cases. (Similar issue to .)
nominating feature-complete
Accepted for backwards-compatible
My last referenced commit is a month old, but I'm still working on this issue (currently finishing up the support for Windows paths).
The issues here of dealing with filesystems that are not utf8 seem related to , at least tangentially.


Question: /// Returns an iterator over all function arguments. #[inline] <del> pub fn args_iter(&self) -> impl Iterator<Item = Local> { </del> <ins> pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator { </ins> let arg_count = self.arg_count; <del> (1..=arg_count).map(Local::new) </del> <ins> (1..arg_count + 1).map(Local::new) </ins> } /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all /// locals that are neither arguments nor the return place). #[inline] <del> pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> { </del> <ins> pub fn vars_and_temps_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator { </ins> let arg_count = self.arg_count; let local_count = self.local_decls.len(); (arg_count + 1..local_count).map(Local::new)

E.g. in we had to use weird code to check that the iterator is the same length as a slice. After changing the function to have an ExactSizeIterator bound, we should undo the hack <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --This issue has been assigned to via . <!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
What do you mean by "many"? Is this about grepping returns in and replacing them with whenever possible? I'd like to give this a try but not sure what exactly this is asking.
Ah, not libstd, just in the compiler. But yea, you got the right idea, grep for it, see if it can be ExactSizeIterator, if not leave it
Hi, this looks pretty easy and I would actually try to get involved into rustc - could I take this one as starting point for incoming weekend?
Go for it. Just search for returns in the compiler source code and replace them with whenever possible.
claim


Question: })); } <ins> let (inh_first, inh_second) = { let mut inh_variants = (0..variants.len()).filter(|&v| { variants[v].iter().all(|f| f.abi != Abi::Uninhabited) }); (inh_variants.next(), inh_variants.next()) }; if inh_first.is_none() { // Uninhabited because it has no variants, or only uninhabited ones. return Ok(tcx.intern_layout(LayoutDetails::uninhabited(0))); } </ins> let is_struct = !def.is_enum() || // Only one variant is inhabited. (inh_second.is_none() &&

Uninhabited variants should ideally be irrelevant to the representation, just like in enums. As a test, this prints out 0 instead of 8: This happens because rustc considers unions more like structs than enums, and the sees a single variant with two fields, one of which is uninhabited. I have a fix for this, but it's slightly easier to bundle it with some other changes I'm working on.
This becomes a problem when making an array of unions: The above code represents a regression (prints 42 on stable, garbage on beta/nightly).
I didn't realize it was a regression to beta - in that case I'll put up an independent fix so that it can be backported if desired.
Although I can't trigger it on the playground, you code is actually triggering an ICE for me: EDIT: I bisected the ICE to somewhere between "rust 1.23.0-nightly ( 2017-11-25)" and "rust 1.23.0-nightly ( 2017-11-26)".
cc
I put up a PR to fix this, but I'm still confused about the ICE (which I moved to ).


Question: for i in 0..tupled_arg_tys.len() { let arg = &fx.fn_ty.args[idx]; idx += 1; <ins> if arg.pad.is_some() { llarg_idx += 1; } </ins> arg.store_fn_arg(bx, &mut llarg_idx, place.project_field(bx, i)); }

This code, when compiled for , results in an ICE: Putting smaller integers in does not trigger this, even if you use a ton of them. Edit: It also does not occur when taking it only as argument, or when only returning it. Panic message and backtrace: Rust version: cc
Looks like this could be caused by this common skipping of padding arguments: Combined with this call (which internally also skips padding arguments): When the latter gets used, each padding argument is skipped twice. I assume this is fallout.
triage: P-high Beta regression. Has pending fix.


Question: } fn crate_matches(crate_data: &[u8], <del> name: ~str, version: ~str, hash: ~str) -> bool { </del> <ins> name: &str, version: &str, hash: &str) -> bool { </ins> let attrs = decoder::get_crate_attributes(crate_data); match attr::find_crateid(attrs) { None => false, Some(crateid) => { if !hash.is_empty() { let chash = decoder::get_crate_hash(crate_data); <del> if chash != hash { return false; } </del> <ins> if chash.as_slice() != hash { return false; } </ins> } name == crateid.name && (version.is_empty() ||

Built glfw-rs using rust 0.10-pre. When referencing this crate in another source file and building, I get error: internal compiler error: unexpected failure This message reflects a bug in the Rust compiler. We would appreciate a bug report: note: the compiler hit an unexpected failure path. this is a bug Ok(task 'rustc' failed at 'assertion failed: ()', ) This is on OSX 10.9: rustc 0.10-pre ( 2014-02-18 10:16:48 -0800) host: x8664-apple-darwin
This means that you've got two versions of the same lying around, and doesn't like having two versions. This will be fixed by , I just need to land it :(
I have just build the library for the first time, and I can only find one dylib for it on my system (next to the rlib, but I gues that shouldn't cause any problems). Is there another possibility for this error? Gesendet: Mittwoch, 19. Februar 2014 um 01:09 UhrVon: "Alex Crichton" : mozilla/rust hhildebr : Re: [rust] Compiler error when referencing crate "glfw-rs" () This means that you've got two versions of the same libglfw- lying around, and rustc doesn't like having two versions. This will be fixed by , I just need to land it :( — Reply to this email directly or view it on GitHub.
my reading of is that having a dylib and an rlib simultaneously is a problem.
Having a dylib and an rlib simultaneously should not be a problem, it is in fact quite common. Having 2 dylibs and 1 rlib or 2 rlibs and 1 dylib however is a problem.
sorry, my mistake in parsing the title of .
Yes, indeed, I had several identical dylibs, but it wasn't the glfw-rs.. there were rust libs in /usr/local/lib and /usr/local/lib/rustlib/... Thanks! Gesendet: Mittwoch, 19.


Question: } fn crate_matches(crate_data: &[u8], <del> name: ~str, version: ~str, hash: ~str) -> bool { </del> <ins> name: &str, version: &str, hash: &str) -> bool { </ins> let attrs = decoder::get_crate_attributes(crate_data); match attr::find_crateid(attrs) { None => false, Some(crateid) => { if !hash.is_empty() { let chash = decoder::get_crate_hash(crate_data); <del> if chash != hash { return false; } </del> <ins> if chash.as_slice() != hash { return false; } </ins> } name == crateid.name && (version.is_empty() ||

Februar 2014 um 17:15 UhrVon: "Alex Crichton" : mozilla/rust hhildebr : Re: [rust] Compiler error when referencing crate "glfw-rs" () Having a dylib and an rlib simultaneously should not be a problem, it is in fact quite common. Having 2 dylibs and 1 rlib or 2 rlibs and 1 dylib however is a problem. — Reply to this email directly or view it on GitHub.
so can we close this ticket now, in that case? Or do you want to wait for alexcrichton's patches to land, and see what things look like for you then?
Nono, the ticket can be closed for now. Thanks for your help! Gesendet: Mittwoch, 19. Februar 2014 um 21:30 UhrVon: "Felix S Klock II" : mozilla/rust hhildebr : Re: [rust] Compiler error when referencing crate "glfw-rs" () so can we close this ticket now, in that case? Or do you want to wait for alexcrichton's patches to land, and see what things look like for you then? — Reply to this email directly or view it on GitHub.


Question: let args = vec!(self_arg); // Add all the fields as a value which needs to be cleaned at the end of <del> // this scope. for (i, ty) in st.fields.iter().enumerate() { </del> <ins> // this scope. Iterate in reverse order so a Drop impl doesn't reverse // the order in which fields get dropped. for (i, ty) in st.fields.iter().enumerate().rev() { </ins> let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false); variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), llfld_a, *ty);

When a type has no impl, it fields appear to be destructed in order of declaration. When a type does have a impl, that order is apparently reversed. This is very surprising. Example: Prints:
cc who first hit this bug.
The LLVM IR for the Drop glue for : The LLVM IR for the Drop glue for : I don't know why it's getting pointers to each field before calling , they're not used until the cleanup, and they're cleaned up in reverse order. It's also, for some reason, grabbing a pointer to the drop flag (), even though it doesn't use it.
Nominating. Seems pretty strange.
I have an approved commit for this already, it's just failing on the pretty-rpass test at the moment.
I'm OK with disabling the test. Going forward the pretty printer should mainly be used for compiler diagnostics and rustfmt should cover the reformatting use cases, IMO.


Question: /// # Examples /// /// ``` <ins> /// #![feature(inner_deref)] /// let mut s = "HELLO".to_string(); </ins> /// let mut x: Result<String, u32> = Ok("hello".to_string()); <del> /// let y: Result<&mut str, &mut u32> = Ok("HELLO"); </del> <ins> /// let y: Result<&mut str, &mut u32> = Ok(&mut s); </ins> /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); /// <ins> /// let mut i = 42; </ins> /// let mut x: Result<String, u32> = Err(42); <del> /// let y: Result<&mut str, &mut u32> = Err(&42); </del> <ins> /// let y: Result<&mut str, &mut u32> = Err(&mut i); </ins> /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); /// ``` pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {

I would expect the following command to run the libcore doc tests: This used to work, but now all it does it build libcore and its test binaries. No tests are actually being run (which I verified by breaking one of them deliberately). any idea what is happening?
I can confirm, doctests are not being run for std. I think a bigger question is, have they ever worked? Cargo will skip doctests whenever is used, which AFAIK is how std is always built/tested.
I am pretty sure that have used this command before and got test failures when I had screwed up. If you want, I can go back to older versions and verify.
I'll try to figure out what's going on. I tried running with and fortunately nothing looks broken. It's also very possible I am missing something, but I edited some doctests with errors, and a bare doesn't fail.
This was wrong, see below. I'll try to put together a fix.
Ouch. Is there a way we can ensure this does not happen again in the future? Looks like our test suite needs a test suite...
It's pretty hard :/ I guess we can add a dummy doc test that writes some "well known" file and we can assert that the file is present -- perhaps do this per-crate.
OK, it wasn't as bad as I originally reported. This regressed via which is only in 1.45 (beta). I have a fix started at This will require various steps: cargo. to beta. cargo on beta. for new beta release. bootstrap on nightly.
Well, but it does mean that currently on CI we do not run doctests, right? does not change this.
Right, I just mean it hasn't been that long (only about a week).


Question: if let (local, []) = (&place.local, proj_base) { let decl = &self.body.local_decls[*local]; if decl.internal { <del> // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; </del> <ins> if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; } } else { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; </ins> } } }

root: updns-0.0.6: v.
triage: P-high. Nominating for discussion.
self-assigned for investigation in short term (as in, next two or three days). However I suspect someone from will be a better choice to investigate this.
We should try to bisect this
used . Determined: searched nightlies: from nightly-2019-11-26 to nightly-2020-01-03 regressed nightly: nightly-2019-12-01 searched commits: from to  regressed commit:
is a rollup commit of the following PR's: I'm guessing this is due to PR
I'm still working on reducing this down to something that I could put into the playpen. However, one interesting thing I've found locally during my reduction: This version of the will signal an analogous compilation error: but if I lift the first argument out to a separate -binding (i.e. change it to use above, or the sub-expression out to a separate -binding (i.e. change the argument expression to use above), then the error goes away. I'll admit that I don't know all the details of how the fn-transformation works to support , but I strongly suspect that if this kind of local code change can make an error go away, then that represents a weakness somewhere (either in the fn-transformation, or in the borrowck).
Okay in the details block is a standalone version suitable for the : <details</detailsand the error it generates:
So this does seem like somewhat clear (expected?) fallout from PR : a use of a in a generator witness will be recorded as a unsafe pointer , and then is never , but the method requires that the task you give it is . I believe we can readily update the crate in question to avoid using the in the expression under the RHS of . But I do wonder whether we can/should improve the diagnostics here to try to guide the user towards such a solution ...?
I might have worded this too strongly, and/or over-reduced my example. In particular, its easy to move around the access to . But the borrow of may be trickier to deal with.
I'll have a look at addressing this with another approach I considered for . If that doesn't work out then I'll have a look at the error message.


Question: if let (local, []) = (&place.local, proj_base) { let decl = &self.body.local_decls[*local]; if decl.internal { <del> // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; </del> <ins> if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; } } else { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; </ins> } } }

The patch linked is enough to fix the crate in question, but I'm all for finding an in-compiler solution if we can do it soundly.
OK. I'm going to write some things up because I've changed my mind a bunch of times about how/if this can be fixed in MIR building and I don't want to keep forgetting things. Generators store values that if their value needs to be preserved across a yield. These values need to be visible for auto-traits, for example a generator may be resumed on a different thread after it yields, and so cannot be if any of theses values isn't . There are two passes that determine which values can be included in the generator: A pass that runs as part of typeck that walks the HIR to find the types of expressions and then checks for yields in the values scope (as determined by the RegionScopeTree). The types recorded here are stored in the GeneratorWitnesss type contained in the generator, which is then used for auto trait checking. This notably uses the types of expressions that HIR sees. The MIR transform that lowers the generator to a state machine. This determines the values that the generator actually stores. As a check for the compiler, we assert that any types that we capture here are included in the witness type (we don't know all auto traits, so can't check only for them). After statics no longer have a special representation in MIR. They are instead lowered to a dereference of a pointer to the given static: is lowered as if it were: Which becomes: The example above is somewhat deceptive in that the temporary that holds the pointer is used immediately after it's assigned. In this case it cannot end up in the generator since it's not live across any user code. However this isn't true in all cases, index and match expressions allow running user code while the pointer is live: In these cases MIR has to put the temporary pointer into the generator state and promptly ICEs. The obvious solution now is make type checking record the new pointer types in the generator witness in these cases. Unfortunately HIR is not a great tool for specifying "these cases". The methods that the region scope tree provides in HIR are either usually far too large (the "temporary scope") or occasionally too small (the "enclosing scope"). went for the sound but rather approximate approach, leaving us here.


Question: if let (local, []) = (&place.local, proj_base) { let decl = &self.body.local_decls[*local]; if decl.internal { <del> // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; </del> <ins> if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; } } else { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; </ins> } } }

One idea might be to try changing MIR building so that the temporary is never live across user code. For example, one might change the lowering as follows However working out how to do this for in a reasonable to implement way is harder. MIR actually already contains an escape hatch for values that are in the MIR but aren't in the HIR in the form of a flag (called ) on the variable. We currently use it for drop flags and boxes created by expressions. It's unclear what exactly the difference is between is. I guess one could argue that auto traits are for layout introspection and this would be further breaking that. I think that's everything for now.
Visiting from triage. were you planning to work on this further?
It's definitely tempting to take advantage of the constraints around statics to just declare these equivalent, and use the flag to get out of this. While I don't see any soundness issues around that, I also don't quite trust myself to get this right :) Can you expand on this? I'm not sure I follow.
Another solution that comes to mind relies on the fact that these pointers never need to be stored in a generator. They are consts, and the temporaries containing them shouldn't ever be mutated. We could add semantics for "const temporaries" to MIR, and never store them inside generators. The semantics would (hopefully) be simple: defined once and assigned a value that doesn't depend on any other temporaries; never mutated or borrowed mutably. We can move the statements defining them to the top of the function inside the generator transform. But that would be adding more semantics and special casing to MIR to fix a change which removed extra semantics and special casing, so I'm not sure if that's what we want :)
The argument is that the given the following auto trait we guarantee that if then there are no raw pointers directly stored in an instance of . If we make that guarantee then using internal in generators would not be OK. I would argue that we're not making such (or really any) guarantees with user defined auto traits.
Yeah, I don't think auto traits should expose layout implementation details of generators. And this really does seem like a pure implementation detail -- it doesn't have any bearing on what kinds of (unsafe) operations are allowed on a generator, like a self-reference would.


Question: if let (local, []) = (&place.local, proj_base) { let decl = &self.body.local_decls[*local]; if decl.internal { <del> // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; </del> <ins> if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; } } else { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; </ins> } } }

cc
So, I've been putting off commenting here to let these ideas sit, but let me leave a comment. I think I've reached a conclusion. TL;DR. I think we should mark these types as internal, but I think there are some better options for fixing this in the medium term, and this interaction should be taken into account as part of the "MIR 2.0" effort to rework places. Auto traits weren't really intended as a tool for probing layout, but rather semantic considerations. This is why traits like can be implemented by users. So I don't really think that auto traits give any sort of guarantee about their layout. Rather, this question is about is simply "what are the constituent types exposed by a generator", and this should correspond to the types that user code can directly access. The raw pointers here are not directly accessible. The values that are accessible are the "live values" that the user's code may later use -- and of course the code currently makes the constituent types be a superset of those, based on the AST structure. Of course, the real root cause of this error is a simplifying change to the definition of in MIR. It used to be that a Place had this grammar: but now we changed to just , which is why we are required to introduce the new temporary (and that holds the address of the ). As we've been talking about this change, I've been saying that we should be considering the older definition of as the one that is used by various analyses (and in particular by borrow check). This particular transformation of removing statics doesn't affect borrow check, but we failed to take into account the fact that the set of live variables can effect the definition of what is live in a generator. In particular, compiling for some expression requires a temporary unless corresponds to a place -- those places used to include statics like , but they no longer do. But I think that for analysis purposes, it should appear as if they do. We could fix this in two ways. We could write some code motion / duplication that takes temporaries like that are live across a yield and creates a fresh variable after the yield. The idea would be to make them never* live across a yield.


Question: if let (local, []) = (&place.local, proj_base) { let decl = &self.body.local_decls[*local]; if decl.internal { <del> // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; </del> <ins> if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing  violations or data races will cause undefined behavior", UnsafetyViolationKind::General, ); return; } else if self.tcx.is_foreign_item(def_id) { self.require_unsafe( "use of extern static", "extern statics are not controlled by the Rust type system:  invalid data, aliasing violations or data races will cause  undefined behavior", UnsafetyViolationKind::General, ); return; } } else { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. self.source_info = self.body.local_decls[*local].source_info; </ins> } } }

We can do this because that operation is a compile-time constant, really, and thus the value doesn't need to be live across a yield. This might be worth doing as a size optimization regardless. Secondly, some of the proposals we've been kicking around for going further with simplifying include the idea of a distinct sort of temporaries that explicitly represent a "partially constructed that hasn't been used by the user". The idea was to allow borrowck (and other analyses) to trivially reconstruct the . We might want to add this interaction with auto-traits into the consideration for that design, and maybe it takes us some place (e.g., these special temporaries are not considered live for the purposes of auto traits). Having written out both of those options, though, I sort of lean towards the first, at least for this specific issue.
I think these references and raw pointers created by MIR construction should be marked as . They are not visible at the language level. They can be viewed as just prefetching the address of a static, so the compiler could pick any type it likes for it (, , , some compiler internal type) so it must not affect auto trait inference. Drop flags are ignored for similar reasons. You cannot use an auto trait like this to detect them: So I think that should be reverted and the temporary static references should be marked as .
Note: opened instituting this change and I r+'d it, since fixing the regression seems pretty important and time is of the essence; there is general consensus here on the thread; this is only restoring older behavior. In particular, there were some suggestions that this might be a lang team issue; I think there is some 'intersection' and I don't want the perception that I'm trying to shortcircuit discussion. That said, I also think this is primarily a compiler team matter, since it's a deviation from the old behavior, and further this deviation was caused by altering the MIR away from the "natural, Rust-based" definition and towards a lower-level definition.


Question: .arg("--manifest-path") .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml")); cargo.arg("--target").arg(target.rustc_target_arg()); <del> cargo.arg("--tests"); // don't run doctests, they are too confused by the staging </del> cargo.arg("--").args(builder.config.test_args()); <ins> // `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "run", not a "test". // Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage. // So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER). cargo.env("RUSTDOC", builder.rustdoc(compiler_std)); </ins> // Tell `cargo miri` where to find things. cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot);

Currently we do ensure on CI that works, but doctests are enabled as I couldn't figure out how to get this to work within bootstrap. However, that has let slip through. So ideally we can figure out these bootstrap issues and test rustdoc inside on rustc CI.
Here's what currently happens: shows a similar error. So... probably we're using the wrong rustdoc? I assume it's the bootstrap rustdoc, if that's a thing? I can't even see a rustdoc being built in the build log. We want the rustdoc that is produced by stage 0 here, since we are testing the Miri produced by stage 0. How do we get that? Cc
looks to be the reason we're running a random rustdoc here. I suspect we'll need to thread through a custom bootstrap env variable, since IIRC there's no RUSTDOC_WRAPPER that miri can use to thread state. Alternatively it might work to adjust miri such that it remembers which toolchain is running earlier, but I suspect that'll be harder. As-is though it's almost certainly semi-broken for any Rust user doing something like presumably, where their default toolchain isn't nightly?
It seems to be working, AFAIK rustup ensures that nested calls use the -specified toolchain. Or maybe we are just lucky... But yes we should in the outermost wrapper, determine which rustdoc cargo would invoke using the same logic as cargo store that in a miri-private env var invoke that in I assume however we'll also need further changes in how bootstrap invokes cargo-miri to tell it where the right rustdoc lives? Currently we're not even building rustdoc so something surely needs to change in bootstrap. I see this snippet a few times, is that all we need?
Yeah, I'd expect that to be enough to start with at least. Also potentially relevant: If we're already using somewhere in there (we should be, probably?) then that should already get mostly setup, see here: ,
We do that already: Unless you are trying stage 0, you should be able to see rustdoc compilation in the build logs.
This is stage 0. It should still have to build rustdoc, stage 0 Miri needs stage 0 rustdoc (not bootstrap rustdoc) for its doctests.


Question: .arg("--manifest-path") .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml")); cargo.arg("--target").arg(target.rustc_target_arg()); <del> cargo.arg("--tests"); // don't run doctests, they are too confused by the staging </del> cargo.arg("--").args(builder.config.test_args()); <ins> // `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "run", not a "test". // Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage. // So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER). cargo.env("RUSTDOC", builder.rustdoc(compiler_std)); </ins> // Tell `cargo miri` where to find things. cargo.env("MIRI_SYSROOT", &miri_sysroot); cargo.env("MIRI_HOST_SYSROOT", sysroot);

(...) ah fun, so if we invoke RUSTDOC we'll actually invoke bootstrap's rustdoc wrapper. We'll have to see if having both Miri and that wrapper around will work.^^
Never mind, that was for a build. For stage 0 this doesn't happen. I don't think this can work though... The staging with Miri is a bit weird; we need a stage 1 std as well for our stage 0 tests. Specifically we need a host sysroot that was built with a compiler that "is the same as" Miri, i.e. that is fully compatible. (The is wrong, it's not the compiler that built Miri.) This was needed to make build scripts and proc macros work in .
Yes, and if you want to use the actual rustdoc without wrapper, you can invoke . I tried using env instead of plain "rustdoc" and this is the output:
I had to manually pass from the cargo miri test caller; it turns out we are not passing it by default (or it somehow gets removed later?). Anyway, this is how I tested it:
Yeah currently this does not work due to But you have already come closer than I did. :) Was that with or stage 1? Maybe is ?
I guess that needs to be resolved first before we enable doctests on cargo miri test ? It was stage 1. Yeah, it seems like.
Yes. must continue working. I don't want to always build rustc twice when working on Miri in the tree.^^ But if necessary we could enable doc-tests only for higher stages... that would still be better than the status quo.


Question: &[], ); miri.add_rustc_lib_path(builder); <del> // Forward arguments. </del> miri.arg("--").arg("--target").arg(target.rustc_target_arg()); <del> miri.args(builder.config.args()); </del> // miri tests need to know about the stage sysroot <del> miri.env("MIRI_SYSROOT", &miri_sysroot); </del> <ins> miri.arg("--sysroot").arg(miri_sysroot); // Forward arguments. This may contain further arguments to the program // after another --, so this must be at the end. miri.args(builder.config.args()); </ins> let mut miri = Command::from(miri); builder.run(&mut miri);

This used to work fine at some point, but now leads to some strange errors:
somehow Miri searches for its sysroot in instead of its own built sysroot?
When executing Miri: I thought the sysroot was passed to the process with , but I cannot find such an argument... how exactly does it find from this... I don't really understand how that works. But this may help.
I see, it gets the sysroot because is in . Slightly strange, that sysroot is not really one it can use. Why is it linked from there? But either way, the sysroot we want to use for Miri here is an entirely different one that needs to be override manually. How did that work previously?
oh lol, this was almost certainly broken by , in which you even specifically mentioned , looks like you forgot about it :D
oops thanks for fixing!


Question: <ins> - // MIR for `bar` before RevealAll + // MIR for `bar` after RevealAll fn bar(_1: P) -> () { debug _baz => _1;                    // in scope 0 at $DIR/issue-78442.rs:9:5: 9:9 let mut _0: ();                      // return place in scope 0 at $DIR/issue-78442.rs:10:3: 10:3 let _2: ();                          // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 -     let mut _3: &impl std::ops::Fn<()>;  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 -     let _4: impl std::ops::Fn<()>;       // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +     let mut _3: &fn() {foo};             // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 +     let _4: fn() {foo};                  // in scope 0 at $DIR/issue-78442.rs:11:5: 11:15 let mut _5: ();                      // in scope 0 at $DIR/issue-78442.rs:11:5: 11:17 bb0: { StorageLive(_2);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 StorageLive(_3);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_4);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:13 // + literal: Const { ty: fn() -> impl std::ops::Fn<()> {hide_foo}, val: Value(Scalar(<ZST>)) } } bb1: { _3 = &_4;                        // scope 0 at $DIR/issue-78442.rs:11:5: 11:15 StorageLive(_5);                 // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 nop;                             // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 _2 = <impl Fn<()> as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:15 // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl std::ops::Fn<()>, ()) -> <impl std::ops::Fn<()> as std::ops::FnOnce<()>>::Output {<impl std::ops::Fn<()> as std::ops::Fn<()>>::call}, val: Value(Scalar(<ZST>)) } } bb2: { StorageDead(_5);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 StorageDead(_3);                 // scope 0 at $DIR/issue-78442.rs:11:16: 11:17 StorageDead(_4);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 StorageDead(_2);                 // scope 0 at $DIR/issue-78442.rs:11:17: 11:18 _0 = const ();                   // scope 0 at $DIR/issue-78442.rs:10:3: 12:2 drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 } bb3: { return;                          // scope 0 at $DIR/issue-78442.rs:12:2: 12:2 } bb4 (cleanup): { drop(_1) -> bb5;                 // scope 0 at $DIR/issue-78442.rs:12:1: 12:2 } bb5 (cleanup): { resume;                          // scope 0 at $DIR/issue-78442.rs:7:1: 12:2 } } </ins>

Previously: Now: <!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
Inlining exposes a use of unnormalized local in a call terminator (not sure if this is more of an issue with inlining or a validator): Note: revision annotation doesn't work in an auxiliary file (so it isn't tested on CI with mir-opt-level=2). modify labels: +A-mir-opt-inlining
This ICEs again because the fix was reverted Can someone reopen please?
Due to this new requires to trigger. <details<summaryICE:</summary</details
(FWIW can also trigger this: )
fixes this for and , but it still ICEs with on its own or with mir-opt-level 1/2 cc


Question: } ``` <del> Enums with values are quite useful, but as I mentioned, they're even more useful when they're generic across types. But before we get to generics, let's talk about how to fix these big `if`/`else` statements we've been writing. We'll do that with `match`. </del> <ins> And you can also have something like this: ```{rust} enum StringResult { StringOK(String), ErrorReason(String), } ``` Where a `StringResult` is either an `StringOK`, with the result of a computation, or an `ErrorReason` with a `String` explaining what caused the computation to fail. This kind of `enum`s are actually very useful and are even part of the standard library. As you can see `enum`s with values are quite a powerful tool for data representation, and can be even more useful when they're generic across types. But before we get to generics, let's talk about how to use them with pattern matching, a tool that will let us deconstruct this sum type (the type theory term for enums) in a very elegant way and avoid all these messy `if`/`else`s. </ins> # Match

See: The keyword hasn't been introduced until that point but it's used in the code example which is confusing. I believe an if/else solution would be more explanatory, especially because the reader probably wants to see how to unpack the variant of . The same enum could then be used with the keyword in the beginning of the next chapter ().
You are correct. Nice catch!
Are you ok with simply reordering them ? Because introducing sum type without precedent knowledge of pattern matching is a bit pointles (or at least misses the fact that they are juste AWESOME for pattern matching). If you're ok with this I'll PR in a few hours :)
Maybe, if it flows okay, yeah. I do want to put SOME kind of mention of it first.
It's probably easy to find out what is doing by simply looking at it. This part of the tutorial is just a bit confusing and should be fixed. However, my main concern here is that the reader is left clueless on how to solve this problem with if/else: In fact, I really don't know how the equivalent code without would look like. I've briefly tried to figure it out and gave up.
With an Option you coul unwrap I guess. By the way why did you write a fake option enum ? Because that's basically what is done with this, it might be better to give out the real name
Because we haven't talked about generics yet.
Nicely done. However, my other concern, how this example could be done without , remains unresolved. I'm certain that I'm not the only one who wants to know how it works with before continue reading about . Should I open another issue for that matter?
I'm honestly not sure that it is possible with an arbitrary enum... You can test for some arbitrary values but i guess but that's it. Bt it's more an issue of sum types in general rather than a Rust issue (I can't find ways to do that in haskell nor in scala)
Alright, I expected something like this as I was unable to figure out how to write it without . I don't have much experience with statically typed languages, therefore the concept was new to me. If you are right, could we mention in the tutorial that it is actually not possible to write an equivalent solution with ? Certainly, I can't be the only one who was a bit puzzled.


Question: } ``` <del> Enums with values are quite useful, but as I mentioned, they're even more useful when they're generic across types. But before we get to generics, let's talk about how to fix these big `if`/`else` statements we've been writing. We'll do that with `match`. </del> <ins> And you can also have something like this: ```{rust} enum StringResult { StringOK(String), ErrorReason(String), } ``` Where a `StringResult` is either an `StringOK`, with the result of a computation, or an `ErrorReason` with a `String` explaining what caused the computation to fail. This kind of `enum`s are actually very useful and are even part of the standard library. As you can see `enum`s with values are quite a powerful tool for data representation, and can be even more useful when they're generic across types. But before we get to generics, let's talk about how to use them with pattern matching, a tool that will let us deconstruct this sum type (the type theory term for enums) in a very elegant way and avoid all these messy `if`/`else`s. </ins> # Match

Cheers.
Thanks a lot for the remark, it's exactly the kind of comment needed, if you see others don't hesitate to open new issues :) I'll try to add this tonight or tomorrow.


Question: <del> // 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. // Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher // feature gate is not used. macro_rules! m { ($lt:literal) => {} } //~^ ERROR :literal fragment specifier is experimental and subject to change fn main() { m!("some string literal"); } </del>

Tracking issue for rust-lang/rfcs.
Is anyone working on implementation already? If not I can take a crack at it.
I'll probably do it.
Huh oh, we have an issue already: do we mean to include potentially minus-prefixed literals? If yes, we have a problem because 1. it means we have to return an Expr instead of a Lit, which means I'm not sure one will be able to use the bound fragment in a non-expr context (for example in a static array type?) and 2. it's no longer always a single-TT, so the benefits in terms of future-proofing are a bit less good. If we don't... well, we loose expressivity. I have no idea what is more intuitive though... Would you, as a Rust user, expect to parse ? I certainly can think of use cases for this...
good point. I think I would have expected it, I also agree with the complications.
Can't we upgrade Lit to support negative literals?
I'd expect "literal" (or a future integer-literal specifier) to include (negative 5), but not (the negation of positive 5). Perhaps that expectation doesn't match reality, though. For instance, based on parsing rules for non-literals, I'd expect to act like . So, if handling both and as literals makes this easier, that works. But "literal" definitely needs to include negative numbers, or we'd have a weird user trap to explain.
I'd expect "literal" (or a future integer-literal specifier) to include -5 (negative 5), but not - 5 (the negation of positive 5). Unary operators, including minus, are processed purely by the parser at the moment, no lexer involved. So their treatment is whitespace agnostic. (I personally think this is a good thing.)
I agree with is not syntactically different from and has no reason to be. But I also agree with the fact that the user will probably expect negative numbers to work as literals (even it – syntactically – they're not).
is also supported in literal patterns while arbitrary expressions are not. It'd be reasonable to support it in fragments as well.
Another thing that won't match is a macro call, like , or any of the other macros that I think of as expanding to a literal (, ...).


Question: <del> // 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. // Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher // feature gate is not used. macro_rules! m { ($lt:literal) => {} } //~^ ERROR :literal fragment specifier is experimental and subject to change fn main() { m!("some string literal"); } </del>

I dunno, maybe this is not such a good idea after all. Re-reading the RFC in a more skeptical light, I felt like the "Motivation" section could use some more concrete use cases. Maybe this is just failure of imagination on my part, though! I think the likelihood of this feature attracting people who really want constant expressions should be acknowledged as a drawback, too.
That's fine IMO. Personally I'd like it to match only explicit literals in code to distinguish, for example, between literal and identifier and produce different code for them. Right now this is not possible because all of , , are too broad and conflict with each other.
Hi All, I have implemented this feature in my fork of Rust over 1.25.0, under this branch: Following a quick review by a rustc mentor I may have the free time to provide a full pull request for this.
BTW label has the tooltip "implemented in nightly and unstable" but I did not see it there, i.e. commits & pull requests referencing this. Did I miss it?
The implementation that I worked on was merged, yay!
Is there anything stopping an FCP for this?
It's currently merged in unstable; do you mean an FCP to declare it stable?
Yes, an FCP to stabilise. Should have clarified.
Currently, it is not possible to pass a literal from a macro to another macro. . I think this is a bug.
Interesting! That is a bug. I opened to track it.
Agreed, this should be allowed just like passing any other node types.
Is there anything else preventing this from being stabilized? The issue above has been fixed.
This has baked for some time now and I believe it should be ready for stabilization. So let's start the review. merge The feature gate test is here: Unstable book: Tests defined here:
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [x] [x] [x] [x] [x] [ ] [x] [x] [x] [ ] No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!


Question: <del> // 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. // Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher // feature gate is not used. macro_rules! m { ($lt:literal) => {} } //~^ ERROR :literal fragment specifier is experimental and subject to change fn main() { m!("some string literal"); } </del>

See for info about what commands tagged team members can give me.
Reading through the tests, I see that is a literal. While that makes sense to me, I remember hearing that it wasn't, but was instead a negation operator and a literal. Am I misremembering?
cc on
I agree that it makes sense. I would say that even if is interpreted as negation + a literal, I would probably still want the macro matcher to accept since that behavior seems more intuitive. In other words, I would see being more as an implementation detail than what a literal is in the mental model.
I think that the nuance with causes a bit of a problem, because I don't think it should be treated as a literal, but I also don't think that the current implementation of would allow detecting it either. You could naïvely allow but that would allow which is clearly wrong.
there are tests currently implemented that verify that is detected as a literal.
I worded that wrong; I meant that only having a matcher and not being able to distinguish strings and numbers means that you can't easily make not a literal.
for procedural macros the input as lexed by the compiler is (two tokens) but procedural macros can create tokens that are negatives (like ). In that sense matching for makes sense to me.
Are literals generated by the compiler counted as true literals? A quick example would be something like: This fails to match, as the expansion, I guess, happens after the selection. I just naively assumed that would have worked.
is not a literal generated by the compiler, it is an identifier followed by an exclamation mark followed by a set of parentheses containing some tokens. See for example: If you were to use it in expression position, it would be interpreted as an invocation of which expands to a string literal. In this case and in your macro though, it is never in a syntactic position where it would be treated as an expression.
I can understand semantically why it doesn't make sense, I just thought it would have, but that being said, I already changed it to , so there's no issue. It just made more sense to me as a literal, because according to the compiler, it could generate a literal from it. I guess it was more a question than an actual issue.
This is true, but there's more to it!


Question: <del> // 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. // Test that the :lifetime macro fragment cannot be used when macro_lifetime_matcher // feature gate is not used. macro_rules! m { ($lt:literal) => {} } //~^ ERROR :literal fragment specifier is experimental and subject to change fn main() { m!("some string literal"); } </del>

A few built-in macros can expand their arguments eagerly through ~m a g i c~, so they accept and likes even if they expect string literals: Fortunately (or not), this currently cannot be done in user-defined macros.
I actually just realised that I can't change it to , as it's used in . So, I've just had to manually unroll the macro. ! It doesn't look pretty. :( Ninja edit: I just tested what actually happens if you try to pass in a non-literal with . It rejects it the exact same way. Does the already make use of this feature? If not, the seems to propagate the required token. Oh, unless the compiler steps in... That's actually probably the case... I've reverted it back to the type.
:bell: This is now entering its final comment period, as per the . :bell:
The final comment period, with a disposition to merge, as per the , is now complete.
Since you implemented this, would you be willing to write up the stabilization PR?
sure
This appears to be missing from the Rust reference


Question: | ty::Alias(..) | ty::Param(..) | ty::Bound(..) <del> | ty::Error(_) => {} ty::Infer(_) => { </del> <ins> | ty::Error(_) | ty::Infer( ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_) | ty::InferTy::FreshIntTy(_) | ty::InferTy::FreshFloatTy(_), ) => {} ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)) => { </ins> candidates.ambiguous = true; } }

Note: the below reduction originally came from a + in the wild. I haven't found a way to demonstrate this outside of the "float inference vars + method" combo, but: works on stable () and beta (), and errors on nightly with: Even though it doesn't show the source for candidate , I'm almost certain it's this: from (cc On the original PR I left comments like , trying to rectify the issues with the original approach, but they didn't go anywhere and the version that one in the end is the (arguably) more fragile original one, that uses blanket s and works around their unwanted interactions. It's possible in this case all it takes is checking for "float inference vars" and making sure they can never be considered to implement , but I'm worried there might be other edge cases lurking in the shadows. Also, did both of those PRs skip crater? I feel like this shouldn't be that hard to hit in the wild.
WG-prioritization assigning priority (). label -I-prioritize +P-high


Question: let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { let x_ident = Ident::with_dummy_span(sym::result); <del> let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = self.expr_ident(span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(span, x_pat); </del> <ins> let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident); let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(gen_future_span, x_pat); </ins> let ready_pat = self.pat_lang_item_variant( span, hir::LangItem::PollReady,

This code: produces: Which is invalid. Looks like the span of the desugaring of uses only the part, instead of the span of the entire expression. This results in invalid suggestions when used by the code in .
I'm not entirely sure if this means that desugaring should use a bigger span, or if the suggestion diagnostic needs to be interpreted differently.
hmm.. is the only case where the desugared expr's span doesn't cover the whole piece of code it comes from? That doesn't sound right. If wonder if the expr should have the bigger span by default, and then async-specific code could grab the tighter span for diagnostics that need to point at the operator.
Some of the desugaring only uses the span, but the parts relevant for diagnostics like this do use the full span. Not sure if there's a problem there too.
I thought I might have accidentally introduced this bug in , but right after that PR was merged, the output was correct: So something changed in the last two months in what spans are used for await desugarings, it seems.
actually I think it was introduced in in , cc Do you need someone to fix this? I'm happy to put up a quick PR.
Yeah, looks like it: I just finished bisecting, which pointed at a rollup involving .
this was introduced in the PR linked earlier to try and improve other errors. It is tricky because reducing the span to only incurs these kind of bugs. On the other hand, the errors that got improved there became much less noisy, so I wouldn't want to revert the whole change. My fix above will solve this issue, but I'm sure there will be others in the future :-/


Question: } debug!(?choice_regions, "after ub"); <del> // If we ruled everything out, we're done. if choice_regions.is_empty() { return false; } // Otherwise, we need to find the minimum remaining choice, if // any, and take that. debug!("choice_regions remaining are {:#?}", choice_regions); let Some(&min_choice) = choice_regions.iter().find(|&r1| { </del> <ins> // At this point we can pick any member of `choice_regions`, but to avoid potential // non-determinism we will pick the *unique minimum* choice. // // Because universal regions are only partially ordered (i.e, not every two regions are // comparable), we will ignore any region that doesn't compare to all others when picking // the minimum choice. // For example, consider `choice_regions = ['static, 'a, 'b, 'c, 'd, 'e]`, where // `'static: 'a, 'static: 'b, 'a: 'c, 'b: 'c, 'c: 'd, 'c: 'e`. // `['d, 'e]` are ignored because they do not compare - the same goes for `['a, 'b]`. let totally_ordered_subset = choice_regions.iter().copied().filter(|&r1| { </ins> choice_regions.iter().all(|&r2| { <del> self.universal_region_relations.outlives(r2, *r1) </del> <ins> self.universal_region_relations.outlives(r1, r2) || self.universal_region_relations.outlives(r2, r1) </ins> }) <ins> }); // Now we're left with `['static, 'c]`. Pick `'c` as the minimum! let Some(min_choice) = totally_ordered_subset.reduce(|r1, r2| { let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2); let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1); match (r1_outlives_r2, r2_outlives_r1) { (true, true) => r1.min(r2), (true, false) => r2, (false, true) => r1, (false, false) => bug!("incomparable regions in total order"), } </ins> }) else { <del> debug!("no choice region outlived by all others"); </del> <ins> debug!("no unique minimum choice"); </ins> return false; };

The following code should pass regardless of the declaration order of lifetimes: This is related to but it's different in that we do have a lower bound region, , but we fail to recognize that because , which is responsible for calculating from , assumes that the outlive relation is a total order, which is not true. Here is the graph of : ! So we need an efficient algorithm that works for partial order relations, but the one that comes to mind is . The perf may not be really important here but I'm curious to see the alternatives. label C-bug T-compiler A-borrow-checker E-mentor E-help-wanted <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
Here is the code of concern The code should calculate the from a set of universal regions (). The relations are encoded in and are guaranteed to be transitive and reflexive. The relation graph may have cycles and can be sparse. The goal here is to find a unique minimum choice that is known to be outlived by all other regions. If none can be found, the function returns . Regions that have cycles between them are considered equivalent so we can pick either one of them as a unique choice. e.g. , we can pick either one of as a minimum choice.


Question: } def load_json_from_response(resp): <ins> # type: (typing.Any) -> typing.Any </ins> content = resp.read() if isinstance(content, bytes): <del> content = content.decode('utf-8') </del> <ins> content_str = content.decode('utf-8') </ins> else: print("Refusing to decode " + str(type(content)) + " to str") <del> return json.loads(content) </del> <ins> return json.loads(content_str) </ins> def validate_maintainers(repo, github_token): <ins> # type: (str, str) -> None </ins> '''Ensure all maintainers are assignable on a GitHub repo''' next_link_re = re.compile(r'<([^>]+)>; rel="next"') # Load the list of assignable people in the GitHub repo <del> assignable = [] url = 'https://api.github.com/repos/%s/collaborators?per_page=100' % repo </del> <ins> assignable = [] # type: typing.List[str] url = 'https://api.github.com/repos/'  + '%s/collaborators?per_page=100' % repo # type: typing.Optional[str] </ins> while url is not None: response = urllib2.urlopen(urllib2.Request(url, headers={ 'Authorization': 'token ' + github_token,

Updated the toolstate repository at https://rust-lang- currently does not seem to work, see e.g. To "tool failed to build"-issues are being created, either. remarked that the error . Cc


Question: // EMIT_MIR jump_threading.assume.JumpThreading.diff // EMIT_MIR jump_threading.aggregate_copy.JumpThreading.diff // EMIT_MIR jump_threading.floats.JumpThreading.diff <ins> // EMIT_MIR jump_threading.bitwise_not.JumpThreading.diff </ins>

<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I tried this code: I expected to see this happen: always panic Instead, this happened: only -Zmir-opt-level=2 panic For mir-opt-level 0, 1 and 3, they all normally return <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
equals , so I think the panic case is incorrect?
Yeah, I think so.
Looks like it's JumpThreading that incorrectly removes the condition
I managed to create an example without panic, just wrong value
Most likely
ha, I found the bug. We're optimizing incorrectly in the jump threading code. Right now it's only written to handle bool correctly. I'll put up a fix claim


Question: --> $DIR/functional-struct-update-respects-privacy.rs:28:49 | LL |     let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... <del> |                                                 ^^^ private field </del> <ins> |                                                 ^^^ field `secret_uid` is private </ins> error: aborting due to previous error

In a recent PR I made a change to unify the wording of multiple privacy errors, but : used to be This one change needs to be reversed while keeping the rest.
Hi! Could I give this issue a shot?
I am sorry I forgot to claim the issue
No worries :-)


Question: use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; use rustc_hir::HirId; use rustc_lint_defs::Applicability; <del> use rustc_resolve::rustdoc::source_span_for_markdown_range; </del> <ins> use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, source_span_for_markdown_range}; </ins> use rustc_span::def_id::DefId; use rustc_span::Symbol;

We've recently begun testing Bevy against the beta toolchain, where it has incorrectly raised an lint against . is not imported in this file, yet rustdoc believes that it is. (See the imports .) As a temporary workaround, I've created to ignore the error. Here is that first failed. In case it expires, here's . Look at . I can reproduce it on using by running the following command: The is optional, but it makes the command finish quicker. I'll continue testing to see if I can create a minimum reproducible example. :
I've created a minimal reproduction in my -repro branch of my fork. Go to the  folder and run . I've managed to squish it down to this:
I've created a reproduction that removes the dependency on Bevy . I've simplified it down to this:
I bisected it, and this bug appears to first be introduced in . I could not reproduce it in .


Question: sess.note(&format!("{:?}", &cmd)); let mut output = prog.stderr.clone(); output.push_all(&prog.stdout); <del> sess.note(str::from_utf8(&output[..]).unwrap()); </del> <ins> sess.note(&*escape_string(&output[..])); </ins> sess.abort_if_errors(); } <del> info!("linker stderr:n{}", String::from_utf8(prog.stderr).unwrap()); info!("linker stdout:n{}", String::from_utf8(prog.stdout).unwrap()); </del> <ins> info!("linker stderr:n{}", escape_string(&prog.stderr[..])); info!("linker stdout:n{}", escape_string(&prog.stdout[..])); </ins> }, Err(e) => { sess.fatal(&format!("could not exec the linker `{}`: {}", pname, e));

Compiler crashes while compiling using Cargo. Cargo version: cargo 0.6.0-nightly ( 2015-10-17) rustc version: 1.3.0
It looks like this comes from the linker producing output (normal or error) that is not valid UTF-8. Fixing this in any other way than just using a lossy conversion is going to be really painful because it goes through the error logging infrastructure, which all works with s. That's certainly not ideal, because it would be best to relay other programs' messages to the user unchanged, but it's probably the only realistic way to handle this in the near future.
Just dump the bytes as hexadecimal? I am not sure what is going on here.
My first thought was that the path was probably not UTF-8, but because of the way cargo invokes it that crashes rustc long before it tries to link anything, so that can't be it. I'm not sure why else the message would be non-UTF-8. (I can't reproduce the ICE on that crate (I just get a normal link error), but I can reproduce the ICE by constructing a situation where the linker prints non-UTF-8 messages.) But yeah, some kind of lossy conversion with hex escapes is probably the way to go. I'm not aware of an existing function to do that.
Actually, mapping with is probably good enough.
foo'ncollect2: error: ld returned 1 exit statusn` Not great, but not an ICE and probably good enough until we have a dedicated function to do this sort of thing since this should be a very rare error.


Question: codegen_fn_attrs.export_name = Some(s); } } else if attr.check_name(sym::target_feature) { <del> if tcx.fn_sig(id).unsafety() == Unsafety::Normal { </del> <ins> if tcx.is_closure(id) || tcx.fn_sig(id).unsafety() == Unsafety::Normal { </ins> let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions"; tcx.sess .struct_span_err(attr.span, msg)

This code () Produces ICE on any channel
This is the same issue as , attributes on expressions are not converted into HIR properly.
I checked on latest nightly - isn't produced anymore while this one still throws ICE.
could you reopen this issue?
triage: P-high. Removing nomination.
Reduced somewhat:


Question: // except according to those terms. // run-pass <del> #![feature(macro_literal_matcher)] </del> macro_rules! a { ($i:literal) => { "right" };


Question: // except according to those terms. // run-pass <del> #![feature(macro_literal_matcher)] </del> macro_rules! a { ($i:literal) => { "right" };


Question: // except according to those terms. // run-pass <del> #![feature(macro_literal_matcher)] </del> macro_rules! a { ($i:literal) => { "right" };


Question: // except according to those terms. // run-pass <del> #![feature(macro_literal_matcher)] </del> macro_rules! a { ($i:literal) => { "right" };